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
/sandboxprefix, 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
2xxto 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
409is 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_amountandto_amountare 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
messageon some bodies and undererroron 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
401triggers 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_fieldsto 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.
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.