Go live
Going live means a verified business, a funded balance and a live key in place of the test one. Work through the checklist first.
Swap the credential, not the code
Section titled “Swap the credential, not the code”A live key addresses the same organization id and the same endpoints. Only the
prefix changes, from avvio_test_… to avvio_live_…. If anything else in your
integration has to change, that is a bug on our side; tell us.
export AVVIO_API_KEY=avvio_live_…What differs in production
Section titled “What differs in production”| Sandbox | Live | |
|---|---|---|
| Settlement | Seconds | Hours to days, per corridor |
| Rates | Fixed | Real, and they move between quoting and sending |
| Balance | sandbox/fund |
Funded by wire to the account GET .../ returns, or with USDC in your wallet |
| Failure triggers | Account-number suffix | Whatever actually happens |
| Corridors | A handful | What your routing supports. Read the corridors call |
We don’t publish settlement time per corridor, so ask us about the corridors you
plan to use. Each payout carries expectedSettlementAt whenever the network
states a window; read it from GET /orders/{payoutId} and show it instead of a
fixed estimate. The sandbox never simulates a real settlement window.
Corridors and their field names follow your routing, and we may re-route you.
Build forms from GET /recipients/{orgId}/corridors, never hardcoded names.
Read your policy
Section titled “Read your policy”curl -s "$AVVIO_BASE_URL/payments/organizations/$AVVIO_ORG_ID/policy" \ -H "x-api-key: $AVVIO_API_KEY"const policy = await avvio.getPolicy();// → { mode, features, limits: { maxSinglePayoutUsd, … }, approvals: { thresholdUsd, requiredApprovals }, fees: { payout: { bps, fixedUsd, byCurrency, note } }, rateLimits, idempotency }import osimport requests
res = requests.get( f"{os.environ['AVVIO_BASE_URL']}/payments/organizations/{os.environ['AVVIO_ORG_ID']}/policy", headers={ "x-api-key": os.environ["AVVIO_API_KEY"], },)print(res.status_code, res.json())avvio-payments policyThe policy is what your organization is bound by, read live from its configuration:
| Field | Holds |
|---|---|
limits |
USD caps, null for none |
approvals |
thresholdUsd and the approvers a held payout needs |
features, rateLimits |
What is enabled, and requests per minute |
idempotency |
The replay windows |
purposeOfPayment |
Currencies that require a purpose |
fees.payout |
The fee schedule (Fees) |
A live organization can differ from its sandbox. Read it again with the live
key rather than discovering a cap from a 422.
The checklist
Section titled “The checklist”Before your first live payout
Section titled “Before your first live payout”-
You store your
Idempotency-Keybefore you send and reuse it on every retry. A new key per attempt is refused for 15 minutes (409 DUPLICATE_REQUEST_DETECTED) and pays twice after that. -
You treat a timeout as an unknown outcome and retry it with the same key.
-
Your ledger does not treat
completedas final (test with suffix0003). -
You have run every payout scenario that applies,
0001to0007(Test scenarios). -
You read
fundsReturnedinstead of inferring it fromfailureCode. Absent means unknown, notfalse. -
You reconcile from
GET /events, sendingnextSinceback assince, and dedupe onid(Reconcile your ledger).curl -s "$AVVIO_BASE_URL/payments/organizations/$AVVIO_ORG_ID/events?since=624" \-H "x-api-key: $AVVIO_API_KEY"[!WARNING] Unknown query parameters are ignored, so
?nextSince=replays your whole history on every poll.Don’t drive your ledger from
GET /orders?updatedSince=:updatedAtmoves whenever a payout does, so rows land behind a cursor you already passed. -
Your webhook receiver (Receive and verify webhooks) verifies signatures over the raw bytes and rejects a wrong secret (tested), accepts either signature during a rotation, dedupes on
svix-id, ignores events older than the state you hold, returns2xxbefore its own work, and is reachable over public HTTPS. -
You still reconcile against
GET /eventson a schedule: a webhook you never received looks exactly like one that never fired.
If you accept payments, also confirm:
- Fulfillment runs from
checkout_payment.paid, not the redirect, joined onclientReferenceIdwith amount and currency checked against your record. - The endpoint names the
checkout_payment.*types; an emptyeventslist receives none of them. - You handle a decline (
.01,.05, with differingfailureCodes), a full refund (.03), a chargeback after booking (.04), and a partial refund (.06:checkout_payment.partially_refunded, status stillpaid).
Operationally
Section titled “Operationally”- Business verification (KYB) is complete. Live keys are issued only after it, so start it first.
- Every corridor you need appears in
GET /recipients/{orgId}/corridorsfor your organization. - Your balance is funded by wire or USDC; there is no live
sandbox/fund. Wire lead time depends on both banks, so confirm it with your Avvio contact and fund ahead of your first run. - A person has registered your live webhook endpoint in the dashboard and stored its secret. An API key cannot create, change or delete live endpoints, so a leaked key cannot redirect your notifications; it can still read them and their deliveries.
- You log
requestId. On a success it is only in thex-request-idheader, so readingres.body.requestIdlogsundefined. - Someone can review a
compliance_rejectedpayout, whose funds do not come back automatically. - Your compliance team has read the written screening delegation. Sanctions and
name screening of recipients is delegated to the network that executes the
payout, and we hold the letter. Destination-country screening is ours and
answers
422 PAYOUT_REFUSED; give someone a place to see those. - With approvals on, you treat a
202 pending_approvalfromPOST /payoutsor batchconfirmas held, and wait forpayout_approval.executedfor thepayoutId.
Rate limits
Section titled “Rate limits”Limits match the sandbox (Environments & sandbox).
Back off by the 429’s Retry-After.
Tell us before you scale
Section titled “Tell us before you scale”Tell us before a big run (“5,000 payouts on Friday”). Corridor limits, balance headroom and rate ceilings can all be raised, but not retroactively.
Was this page helpful?