Regulated global fiat onramp and offramp with hosted checkout, iframe widget, and direct REST API. Strong APAC and bank-rail coverage (POLi, PayID, SEPA, Faster Payments).
- 01APAC fiat onramp (AU/NZ/SG)
- 02regulated bank-rail payments
- 03hosted checkout redirect
- 04direct API integration (custom UX)
- 05compliance-heavy partners
| Variable | Scope | Description |
|---|---|---|
| BANXA_API_KEY | Server | Banxa partner API key issued in the Partner Dashboard. Sent as part of the HMAC-signed `Authorization` header. |
| BANXA_API_SECRET | Server | Partner API secret used to compute the request HMAC over `nonce + method + url + body`. |
| BANXA_SUBDOMAIN | Client | Your tenant subdomain, e.g. `yourbrand.banxa.com` for prod or `yourbrand.banxa-sandbox.com` for sandbox. Hosted checkout URLs hang off this. |
Use Banxa for regulated fiat on/offramp. Server-side, sign requests with HMAC-SHA256 over `nonce + HTTP_METHOD + request_path + body_json` and send `Authorization: <API_KEY>:<signature>:<nonce>` to `https://<BANXA_SUBDOMAIN>/api/...`. Get a quote with `POST /api/prices`, then create an order with `POST /api/orders` (body: `account_reference`, `source` fiat, `target` crypto, `wallet_address`, `return_url_on_success`). Banxa returns a `checkout_url` — redirect the user there for KYC + payment. Listen on the partner webhook for `order_status` transitions (`pendingPayment` → `inProgress` → `complete` / `expired` / `failed`) and verify the HMAC signature before crediting. For offramp use `POST /api/orders` with `payment_type: SELL` and supply the user's bank account.
- ⚑API auth is per-request HMAC with a strictly monotonic nonce — replaying or sending nonces out of order returns 401 with no body. Use `Date.now()` and persist the last nonce per key.
- ⚑Sandbox and production are separate subdomains (`yourbrand.banxa-sandbox.com` vs `yourbrand.banxa.com`) with distinct API keys, distinct hosted checkout URLs, and different KYC providers — copying a sandbox order id into prod returns 404.
- ⚑Hosted checkout sessions expire (default 10 minutes from creation, locked-in price). Re-quoting after expiry will return a different fiat-amount; surface the timer to the user.
- ⚑Asset / fiat / payment-method support varies wildly by country (e.g. POLi for AU, PIX for BR, SEPA for EU). Always call `GET /api/coins` and `GET /api/payment-methods?source=<fiat>&target=<asset>` per session — hard-coded lists go stale.
- ⚑KYC happens inside Banxa's hosted flow on first purchase; the user leaves your app and returns via `return_url_on_success` — you do not get the KYC docs, just a pass/fail status on the order.
- ⚑Settlement to merchants (when partners receive a rev-share) is monthly invoiced, but on-chain delivery to the end user is typically T+0 once `complete` fires.
- ⚑Banxa offers iframe widget, hosted redirect, and pure REST flows — pure REST requires extra compliance review and is gated; do not assume your partner agreement covers it.