Docs
View as Markdown

Production checklist

What to settle before an integration runs unattended. Each item links to the page that has the detail.

One request wrapper#

Send every call through one function so the rules below live in one place. It should:

  1. Add the x-api-key header from an environment variable (never from source control or browser code). See Authentication.
  2. Set a timeout. Fresh fetches from hard-to-reach platforms take longer than cache hits; start with 30 seconds for single calls and longer for batch and universal search.
  3. Check success before reading data. A failure has data: null and an error block with a type. See Response format.
  4. Log metadata.request_id (also the X-Request-Id header) on every call. It is the one thing we need if you write to us.
  5. Return the error.type to the caller so it can branch.

Retry only what can succeed#

AnswerRetry?
429 RATE_LIMITED, 503 and the idempotency 409Yes, after the Retry-After header.
500, 502, 504 (UPSTREAM_ERROR, UPSTREAM_TIMEOUT)Yes, with backoff: 1 s, 2 s, 4 s plus jitter, 3 or 4 tries. These calls were refunded.
400, 401, 402, 403, 404, 405, 422No. The same request fails the same way.

See Rate limits for the full rule and Errors for each type.

Make retries safe#

A call that timed out may or may not have been billed. Send an Idempotency-Key on any call you might repeat: the retry within 24 hours is replayed from the stored answer for 0 credits. See Idempotency. Generate the key once per logical operation, not once per attempt.

Drain pages properly#

Loop on pagination.has_more and send pagination.next_cursor back untouched as cursor with the same other parameters. Never build or edit a cursor. See Pagination.

Control rate and spend#

  • The default is 600 requests per minute per key and 50 requests in flight at once; X-RateLimit-Remaining on every response tells you where you are. Slow down before it reaches zero, and keep your worker pool below the in-flight cap. See Rate limits.
  • Use one key per app and environment, and give each a credit limit, so a bug in one cannot drain the account.
  • For bulk work use batch: the call checks the worst case first and bills only the rows that returned data.
  • Watch your balance with GET /v1/account (free). The X-Credits-Remaining header is authoritative on any call that charged something.

Decide what stale means#

Cache hits are free and fast, and a stale copy is served when the source is down. If your use needs a live number, read metadata.cached, metadata.stale and metadata.age_s and decide in code. See Caching.

Check the source before you panic#

If one platform keeps failing, call the free status endpoint. A platform reported down will not recover by retrying faster.

Prefer a monitor over a poll#

If the job is "tell me when it changes", create a monitor: it re-runs on a schedule and sends a signed webhook. Verify the signature on every delivery, answer 2xx within 5 seconds, and de-duplicate on Onekey-Delivery-Id.

Stable before beta#

Beta endpoints are not yet verified against the live source. Do not build anything critical on them without a fallback. See Data availability.

Deployment checklist#

  • [ ] Key in a secret store, one key per app and environment, each with a credit limit.
  • [ ] One request wrapper with timeout, success check and request_id logging.
  • [ ] Retries only on 429, 5xx; backoff with jitter; Retry-After honoured.
  • [ ] Idempotency-Key on every call that may be repeated.
  • [ ] Pagination loop on has_more, cursor passed back verbatim.
  • [ ] Unknown response fields and unknown error types tolerated.
  • [ ] null handled as unknown, not as zero.
  • [ ] Alerting on 402 (balance) and KEY_BUDGET_EXCEEDED.
  • [ ] A failing platform checked against /v1/status before retries are escalated.

Next#