Skip to content
API

Steam 429 handling

Steam inventory 429 handling for production clients

WOK separates client-plan rate limits from Steam upstream availability. A cache hit avoids duplicate Steam work but still consumes the API operation/rate quota; native upstream capacity can be reported as status=limited while the HTTP response is 200.

GET /v1/inventoryBearer authentication

Updated

curlWOK API
curl --fail-with-body --retry 3 --retry-delay 2 --retry-max-time 30 \
  -H "Authorization: Bearer $WOK_API_KEY" \
  "https://woksteamapi.com/v1/inventory?steam_id=76561198090744629&game=cs2"
Cache firstreuse a fresh snapshot
Singleflightcoalesce concurrent misses
Bounded retrycap attempts and total time
Status awareseparate WOK 429 from Steam limited

Quickstart

Use WOK from a trusted server. Keep the API key outside browser bundles and public repositories.

curlWOK API
curl --fail-with-body --retry 3 --retry-delay 2 --retry-max-time 30 \
  -H "Authorization: Bearer $WOK_API_KEY" \
  "https://woksteamapi.com/v1/inventory?steam_id=76561198090744629&game=cs2"
JavaScript (Node.js)WOK API
// Node.js: retry HTTP 429 or native status=limited.
const url = "https://woksteamapi.com/v1/inventory?steam_id=76561198090744629&game=cs2";
for (let attempt = 0; attempt < 3; attempt += 1) {
  const response = await fetch(url, {
    headers: {Authorization: `Bearer ${process.env.WOK_API_KEY}`}
  });
  const payload = await response.json().catch(() => ({}));
  const upstreamLimited = response.ok && payload.status === "limited";
  if (response.ok && !upstreamLimited) { console.log(payload); break; }
  if ((!upstreamLimited && response.status !== 429) || attempt === 2) {
    throw new Error(`${response.status}: ${JSON.stringify(payload)}`);
  }
  const retryAfter = Number(response.headers.get("Retry-After"));
  const seconds = Number.isFinite(retryAfter) && retryAfter > 0 ? retryAfter : 2;
  await new Promise(resolve => setTimeout(resolve, seconds * 1000));
}
PythonWOK API
import os
import time
import requests

url = "https://woksteamapi.com/v1/inventory"
for attempt in range(3):
    response = requests.get(url, headers={
        "Authorization": f"Bearer {os.environ['WOK_API_KEY']}"
    }, params={"steam_id": "76561198090744629", "game": "cs2"}, timeout=30)
    payload = response.json()
    upstream_limited = response.ok and payload.get("status") == "limited"
    if response.ok and not upstream_limited:
        inventory = payload
        break
    if (not upstream_limited and response.status_code != 429) or attempt == 2:
        response.raise_for_status()
        raise RuntimeError("inventory remained limited after retries")
    try:
        seconds = max(0.1, float(response.headers.get("Retry-After", "2")))
    except ValueError:
        seconds = 2.0
    time.sleep(seconds)

Response example

The values below illustrate the response shape. Field names and types match the public contract.

JSON

application/json
HTTP 429 (WOK key rate limit)
Content-Type: application/json
Cache-Control: no-store
Retry-After: 17
X-RateLimit-Limit: 300
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1787252400

{"error":"rate limit exceeded","status":429}

HTTP 200 (native Steam capacity outcome)
Cache-Control: private, no-store

{"status":"limited","meta":{"cache_ttl":0}}

Response schema

Stable fields for typed clients, storage and error handling.

Steam inventory 429 handling for production clients response schema
FieldTypeMeaning
HTTP statusinteger429 is the WOK key rate/quota response; native upstream capacity is HTTP 200 with status=limited.
statusstringNative inventory outcome; limited means temporary upstream capacity.
Retry-AfterheaderMinimum delay before the current WOK minute window resets; use a capped fallback for upstream-limited results.
errorstring/objectMachine-readable error body; do not parse prose.
X-Wok-Cache-AgeheaderAge when the corresponding inventory result path supplies it.
X-Wok-Cache-TTLheaderFreshness window when the corresponding inventory result path supplies it.

Limits and error behavior

Rules clients should handle explicitly in production.

No service can guarantee that Steam will never rate-limit an inventory request. WOK can reduce duplicate upstream work, not change Steam's external availability.

A 429 from your WOK plan requires backoff. Native temporary upstream capacity is returned as HTTP 200 status=limited and also requires backoff; treat Retry-After as the minimum wait when the response includes it.

Retry only idempotent reads, cap the attempt count and add jitter in high-concurrency systems. Do not retry 400, 401, 402, 403 or 404.

no_cache=1 deliberately bypasses a reusable snapshot and can increase upstream work; reserve it for explicit refresh actions.

Cache and freshness semantics

How to tell whether data was reused, shared or refreshed.

Successful inventory snapshots use a 1,800-second default TTL. Negative defaults are 21,600 seconds for empty, 3,600 seconds for private and 600 seconds for not found.

For authenticated inventory responses that reach validation/result handling, read X-Wok-Cache-Age and X-Wok-Cache-TTL when present; authentication and quota errors may omit them.

Identical concurrent misses are coalesced. A waiter receives X-Wok-Singleflight: 1 and does not start another Steam inventory fetch.

Use refresh_prices=1 or POST /v1/inventory/refresh-prices only with an active compatible OK/EMPTY snapshot. Repricing never fetches Steam or resets inventory age/TTL; 404 inventory_cache_miss means run a normal inventory scan. refresh_prices=1 cannot be combined with no_cache=1; prices_updated_at identifies the repricing operation.

Cache-Control is private, no-store, so shared intermediaries must not reuse user-specific inventory bodies. WOK's server-side cache is described by the X-Wok headers instead.

A cache hit still counts as a WOK API operation and rate-limit unit even though it avoids another Steam request.

Frequently asked questions

Direct answers about access, freshness and result semantics.

Can any API guarantee no Steam 429 responses?

No. Caching, singleflight and bounded retries reduce duplicate upstream work, but they cannot change Steam's external availability.

Should clients retry every error?

No. Retry temporary 429 or limited outcomes with a cap and jitter. Do not retry validation, authentication, payment or not-found responses as a burst.