Best practices
Make every money call retry-safe
Derive each Idempotency-Key from your own record of the operation — the
invoice id, the payment run — store it with that record, and reuse it on
every retry. A key generated per attempt protects nothing. Know what a replay
returns on each route: a payout replays as 200 with its current status, a
conversion as 409 conflict with the first attempt's status in the message.
Idempotency.
Treat "accepted" and "arrived" as different events
POST /v1/banking/payouts answers 202. In production that means
submitted; the money has arrived only when the status is settled and
settled_at is set. The sandbox settles inside the request, which is exactly
how code that skips this step passes every test.
Payouts.
Poll payouts; do not wait for a webhook
There is no payout event today. Poll GET /v1/banking/payouts/{id} with
backoff until the status is final. Webhooks.
Show the payer what the bank said
When a payout is refused with payee_name_mismatch, show the payer the bank's
answer before you call accept-verification and resend the payout under the
same key. The acceptance is a statement that a person saw it, scoped to that
one payment. An invalid destination cannot be accepted — correct it. The
sandbox never produces a mismatch, so test this path from the documented
responses.
Beneficiaries.
Store our ids and our request ids
Keep the payout id, the beneficiary id, the quote quote_id and the
X-Request-Id of every call. With them, support can answer in minutes.
Request IDs and logs.
Handle the generic codes, not only the specific ones
A few refusals are specific codes in the sandbox but come from our partner in
production — insufficient funds, or a conversion's expired or used quote — as a
400 bad_request, or as a failed status after the request was accepted. Show
message to the payer in every case.
Environments.
Keep keys narrow by keeping them separate
The money API takes a secret key, and a secret key ignores scopes. Least privilege therefore means one key per service, kept on that service's servers, so that one leak is one revocation. Use restricted keys for the developer routes they can reach. Authentication.
Reconcile against statements
GET /v1/banking/payouts lists payouts and conversions;
POST /v1/banking/accounts/{account_id}/statements gives the booked lines with
running balances. Reconcile daily. Accounts.