Install and fetch a page
Install the package in your application. No API key is needed.
npm install @zoniboy/gzw-data-clientimport { GzwDataClient } from "@zoniboy/gzw-data-client";
const gzw = new GzwDataClient();
const page = await gzw.dataset("weapons").list({
page: 1,
perPage: 20,
});
console.log(page.data);
console.log(page.total);The SDK uses camelCase options such as perPage. Direct REST requests use the API's query spelling, per_page.
Discover datasets at runtime
Use metadata() when an application needs the current dataset names. Newly added API datasets can be passed to dataset(name) immediately; the SDK does not need a release for data-only additions.
const registry = await gzw.metadata();
const datasetNames = registry.datasets.map((dataset) => dataset.name);
// Use these names to populate an application menu or picker.
const selectedName: string = datasetNames[0] ?? "weapons";
const selectedDataset = gzw.dataset(selectedName);
const info = await selectedDataset.info();
const records = await selectedDataset.list({ page: 1, perPage: 20 });Dataset records and metadata come from the API. For a newly discovered dataset, TypeScript uses the generic GzwRecord fallback: fields remain accessible, but fields without a curated model have type unknown.
List, filter, search and fetch
Each dataset resource provides the same core operations. Filters and pagination can be combined.
const keys = gzw.dataset("keys");
const keycards = await keys.filter(
{ type: "Keycard" },
{ page: 1, perPage: 25 },
);
const akWeapons = await gzw.dataset("weapons").search("AK", {
page: 1,
perPage: 10,
});
const weapon = await gzw.dataset("weapons").get("ak-12");
if (weapon) console.log(weapon.name);A missing record from get(id) returns undefined. Other API errors throw GzwApiError.
Cross-dataset search
const results = await gzw.search("AK-12", {
datasets: ["weapons"],
fields: ["name"],
fuzzy: true,
limit: 5,
});Iterate, batch-load and use helpers
iterate() yields records page by page. getMany() loads known IDs with bounded concurrency; dataset.export({ limit }) is still capped by the API's server-side maximum.
for await (const weapon of gzw.dataset("weapons").iterate({ perPage: 50 })) {
console.log(weapon.name);
}
const records = await gzw.dataset("weapons").getMany(
["ak-12", "ak-74"],
{ concurrency: 4 },
);Convenience helpers are also available for stats(), health(), ready(), version(), metadata(), schema(), changes(), images(), spec(), and stable smart routes such as armor().
Autocomplete is a snapshot; runtime discovery is live
The KnownGzwDataset union provides editor suggestions for names in the published SDK snapshot. TypeScript autocomplete is computed from local declarations, so it cannot query the API while you type. For a live picker inside your app, populate it from gzw.metadata().
GzwDataset also accepts arbitrary strings, so a name returned by the API works even if it is absent from the snapshot. Strongly typed models are maintained for selected stable datasets; unknown records use GzwRecord.
When does autocomplete change?
The SDK repository can refresh its generated names with npm run generate-types. All SDK consumers receive those new editor suggestions only when a later SDK package version is published and installed. Routine API dataset or count changes do not trigger an npm release.
Errors, retries and cancellation
HTTP failures are exposed as GzwApiError, with status, stable code, request URL and retry information when available. The client retries eligible rate-limit, server, transient network and invalid-response failures by default; it respects Retry-After and does not retry caller-aborted requests.
import { GzwApiError } from "@zoniboy/gzw-data-client";
try {
await gzw.dataset("weapons").list();
} catch (error) {
if (error instanceof GzwApiError) {
console.error(error.status, error.code, error.retryAfter);
}
}Pass an AbortSignal as the final method argument to cancel a request. A configured timeoutMs bounds each network attempt.
Configure retries, timeout and cache
Defaults work for a small app. The response cache is disabled unless a positive TTL is configured; it is in-memory per process, not persistent storage.
const gzw = new GzwDataClient({
retries: 2,
timeoutMs: 15_000,
cache: { ttlMs: 30_000, maxEntries: 100 },
});Cache successful GET responses only. Use clearCache() to clear all entries, or pass a path to invalidate a route's cached query variants.
Runtime, freshness and limits
- The client targets Node.js 18+ and modern browsers with native
fetch; browser projects should use a bundler such as Vite. - The API is public, read-only and requires no key. It has a best-effort rate limit of 100 requests per minute per IP; cache responses and respect
Retry-After. - The API's published dataset is refreshed by the scraper workflow. Data routes use a CDN cache window, so newly scraped data may not appear immediately.
- Use
gzw.version(), responsedataVersion, orgzw.metadata()to inspect current API and data metadata. A data refresh is not an SDK release.
For endpoint behavior, query parameters, response envelopes and rate-limit headers, see the API reference. For copyable cURL, browser, Python and SDK recipes, see API & SDK examples.
Ask the right project
Report SDK behavior to the client repository; report missing or incorrect game data to GZW Data.
