{"templateId":"markdown","sharedDataIds":{"sidebar":"sidebar-products/hosted-checkout/sidebars.yaml"},"props":{"metadata":{"markdoc":{"tagList":["code-group"]},"type":"markdown"},"seo":{"title":"Webhooks","description":"Official Banxa API documentation – on-ramp and off-ramp transfers with identity verification and compliance.","llmstxt":{"hide":false,"sections":[{"title":"Table of contents","includeFiles":["**/*"],"excludeFiles":[]}],"excludeFiles":[]}},"dynamicMarkdocComponents":[],"compilationErrors":[],"ast":{"$$mdtype":"Tag","name":"article","attributes":{},"children":[{"$$mdtype":"Tag","name":"Heading","attributes":{"level":1,"id":"webhooks","__idx":0},"children":["Webhooks"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Banxa sends webhook notifications to your webhook endpoint URL whenever an order's status changes or a user's KYC/Account state updates. This eliminates the need to poll our APIs and allows you to track the complete user journey in real-time."]},{"$$mdtype":"Tag","name":"hr","attributes":{},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"setup","__idx":1},"children":["Setup"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Configure your webhook endpoint URL in the ",{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"https://dashboard.banxa.com/"},"children":["Partner Dashboard"]},". You can set separate URLs for sandbox and production."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The webhook URL must:"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Be publicly accessible over HTTPS."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Return a ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["200"]}," HTTP response to acknowledge receipt."]}]},{"$$mdtype":"Tag","name":"hr","attributes":{},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"available-webhooks","__idx":2},"children":["Available Webhooks"]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"1-order-webhooks","__idx":3},"children":["1. Order Webhooks"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Order webhooks are triggered on all order status transitions. We will send an HTTP ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["POST"]}," request with a JSON body."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Payload Example:"]}]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"json","header":{"controls":{"copy":{}}},"source":"{\n  \"order_id\": \"d9efc5d228cb7edfc4b6bb82f7b39f94\",\n  \"status\": \"complete\",\n  \"status_date\": \"2026-01-1604:04:21\",\n  \"created_at\": \"2026-01-1604:04:20\",\n  \"updated_at\": \"2026-01-1604:04:20\",\n  \"external_id\": null,\n  \"order_type\": \"BUY\",\n  \"crypto_coin\": \"USDT\",\n  \"crypto_blockchain\": \"ETH\",\n  \"crypto_amount\": \"67.1000000000000000\",\n  \"fiat_currency\": \"AUD\",\n  \"fiat_amount\": \"100\",\n  \"asset_price\": \"1.490312965722801\",\n  \"payment_method\": \"payid-bank-transfer\",\n  \"processing_fee\": \"0\",\n  \"network_fee\": \"0\",\n  \"usd_exchange_rate\": \"1.4923330\",\n  \"transaction_hash\": \"0\",\n  \"metadata\": []\n}\n","lang":"json"},"children":[]},{"$$mdtype":"Tag","name":"div","attributes":{"className":"md-table-wrapper"},"children":[{"$$mdtype":"Tag","name":"table","attributes":{"className":"md"},"children":[{"$$mdtype":"Tag","name":"thead","attributes":{},"children":[{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"th","attributes":{"align":"left","data-label":"Field"},"children":["Field"]},{"$$mdtype":"Tag","name":"th","attributes":{"align":"left","data-label":"Description"},"children":["Description"]}]}]},{"$$mdtype":"Tag","name":"tbody","attributes":{},"children":[{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{"align":"left"},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["order_id"]}]},{"$$mdtype":"Tag","name":"td","attributes":{"align":"left"},"children":["The unique Banxa identifier for the order."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{"align":"left"},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["status"]}]},{"$$mdtype":"Tag","name":"td","attributes":{"align":"left"},"children":["The new order status. See ",{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"/products/hosted-checkout/docs/transaction-lifecycle/order-statuses"},"children":["Order Statuses"]}," for all possible values."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{"align":"left"},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["status_date"]}]},{"$$mdtype":"Tag","name":"td","attributes":{"align":"left"},"children":["ISO 8601 timestamp of the most recent status transition."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{"align":"left"},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["created_at"]}]},{"$$mdtype":"Tag","name":"td","attributes":{"align":"left"},"children":["ISO 8601 timestamp of when the order was initially created."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{"align":"left"},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["updated_at"]}]},{"$$mdtype":"Tag","name":"td","attributes":{"align":"left"},"children":["ISO 8601 timestamp of the last time the order record was modified."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{"align":"left"},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["external_id"]}]},{"$$mdtype":"Tag","name":"td","attributes":{"align":"left"},"children":["The unique ID provided by the partner during order creation (if applicable)."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{"align":"left"},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["order_type"]}]},{"$$mdtype":"Tag","name":"td","attributes":{"align":"left"},"children":["The transaction direction: ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["BUY"]}," (Fiat to Crypto) or ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["SELL"]}," (Crypto to Fiat)."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{"align":"left"},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["crypto_coin"]}]},{"$$mdtype":"Tag","name":"td","attributes":{"align":"left"},"children":["The ticker symbol of the cryptocurrency (e.g., ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["USDT"]},", ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["BTC"]},")."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{"align":"left"},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["crypto_blockchain"]}]},{"$$mdtype":"Tag","name":"td","attributes":{"align":"left"},"children":["The specific network/blockchain used for the transaction (e.g., ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["ETH"]},", ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["SOL"]},")."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{"align":"left"},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["crypto_amount"]}]},{"$$mdtype":"Tag","name":"td","attributes":{"align":"left"},"children":["The total amount of cryptocurrency involved in the transaction."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{"align":"left"},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["fiat_currency"]}]},{"$$mdtype":"Tag","name":"td","attributes":{"align":"left"},"children":["The 3-letter ISO code of the fiat currency used (e.g., ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["AUD"]},", ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["CAD"]},")."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{"align":"left"},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["fiat_amount"]}]},{"$$mdtype":"Tag","name":"td","attributes":{"align":"left"},"children":["The total fiat amount of the transaction."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{"align":"left"},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["asset_price"]}]},{"$$mdtype":"Tag","name":"td","attributes":{"align":"left"},"children":["The price of one unit of the cryptocurrency in the source fiat currency."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{"align":"left"},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["payment_method"]}]},{"$$mdtype":"Tag","name":"td","attributes":{"align":"left"},"children":["The specific payment rail used for the transaction (e.g., ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["payid-bank-transfer"]},")."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{"align":"left"},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["processing_fee"]}]},{"$$mdtype":"Tag","name":"td","attributes":{"align":"left"},"children":["The service/gateway fee charged by Banxa in the source fiat currency."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{"align":"left"},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["network_fee"]}]},{"$$mdtype":"Tag","name":"td","attributes":{"align":"left"},"children":["The blockchain network (gas) fee in the source fiat currency."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{"align":"left"},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["usd_exchange_rate"]}]},{"$$mdtype":"Tag","name":"td","attributes":{"align":"left"},"children":["The exchange rate used to convert 1 unit of source fiat to USD at the time of order creation."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{"align":"left"},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["transaction_hash"]}]},{"$$mdtype":"Tag","name":"td","attributes":{"align":"left"},"children":["The on-chain identifier (TXID) for the crypto transfer, if available."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{"align":"left"},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["metadata"]}]},{"$$mdtype":"Tag","name":"td","attributes":{"align":"left"},"children":["A collection of custom key-value pairs passed by the partner for tracking purposes."]}]}]}]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["After receiving a webhook, use the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["order_id"]}," to fetch full order details from the ",{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"/products/hosted-checkout/docs/transaction-lifecycle/order-lookup"},"children":["order lookup endpoint"]}," if you need additional data."]},{"$$mdtype":"Tag","name":"hr","attributes":{},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"2-identity--kyc-webhooks","__idx":4},"children":["2. Identity & KYC Webhooks"]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"21-kyc-webhooks","__idx":5},"children":["2.1 KYC Webhooks"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["KYC webhooks are triggered whenever a user's identity verification state changes."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Please reach out to your Banxa contact if you would like to have this webhook enabled."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Payload Example:"]}]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"json","header":{"controls":{"copy":{}}},"source":"{\n  \"external_customer_id\": \"demomerchant-61466523855\",\n  \"account\": {\n    \"exists\": true,\n    \"blocked\": false,\n    \"createdAt\": \"2026-03-30T05:08:11Z\"\n  },\n  \"kyc\": {\n    \"status\": \"UNDER_REVIEW\"\n  }\n}\n","lang":"json"},"children":[]},{"$$mdtype":"Tag","name":"div","attributes":{"className":"md-table-wrapper"},"children":[{"$$mdtype":"Tag","name":"table","attributes":{"className":"md"},"children":[{"$$mdtype":"Tag","name":"thead","attributes":{},"children":[{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"th","attributes":{"align":"left","data-label":"Field"},"children":["Field"]},{"$$mdtype":"Tag","name":"th","attributes":{"align":"left","data-label":"Description"},"children":["Description"]}]}]},{"$$mdtype":"Tag","name":"tbody","attributes":{},"children":[{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{"align":"left"},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["external_customer_id"]}]},{"$$mdtype":"Tag","name":"td","attributes":{"align":"left"},"children":["Your system's unique identifier for the user."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{"align":"left"},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["account.exists"]}]},{"$$mdtype":"Tag","name":"td","attributes":{"align":"left"},"children":["Boolean indicating if the user profile is successfully created in our system."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{"align":"left"},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["account.blocked"]}]},{"$$mdtype":"Tag","name":"td","attributes":{"align":"left"},"children":["Boolean indicating if the user has been banned, suspended, or hit a compliance block."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{"align":"left"},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["account.createdAt"]}]},{"$$mdtype":"Tag","name":"td","attributes":{"align":"left"},"children":["ISO 8601 timestamp of account creation."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{"align":"left"},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["kyc.status"]}]},{"$$mdtype":"Tag","name":"td","attributes":{"align":"left"},"children":["The verification outcome of the customer's submitted identity documents (selfie + document). See status table below."]}]}]}]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["kyc.status"]}," values:"]}]},{"$$mdtype":"Tag","name":"div","attributes":{"className":"md-table-wrapper"},"children":[{"$$mdtype":"Tag","name":"table","attributes":{"className":"md"},"children":[{"$$mdtype":"Tag","name":"thead","attributes":{},"children":[{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"th","attributes":{"align":"left","data-label":"Status"},"children":["Status"]},{"$$mdtype":"Tag","name":"th","attributes":{"align":"left","data-label":"Description"},"children":["Description"]}]}]},{"$$mdtype":"Tag","name":"tbody","attributes":{},"children":[{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{"align":"left"},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["PENDING"]}]},{"$$mdtype":"Tag","name":"td","attributes":{"align":"left"},"children":["No identity documents have been submitted yet."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{"align":"left"},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["UNDER_REVIEW"]}]},{"$$mdtype":"Tag","name":"td","attributes":{"align":"left"},"children":["Documents are being reviewed."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{"align":"left"},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["ACTION_REQUIRED"]}]},{"$$mdtype":"Tag","name":"td","attributes":{"align":"left"},"children":["Additional action is required from the customer."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{"align":"left"},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["VERIFIED"]}]},{"$$mdtype":"Tag","name":"td","attributes":{"align":"left"},"children":["Document and liveness verification passed."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{"align":"left"},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["REJECTED"]}]},{"$$mdtype":"Tag","name":"td","attributes":{"align":"left"},"children":["Verification was unsuccessful."]}]}]}]}]},{"$$mdtype":"Tag","name":"blockquote","attributes":{},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Important:"]}," ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["kyc.status"]}," reflects document and liveness verification only — it does not account for supplementary fields (e.g. purpose of transaction, occupation) or overall transaction eligibility. A ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["VERIFIED"]}," status means the identity documents passed review; it does not mean the customer is eligible to transact. Use the order creation flow to determine whether a customer can proceed."]}]},{"$$mdtype":"Tag","name":"hr","attributes":{},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"22-enhanced-due-diligence-edd-webhook","__idx":6},"children":["2.2 Enhanced Due Diligence (EDD) Webhook"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["This identity-level webhook is triggered when an order requires manual intervention or additional documentation (Enhanced Due Diligence). It allows you to monitor when a user has been flagged for specific verification steps beyond standard KYC."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Please reach out to your Banxa contact if you would like to have this webhook enabled."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Payload Example:"]},":"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"json","header":{"controls":{"copy":{}}},"source":"{\n  \"identity_reference\": \"demomerchant-61466233701\",\n  \"status\": \"extraVerification\",\n  \"status_date\": \"2026-02-13 04:39:38\",\n  \"internal_reason\": \"Customer requires extra verification\",\n  \"external_reason\": \"Your order is pending additional verification. We'll notify you once it's complete\"\n}\n","lang":"json"},"children":[]},{"$$mdtype":"Tag","name":"div","attributes":{"className":"md-table-wrapper"},"children":[{"$$mdtype":"Tag","name":"table","attributes":{"className":"md"},"children":[{"$$mdtype":"Tag","name":"thead","attributes":{},"children":[{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"th","attributes":{"align":"left","data-label":"Field"},"children":["Field"]},{"$$mdtype":"Tag","name":"th","attributes":{"align":"left","data-label":"Description"},"children":["Description"]}]}]},{"$$mdtype":"Tag","name":"tbody","attributes":{},"children":[{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{"align":"left"},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["identity_reference"]}]},{"$$mdtype":"Tag","name":"td","attributes":{"align":"left"},"children":["The unique identifier for the user (matches ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["external_customer_id"]}," or ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["account_reference"]},")."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{"align":"left"},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["status"]}]},{"$$mdtype":"Tag","name":"td","attributes":{"align":"left"},"children":["The verification status (typically ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["extraVerification"]},")."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{"align":"left"},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["status_date"]}]},{"$$mdtype":"Tag","name":"td","attributes":{"align":"left"},"children":["ISO 8601 timestamp of when the additional verification was triggered."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{"align":"left"},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["internal_reason"]}]},{"$$mdtype":"Tag","name":"td","attributes":{"align":"left"},"children":["The internal system categorization for the verification request."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{"align":"left"},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["external_reason"]}]},{"$$mdtype":"Tag","name":"td","attributes":{"align":"left"},"children":["The user-facing message explaining why the transaction is pending."]}]}]}]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Triggers:"]}," ","This webhook is sent when any of the following identity-level exceptions are required:"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Enhanced Due Diligence (EDD):"]}," High-level manual review."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Verification Phone Call (VPC):"]}," Requirement for a manual call with the user."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Questionnaire:"]}," Scam check or suitability assessment."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Proof of Address (POA):"]}," Request for residency documentation."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Source of Funds (SOF):"]}," Request for documentation regarding the origin of funds."]}]},{"$$mdtype":"Tag","name":"hr","attributes":{},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"23-account-blocked-webhook","__idx":7},"children":["2.3 Account Blocked Webhook"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["This identity-level webhook is triggered when a customer has been restricted from creating or completing orders due to compliance or risk policies. It provides the necessary context to inform your internal teams or the end user."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Payload Example:"]}]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"json","header":{"controls":{"copy":{}}},"source":"{\n  \"identity_reference\": \"partner-customer-123\",\n  \"status\": \"cancelled\",\n  \"status_date\": \"2026-03-05 19:53:08\",\n  \"internal_reason\": \"Account is blocked.\",\n  \"external_reason\": \"Your account has been restricted from further transactions.\"\n}\n","lang":"json"},"children":[]},{"$$mdtype":"Tag","name":"div","attributes":{"className":"md-table-wrapper"},"children":[{"$$mdtype":"Tag","name":"table","attributes":{"className":"md"},"children":[{"$$mdtype":"Tag","name":"thead","attributes":{},"children":[{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"th","attributes":{"align":"left","data-label":"Field"},"children":["Field"]},{"$$mdtype":"Tag","name":"th","attributes":{"align":"left","data-label":"Description"},"children":["Description"]}]}]},{"$$mdtype":"Tag","name":"tbody","attributes":{},"children":[{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{"align":"left"},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["identity_reference"]}]},{"$$mdtype":"Tag","name":"td","attributes":{"align":"left"},"children":["A unique customer identifier provided by the partner"]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{"align":"left"},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["status"]}]},{"$$mdtype":"Tag","name":"td","attributes":{"align":"left"},"children":["The specific account status. Enum: ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["cancelled"]},"."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{"align":"left"},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["status_date"]}]},{"$$mdtype":"Tag","name":"td","attributes":{"align":"left"},"children":["ISO 8601 timestamp of the status update."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{"align":"left"},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["internal_reason"]}]},{"$$mdtype":"Tag","name":"td","attributes":{"align":"left"},"children":["Internal system message detailing the specific reason for the block."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{"align":"left"},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["external_reason"]}]},{"$$mdtype":"Tag","name":"td","attributes":{"align":"left"},"children":["The designated message to be displayed to the end customer via your UI."]}]}]}]}]},{"$$mdtype":"Tag","name":"hr","attributes":{},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"retry-behaviour","__idx":8},"children":["Retry behaviour"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The webhook retry mechanism ensures reliable delivery of event notifications. If your endpoint does not respond with ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["200 OK"]},", Banxa will automatically retry delivery. The payload is unchanged across all retry attempts."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Retries follow a ",{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Fibonacci sequence"]},": 1s, 2s, 3s, 5s, 8s, 13s, and so on. This continues for a ",{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["maximum of 2 hours"]},", with up to ",{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["18 retries"]}," over that period."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Respond with ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["200 OK"]}," immediately and process the event asynchronously to avoid unnecessary retries."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["We recommend implementing idempotent webhook handling. In rare cases your endpoint may receive the same event more than once. Using ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["order_id"]}," and ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["status"]}," as a deduplication key will prevent duplicate processing."]},{"$$mdtype":"Tag","name":"hr","attributes":{},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"securing-webhooks","__idx":9},"children":["Securing Webhooks"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Banxa signs every webhook it sends using HMAC-SHA256. You verify this signature to confirm the request genuinely came from Banxa."]},{"$$mdtype":"Tag","name":"blockquote","attributes":{},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Webhook verification is the reverse of request signing."]}," When you sign outbound API requests, you use a Banxa API path in the canonical string. When you verify an incoming webhook, you use the URI path of ",{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["your own webhook endpoint"]}," — not a Banxa API path. Everything else is the same algorithm."]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Each webhook includes an ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["Authorization"]}," header:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"header":{"controls":{"copy":{}}},"source":"Authorization: Bearer {API_KEY}:{SIGNATURE}:{NONCE}\n"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Banxa constructs the signature from:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"header":{"controls":{"copy":{}}},"source":"POST\\nYOUR_WEBHOOK_PATH\\nNONCE\\nPAYLOAD\n"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Where ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["YOUR_WEBHOOK_PATH"]}," is the path of the endpoint Banxa is calling — for example, ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["/webhooks/banxa"]}," — not any Banxa API path."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"verification-flow","__idx":10},"children":["Verification flow"]},{"$$mdtype":"Tag","name":"ol","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Extract the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["Authorization"]}," header from the incoming request"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Strip the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["Bearer "]}," prefix and split on ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":[":"]}," to get ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["receivedKey"]},", ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["receivedSignature"]},", ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["nonce"]}]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Recompute the expected signature using the same algorithm, your secret, and ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["YOUR_WEBHOOK_PATH"]}]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Use a ",{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["timing-safe comparison"]}," to check that ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["receivedSignature"]}," matches — never use ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["=="]}]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"code-examples","__idx":11},"children":["Code examples"]},{"$$mdtype":"Tag","name":"CodeGroup","attributes":{"mode":"tabs"},"children":[{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"python","data-title":"Python","header":{"title":"Python","controls":{"copy":{}}},"source":"import hmac\n\nMY_WEBHOOK_PATH = '/webhooks/banxa'\nKEY = '[YOUR_API_KEY]'\nSECRET = '[YOUR_API_SECRET]'\n\ndef verify_webhook(auth_header, request_body):\n    _, token = auth_header.split('Bearer ', 1)\n    received_key, received_signature, nonce = token.split(':')\n\n    data = f\"POST\\n{MY_WEBHOOK_PATH}\\n{nonce}\\n{request_body}\"\n    expected = hmac.new(SECRET.encode('utf-8'), data.encode('utf-8'), 'sha256').hexdigest()\n\n    return hmac.compare_digest(received_signature, expected)\n","lang":"python"},"children":[]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"javascript","data-title":"Node.js","header":{"title":"Node.js","controls":{"copy":{}}},"source":"const crypto = require('crypto');\n\nconst MY_WEBHOOK_PATH = '/webhooks/banxa';\nconst KEY = '[YOUR_API_KEY]';\nconst SECRET = '[YOUR_API_SECRET]';\n\nfunction verifyWebhook(authHeader, requestBody) {\n    const token = authHeader.replace('Bearer ', '');\n    const [receivedKey, receivedSignature, nonce] = token.split(':');\n\n    const data = `POST\\n${MY_WEBHOOK_PATH}\\n${nonce}\\n${requestBody}`;\n    const expected = crypto.createHmac('sha256', SECRET).update(data).digest('hex');\n\n    return crypto.timingSafeEqual(Buffer.from(receivedSignature), Buffer.from(expected));\n}\n","lang":"javascript"},"children":[]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"php","data-title":"PHP","header":{"title":"PHP","controls":{"copy":{}}},"source":"$MY_WEBHOOK_PATH = '/webhooks/banxa';\n$KEY = '[YOUR_API_KEY]';\n$SECRET = '[YOUR_API_SECRET]';\n\nfunction verifyWebhook($authHeader, $requestBody, $myWebhookPath, $key, $secret) {\n    $token = str_replace('Bearer ', '', $authHeader);\n    [$receivedKey, $receivedSignature, $nonce] = explode(':', $token);\n\n    $data = implode(\"\\n\", ['POST', $myWebhookPath, $nonce, $requestBody]);\n    $expected = hash_hmac('sha256', $data, $secret);\n\n    return hash_equals($expected, $receivedSignature);\n}\n","lang":"php"},"children":[]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"java","data-title":"Java","header":{"title":"Java","controls":{"copy":{}}},"source":"import javax.crypto.Mac;\nimport javax.crypto.spec.SecretKeySpec;\nimport java.security.MessageDigest;\nimport java.util.Formatter;\n\nprivate static final String MY_WEBHOOK_PATH = \"/webhooks/banxa\";\nprivate static final String SECRET = \"[YOUR_API_SECRET]\";\n\npublic boolean verifyWebhook(String authHeader, String requestBody) throws Exception {\n    String token = authHeader.replace(\"Bearer \", \"\");\n    String[] parts = token.split(\":\");\n    String nonce = parts[2];\n    String receivedSignature = parts[1];\n\n    String data = \"POST\\n\" + MY_WEBHOOK_PATH + \"\\n\" + nonce + \"\\n\" + requestBody;\n    SecretKeySpec signingKey = new SecretKeySpec(SECRET.getBytes(), \"HmacSHA256\");\n    Mac mac = Mac.getInstance(\"HmacSHA256\");\n    mac.init(signingKey);\n    Formatter formatter = new Formatter();\n    for (byte b : mac.doFinal(data.getBytes())) formatter.format(\"%02x\", b);\n    String expected = formatter.toString();\n\n    return MessageDigest.isEqual(receivedSignature.getBytes(), expected.getBytes());\n}\n","lang":"java"},"children":[]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"swift","data-title":"Swift","header":{"title":"Swift","controls":{"copy":{}}},"source":"import CryptoKit\n\nlet MY_WEBHOOK_PATH = \"/webhooks/banxa\"\nlet SECRET = \"[YOUR_API_SECRET]\"\n\nfunc verifyWebhook(authHeader: String, requestBody: String) -> Bool {\n    let token = authHeader.replacingOccurrences(of: \"Bearer \", with: \"\")\n    let parts = token.split(separator: \":\")\n    guard parts.count == 3 else { return false }\n    let nonce = String(parts[2])\n    let receivedSignature = String(parts[1])\n\n    let data = \"POST\\n\\(MY_WEBHOOK_PATH)\\n\\(nonce)\\n\\(requestBody)\"\n    let secretKey = SymmetricKey(data: SECRET.data(using: .utf8)!)\n    let expected = HMAC<SHA256>.authenticationCode(for: data.data(using: .utf8)!, using: secretKey)\n        .map { String(format: \"%02hhx\", $0) }.joined()\n\n    return receivedSignature == expected\n}\n","lang":"swift"},"children":[]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"ruby","data-title":"Ruby","header":{"title":"Ruby","controls":{"copy":{}}},"source":"require 'openssl'\n\nMY_WEBHOOK_PATH = '/webhooks/banxa'\nSECRET = '[YOUR_API_SECRET]'\n\ndef verify_webhook(auth_header, request_body)\n    token = auth_header.sub('Bearer ', '')\n    received_key, received_signature, nonce = token.split(':')\n\n    data = \"POST\\n#{MY_WEBHOOK_PATH}\\n#{nonce}\\n#{request_body}\"\n    expected = OpenSSL::HMAC.hexdigest('sha256', SECRET, data)\n\n    ActiveSupport::SecurityUtils.secure_compare(received_signature, expected)\nend\n","lang":"ruby"},"children":[]}]}]},"headings":[{"value":"Webhooks","id":"webhooks","depth":1},{"value":"Setup","id":"setup","depth":2},{"value":"Available Webhooks","id":"available-webhooks","depth":2},{"value":"1. Order Webhooks","id":"1-order-webhooks","depth":3},{"value":"2. Identity & KYC Webhooks","id":"2-identity--kyc-webhooks","depth":3},{"value":"2.1 KYC Webhooks","id":"21-kyc-webhooks","depth":4},{"value":"2.2 Enhanced Due Diligence (EDD) Webhook","id":"22-enhanced-due-diligence-edd-webhook","depth":4},{"value":"2.3 Account Blocked Webhook","id":"23-account-blocked-webhook","depth":4},{"value":"Retry behaviour","id":"retry-behaviour","depth":2},{"value":"Securing Webhooks","id":"securing-webhooks","depth":2},{"value":"Verification flow","id":"verification-flow","depth":3},{"value":"Code examples","id":"code-examples","depth":3}],"frontmatter":{"title":"Webhooks | Banxa Docs","description":"Banxa webhook notifications for order status changes and KYC/identity events. Payload reference, retry behaviour, and HMAC signature verification.","seo":{"title":"Webhooks"}},"lastModified":"2026-05-19T23:30:38.000Z","pagePropGetterError":{"message":"","name":""}},"slug":"/products/hosted-checkout/docs/transaction-lifecycle/webhooks","userData":{"isAuthenticated":false,"teams":["anonymous"]},"isPublic":true}