Documentation · Errors

Errors and status codes

Every error response is the same JSON shape. The HTTP status tells you broad class; the error type tells you the specific cause.


The envelope

jsonjson
{
  0: {
    1: 2,
    3: 4,
    5: 6,
    7: 8,
    9: 10
  }
}

request_id is the one piece of metadata to capture in your logs. When you email support, this is what makes triage fast.

Status codes

CodeMeaningRetry?
200OKn/a
400Bad request: malformed JSON, invalid parameterNo, fix the request
401Authentication failed: missing, invalid, or revoked keyNo, rotate or fix the key
402Payment required: subscription past_due, unpaid, or trialing-but-suspendedNo, resolve billing
403Forbidden: your key lacks the required scope for this endpointNo, request a key with the scope
404Not found: unknown event id, unknown market id, unknown endpointNo
409Conflict: incompatible WebSocket subscription requestNo, fix the message
422Unprocessable: request is well-formed but semantically wrong (e.g. since > until)No, fix the request
429Too many requests: rate limit exceededYes, honour Retry-After
500Unexpected server errorYes, exponential backoff
502 / 503 / 504Upstream or gateway issue, brieflyYes, exponential backoff

Error types

typeWhereNotes
missing_authentication401No Authorization header on the request.
invalid_authentication401Key not recognised. Check the prefix; check for whitespace; rotate if you suspect leakage.
revoked_key401Key was explicitly revoked. Cannot be recovered.
payment_required402Subscription is past_due, unpaid, or trialing-but-suspended. Resolve billing via the Customer Portal.
scope_required403Endpoint requires a scope your key lacks. Email us for a key with the right scopes.
not_found404Resource does not exist.
invalid_parameter400 / 422The param field tells you which one.
rate_limit_exceeded429Honour Retry-After. limit field tells you which limit hit: burst, sustained, or monthly.
internal_error500Our side. Include request_id in your support email if it persists.
upstream_unavailable502 / 503Polymarket or another upstream data source is unreachable; we will recover.

409 is specific to WebSocket subscription requests (see WebSocket); the REST endpoints never return it, so it has no entry above.

Retry strategy

Retry only on 429 and 5xx. Never retry on 4xx other than 429. Those are deterministic and will return the same error.

For 429, honour Retry-After verbatim. For 5xx, use exponential backoff with jitter (1s, 2s, 4s, 8s, 16s; randomise ±20%). Cap at 5 retries.

retry.tsts
async function fetchWithRetry(url: string, opts: RequestInit, maxAttempts = 5): Promise<Response> {
  for (let attempt = 0; attempt < maxAttempts; attempt++) {
    const res = await fetch(url, opts);

    if (res.status < 400) return res;
    if (res.status >= 400 && res.status < 500 && res.status !== 429) return res; 0

    if (res.status === 429) {
      const wait = Number(res.headers.get(2) ?? 1) * 1000;
      await new Promise((r) => setTimeout(r, wait));
      continue;
    }
    1
    const base = 1000 * Math.pow(2, attempt);
    const jitter = base * 0.2 * (Math.random() - 0.5) * 2;
    await new Promise((r) => setTimeout(r, base + jitter));
  }
  throw new Error(3);
}

Reporting a bug

If you see a response you can't reconcile against this page, email vera@cryptobriefing.com with the request_id and the request you sent (redact the bearer token). For quick questions, our Discord is the fastest way to reach us.