> ## Documentation Index
> Fetch the complete documentation index at: https://docs.kirafin.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Go-live checklist

> What has to be true before you point a working sandbox integration at production.

Going live is a configuration change, not a rewrite — provided the items below are already true. Each one is a thing that has broken a real integration on its first production day.

## Credentials and environment

* [ ] **Production credentials issued**, and separate from sandbox. A sandbox key does not work against production.
* [ ] **The base URL comes from configuration**, not from a constant. Production is the same host without the `/sandbox` prefix, and that prefix applies to *every* path.
* [ ] **Credentials are not in your source tree.** Environment variables or a secret manager, never a committed file.
* [ ] **The version header is sent on every request**, with the same value everywhere.

## Webhooks

* [ ] **Your production URL is registered**, in the Developers section of the dashboard, subscribed to the events you handle.
* [ ] **Your endpoint answers quickly and acknowledges before doing work.** A handler slower than 30 seconds is cut off; that counts as a transient failure and is retried, but the event arrives late.
* [ ] **Handlers are idempotent.** The same event can arrive more than once, and must not pay anyone twice.
* [ ] **You answer `2xx` to event names you do not recognise.** A refusal is the one failure that is never retried.
* [ ] **You reconcile against a read**, for anything where missing an event would be wrong. Retries stop after roughly 80 minutes.
* [ ] **You react to state changes rather than polling for them.** Anything you poll for in production is latency you chose.

## Money handling

* [ ] **Every create call sends an `Idempotency-Key`**, a fresh UUID per operation and not per retry.
* [ ] **A `409` is handled as "already done"**, not as a failure to retry with the same key.
* [ ] **Amounts are parsed as decimals, never as floats.** They arrive as strings — `"1000.00"` — and a float will eventually round money.
* [ ] **`from_amount` and `to_amount` are expected to differ.** The gap is fees and conversion, not a bug.
* [ ] **A price shown to your customer came from a lock that has not expired**, or is presented as an estimate.

## Failures

* [ ] **Your error handling does not read one field.** The reason sits under `message` on some bodies and under `error` on others, so a handler that reads only one logs nothing useful for the rest.
* [ ] **You branch on the status code and on `code`**, compared case-insensitively, and treat everything else as display text.
* [ ] **A `401` triggers a token refresh** rather than a support ticket.
* [ ] **In-flight is a state you show**, not one you resolve by guessing. A transfer is delivered when it says so and failed when it says so.

## Compliance

* [ ] **Someone has dashboard access** and knows they are the one who answers a request for information.
* [ ] **You surface `missing_fields` to whoever can collect it** — usually your own customer, not your engineers.
* [ ] **Your flow tolerates a customer being held.** Verification is not instant and can reopen later.

## Before you flip

* [ ] **Run the full cycle in sandbox once more**, on the code you are about to deploy rather than on the code you tested weeks ago.
* [ ] **Move one real payment first**, small, and watch it land before opening the tap.
* [ ] **Know who to contact**, and have the account id ready when you do.

<Note>
  If any box above is unchecked because the documentation did not answer it, that is a defect worth reporting rather than a gap to work around. Tell your Kira contact which one.
</Note>
