When quoting fails
Branch on
429 by its code. Treating budget_exceeded like an ordinary rate limit makes you retry for hours.
When submitting fails
A
409 conflict usually means a retry after a timeout. If the first submit reached Bitnob, the transfer is already moving. Retries with the same Idempotency-Key and body return the original response instead of 409, so reuse the key when you retry a submit.
When the transfer fails on chain
A transfer infailed status carries failure_code and failure_reason. It is terminal: that transfer won’t be retried.
Other codes may be added. Show
failure_reason in your logs, and fall back to a generic message for codes you don’t recognize.
Expired and canceled transfers
expired means the quote passed expires_at without a valid submission. Nothing was signed by Bitnob, and nothing moved. The status can lag: a quote may still read quoted shortly after expires_at. Treat any quote past expires_at as expired, whatever its status says. cancelled means the transfer was canceled before broadcast. Both are terminal and safe to retry with a new quote.
Never double-send
The user’s funds only move when a submitted quote broadcasts. Use these rules to make sure each payment intent results in at most one transfer:- Give each payment intent one quote
Idempotency-Keyand one submitIdempotency-Key, and reuse them on retries. - Before you request a replacement quote, check that the previous transfer is
expired,failed, orcancelled, not stillpending. - Store the transfer
idagainst your payment intent as soon as the quote returns.