{"templateId":"markdown","versions":[{"version":"v0-beta","label":"Beta (v0)","link":"/products/native-api/docs/guides/bank-transfer","default":true,"active":true,"folderId":"e4cb5a06"}],"sharedDataIds":{"sidebar":"sidebar-products/native-api/@v0-beta/sidebars.yaml"},"props":{"metadata":{"markdoc":{"tagList":["admonition"]},"type":"markdown"},"seo":{"title":"Bank Transfer","description":"Official Banxa API documentation – on-ramp and off-ramp transfers with identity verification and compliance.","llmstxt":{"title":"Banxa Developer Documentation","description":"Integrate crypto-fiat exchange with Banxa's licensed infrastructure: payments, KYC, compliance, and settlement handled. 150+ countries, 45 global licences.","details":{"content":"Two integration products: **Banxa Native API** for partners who manage their own KYC and want full UX control (headless, HMAC server-to-server, no Banxa-hosted screens); **Banxa Hosted Checkout** for partners who want Banxa to handle KYC and payments (three paths: Referral URL, API, or React Native SDK). Both use the same sandbox and production environments at `https://api.banxa-sandbox.com` and `https://api.banxa.com`.\n\n## Constraints\n\n- **Authentication**: HMAC credentials must be stored server-side only, never expose in frontend, mobile, or client-side code. HMAC is required for all Native API calls and for KYC sharing in Hosted Checkout; `x-api-key` is used for all other Hosted Checkout endpoints.\n- **`externalCustomerId`**: Required on every buy and sell order. Use a stable opaque identifier, never PII.\n- **`identityReference`**: Must remain constant for the same user across all requests. Must not contain PII. If you attempt to create an identity for an email that already exists, you will receive a 422 / code 81, so retrieve the existing record rather than retrying creation. Use `GET /eapi/v0/identities/{identityReference}?email=user@example.com` to look up the real `identityReference` linked to an email.\n- **`quoteId`**: Only supported by `POST /eapi/v0/ramps` (bank transfer). The React Native SDK and Embedded Payment Button do not accept a `quoteId`, so use indicative pricing (`GET /eapi/v0/price`) for SDK and Embedded Payment Button flows.\n- **Quotes**: Indicative prices are not rate-locked, so refresh close to order creation to minimise rate drift. Locked quotes (`GET /eapi/v0/quote`) expire after approximately 3 minutes and are only valid for bank transfer ramp creation.\n- **Eligibility gate**: Never create a ramp or invoke the SDK when `paymentReady` is `false`. Always check eligibility and satisfy all requirements before payment execution.\n- **Webhooks**: Verify all inbound webhook signatures with HMAC-SHA256 before processing. Return HTTP 200 immediately and process asynchronously.\n- **Product selection**: Banxa Native is for partners who manage their own KYC. Banxa Hosted Checkout is for partners who do not do KYC. These are separate products with separate flows: do not mix endpoints across products.\n- **SDK scope**: The React Native SDK has no `banxa.customerIdentity` module. Identity and KYC are handled through the Native API only. `primerCallbacks` and `primerSettings` are Native context only and must not be referenced in Hosted Checkout integrations.\n- **Payment method naming**: Never use \"eAPI\" or \"EAPI\" as a product name. The correct name is \"Banxa Native API\". The URL path prefix `/eapi/` is correct and should not be changed.\n"},"hide":false,"excludeFiles":[]}},"dynamicMarkdocComponents":[],"compilationErrors":[],"ast":{"$$mdtype":"Tag","name":"article","attributes":{},"children":[{"$$mdtype":"Tag","name":"Heading","attributes":{"level":1,"id":"bank-transfer","__idx":0},"children":["Bank Transfer"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Bank transfers are fully API-driven. There is no SDK involved — your backend creates the ramp, and the API returns payment instructions for the user to complete the transfer. This makes bank transfer the simplest Native API integration path: no platform setup, no payment sheet."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["This guide covers on-ramp (fiat → crypto) and off-ramp (crypto → fiat) via bank transfer. Identity creation, KYC, eligibility, and pricing are covered in the ",{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"/products/native-api/docs/guides/foundations"},"children":["Integration Guide"]}," — start there if you haven't set those up yet. This guide picks up from ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["paymentReady: true"]},"."]},{"$$mdtype":"Tag","name":"hr","attributes":{},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"on-ramp-buy-crypto","__idx":1},"children":["On-ramp (buy crypto)"]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"create-the-ramp","__idx":2},"children":["Create the ramp"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Once your backend confirms ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["paymentReady: true"]},", create the ramp with ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["POST /eapi/v0/ramps"]},". Pass the fiat currency, payment method, crypto asset, blockchain, and wallet address. Set either ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["fiatAmount"]}," or ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["cryptoAmount"]}," — not both."]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"http","header":{"controls":{"copy":{}}},"source":"POST /eapi/v0/ramps\nContent-Type: application/json\n\n{\n  \"identityReference\": \"partner-abc123\",\n  \"source\": {\n    \"fiat\": {\n      \"id\": \"AUD\",\n      \"method\": \"payid-bank-transfer\"\n    }\n  },\n  \"target\": {\n    \"crypto\": {\n      \"id\": \"USDT\",\n      \"blockchain\": \"TRON\",\n      \"walletAddress\": \"TYDzsYUEpvnYmQk4zGP9sWWcTEd2MiAtW6\"\n    }\n  },\n  \"fiatAmount\": \"500.00\"\n}\n","lang":"http"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Use the same ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["identityReference"]}," you used for eligibility."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"display-payment-instructions","__idx":3},"children":["Display payment instructions"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The response includes ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["sourceDepositInstructions"]}," — the details the user needs to complete the bank transfer. Display these in your UI."]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"json","header":{"controls":{"copy":{}}},"source":"{\n  \"id\": \"b7f1ffbb2f1bd7a5e2ba152b4049d234\",\n  \"status\": \"INITIALIZED\",\n  \"source\": {\n    \"fiat\": { \"id\": \"AUD\", \"method\": \"payid-bank-transfer\" },\n    \"amount\": \"500.00\"\n  },\n  \"target\": {\n    \"crypto\": {\n      \"id\": \"USDT\",\n      \"blockchain\": \"TRON\",\n      \"walletAddress\": \"TYDzsYUEpvnYmQk4zGP9sWWcTEd2MiAtW6\"\n    },\n    \"amount\": \"324.51\"\n  },\n  \"sourceDepositInstructions\": {\n    \"recipientEmail\": \"15600270@banxa.com\",\n    \"depositReference\": \"BNX-12345678\"\n  },\n  \"receipt\": {\n    \"gatewayFee\": \"2.50\",\n    \"networkFee\": \"2.00\",\n    \"sourceAmount\": \"500.00\",\n    \"targetAmount\": \"324.51\"\n  },\n  \"createdAt\": \"2026-04-17T03:45:00.000Z\"\n}\n","lang":"json"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The instruction fields vary by payment method — for PayID, ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["recipientEmail"]}," and ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["depositReference"]}," are returned. The user sends the transfer from their bank, using the deposit reference so Banxa can match the payment."]},{"$$mdtype":"Tag","name":"Admonition","attributes":{"type":"warning","name":"Reference is required"},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Instruct users to include the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["depositReference"]}," when making the transfer. Without it, Banxa cannot match the payment to the transaction."]}]},{"$$mdtype":"Tag","name":"hr","attributes":{},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"off-ramp-sell-crypto","__idx":4},"children":["Off-ramp (sell crypto)"]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"provide-bank-account-details","__idx":5},"children":["Provide bank account details"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["For off-ramp transactions, include the user's bank account ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["instructions"]}," in the request — Banxa needs these to pay out the fiat."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The fields required depend on the payment method. For PayID (AUD):"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"http","header":{"controls":{"copy":{}}},"source":"POST /eapi/v0/ramps\nContent-Type: application/json\n\n{\n  \"identityReference\": \"partner-abc123\",\n  \"source\": {\n    \"crypto\": {\n      \"id\": \"USDT\",\n      \"blockchain\": \"TRON\",\n      \"walletAddress\": \"TYDzsYUEpvnYmQk4zGP9sWWcTEd2MiAtW6\"\n    }\n  },\n  \"target\": {\n    \"fiat\": {\n      \"id\": \"AUD\",\n      \"method\": \"payid-bank-transfer\",\n      \"instructions\": [\n        {\n          \"accountName\": \"Jane Smith\",\n          \"accountNumber\": \"12345678\",\n          \"bsb\": \"063123\"\n        }\n      ]\n    }\n  },\n  \"cryptoAmount\": \"100.00\"\n}\n","lang":"http"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"display-the-deposit-address","__idx":6},"children":["Display the deposit address"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The response returns a crypto deposit address. The user sends their crypto to this address — once Banxa receives it, the fiat payout is initiated."]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"json","header":{"controls":{"copy":{}}},"source":"{\n  \"id\": \"c8g2ggcc3g2ce8b6f3cb263b5150e345\",\n  \"status\": \"AWAITING_FUNDS\",\n  \"source\": {\n    \"crypto\": {\n      \"id\": \"USDT\",\n      \"blockchain\": \"TRON\",\n      \"walletAddress\": \"TYDzsYUEpvnYmQk4zGP9sWWcTEd2MiAtW6\"\n    },\n    \"amount\": \"100.00\"\n  },\n  \"target\": {\n    \"fiat\": { \"id\": \"AUD\", \"method\": \"payid-bank-transfer\" },\n    \"amount\": \"150.20\"\n  },\n  \"sourceDepositInstructions\": {\n    \"depositAddress\": \"TBanxaDepositAddress123456\"\n  }\n}\n","lang":"json"},"children":[]},{"$$mdtype":"Tag","name":"hr","attributes":{},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"locking-the-exchange-rate","__idx":7},"children":["Locking the exchange rate"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Optionally, lock the exchange rate before creating the ramp. Get a quote first:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"http","header":{"controls":{"copy":{}}},"source":"GET /eapi/v0/quote?fiat=AUD&crypto=USDT&blockchain=TRON&method=payid-bank-transfer&transactionType=ONRAMP&fiatAmount=500\n","lang":"http"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The response includes a ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["quoteId"]}," valid for 3 minutes. Pass it in your ramp creation request:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"json","header":{"controls":{"copy":{}}},"source":"{\n  \"identityReference\": \"partner-abc123\",\n  \"quoteId\": \"q_abc123xyz\"\n}\n","lang":"json"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The source, target, and amount are inferred from the quote — you don't repeat them in the request body."]},{"$$mdtype":"Tag","name":"Admonition","attributes":{"type":"info","name":"quoteId support"},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["quoteId"]}," is currently only accepted by ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["POST /eapi/v0/ramps"]},". If you are building a card or mobile wallet flow, use indicative pricing (",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["GET /eapi/v0/price"]},") instead."]}]},{"$$mdtype":"Tag","name":"hr","attributes":{},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"tracking-transaction-status","__idx":8},"children":["Tracking transaction status"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Bank transfers are asynchronous — the user completes the transfer independently, and processing takes time. Configure a webhook endpoint to receive status updates, or poll using ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["GET /eapi/v0/ramps/{id}"]},"."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Typical on-ramp lifecycle: ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["INITIALIZED"]}," → ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["PAYMENT_RECEIVED"]}," → ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["IN_PROGRESS"]}," → ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["COMPLETED"]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Typical off-ramp lifecycle: ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["AWAITING_FUNDS"]}," → ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["IN_PROGRESS"]}," → ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["COMPLETED"]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["See ",{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"/products/native-api/docs/transaction-lifecycle/webhooks"},"children":["Webhooks"]}," for the full payload schema and all status values."]}]},"headings":[{"value":"Bank Transfer","id":"bank-transfer","depth":1},{"value":"On-ramp (buy crypto)","id":"on-ramp-buy-crypto","depth":2},{"value":"Create the ramp","id":"create-the-ramp","depth":3},{"value":"Display payment instructions","id":"display-payment-instructions","depth":3},{"value":"Off-ramp (sell crypto)","id":"off-ramp-sell-crypto","depth":2},{"value":"Provide bank account details","id":"provide-bank-account-details","depth":3},{"value":"Display the deposit address","id":"display-the-deposit-address","depth":3},{"value":"Locking the exchange rate","id":"locking-the-exchange-rate","depth":2},{"value":"Tracking transaction status","id":"tracking-transaction-status","depth":2}],"frontmatter":{"title":"Bank Transfer","description":"How to add bank transfer payments to a Banxa Native integration — on-ramp and off-ramp via the Native API.","seo":{"title":"Bank Transfer"}},"lastModified":"2026-06-01T06:29:39.000Z","pagePropGetterError":{"message":"","name":""}},"slug":"/products/native-api/docs/guides/bank-transfer","userData":{"isAuthenticated":false,"teams":["anonymous"]},"isPublic":true}