# 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](https://onekey.dev/docs/authentication.md).
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](https://onekey.dev/docs/batch.md) and [universal search](https://onekey.dev/docs/universal-search.md).
3. Check `success` before reading `data`. A failure has `data: null` and an `error` block with a `type`. See [Response format](https://onekey.dev/docs/response-envelope.md).
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

| Answer | Retry? |
| --- | --- |
| `429` [`RATE_LIMITED`](https://onekey.dev/docs/errors.md#rate-limited), `503` and the idempotency `409` | Yes, after the `Retry-After` header. |
| `500`, `502`, `504` ([`UPSTREAM_ERROR`](https://onekey.dev/docs/errors.md#upstream-error), [`UPSTREAM_TIMEOUT`](https://onekey.dev/docs/errors.md#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`, `422` | No. The same request fails the same way. |

See [Rate limits](https://onekey.dev/docs/rate-limits.md#how-to-retry-safely) for the full rule and [Errors](https://onekey.dev/docs/errors.md) 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](https://onekey.dev/docs/idempotency.md). 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](https://onekey.dev/docs/pagination.md).

## 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](https://onekey.dev/docs/rate-limits.md).
- Use one key per app and environment, and give each a [credit limit](https://onekey.dev/docs/key-limits.md), so a bug in one cannot drain the account.
- For bulk work use [batch](https://onekey.dev/docs/batch.md): 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](https://onekey.dev/docs/caching.md).

## Check the source before you panic

If one platform keeps failing, call the free [status endpoint](https://onekey.dev/docs/status.md). 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](https://onekey.dev/docs/monitors.md): 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](https://onekey.dev/docs/data-availability.md#stable-and-beta).

## 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

- [Testing your integration](https://onekey.dev/docs/testing.md).
- [Security](https://onekey.dev/docs/security.md).
- [Versioning and compatibility](https://onekey.dev/docs/versioning.md).
