# Create a scoped API key Source: https://apidocs.bridge.xyz/api-reference/api-keys/create-a-scoped-api-key https://withbridge-image1-sv-usw2-monorail-openapi.s3.amazonaws.com/latest.json post /api_keys Create a new API key restricted to a subset of scopes. The returned `value` is the only opportunity to retrieve the plaintext secret — store it securely. This endpoint does not accept an `Idempotency-Key` header; each call creates a new key. Callers may only grant scopes they themselves hold (scope subsetting). Unrestricted keys may create scoped keys; scoped keys need the `api_key:create` scope. Up to 500 scoped keys may exist per developer. # Describe the calling API key Source: https://apidocs.bridge.xyz/api-reference/api-keys/describe-the-calling-api-key https://withbridge-image1-sv-usw2-monorail-openapi.s3.amazonaws.com/latest.json get /api_keys/whoami Return metadata about the API key authenticating this request, including its scopes. The plaintext secret is never returned. # Delete a single associated person Source: https://apidocs.bridge.xyz/api-reference/associated-persons/delete-a-single-associated-person https://withbridge-image1-sv-usw2-monorail-openapi.s3.amazonaws.com/latest.json delete /associated_persons/{associatedPersonID} Delete an associated person by ID # Get a single associated person Source: https://apidocs.bridge.xyz/api-reference/associated-persons/get-a-single-associated-person https://withbridge-image1-sv-usw2-monorail-openapi.s3.amazonaws.com/latest.json get /associated_persons/{associatedPersonID} Retrieve an associated person by ID # Update a single associated person Source: https://apidocs.bridge.xyz/api-reference/associated-persons/update-a-single-associated-person https://withbridge-image1-sv-usw2-monorail-openapi.s3.amazonaws.com/latest.json put /associated_persons/{associatedPersonID} # Create a Batch Settlement Schedule Source: https://apidocs.bridge.xyz/api-reference/batch-settlements/create-a-batch-settlement-schedule https://withbridge-image1-sv-usw2-monorail-openapi.s3.amazonaws.com/latest.json post /customers/{customerID}/batch_settlement_schedules Creates a Batch Settlement Schedule that can be used as the destination of a liquidation address. # Create a Bridge Wallet Source: https://apidocs.bridge.xyz/api-reference/bridge-wallets/create-a-bridge-wallet https://withbridge-image1-sv-usw2-monorail-openapi.s3.amazonaws.com/latest.json post /customers/{customerID}/wallets # Get a Bridge Wallet Source: https://apidocs.bridge.xyz/api-reference/bridge-wallets/get-a-bridge-wallet https://withbridge-image1-sv-usw2-monorail-openapi.s3.amazonaws.com/latest.json get /wallets/{bridgeWalletID} Retrieve a Bridge Wallet by its ID # Get a Bridge Wallet Source: https://apidocs.bridge.xyz/api-reference/bridge-wallets/get-a-bridge-wallet-1 https://withbridge-image1-sv-usw2-monorail-openapi.s3.amazonaws.com/latest.json get /customers/{customerID}/wallets/{bridgeWalletID} Retrieve a Bridge Wallet for the specified Bridge Wallet ID # Get all Bridge Wallets Source: https://apidocs.bridge.xyz/api-reference/bridge-wallets/get-all-bridge-wallets https://withbridge-image1-sv-usw2-monorail-openapi.s3.amazonaws.com/latest.json get /wallets List of Bridge Wallets # Get all Bridge Wallets for a customer Source: https://apidocs.bridge.xyz/api-reference/bridge-wallets/get-all-bridge-wallets-for-a-customer https://withbridge-image1-sv-usw2-monorail-openapi.s3.amazonaws.com/latest.json get /customers/{customerID}/wallets List of Bridge Wallets for the specified Customer ID # Get total balances of all Bridge Wallets Source: https://apidocs.bridge.xyz/api-reference/bridge-wallets/get-total-balances-of-all-bridge-wallets https://withbridge-image1-sv-usw2-monorail-openapi.s3.amazonaws.com/latest.json get /wallets/total_balances Get the total balances of all Bridge Wallets # Get transaction history for a Bridge Wallet Source: https://apidocs.bridge.xyz/api-reference/bridge-wallets/get-transaction-history-for-a-bridge-wallet https://withbridge-image1-sv-usw2-monorail-openapi.s3.amazonaws.com/latest.json get /wallets/{bridgeWalletID}/history Get the list of transactions involving this Bridge Wallet # Create a funds withdrawal request Source: https://apidocs.bridge.xyz/api-reference/cards/create-a-funds-withdrawal-request https://withbridge-image1-sv-usw2-monorail-openapi.s3.amazonaws.com/latest.json post /customers/{customerID}/card_accounts/{cardAccountID}/withdrawals Request a funds withdrawal from the card account, applicable to top-up accounts only. For Bridge wallets, create a [transfer](/api-reference/transfers/create-a-transfer) from the Bridge wallet. # Create a mobile wallet push provisioning request Source: https://apidocs.bridge.xyz/api-reference/cards/create-a-mobile-wallet-push-provisioning-request https://withbridge-image1-sv-usw2-monorail-openapi.s3.amazonaws.com/latest.json post /customers/{customerID}/card_accounts/{cardAccountID}/create_mobile_wallet_provisioning_request Create a request to push-provision a virtual card to a mobile wallet. This endpoint is part of a multiple-step integration that must be completed with each mobile wallet partner # Create Card PIN Update URL Source: https://apidocs.bridge.xyz/api-reference/cards/create-card-pin-update-url https://withbridge-image1-sv-usw2-monorail-openapi.s3.amazonaws.com/latest.json post /customers/{customerID}/card_accounts/{cardAccountID}/pin Generates a URL that can be used to render a secure frame to update the PIN for a card account. The URL is single-use and time-limited. # Generate a card account statement Source: https://apidocs.bridge.xyz/api-reference/cards/generate-a-card-account-statement https://withbridge-image1-sv-usw2-monorail-openapi.s3.amazonaws.com/latest.json post /customers/{customerID}/card_accounts/{cardAccountID}/statements/{period}.pdf Generate a card account statement for the specified period # Generate a card statement using Stripe IDs Source: https://apidocs.bridge.xyz/api-reference/cards/generate-a-card-statement-using-stripe-ids https://withbridge-image1-sv-usw2-monorail-openapi.s3.amazonaws.com/latest.json post /cardholders/{cardholderID}/cards/{cardID}/statements/{period}.pdf Generate a card account statement for the specified period, using Stripe cardholder and card IDs instead of Bridge internal IDs # Generate an Ephemeral Key to Reveal Card Details Source: https://apidocs.bridge.xyz/api-reference/cards/generate-an-ephemeral-key-to-reveal-card-details https://withbridge-image1-sv-usw2-monorail-openapi.s3.amazonaws.com/latest.json post /customers/{customerID}/card_accounts/{cardAccountID}/ephemeral_keys Generates a one-time ephemeral key that can be used to reveal card details. Please see the integration guide on [safely revealing card details](https://apidocs.bridge.xyz/docs/safely-reveal-card-details-to-customers) for more information. # Get a listing of your card program's card designs Source: https://apidocs.bridge.xyz/api-reference/cards/get-a-listing-of-your-card-programs-card-designs https://withbridge-image1-sv-usw2-monorail-openapi.s3.amazonaws.com/latest.json get /developer/cards/designs Get a listing of the designs that you can use to issue a card with. # Get a summary of your card program Source: https://apidocs.bridge.xyz/api-reference/cards/get-a-summary-of-your-card-program https://withbridge-image1-sv-usw2-monorail-openapi.s3.amazonaws.com/latest.json get /developer/cards/summary Get a summary of your card program, optionally for a specific period. # Get all card accounts Source: https://apidocs.bridge.xyz/api-reference/cards/get-all-card-accounts https://withbridge-image1-sv-usw2-monorail-openapi.s3.amazonaws.com/latest.json get /customers/{customerID}/card_accounts Retrieve all card accounts for a customer. Currently, only one account is supported. An empty array will be returned if no card has been provisioned # Place a freeze on the card account Source: https://apidocs.bridge.xyz/api-reference/cards/place-a-freeze-on-the-card-account https://withbridge-image1-sv-usw2-monorail-openapi.s3.amazonaws.com/latest.json post /customers/{customerID}/card_accounts/{cardAccountID}/freeze Place a freeze on the card account # Provision a card account Source: https://apidocs.bridge.xyz/api-reference/cards/provision-a-card-account https://withbridge-image1-sv-usw2-monorail-openapi.s3.amazonaws.com/latest.json post /customers/{customerID}/card_accounts Provision a card account. NOTE: the legacy Bridge Cards API is deprecated, and stablecoin card issuing capabilities are now natively integrated into Stripe Issuing. Please see [this guide](https://apidocs.bridge.xyz/platform/cards/overview/stripe-issuing) for more details on how to enable your account for Stripe Issuing. # Provision an additional top-up deposit address for the card account Source: https://apidocs.bridge.xyz/api-reference/cards/provision-an-additional-top-up-deposit-address-for-the-card-account https://withbridge-image1-sv-usw2-monorail-openapi.s3.amazonaws.com/latest.json post /customers/{customerID}/card_accounts/{cardAccountID}/deposit_addresses Provision an additional deposit address for the card account, to allow topping up the card from multiple chains. This is only applicable to Bridge-custodied top-up card accounts. These additional deposit addresses will also be shown in the `additional_funding_instructions` field when fetching the card account details afterwards. # Retrieve a card account Source: https://apidocs.bridge.xyz/api-reference/cards/retrieve-a-card-account https://withbridge-image1-sv-usw2-monorail-openapi.s3.amazonaws.com/latest.json get /customers/{customerID}/card_accounts/{cardAccountID} Retrieve the card account with the specified ID # Retrieve a card transaction Source: https://apidocs.bridge.xyz/api-reference/cards/retrieve-a-card-transaction https://withbridge-image1-sv-usw2-monorail-openapi.s3.amazonaws.com/latest.json get /customers/{customerID}/card_accounts/{cardAccountID}/transactions/{transactionID} Retrieve a card transaction with the specified ID # Retrieve a card withdrawal Source: https://apidocs.bridge.xyz/api-reference/cards/retrieve-a-card-withdrawal https://withbridge-image1-sv-usw2-monorail-openapi.s3.amazonaws.com/latest.json get /customers/{customerID}/card_accounts/{cardAccountID}/withdrawals/{cardWithdrawalID} Retrieve a card withdrawal with the specified ID, applicable to top-up accounts only # Retrieve authorization controls Source: https://apidocs.bridge.xyz/api-reference/cards/retrieve-authorization-controls https://withbridge-image1-sv-usw2-monorail-openapi.s3.amazonaws.com/latest.json get /customers/{customerID}/card_accounts/{cardAccountID}/auth_controls Retrieve the applicable spend limits for the given card account # Retrieve card transactions Source: https://apidocs.bridge.xyz/api-reference/cards/retrieve-card-transactions https://withbridge-image1-sv-usw2-monorail-openapi.s3.amazonaws.com/latest.json get /customers/{customerID}/card_accounts/{cardAccountID}/transactions Retrieve completed card transactions and card-related crypto transaction activities # Retrieve pending card authorizations Source: https://apidocs.bridge.xyz/api-reference/cards/retrieve-pending-card-authorizations https://withbridge-image1-sv-usw2-monorail-openapi.s3.amazonaws.com/latest.json get /customers/{customerID}/card_accounts/{cardAccountID}/authorizations Retrieve pending card authorizations. Note: this endpoint is not paginated # Retrieve the withdrawal history of funds Source: https://apidocs.bridge.xyz/api-reference/cards/retrieve-the-withdrawal-history-of-funds https://withbridge-image1-sv-usw2-monorail-openapi.s3.amazonaws.com/latest.json get /customers/{customerID}/card_accounts/{cardAccountID}/withdrawals Retrieve the withdrawal history of funds, applicable to top-up accounts only # Unfreeze the card account Source: https://apidocs.bridge.xyz/api-reference/cards/unfreeze-the-card-account https://withbridge-image1-sv-usw2-monorail-openapi.s3.amazonaws.com/latest.json post /customers/{customerID}/card_accounts/{cardAccountID}/unfreeze Remove the freeze on the card account placed by the specified initiator # Update a card account Source: https://apidocs.bridge.xyz/api-reference/cards/update-a-card-account https://withbridge-image1-sv-usw2-monorail-openapi.s3.amazonaws.com/latest.json put /customers/{customerID}/card_accounts/{cardAccountID} Update a card account. Supports changing the settlement currency or closing a card account by setting the status to "inactive". Closing permanently cancels all associated cards and is irreversible. # Create a new crypto return policy Source: https://apidocs.bridge.xyz/api-reference/crypto-return-policies/create-a-new-crypto-return-policy https://withbridge-image1-sv-usw2-monorail-openapi.s3.amazonaws.com/latest.json post /crypto_return_policies # Delete a single crypto return policy object Source: https://apidocs.bridge.xyz/api-reference/crypto-return-policies/delete-a-single-crypto-return-policy-object https://withbridge-image1-sv-usw2-monorail-openapi.s3.amazonaws.com/latest.json delete /crypto_return_policies/{policyID} Delete a crypto return policy object from the passed in crypto return policy ID # Get all crypto return policies Source: https://apidocs.bridge.xyz/api-reference/crypto-return-policies/get-all-crypto-return-policies https://withbridge-image1-sv-usw2-monorail-openapi.s3.amazonaws.com/latest.json get /crypto_return_policies Retrieve all crypto return policies for the authenticated developer # Update an existing crypto return policy Source: https://apidocs.bridge.xyz/api-reference/crypto-return-policies/update-an-existing-crypto-return-policy https://withbridge-image1-sv-usw2-monorail-openapi.s3.amazonaws.com/latest.json put /crypto_return_policies/{policyID} # Create a customer Source: https://apidocs.bridge.xyz/api-reference/customers/create-a-customer https://withbridge-image1-sv-usw2-monorail-openapi.s3.amazonaws.com/latest.json post /customers # Create a new associated person for a business customer Source: https://apidocs.bridge.xyz/api-reference/customers/create-a-new-associated-person-for-a-business-customer https://withbridge-image1-sv-usw2-monorail-openapi.s3.amazonaws.com/latest.json post /customers/{customerID}/associated_persons # Delete a single associated person Source: https://apidocs.bridge.xyz/api-reference/customers/delete-a-single-associated-person https://withbridge-image1-sv-usw2-monorail-openapi.s3.amazonaws.com/latest.json delete /customers/{customerID}/associated_persons/{associatedPersonID} Delete an associated person by ID # Delete a single customer object Source: https://apidocs.bridge.xyz/api-reference/customers/delete-a-single-customer-object https://withbridge-image1-sv-usw2-monorail-openapi.s3.amazonaws.com/latest.json delete /customers/{customerID} Delete a customer object from the passed in customer ID # Get a single associated person Source: https://apidocs.bridge.xyz/api-reference/customers/get-a-single-associated-person https://withbridge-image1-sv-usw2-monorail-openapi.s3.amazonaws.com/latest.json get /customers/{customerID}/associated_persons/{associatedPersonID} Retrieve an associated person by ID # Get a single customer object Source: https://apidocs.bridge.xyz/api-reference/customers/get-a-single-customer-object https://withbridge-image1-sv-usw2-monorail-openapi.s3.amazonaws.com/latest.json get /customers/{customerID} Retrieve a customer object from the passed in customer ID # Get all customers Source: https://apidocs.bridge.xyz/api-reference/customers/get-all-customers https://withbridge-image1-sv-usw2-monorail-openapi.s3.amazonaws.com/latest.json get /customers Get the full list of all customers created on Bridge # Get all static templates for a customer Source: https://apidocs.bridge.xyz/api-reference/customers/get-all-static-templates-for-a-customer https://withbridge-image1-sv-usw2-monorail-openapi.s3.amazonaws.com/latest.json get /customers/{customerID}/transfers/static_templates Get all static templates for a customer. Static templates are transfers that are used as templates for other transfers and can be created using the static_templates feature flag. # Get all transfers Source: https://apidocs.bridge.xyz/api-reference/customers/get-all-transfers https://withbridge-image1-sv-usw2-monorail-openapi.s3.amazonaws.com/latest.json get /customers/{customerID}/transfers Get all active and completed transfers for a customer. # Get associated persons for a business customer Source: https://apidocs.bridge.xyz/api-reference/customers/get-associated-persons-for-a-business-customer https://withbridge-image1-sv-usw2-monorail-openapi.s3.amazonaws.com/latest.json get /customers/{customerID}/associated_persons Get all associated persons for a business customer. # Request a hosted URL for ToS acceptance for new customer creation Source: https://apidocs.bridge.xyz/api-reference/customers/request-a-hosted-url-for-tos-acceptance-for-new-customer-creation https://withbridge-image1-sv-usw2-monorail-openapi.s3.amazonaws.com/latest.json post /customers/tos_links The URL endpoint returned will guide the user through a Bridge TOS flow. Signing this acceptance flow is a requirement for creating customers. # Retrieve a hosted KYC Link for an existing customer Source: https://apidocs.bridge.xyz/api-reference/customers/retrieve-a-hosted-kyc-link-for-an-existing-customer https://withbridge-image1-sv-usw2-monorail-openapi.s3.amazonaws.com/latest.json get /customers/{customerID}/kyc_link The page at the returned URL will guide the user through a Bridge KYC flow. This can be used by existing customers to provide additional KYC information required for certain features or services that Bridge offers. For example, to enable an existing customer to use the `SEPA`/`Euro` services, they are required to provide `proof of address`. An additional parameter, `endorsement=sepa`, can be included to request a KYC link specifically for this purpose # Retrieve a hosted URL for ToS acceptance for an existing customer Source: https://apidocs.bridge.xyz/api-reference/customers/retrieve-a-hosted-url-for-tos-acceptance-for-an-existing-customer https://withbridge-image1-sv-usw2-monorail-openapi.s3.amazonaws.com/latest.json get /customers/{customerID}/tos_acceptance_link The page at the returned URL will guide the user through the Bridge Terms of Service (ToS) acceptance flow. This can be used by existing customers to accept a new version of the ToS. # Update a single associated person Source: https://apidocs.bridge.xyz/api-reference/customers/update-a-single-associated-person https://withbridge-image1-sv-usw2-monorail-openapi.s3.amazonaws.com/latest.json put /customers/{customerID}/associated_persons/{associatedPersonID} # Update a single customer object Source: https://apidocs.bridge.xyz/api-reference/customers/update-a-single-customer-object https://withbridge-image1-sv-usw2-monorail-openapi.s3.amazonaws.com/latest.json put /customers/{customerID} Updates to be made to the specified customer. No fields are strictly required by the API. It is generally valid to provide any subset of data in a PUT request. For business customers, associated persons cannot be updated via PUT, and should instead be managed using v0/associated_persons. # Configure a fee External Account Source: https://apidocs.bridge.xyz/api-reference/developers/configure-a-fee-external-account https://withbridge-image1-sv-usw2-monorail-openapi.s3.amazonaws.com/latest.json post /developer/fee_external_account Configure a fee External Account. # Get the configured fee External Account Source: https://apidocs.bridge.xyz/api-reference/developers/get-the-configured-fee-external-account https://withbridge-image1-sv-usw2-monorail-openapi.s3.amazonaws.com/latest.json get /developer/fee_external_account Get the configured fee External Account. # Get the configured fees Source: https://apidocs.bridge.xyz/api-reference/developers/get-the-configured-fees https://withbridge-image1-sv-usw2-monorail-openapi.s3.amazonaws.com/latest.json get /developer/fees Get fees that have been configured for supported products. # Update the configured fees Source: https://apidocs.bridge.xyz/api-reference/developers/update-the-configured-fees https://withbridge-image1-sv-usw2-monorail-openapi.s3.amazonaws.com/latest.json post /developer/fees Update fees for supported products. # Get current exchange rate between two currencies. Source: https://apidocs.bridge.xyz/api-reference/exchange-rates/get-current-exchange-rate-between-two-currencies https://withbridge-image1-sv-usw2-monorail-openapi.s3.amazonaws.com/latest.json get /exchange_rates Returns the current exchange rate from the "from" currency to the "to" currency. The exchange rate is updated roughly every 30s. Note that as of this writing, Bridge does not offer a "quote" by which a user can lock in a rate for a given amount of time. This is provided only as a courtesy to estimate what you are likely to get in a subsequent transfer request that involves currency exchange. As of March 2026, we support: - `USD <> BRL` - `USD <> COP` - `USD <> EUR` - `USD <> GBP` - `USD <> MXN` - `USD <> USDT` # Create a new External Account Source: https://apidocs.bridge.xyz/api-reference/external-accounts/create-a-new-external-account https://withbridge-image1-sv-usw2-monorail-openapi.s3.amazonaws.com/latest.json post /customers/{customerID}/external_accounts _Note_: If adding US external accounts, we recommend reading through the US Beneficiary Address Validation doc ([link](https://apidocs.bridge.xyz/docs/us-beneficiary-address-validation)) to avoid issues related to incorrect addresses. # Deactivate an External Account Source: https://apidocs.bridge.xyz/api-reference/external-accounts/deactivate-an-external-account https://withbridge-image1-sv-usw2-monorail-openapi.s3.amazonaws.com/latest.json post /customers/{customerID}/external_accounts/{externalAccountID}/deactivate Deactivate an active External Account. The External Account is preserved and can be reactivated later via the reactivate endpoint. # Delete a single External Account object Source: https://apidocs.bridge.xyz/api-reference/external-accounts/delete-a-single-external-account-object https://withbridge-image1-sv-usw2-monorail-openapi.s3.amazonaws.com/latest.json delete /customers/{customerID}/external_accounts/{externalAccountID} Delete an External Account object from the passed in External Account ID # Get all External Accounts Source: https://apidocs.bridge.xyz/api-reference/external-accounts/get-all-external-accounts https://withbridge-image1-sv-usw2-monorail-openapi.s3.amazonaws.com/latest.json get /customers/{customerID}/external_accounts Get all External Accounts for a passed in customer. # Get all External Accounts Source: https://apidocs.bridge.xyz/api-reference/external-accounts/get-all-external-accounts-1 https://withbridge-image1-sv-usw2-monorail-openapi.s3.amazonaws.com/latest.json get /external_accounts Get all External Accounts. # Reactivate an External Account Source: https://apidocs.bridge.xyz/api-reference/external-accounts/reactivate-an-external-account https://withbridge-image1-sv-usw2-monorail-openapi.s3.amazonaws.com/latest.json post /customers/{customerID}/external_accounts/{externalAccountID}/reactivate Reactivate a previously deactivated External Account # Retrieve an External Account object Source: https://apidocs.bridge.xyz/api-reference/external-accounts/retrieve-an-external-account-object https://withbridge-image1-sv-usw2-monorail-openapi.s3.amazonaws.com/latest.json get /customers/{customerID}/external_accounts/{externalAccountID} Retrieve an External Account object (banks, debit cards etc) from the passed in customer ID and External Account ID # Update an External Account Source: https://apidocs.bridge.xyz/api-reference/external-accounts/update-an-external-account https://withbridge-image1-sv-usw2-monorail-openapi.s3.amazonaws.com/latest.json put /customers/{customerID}/external_accounts/{externalAccountID} # Verify an External Account Source: https://apidocs.bridge.xyz/api-reference/external-accounts/verify-an-external-account https://withbridge-image1-sv-usw2-monorail-openapi.s3.amazonaws.com/latest.json post /customers/{customerID}/external_accounts/{externalAccountID}/verify Trigger a verification check for an external account. Verifies that the `account_owner_name` matches the actual account holder at the receiving bank. Supported for `iban` (EUR) and `gb` (GBP) account types only. Does not require an Idempotency-Key header. After triggering, poll the external account's `account_verification` field until `completed_at` is populated. # Get the fiat payout configuration for a customer Source: https://apidocs.bridge.xyz/api-reference/fiat-payout-configuration/get-the-fiat-payout-configuration-for-a-customer https://withbridge-image1-sv-usw2-monorail-openapi.s3.amazonaws.com/latest.json get /customers/{customerID}/fiat_payout_configuration Retrieve the fiat payout configuration for the given customer ID. This configuration determines which payout method (bridge, developer, payment_provider, or customer) is used for each currency and payment rail combination. The configuration is a nested hash structure where: - Top-level keys are currency codes (e.g., "usd", "eur", "brl", "mxn") - Second-level keys are payment rail codes (e.g., "wire", "ach", "sepa", "pix", "spei") - Values are payout names: `bridge`, `developer`, `payment_provider`, or `customer` Currently, only the following values are supported for the payout method: - usd.wire: `developer`, `customer` - usd.ach: `bridge` - eur.sepa: `bridge` - brl.pix: `payment_provider` - mxn.spei: `payment_provider` # Update the fiat payout configuration for a customer Source: https://apidocs.bridge.xyz/api-reference/fiat-payout-configuration/update-the-fiat-payout-configuration-for-a-customer https://withbridge-image1-sv-usw2-monorail-openapi.s3.amazonaws.com/latest.json patch /customers/{customerID}/fiat_payout_configuration Update the fiat payout configuration for the given customer ID. This configuration determines which payout method (bridge, developer, payment_provider, or customer) is used for each currency and payment rail combination. The configuration is a nested hash structure where: - Top-level keys are currency codes (e.g., "usd", "eur", "brl", "mxn") - Second-level keys are payment rail codes (e.g., "wire", "ach", "sepa", "pix", "spei") - Values are payout names: `bridge`, `developer`, `payment_provider`, or `customer` Currently, only the following values are supported for the payout method: - usd.wire: `developer`, `customer` - usd.ach: `bridge` - eur.sepa: `bridge` - brl.pix: `payment_provider` - mxn.spei: `payment_provider` Only the currency/payment rail combinations provided will be updated. Other existing configurations will remain unchanged. # Get all funds requests Source: https://apidocs.bridge.xyz/api-reference/funds-requests/get-all-funds-requests https://withbridge-image1-sv-usw2-monorail-openapi.s3.amazonaws.com/latest.json get /funds_requests Retrieve a list of all funds requests submitted by partnered banks and financial institutions # Deprecation Source: https://apidocs.bridge.xyz/api-reference/introduction/deprecation ### Deprecation When Bridge marks an API as **deprecated**, it means we've found a better way to accomplish the same thing. The deprecated endpoint still works today, but a superior alternative exists — and you should plan to migrate. > Deprecated APIs are subject to removal in a future breaking change. We will always provide sufficient advance notice before removing a deprecated API. ### What Deprecation Means * **A better path exists.** Every deprecated API has a recommended replacement. You'll find migration guidance documented directly on the deprecated method itself. * **It still works — for now.** Deprecation is not removal. Your existing integrations will continue to function, giving you time to migrate on your own schedule. * **It will eventually go away.** Deprecated APIs are candidates for removal in a future breaking change. When that happens, we'll communicate a timeline and provide support for the transition. ### Best Practices * When you encounter a deprecated API, review the in-line migration guidance and plan your move to the recommended alternative. * Avoid building new integrations on deprecated APIs. Use the recommended replacement from the start. * Subscribe to the [Changelog](/changelog/changelog) to stay informed about deprecations, removals, and breaking changes. # Idempotency Source: https://apidocs.bridge.xyz/api-reference/introduction/idempotence ### Idempotency All `POST` APIs in Bridge require [idempotency](https://developer.mozilla.org/en-US/docs/Glossary/Idempotent) to guarantee safe retries and prevent duplicate operations. You must include an `Idempotency-Key` header with a unique value for each request. This ensures that if a request is retried (due to network errors, client timeouts, or unexpected failures), Bridge can detect the duplication and return the same response, without performing the operation again. > Do not include an Idempotency-Key with GET, PUT, PATCH, or DELETE requests. These methods are naturally idempotent and do not require this header. ### How It Works * Include a unique Idempotency-Key (typically a UUID) in the request header of every POST. * Bridge guarantees idempotent behavior for 24 hours after the initial request. During this window, any subsequent request with the same Idempotency-Key will return the original response — with no side effects or duplicated operations. * For example, if a request to create a Customer or a Transfer fails or times out, you can safely retry it using the same key to ensure that only one object is ever created. * Retries must use the same request body. Reusing an Idempotency-Key with changed, added, or removed fields, including transfer `initiation` data, returns an idempotency error. * After the 24-hour window expires, reusing the same Idempotency-Key will result in a 422 Unprocessable Entity error. ### Best Practices * Use a UUID for each new request. * Store the UUID in your database to track request state. * Reuse the same UUID when retrying a failed request. ### Example ```shell theme={null} curl --location --request POST 'https://api.bridge.xyz/v1/customers' \ --header 'Content-Type: application/json' \ --header 'Api-Key: ' \ --header 'Idempotency-Key: ' \ --data-raw '{ "first_name": "John", "last_name": "Doe", "email": "johndoe@johndoe.com", "address": { "street_line_1": "123 Washington St", "street_line_2": "Apt 2F", "city": "New York", "state": "NY", "postal_code": "10001", "country": "USA" }, "birth_date": "1989-09-09", "tax_identification_number": "111-11-1111" }' ``` # Authentication Source: https://apidocs.bridge.xyz/api-reference/introduction/introduction Bridge uses API keys to authenticate your requests. You can generate them from the [dashboard](http://dashboard.bridge.xyz/app/keys) . **⚠️ API keys are shown only once** at the time of creation. Be sure to copy and store them securely — they cannot be retrieved later. ### 🔑 How Authentication Works * Pass your API key in the Api-Key header using HTTP Basic Auth. * No username or password is required — just the API key. * All requests must be made over HTTPS; requests over plain HTTP are rejected. * Invalid or missing keys will return a 401 Unauthorized. > ❗️ Keep your API keys secure. They grant full access to your account and should never be shared publicly or within internal tools like Slack or dashboards. ### Sandbox Environment * In the sandbox, API keys are scoped to individual developer accounts. * Keys generated in sandbox are not visible to teammates, even if production keys are shared across the org. ### Example Request ```shell theme={null} curl --location --request GET 'https://api.bridge.xyz/v0/customers' \ --header 'Content-Type: application/json' \ --header 'Api-Key: ' ``` # Postman collection Source: https://apidocs.bridge.xyz/api-reference/introduction/postman ### Try the API with Postman Click [here](https://god.gw.postman.com/run-collection/38333379-c2e057c8-d066-4c73-bb66-275c028a00f6?action=collection%2Ffork\&source=rip_markdown\&collection-url=entityId%3D38333379-c2e057c8-d066-4c73-bb66-275c028a00f6%26entityType%3Dcollection%26workspaceId%3D3ea438c8-19f4-48e9-8a0c-9b2091303747) to fork our Postman collection and start testing the Bridge API in your own workspace: ### What's included: * All core endpoints (transfers, deposits, refunds, etc.) * Environment variables for managing your API keys * Pre-configured request examples for common flows * Built-in support for test environments ### How to use it: * Click the link above. * Fork the collection into your Postman workspace. * Set up your API key and environment variables. * Start making requests! # Check the status of a KYC link Source: https://apidocs.bridge.xyz/api-reference/kyc-links/check-the-status-of-a-kyc-link https://withbridge-image1-sv-usw2-monorail-openapi.s3.amazonaws.com/latest.json get /kyc_links/{kycLinkID} Retrieve the status of a KYC request from the passed in KYC link id # Generate the Links needs to complete KYC for an individual or business Source: https://apidocs.bridge.xyz/api-reference/kyc-links/generate-the-links-needs-to-complete-kyc-for-an-individual-or-business https://withbridge-image1-sv-usw2-monorail-openapi.s3.amazonaws.com/latest.json post /kyc_links # Get all KYC links. Source: https://apidocs.bridge.xyz/api-reference/kyc-links/get-all-kyc-links https://withbridge-image1-sv-usw2-monorail-openapi.s3.amazonaws.com/latest.json get /kyc_links Retrieve the full list of kyc links. # Create a Liquidation Address Source: https://apidocs.bridge.xyz/api-reference/liquidation-addresses/create-a-liquidation-address https://withbridge-image1-sv-usw2-monorail-openapi.s3.amazonaws.com/latest.json post /customers/{customerID}/liquidation_addresses # Execute a pending USDT trade on a drain Source: https://apidocs.bridge.xyz/api-reference/liquidation-addresses/execute-a-pending-usdt-trade-on-a-drain https://withbridge-image1-sv-usw2-monorail-openapi.s3.amazonaws.com/latest.json post /customers/{customerID}/liquidation_addresses/{liquidationAddressID}/drains/{drainID}/execute Force-executes a stuck USDT-to-USD trade at the current market rate. The drain must have a pending trade (i.e. appear in `GET /liquidation_addresses/drains/pending`). After execution, the drain will continue processing normally with the executed market rate. # Get a Liquidation Address Source: https://apidocs.bridge.xyz/api-reference/liquidation-addresses/get-a-liquidation-address https://withbridge-image1-sv-usw2-monorail-openapi.s3.amazonaws.com/latest.json get /customers/{customerID}/liquidation_addresses/{liquidationAddressID} Retrieve a Liquidation Address for the specified Liquidation Address ID # Get all Liquidation Addresses Source: https://apidocs.bridge.xyz/api-reference/liquidation-addresses/get-all-liquidation-addresses https://withbridge-image1-sv-usw2-monorail-openapi.s3.amazonaws.com/latest.json get /liquidation_addresses Get Liquidation Addresses # Get all Liquidation Addresses for a customer Source: https://apidocs.bridge.xyz/api-reference/liquidation-addresses/get-all-liquidation-addresses-for-a-customer https://withbridge-image1-sv-usw2-monorail-openapi.s3.amazonaws.com/latest.json get /customers/{customerID}/liquidation_addresses Get Liquidation Addresses # Get drain history of a Liquidation Address Source: https://apidocs.bridge.xyz/api-reference/liquidation-addresses/get-drain-history-of-a-liquidation-address https://withbridge-image1-sv-usw2-monorail-openapi.s3.amazonaws.com/latest.json get /customers/{customerID}/liquidation_addresses/{liquidationAddressID}/drains Get drain history of a Liquidation Address # Get the balance of a Liquidation Address (deprecated) Source: https://apidocs.bridge.xyz/api-reference/liquidation-addresses/get-the-balance-of-a-liquidation-address-deprecated https://withbridge-image1-sv-usw2-monorail-openapi.s3.amazonaws.com/latest.json get /customers/{customerID}/liquidation_addresses/{liquidationAddressID}/balances Get the balance of a Liquidation Address. Note that most Liquidation Addresses no longer hold a balance. To check recent activity on a Liquidation Address, use the `/customers/{customerID}/liquidation_addresses/{liquidationAddressID}/drains` endpoint. # Liquidation Address Activity Across All Customers Source: https://apidocs.bridge.xyz/api-reference/liquidation-addresses/liquidation-address-activity-across-all-customers https://withbridge-image1-sv-usw2-monorail-openapi.s3.amazonaws.com/latest.json get /liquidation_addresses/drains History of activity across all customers and Liquidation Addresses # List drains with pending USDT trades Source: https://apidocs.bridge.xyz/api-reference/liquidation-addresses/list-drains-with-pending-usdt-trades https://withbridge-image1-sv-usw2-monorail-openapi.s3.amazonaws.com/latest.json get /liquidation_addresses/drains/pending Returns drains that have a stuck USDT-to-USD trade awaiting execution. Results are sorted by creation time (newest first) and paginated. Use `POST /customers/{customerID}/liquidation_addresses/{liquidationAddressID}/drains/{drainID}/execute` to force-execute a pending trade at the current market rate. # Update a Liquidation Address Source: https://apidocs.bridge.xyz/api-reference/liquidation-addresses/update-a-liquidation-address https://withbridge-image1-sv-usw2-monorail-openapi.s3.amazonaws.com/latest.json put /customers/{customerID}/liquidation_addresses/{liquidationAddressID} Update a Liquidation Address for the specified liquidation address ID. Note that `external_account_id` and `custom_developer_fee_percent` can be updated independently and are not both required. # Get countries Source: https://apidocs.bridge.xyz/api-reference/lists/get-countries https://withbridge-image1-sv-usw2-monorail-openapi.s3.amazonaws.com/latest.json get /lists/countries Returns a list of countries and subdivisions recognized by Bridge. Inclusion in this list does not guarantee Bridge product support for any country or subdivision. # Get occupation codes Source: https://apidocs.bridge.xyz/api-reference/lists/get-occupation-codes https://withbridge-image1-sv-usw2-monorail-openapi.s3.amazonaws.com/latest.json get /lists/occupation_codes Provide this list of occupation codes to your users as possible answers to the Source of Funds section in the KYC flow. The returned list will resemble the list of occupation codes found [here](https://apidocs.bridge.xyz/page/sof-eu-most-recent-occupation-list). # Bridge API Pagination Guide Source: https://apidocs.bridge.xyz/api-reference/pagination This page describes how to paginate any Bridge “list” endpoint using cursor-based pagination. It applies across resources (transactions, deposits, payouts, etc.), not just a single API. Most list endpoints return results in reverse chronological order (newest to oldest) and support stable, cursor-based pagination with `starting_after` and `ending_before`. ## **Endpoint shape** * Base URL: [**https://api.bridge.xyz**](https://api.bridge.xyz) * Typical list endpoint pattern: GET /v0/ * Default order: newest → oldest (unless an endpoint specifies otherwise) * Page size: controlled by `limit` (maximum 100) * Pagination: cursor-based using item `id` values Authentication: send your API key in the `Api-Key` header. Security note: do not hardcode live keys in source or docs; use environment variables. ## **Query parameters** * `limit` * Description: number of items to return * Range: 1–100 * Tip: set explicitly (e.g., `limit=50`) for predictable pagination * `starting_after` * Description: fetches items that come after the given id in the default ordering, i.e., older items * How to use: pass the last item’s id from your current page to get the next page of older results * `ending_before` * Description: fetches items that come before the given id in the default ordering, i.e., newer items * How to use: pass the first item’s id from a known page to retrieve any items that are newer than it Use only one of `starting_after` or `ending_before` per request. ## **Response shape** * data: array of resource objects (0 to `limit` items) * count: number of items in this page (if provided by the endpoint) * Stop condition: when `data` is empty, there are no more items in that direction Note: Field names inside `data` vary by resource. All paginable resources include an `id` used as the cursor. ## **cURL examples** Use an environment variable for your API key: * macOS/Linux: export BRIDGE\_API\_KEY="sk\_live\_..." * Windows PowerShell: \$env:BRIDGE\_API\_KEY = "sk\_live\_..." Replace with the list endpoint you’re using (e.g., transactions, payouts, etc.). ### **1) Fetch the first page (newest first)** This returns the newest 3 items: ``` curl --location 'https://api.bridge.xyz/v0/{resource}?limit=3' \ --header 'Accept: application/json' \ --header "Api-Key: $BRIDGE_API_KEY" ``` Take note of: * First item’s id: newest on this page * Last item’s id: oldest on this page ### **2) Get the next page of older items** Use `starting_after` with the last id from the previous page: ``` curl --location 'https://api.bridge.xyz/v0/{resource}?limit=3&starting_after={LAST_ID_FROM_PREVIOUS_PAGE}' \ --header 'Accept: application/json' \ --header "Api-Key: $BRIDGE_API_KEY" ``` ### **3) Fetch newer items since a known id** If your last run’s first item id was , use `ending_before` to get any newer items: ``` curl --location 'https://api.bridge.xyz/v0/{resource}?ending_before={FIRST_ID_YOU_SAW}' \ --header 'Accept: application/json' \ --header "Api-Key: $BRIDGE_API_KEY" ``` If there are new items, they’ll be returned; otherwise you may see an empty page. ## **Practical patterns** ### **Backfill all historical items (older direction)** 1. Request with your chosen `limit` (e.g., 100). 2. Process the page. 3. Save the last id from the page (the oldest in this batch). 4. Repeat with `starting_after=` until `data` is empty. ### **Periodically check for new items (newer direction)** 1. Save the first id from your last successful fetch (the newest you’ve seen). 2. Request with `ending_before=`. 3. If `data` is non-empty, process the new items and update your saved first id to the newest id returned. 4. If empty, nothing new is available. ### **Boundary behavior** * Reached oldest items: using `starting_after` eventually returns `data: []`. * No newer items: using `ending_before` may return `data: []`. ## **Tips and best practices** * Treat item ids as stable cursors; always use the first and last ids from each page for the next request. * Don’t combine `starting_after` and `ending_before` in the same call. * Stick to a consistent `limit` for predictable throughput; max is 100. * Expect partial pages near the ends (fewer than `limit` items). * If you need to process items oldest-to-newest, reverse the page locally after fetching. * When running concurrent pagination and ingestion, de-duplicate by `id` in your datastore. ## **Minimal JavaScript examples** Assume a helper fetchFn(path) that does authenticated fetches relative to [**https://api.bridge.xyz**](https://api.bridge.xyz). ### **Backfill older pages** ``` // Fetch older pages until no more items are returned. const backfillAll = async (fetchFn) => { let startingAfter = null; const pageSize = 100; while (true) { const qs = new URLSearchParams({ limit: String(pageSize) }); if (startingAfter) qs.set("starting_after", startingAfter); const res = await fetchFn(`/v0/{resource}?${qs.toString()}`); const { data = [] } = await res.json(); if (data.length === 0) break; // Process items (newest → oldest on this page) // ... // Next cursor: last id (oldest on this page) startingAfter = data[data.length - 1].id; } }; ``` ### **Poll for newer items since a known id** ``` // Fetch any items newer than `firstSeenId`. // Returns the updated newest id to store for next poll. const fetchNewerSince = async (fetchFn, firstSeenId) => { const qs = new URLSearchParams({ ending_before: firstSeenId }); const res = await fetchFn(`/v0/{resource}?${qs.toString()}`); const { data = [] } = await res.json(); if (data.length > 0) { // Items returned are newest → oldest within the page. // Update the cursor to the newest id we now know about. return data[0].id; } return firstSeenId; }; ``` ## **Summary** * Results are newest → oldest by default. * Use `starting_after=` to go older. * Use `ending_before=` to fetch items newer than a known id. * Control page size with `limit` (max 100). * Stop when `data` is empty in the direction you’re traversing. # Exchange Plaid public token for an access token Source: https://apidocs.bridge.xyz/api-reference/plaid/exchange-plaid-public-token-for-an-access-token https://withbridge-image1-sv-usw2-monorail-openapi.s3.amazonaws.com/latest.json post /plaid_exchange_public_token/{link_token} # Generate a Plaid Link token for a customer Source: https://apidocs.bridge.xyz/api-reference/plaid/generate-a-plaid-link-token-for-a-customer https://withbridge-image1-sv-usw2-monorail-openapi.s3.amazonaws.com/latest.json post /customers/{customerID}/plaid_link_requests # Get a list of all Prefunded Account Source: https://apidocs.bridge.xyz/api-reference/prefunded-accounts/get-a-list-of-all-prefunded-account https://withbridge-image1-sv-usw2-monorail-openapi.s3.amazonaws.com/latest.json get /prefunded_accounts Retrieve a all Prefunded Accounts # Get details for a specific Prefunded Account Source: https://apidocs.bridge.xyz/api-reference/prefunded-accounts/get-details-for-a-specific-prefunded-account https://withbridge-image1-sv-usw2-monorail-openapi.s3.amazonaws.com/latest.json get /prefunded_accounts/{prefundedAccountID} Retrieve a Prefunded Account # Get funding history of a Prefunded Account Source: https://apidocs.bridge.xyz/api-reference/prefunded-accounts/get-funding-history-of-a-prefunded-account https://withbridge-image1-sv-usw2-monorail-openapi.s3.amazonaws.com/latest.json get /prefunded_accounts/{prefundedAccountID}/history Retrieve the funding events and returns for a Prefunded Account # Get a history of a customer's rewards Source: https://apidocs.bridge.xyz/api-reference/rewards/get-a-history-of-a-customers-rewards https://withbridge-image1-sv-usw2-monorail-openapi.s3.amazonaws.com/latest.json get /rewards/{currency}/customer/{customerID}/history Get a history of a customer's rewards. Data is calculated with a t-2 business day lag; the most recent available record corresponds to two business days prior to the current date. # Get a summary of a customer's rewards Source: https://apidocs.bridge.xyz/api-reference/rewards/get-a-summary-of-a-customers-rewards https://withbridge-image1-sv-usw2-monorail-openapi.s3.amazonaws.com/latest.json get /rewards/{currency}/customer/{customerID} Get a summary of a customer's rewards # Get a summary of all rewards for a given stablecoin Source: https://apidocs.bridge.xyz/api-reference/rewards/get-a-summary-of-all-rewards-for-a-given-stablecoin https://withbridge-image1-sv-usw2-monorail-openapi.s3.amazonaws.com/latest.json get /rewards/{currency} Get a summary of all rewards for a given stablecoin # Get daily reward history for a stablecoin Source: https://apidocs.bridge.xyz/api-reference/rewards/get-daily-reward-history-for-a-stablecoin https://withbridge-image1-sv-usw2-monorail-openapi.s3.amazonaws.com/latest.json get /rewards/{currency}/history Returns paginated daily reward records with per-provider breakdowns, AUM, fees, and distribution status. Data is calculated with a t-2 business day lag; the most recent available record corresponds to two business days prior to the current date. # Simulate KYC approval (sandbox only) Source: https://apidocs.bridge.xyz/api-reference/sandbox/simulate-kyc-approval-sandbox-only https://withbridge-image1-sv-usw2-monorail-openapi.s3.amazonaws.com/latest.json post /customers/{customerID}/simulate_kyc_approval Simulates a KYC/KYB approval for a customer in the sandbox environment. This endpoint is not available in production. Mimics what happens when a customer completes identity verification through the KYC provider in production: - Sets the customer's KYC status to `approved` - Populates required entity data (name, address, date of birth) using any data already on the customer, falling back to sandbox defaults - Approves any pending endorsements, enabling the customer to initiate transfers Useful for testing the full customer lifecycle without integrating with a real KYC provider. # Create a Static Memo Source: https://apidocs.bridge.xyz/api-reference/static-memos/create-a-static-memo https://withbridge-image1-sv-usw2-monorail-openapi.s3.amazonaws.com/latest.json post /customers/{customerID}/static_memos Create a Static Memo for the specified customer # Get a Static Memo Source: https://apidocs.bridge.xyz/api-reference/static-memos/get-a-static-memo https://withbridge-image1-sv-usw2-monorail-openapi.s3.amazonaws.com/latest.json get /customers/{customerID}/static_memos/{staticMemoID} Retrieve the Static Memo object from the passed ID # List Static Memos Source: https://apidocs.bridge.xyz/api-reference/static-memos/list-static-memos https://withbridge-image1-sv-usw2-monorail-openapi.s3.amazonaws.com/latest.json get /static_memos List all Static Memo objects # List Static Memos for Customer Source: https://apidocs.bridge.xyz/api-reference/static-memos/list-static-memos-for-customer https://withbridge-image1-sv-usw2-monorail-openapi.s3.amazonaws.com/latest.json get /customers/{customerID}/static_memos List all Static Memo objects for a customer # Static Memo Activity Source: https://apidocs.bridge.xyz/api-reference/static-memos/static-memo-activity https://withbridge-image1-sv-usw2-monorail-openapi.s3.amazonaws.com/latest.json get /customers/{customerID}/static_memos/{staticMemoID}/history History of activity for a Static Memo # Static Memo Activity Across All Customers Source: https://apidocs.bridge.xyz/api-reference/static-memos/static-memo-activity-across-all-customers https://withbridge-image1-sv-usw2-monorail-openapi.s3.amazonaws.com/latest.json get /static_memos/history History of activity across all customers and Virtual Accounts # Update a Static Memo Source: https://apidocs.bridge.xyz/api-reference/static-memos/update-a-static-memo https://withbridge-image1-sv-usw2-monorail-openapi.s3.amazonaws.com/latest.json put /customers/{customerID}/static_memos/{staticMemoID} Update instructions for an existing Static Memo # Create a transfer Source: https://apidocs.bridge.xyz/api-reference/transfers/create-a-transfer https://withbridge-image1-sv-usw2-monorail-openapi.s3.amazonaws.com/latest.json post /transfers Create a transfer. If this transfer cannot be created because the funding source is temporarily busy processing another update, this endpoint may return `409 resource_state_conflict`. This is a transient, retryable response. You may safely retry the same request with the same `Idempotency-Key`. # Delete a transfer Source: https://apidocs.bridge.xyz/api-reference/transfers/delete-a-transfer https://withbridge-image1-sv-usw2-monorail-openapi.s3.amazonaws.com/latest.json delete /transfers/{transferID} Delete a transfer that was previously created. Must be in the awaiting_funds state. # Execute a pending USDT trade on a transfer Source: https://apidocs.bridge.xyz/api-reference/transfers/execute-a-pending-usdt-trade-on-a-transfer https://withbridge-image1-sv-usw2-monorail-openapi.s3.amazonaws.com/latest.json post /transfers/{transferID}/execute Force-executes a stuck USDT-to-USD trade at the current market rate. The transfer must have a pending trade (i.e. appear in `GET /transfers/pending`). After execution, the transfer will continue processing normally with the executed market rate. # Get a transfer Source: https://apidocs.bridge.xyz/api-reference/transfers/get-a-transfer https://withbridge-image1-sv-usw2-monorail-openapi.s3.amazonaws.com/latest.json get /transfers/{transferID} Retrieve a transfer object from the passed in transfer ID # Get all static templates Source: https://apidocs.bridge.xyz/api-reference/transfers/get-all-static-templates https://withbridge-image1-sv-usw2-monorail-openapi.s3.amazonaws.com/latest.json get /transfers/static_templates # Get all transfers Source: https://apidocs.bridge.xyz/api-reference/transfers/get-all-transfers https://withbridge-image1-sv-usw2-monorail-openapi.s3.amazonaws.com/latest.json get /transfers # List transfers with pending USDT trades Source: https://apidocs.bridge.xyz/api-reference/transfers/list-transfers-with-pending-usdt-trades https://withbridge-image1-sv-usw2-monorail-openapi.s3.amazonaws.com/latest.json get /transfers/pending Returns transfers that have a stuck USDT-to-USD trade awaiting execution. Results are sorted by creation time (newest first) and paginated. Use `POST /transfers/{transferID}/execute` to force-execute a pending trade at the current market rate. # Update a transfer Source: https://apidocs.bridge.xyz/api-reference/transfers/update-a-transfer https://withbridge-image1-sv-usw2-monorail-openapi.s3.amazonaws.com/latest.json put /transfers/{transferID} Update a transfer that was previously created. Must be in the awaiting_funds state. # Submit travel rule data. Source: https://apidocs.bridge.xyz/api-reference/travel-rule/submit-travel-rule-data https://withbridge-image1-sv-usw2-monorail-openapi.s3.amazonaws.com/latest.json post /travel_rule_data/{id} Use this endpoint to submit originator, beneficiary, and transfer purpose data for travel rule compliance. # Create a Virtual Account Source: https://apidocs.bridge.xyz/api-reference/virtual-accounts/create-a-virtual-account https://withbridge-image1-sv-usw2-monorail-openapi.s3.amazonaws.com/latest.json post /customers/{customerID}/virtual_accounts Create a Virtual Account or Virtual IBAN for the specified customer # Deactivate a Virtual Account Source: https://apidocs.bridge.xyz/api-reference/virtual-accounts/deactivate-a-virtual-account https://withbridge-image1-sv-usw2-monorail-openapi.s3.amazonaws.com/latest.json post /customers/{customerID}/virtual_accounts/{virtualAccountID}/deactivate Deactivate a Virtual Account to prevent it from acceping new incoming transactions # Get a Virtual Account Source: https://apidocs.bridge.xyz/api-reference/virtual-accounts/get-a-virtual-account https://withbridge-image1-sv-usw2-monorail-openapi.s3.amazonaws.com/latest.json get /customers/{customerID}/virtual_accounts/{virtualAccountID} Retrieve the Virtual Account object from the passed ID # List Virtual Accounts Source: https://apidocs.bridge.xyz/api-reference/virtual-accounts/list-virtual-accounts https://withbridge-image1-sv-usw2-monorail-openapi.s3.amazonaws.com/latest.json get /virtual_accounts List all Virtual Account objects # List Virtual Accounts by Customer Source: https://apidocs.bridge.xyz/api-reference/virtual-accounts/list-virtual-accounts-by-customer https://withbridge-image1-sv-usw2-monorail-openapi.s3.amazonaws.com/latest.json get /customers/{customerID}/virtual_accounts List all Virtual Account objects for a customer # Reactivate a Virtual Account Source: https://apidocs.bridge.xyz/api-reference/virtual-accounts/reactivate-a-virtual-account https://withbridge-image1-sv-usw2-monorail-openapi.s3.amazonaws.com/latest.json post /customers/{customerID}/virtual_accounts/{virtualAccountID}/reactivate Reactivate a previously deactivated Virtual Account # Update a Virtual Account Source: https://apidocs.bridge.xyz/api-reference/virtual-accounts/update-a-virtual-account https://withbridge-image1-sv-usw2-monorail-openapi.s3.amazonaws.com/latest.json put /customers/{customerID}/virtual_accounts/{virtualAccountID} Update instructions for an existing Virtual Account # Virtual Account Activity Source: https://apidocs.bridge.xyz/api-reference/virtual-accounts/virtual-account-activity https://withbridge-image1-sv-usw2-monorail-openapi.s3.amazonaws.com/latest.json get /customers/{customerID}/virtual_accounts/{virtualAccountID}/history History of activity for a Virtual Account # Virtual Account Activity Across All Customers Source: https://apidocs.bridge.xyz/api-reference/virtual-accounts/virtual-account-activity-across-all-customers https://withbridge-image1-sv-usw2-monorail-openapi.s3.amazonaws.com/latest.json get /virtual_accounts/history History of activity across all customers and Virtual Accounts # Create a webhook endpoint Source: https://apidocs.bridge.xyz/api-reference/webhooks/create-a-webhook-endpoint https://withbridge-image1-sv-usw2-monorail-openapi.s3.amazonaws.com/latest.json post /webhooks Create a new webhook endpoint to receive events from Bridge. Webhook endpoints begin in a disabled state and can be enabled with a PUT request. A maximum of 5 webhooks can be active or disabled at one time. Webhook endpoints can be created in Sandbox, but no webhook events will be sent. # Delete a webhook Source: https://apidocs.bridge.xyz/api-reference/webhooks/delete-a-webhook https://withbridge-image1-sv-usw2-monorail-openapi.s3.amazonaws.com/latest.json delete /webhooks/{webhookID} Delete the specified webhook object. This webhook will no longer be accessible via API. # Get all webhook endpoints Source: https://apidocs.bridge.xyz/api-reference/webhooks/get-all-webhook-endpoints https://withbridge-image1-sv-usw2-monorail-openapi.s3.amazonaws.com/latest.json get /webhooks Get the full list of active and disabled webhook endpoints configured on Bridge # List upcoming events Source: https://apidocs.bridge.xyz/api-reference/webhooks/list-upcoming-events https://withbridge-image1-sv-usw2-monorail-openapi.s3.amazonaws.com/latest.json get /webhooks/{webhookID}/events List the next 10 events that will be delivered to the specified webhook. # List webhook events Source: https://apidocs.bridge.xyz/api-reference/webhooks/list-webhook-events https://withbridge-image1-sv-usw2-monorail-openapi.s3.amazonaws.com/latest.json get /webhook_events List all webhook events for your account. Events are ordered by their event_sequence in ascending order. Results are limited to the events created in last 90 days. # Send event Source: https://apidocs.bridge.xyz/api-reference/webhooks/send-event https://withbridge-image1-sv-usw2-monorail-openapi.s3.amazonaws.com/latest.json post /webhooks/{webhookID}/send Send an event to the specified webhook endpoint. This will not effect other events in the delivery queue. This operation is possible for both active and disabled webhook endpoints. # Update a webhook Source: https://apidocs.bridge.xyz/api-reference/webhooks/update-a-webhook https://withbridge-image1-sv-usw2-monorail-openapi.s3.amazonaws.com/latest.json put /webhooks/{webhookID} Update the specified webhook object # View logs Source: https://apidocs.bridge.xyz/api-reference/webhooks/view-logs https://withbridge-image1-sv-usw2-monorail-openapi.s3.amazonaws.com/latest.json get /webhooks/{webhookID}/logs Display the most recent logs for deliveries to the specified webhook. # Changelog Source: https://apidocs.bridge.xyz/changelog/changelog ## **USDT on Tempo and USDC on XDC support in Orchestration APIs** We've added support for USDT on Tempo (`usdt.tempo`) and USDC on XDC (`usdc.xdc`) in our Orchestration APIs. ## **Webhook behavior improvement** Starting 06/29, we're making a small improvement to how reactivated webhook endpoints behave. Previously, when a developer reactivated a webhook endpoint that had been deactivated, Bridge would replay all the webhooks that had queued up during the deactivation period. This could create bottlenecks and throughput issues. Going forward, reactivating a webhook endpoint will only deliver webhooks from that point onward—no backlog replay. This makes the behavior more intuitive and avoids the throughput problems. If you would like to replay webhooks, you can list upcoming webhook events and resend events. ## **Webhook behavior improvement on reactivation** Starting 06/29, we're making a small improvement to how reactivated webhook endpoints behave. Previously, when a developer reactivated a webhook endpoint that had been deactivated, Bridge would replay all the webhooks that had queued up during the deactivation period. This could create bottlenecks and throughput issues. Going forward, reactivating a webhook endpoint will only deliver webhooks from that point onward—no backlog replay. This makes the behavior more intuitive and avoids the throughput problems. If you would like to replay webhooks, you can [list upcoming webhook events](/api-reference/webhooks/list-upcoming-events) and [resend events](/api-reference/webhooks/send-event). ## **Issuance Rewards History API** A new endpoint gives you visibility into daily reward accruals for your stablecoin issuance program: * `GET /v0/rewards/{currency}/history` — paginated daily reward records across your entire program, including per-provider breakdowns, AUM, fees, and distribution status. Data is calculated with a t-2 business day lag; the most recent available record corresponds to two business days prior to the current date. Results are paginated with a configurable page size (up to 90 days) and cursor-based pagination. Learn more in the [Rewards API reference](/api-reference/rewards). ## **Prefunded wallet activity webhooks** Prefunded wallets now support `bridge_wallet.activity` webhooks for balance activity. Subscribe your webhook endpoint to `bridge_wallet.activity` to track when a prefunded wallet is credited or debited using the same activity model as Bridge Wallet history. Fiat-funded prefunded wallets may still emit `virtual_account.activity` or `static_memo.activity` webhooks for the fiat instruction lifecycle. Use `bridge_wallet.activity` for the wallet balance event. ## **Time filtering for Bridge Wallet history** The Bridge Wallet history API now supports `starting_time` and `ending_time` query parameters, letting you retrieve wallet activity within a specific time window. Times must be provided in ISO 8601 format. `starting_time` is inclusive and `ending_time` is exclusive. You can also combine these filters with event ID cursors to paginate within the filtered results. Learn more in the [Bridge Wallet history API](/api-reference/bridge-wallets/get-transaction-history-for-a-bridge-wallet). ## **return\_instructions for Liquidation Addresses** Liquidation Addresses now support a `return_instructions` field, giving you control over where Bridge sends funds when a transaction fails or is returned. `return_instructions` accepts an `address` and an optional `memo`, replacing the deprecated `return_address` field. For Stellar addresses, a `memo` is required to route funds to the correct end-customer. `return_instructions` and `return_address` are mutually exclusive — set one or the other, not both. The deprecated `return_address` field continues to work for non-Stellar chains but will be removed in a future release. ## **FedNow onramps are now live ⚡️** Your customers can now receive funds via FedNow – settling in seconds, 24/7/365 – with no integration changes required on your end. **What this means for you** * **Instant settlement:** Customers can fund time-sensitive actions without waiting hours or days for funds to clear * **Better liquidity management:** Faster settlement means less capital sitting idle in prefunded accounts **How it works**
FedNow is automatically enabled across your existing virtual accounts and transfers. As more institutions adopt FedNow (1,500+ and growing), a portion of inbound USD wire and ACH payments will begin settling instantly via FedNow. The sending institution determines which rail is used – not Bridge – and we expect this transition to happen gradually over time. To check whether a payment arrived via FedNow or another rail, look at the `payment_received_rail` field on the Transfer source, or the `payment_rail` field on Virtual Account source data. Learn more [here](/get-started/guides/move-money/usd-integration-guide).
## **Bridge Wallet activity webhooks and history API** Bridge Wallets now support activity webhooks and history API access. Developers can subscribe to `bridge_wallet.activity` and use `GET /v0/customers/{customerId}/wallets/{walletId}/history` to track deposits, direct deposits, withdrawals, returns, and undeliverables in one consistent activity model. Enable webhook delivery by creating or updating a webhook endpoint subscribed to `bridge_wallet.activity`. Learn more in the [Webhook APIs](/api-reference/webhooks/get-all-webhook-endpoints) and [Bridge Wallet history API](/api-reference/bridge-wallets/get-transaction-history-for-a-bridge-wallet). ## **New Deactivate Endpoint for External Accounts** We've added a new `POST /v0/customers/{customer_id}/external_accounts/{id}/deactivate` endpoint that deactivates an external account while keeping it visible in list and retrieve APIs. Deactivated accounts can be reactivated later via the existing `reactivate` endpoint. Previously, the `DELETE` endpoint was labeled as "Deactivate" in our API documentation, but it actually soft deletes the record and hides it from list and retrieve APIs. We've corrected the documentation to accurately reflect this behavior — `DELETE` is now described as deleting the external account. If you need to temporarily disable an external account while preserving access to the record, use the new `deactivate` endpoint instead of `DELETE`. ## **USDC and usDCBL on Aptos support** Bridge now supports USDC and usDCBL on Aptos across all orchestration products including virtual accounts and transfers. View all supported payment routes [here](/get-started/introduction/what-we-support/payment-routes). ## **Transfers now reflect the rail the payment was received on** The rail on which Bridge actually received funds for this transfer. Populated once funds have been received. This may differ from `payment_rail`, which reflects the rail the transfer was created with. For example, a transfer created with `payment_rail: wire` will have `payment_received_rail: ach` if the funds arrive via ACH. ## **USDC on Sui support** Bridge now supports USDC on Sui across all orchestration products including virtual accounts and transfers. View all supported payment routes [here](/get-started/introduction/what-we-support/payment-routes). ## **Memoless Stellar deposits** Stellar deposits now include the muxed address, `memoless_to_address`, letting customers send funds without needing to attach a memo. The existing memo-based flow remains available for wallets and exchanges that don't yet support muxed addresses. This is a non-breaking change. Please read more [here](/get-started/guides/move-money/supported-blockchains). ## **USDC on HyperEVM Support** Bridge now supports USDC on HyperEVM across all orchestration products including virtual accounts and transfers. Available to all developers. ## **\[Beta] Support for fixed fees for Virtual Account onramps** We’re excited to announce support for fixed fees on Virtual Account onramps, giving developers more flexibility in how they monetize on our platform. In addition to fixed fees, developers can now configure fees by rail and define minimum and maximum fee bounds. This feature is currently available in gated beta. If you’re interested in getting access before we make this feature generally available, please contact us to join our waitlist. Learn more about how you can monetize on our platform [here](/platform/orchestration/fees-and-mins/devfees#developer-fee-configuration-beta-feature). ## **Bridge now supports Tempo Mainnet** All developers can now use the [Tempo blockchain](https://tempo.xyz/) across Bridge's full suite of products including onramps, offramps, wallets, virtual accounts, issuance, and cards. Tempo is purpose-built for payments at scale — with a dedicated payments lane for predictable low fees, instant settlement, and native payment features — powering agentic payment flows, global payouts, supplier payments, remittances, and more. [Read our integration guide](/get-started/guides/move-money/tempo-integration-guide) to learn more. ## **Refund Status Enhancements** We've added two new payment states to give you better visibility into payment returns and refunds: * `refund_in_flight` — refund is in progress * `refund_failed` — refund attempt was unsuccessful, see the return\_reason field to see more details These states appear in Transfers, Virtual Accounts, and Liquidation Address APIs and in the Dashboard, API responses, and webhooks. This is an additive, non-breaking update. ## **Non-Breaking Improvements to Customer Responses** Effective 05/01/2026, we're making additive updates to the `v0/customers` endpoint and customer webhook payloads: * A new `client_reference_id` field will be added to `v0/customers` responses and customer webhook events. * Some `rejection_reasons` values (`developer_reason`, `reason`) may change. Developers should ensure webhook integrations tolerate new fields and treat rejection reason strings as free-form rather than hard-coding them. This is a non-breaking update. ## **Prefunded Account API Deprecation** As of Mar 24, 2026, Prefunded Accounts are deprecated in Bridge’s APIs. We will continue to support Prefunded APIs indefinitely, but incremental improvements will be driven through Bridge Wallets. Read more [here](/platform/wallets/prefunded_wallets). ## **Scoped API Keys** You can now create API keys with granular, resource-level permissions — restricting access to only the resources your integration needs (customers, transfers, wallets, webhooks, etc.). Scoped keys are immutable: permissions are fixed at creation and won't automatically expand as new features ship. Create scoped keys from the API Keys page in the [Dashboard](https://dashboard.bridge.xyz). ## **GBP On/Offramps via Faster Payments — Now Generally Available** GBP on/offramping via the UK's Faster Payment System (FPS) is now generally available. Your individual and business customers can: * Onramp to a unique UK virtual account number from 1st party deposits and 3rd party payments from approved businesses. * Offramp to 1st and 3rd party UK bank accounts. Customers must have the `faster_payments` endorsement. Contact your account manager or [sales@bridge.xyz](mailto:sales@bridge.xyz) to enable. [Read the integration guide](/get-started/guides/move-money/gbp_fps_integration_guide) to learn more. ## **USDT on Solana Support** Bridge now supports USDT on Solana across all orchestration products including virtual accounts and transfers. Available to all developers. Existing USDT pricing applies. ## **USDT On/Offramps with MXN and BRL** Bridge now supports onramps and offramps to/from USDT using MXN (via SPEI) and BRL (via Pix) payment rails. Supported on Ethereum, Plasma, and Tron. Rates and pricing follow existing MXN/BRL terms. Requires MXN/BRL addendum and SPEI/Pix endorsements. ## **Tron Support in Custodial Wallets** Bridge custodial wallets now support custody and on-chain management of USDT on Tron. Fees aligned with existing USDT pricing. ## **External Account Webhook Support** We are adding support for External Account webhooks on 03/09/2026. We will be supporting `created` and `updated` webhooks. ## **Additions to ExternalAccount Fields** We are adding the below fields to the External Account endpoints on 03/09/2026. 1. `deactivation_reason` You can now see why an external account was deactived. Refer to the API for details at [Retrieve an External Account object](/api-reference/external-accounts/retrieve-an-external-account-object). 2. `deactivation_details` You can now see any additional details, if available, as to why an external account was deactived. Refer to the API for details at [Retrieve an External Account object](/api-reference/external-accounts/retrieve-an-external-account-object). *Please note this data will only appear for external accounts that were deactivated after 02/26/2026* ## **USDT on Ethereum in Custodial Wallets** Bridge custodial wallets now support USDT on Ethereum. Available to all developers, with fees aligned with existing pricing. ## **Celo blockchain onramp & offramp support** Bridge now supports onramps and offramps for USDC.Celo. Check out all of our supported orchestration routes [here](https://apidocs.bridge.xyz/get-started/introduction/what-we-support/payment-routes#supported-fiat-rails). ## **Enhanced crypto return support via Transfers API** You can now set return instructions on Transfers to control where crypto deposits are refunded. If a crypto deposit associated with a Transfer needs to be returned, Bridge will send the funds to the address specified in return\_instructions. This is a more flexible alternative to a global crypto return policy, since it lets you configure return destinations per payment—without requiring you to route funds through an omnibus wallet or "be in the flow of funds." Learn more about crypto returns [here](/platform/orchestration/more/returns#returning-crypto-deposits). ## **Fixed Outputs — Fixed Destination Amounts in Transfers** You can now specify a fixed destination-currency amount when creating a Transfer. Bridge automatically calculates the required source amount based on real-time exchange rates, guaranteeing your recipient receives exactly the amount you specify. Useful for payroll, bill payments, and vendor disbursements. Supported currencies: USDC/USDB to EUR, MXN, BRL, GBP (offramps) and MXN, BRL, EUR, GBP to USDC/USDB (onramps). [Read the integration guide](/get-started/guides/move-money/fixed_outputs_integration_guide) to learn more. ## **EURC on Ethereum Support** Bridge now supports EURC on Ethereum across all Orchestration APIs including virtual accounts and transfers. Available to all developers. Existing orchestration pricing applies. ## **USDT on Plasma Support** Bridge now supports USDT on Plasma across all Orchestration APIs including virtual accounts and transfers. Available to all developers. Existing USDT pricing applies. ## **GBP onramps and offramps via Faster Payments (Beta)** Bridge now supports GBP (British Pound) onramps and offramps via UK's Faster Payment System (FPS) in beta. Your individual and business customers can now: * Onramp to a unique UK virtual account number from 1st party deposits and 3rd party payments from approved businesses (Individual 3rd party payments not supported). * Offramp to 1st and 3rd party UK bank accounts, withdrawing funds or completing payments to individuals and businesses. Customers must have the *faster\_payments* endorsement. For more information and to start integrating, please refer to our [GBP FPS Integration Guide](/get-started/guides/move-money/gbp_fps_integration_guide#transfer-onramp). ## **USDG (Global Dollar) on Solana Support** Bridge now supports USDG (Global Dollar) on Solana across all Orchestration APIs including virtual accounts and transfers. USDG is a regulated stablecoin issued with support from the Global Dollar Network. Available to all developers, with existing orchestration pricing. ## 🇧🇷 **BRL onramps and offramps via Pix now available** Create Pix virtual accounts to onramp BRL deposits from external bank accounts and receive payments from approved third parties. You can also offramp BRL to any recipient instantly with Pix payments. If you’d like to enable BRL capabilities, refer to our [integration guide](/get-started/guides/move-money/brl_pix_integration_guide). ## **🔁 Reverse Exchange Rates Now Supported** The Exchange Rates API now supports fetching rates in both directions for all supported fiat pairs.
**Previously:** USD → EUR, USD → MXN, USD → BRL
**Now also:** EUR → USD, MXN → USD, BRL → USD You can use the same request shape — no code changes required.
## **💸 New Payment State: missing\_return\_policy** Bridge will now mark crypto deposits with a new status — `missing_return_policy` — when a refund is required but no return policy is configured. To resolve, [configure a return policy](/platform/orchestration/more/returns) via API or dashboard, and we’ll auto-initiate the refund to the sender’s original address. ## **New dashboard updates!** **Account Page Enhancements** * You can now manage **admin permissions** for your team directly from the **Account** page — no support ticket needed. * Find a summary of **monthly invoices** under the **Billing** tab, with links to download detailed PDFs. **Help & Onboarding Resources** * The left nav now includes quick access to our **Help Center**. * A detailed **Onboarding Guide** is available to help new developers create customers and send payments. **\[Beta] New Payments Module** * Our new payments experience is rolling out in dashboard (public beta). * We welcome your feedback! ## **Handling Proof of Address Requests** We will be more consistently requesting proof of address when we detect conflicting location signals in a user's KYC/KYB. If using the API, you can tell if a customer needs to submit proof of address by looking at the endorsements section of a customer response, where the requirement will show up as missing ```json theme={null} { "endorsements": [ { "name": "base", "status": "incomplete", "requirements": { ... "missing": { "all_of": [ "proof_of_address", ... ] }, ... }, }, ``` To submit a proof of address document via API, include `documents` in your customer put/post request body, with an entry where the purpose is `proof_of_address` ## **Use Your Bridge Wallet to Automate Returns** You can now use a Bridge Wallet to **seamlessly fund fiat returns.** Bridge’s Transfer API already lets you return ACH, Wire, or SEPA deposits in cases of recalls, rejections, or refunds. Now, you can use a Bridge Wallet to **fund those returns directly**—no need to wait for a fresh deposit to initiate a payout. * Pre-fund your wallet at any time * Return funds instantly when needed * Simplify your flows Learn more [here](/platform/orchestration/more/returns)! ## **Additions to LiquidationAddress, VirtualAccount, and StaticMemo Fields** We have added the below fields to Bridge endpoints. 1.`customer_id` added to `LiquidationAddress` You can now identify which customer owns a liquidation address. Refer API reference at [Get a liquidation address](/api-reference/liquidation-addresses/get-a-liquidation-address). 2. `created_at`**added to VirtualAccount and StaticMemo** Timestamp fields are now included to help with auditing and sorting. Refer API reference at [Get a Virtual Account](/api-reference/virtual-accounts/get-a-virtual-account). 3.`source_deposit_instructions.payment_rails` added to `StaticMemo` Includes the source details in the static memo response (supported rails right now are ACH & wire). Refer API reference at [Get a Static Memo](/api-reference/static-memos/get-a-static-memo). 4.`destination_payment_rail`**now included in history records** The `StaticMemo` and `VirtualAccount` objects returned in history endpoints now show the `destination_payment_rail` (e.g. USD.USDC.polygon) once the payment completes successfully. Refer API reference at [Virtual Account Activity](/api-reference/virtual-accounts/virtual-account-activity) and [Static Memo Activity](/api-reference/static-memos/static-memo-activity) # Cards Source: https://apidocs.bridge.xyz/get-started/guides/cards/overview Bridge cards let customers spend stablecoin balances virtually anywhere in the world that accept Visa - with a virtual card, a physical card, or a mobile wallet. Using Bridge APIs, you can seamlessly provision new cards for your customers, manage balances, and more. Bridge cards are: * **Multi-market:** Launch a card product in multiple markets with a single integration. * **Flexible:** Bridge supports custodial and non-custodial wallets. * **Integrated:** Use card issuing with virtual accounts and wallets to build seamless experiences around sending, receiving, storing and spending stablecoins. * **Revenue generating:** Generate revenue based on your customers’ card spend. Earn a share of profit earned from the card program. Refer the [Cards](/platform/cards/overview/overview) section for more in depth details. # Spend wallet balances using a card Source: https://apidocs.bridge.xyz/get-started/guides/cards/spend You can issue a virtual or physical card that spends directly from a Bridge-managed wallet or external crypto wallet. Here's how to set that up. ![](https://files.readme.io/abd125101ad0ef13134d7af37f6937eaaaa254bb7824de1552694da371805f0c-image.png) *** ### Create a wallet First, create a Bridge wallet (optional if you're using an external wallet). Use the wallet’s `address` when issuing a card. ```bash Request expandable theme={null} curl --request POST \ --url https://api.bridge.xyz/v0/customers//wallets \ --header 'Api-Key: ' \ --header 'Idempotency-Key: ' \ --header 'Content-Type: application/json' \ --data '{ "chain": "solana" }' ``` ```json Response expandable theme={null} { "id": "wallet_abc123", "address": "4oG1sWkP8vcrnhbkzZc1m9RTT2VUjZHKx92qiVFK7FuZ", "chain": "solana" } ``` Keep note of the wallet ID and address as you will need this in the next step. ### Fund the wallet The below example uses Bridge's transfer API to fund the wallet. There are a variety of methods to fund the wallet using Bridge's orchestration APIs (virtual accounts, transfers, or liquidation addresses). Learn more at [Bridge Wallets](/platform/wallets/overview). ```bash expandable theme={null} curl --location --request POST 'https://api.bridge.xyz/v0/transfers' \ --header 'Api-Key: ' \ --header 'Idempotency-Key: ' \ --data-raw '{ "on_behalf_of": "cust_alice", "source": { "payment_rail": "ach_push", "currency": "usd", }, "destination": { "payment_rail": "solana", "currency": "usdb", "bridge_wallet_id": "wallet_abc123" } "features": { "flexible_amount": true // allows for any deposit amount } }' ``` Now create a card account tied to a Bridge wallet. ```bash expandable theme={null} curl --request POST \ --url https://api.bridge.xyz/v0/customers/customerID/card_accounts \ --header 'accept: application/json' \ --header 'content-type: application/json' \ --data '{ "currency": "usdb", "chain": "solana", "crypto_account": { "type": "bridge_wallet", "address": "4oG1sWkP8vcrnhbkzZc1m9RTT2VUjZHKx92qiVFK7FuZ" } }' ``` ### Retrieve card details Access card metadata, expiration, and access a secure image of the card. ```bash Request expandable theme={null} curl -X GET 'https://api.bridge.xyz/v0/customers//card_accounts/' \ --header 'Api-Key: ' ``` ```json Response expandable theme={null} { "id": "XXX-YYY", "status": "active", "card_image_url": "https://...", "card_details": { "last_4": "1264", "expiry": "10/24", "bin": "44325280" } } ``` You can now share these card details with your customer to **start spending!** Now that you have the details for your card, you can use it to make transactions! Use your Bridge issued card like any normal card in e-commerce checkout flows. Subscribe to the `card_transaction.created` webhook to see newly created transactions. ```json theme={null} { "event_type": "card_transaction.created", "event_object": { "status": "approved", "amount": "-10.25", "merchant_name": "ROCKET RIDES", "authorized_at": "2025-02-04T05:19:25.000Z" } } ``` Subscribe to the `card_transaction.updated.status_transitioned` webhook to see settled transactions. ```json theme={null} { "event_type": "card_transaction.updated.status_transitioned", "event_object": { "status": "settled", "settled_amount": "-10.25", "posted_at": "2025-02-06T03:01:30.000Z" }, "event_object_changes": { "status": ["approved", "settled"], "settled_amount": [null, "-10.25"], "posted_at": [null, "2025-02-06T03:01:30.000Z"] } } ``` Or you can fetch transactions via the [Retrieve card transactions](/api-reference/cards/retrieve-card-transactions) API. *** ## Money Movement Overview ![](https://files.readme.io/6929a243e3e872e7d1dcfd126c26611127127713f65bd0f0c92e4fd921ec4642-image.png) ## Resources Check out the [Cards](/platform/cards/overview/overview) section for more in depth details! # Cross-border payments Source: https://apidocs.bridge.xyz/get-started/guides/common-use-cases/cross-border-payments Enable customers to make cross-border payments to suppliers by creating a virtual account and wallet for each customer and an external account that stores a supplier’s bank details. Fiat deposits into the virtual account are converted to stablecoins and sent to the customer’s wallet. Use the Transfers API to convert the stablecoins to local currency and pay each supplier. Cross Border Payments.png *** ## Step 1: Generate your API Keys Head over to [**dashboard.bridge.xyz**](https://dashboard.bridge.xyz/). Once logged in, click on the “API Keys” tab on the top menu bar and generate a new API key. Bridge will make your **API key available only once**, so make sure to **immediately copy and save the key safely and securely**. \ \ Your key is used to authenticate into our APIs and is highly sensitive. If it ever gets compromised, you can immediately revoke key access from our dashboard and generate a new key. ## Step 2: Onboard a customer Create a customer ID for each business that needs to pay suppliers. Customers will need to accept our terms of service and complete KYC. Check out this [guide](/get-started/introduction/quick-start/create-your-first-customer) for a full in depth explanation on onboarding customers. The below example walks you through using a KYC link to onboard your customer. ```bash Request theme={null} curl --location --request POST 'https://api.bridge.xyz/v0/kyc_links' \ --header 'Content-Type: application/json' \ --header 'Api-Key: ' \ --header 'Idempotency-Key: ' \ --data-raw '{ "full_name": "John Doe", "email": "johndoe@example.com", "type": "individual" }' ``` ```json Response theme={null} { "id": "uuid", "full_name": "John Doe", "email": "johndoe@example.com", "type": "individual", // or "business" "kyc_link": "https://bridge.withpersona.com/verify?", "tos_link": "https://dashboard.bridge.xyz/accept-terms-of-service?", "kyc_status": "not_started", // or "under_review", "incomplete", "approved" or "rejected" "rejection_reasons": [], "tos_status": "pending", // or "approved" "created_at": "2025-07-16T18:28:25.970Z", "customer_id": "customer_id", "persona_inquiry_type": "gov_id_db" } ``` Guide the user through: 1. Visiting the `tos_link` and accepting terms of service 2. Completing identity verification via the `kyc_link` This process typically takes less than a minute and updates automatically once complete. ## Step 3: Create a wallet Create a wallet for your customer to hold stablecoins and send supplier payments from. The below example explains how to create a Bridge wallet associated with a customer object. ```bash Request theme={null} curl --request POST \ --url https://api.bridge.xyz/v0/customers//wallets \ --header 'Api-Key: ' \ --header 'Idempotency-Key: ' \ --header 'Content-Type: application/json' \ --data-raw '{ "chain": "solana" }' ``` ```json Response theme={null} { "id": "wallet_123", "chain": "solana", "address": "4oG1sWkP8vcrnhbkzZc1m9RTT2VUjZHKx92qiVFK7FuZ", "created_at": "2025-07-15T18:00:00Z" } ``` Use the `bridge_wallet_id` when referencing the wallet in other Bridge APIs. Check out this [guide](/get-started/guides/wallets/overview) for more information on using Bridge wallets. ## Step 4: Create a virtual account Create a USD or EUR account for the customer. Provide them with the bank instructions so they can deposit supplier payments. Deposits are converted to stablecoins and held in their wallet. Use the [Virtual Accounts](/api-reference/virtual-accounts/create-a-virtual-account) API to provision permanent fiat deposit addresses for your customers. You define the `source` currency for the account and configure the `destination` to specify where Bridge should deliver the converted funds. Bridge handles the fiat-to-crypto conversion and sends the funds on-chain automatically. ```bash Request theme={null} curl --location --request POST 'https://api.bridge.xyz/v0/customers//virtual_accounts' \ --header 'Content-Type: application/json' \ --header 'Api-Key: ' \ --header 'Idempotency-Key: ' \ --data-raw '{ # The source object specifies a USD virtual account. "source": { "currency": "usd", }, # The destination object instructs Bridge where to send the USD deposits to. # Bridge will automatically handle converting and sending USD to the crypto destination. "destination": { "payment_rail": "ethereum", "currency": "usdc", "address": "0x3f5CE5FBFe3E9af3971dD833D26BA9b5C936f0bE" }, # You can specifcy an optional developer fee to monetize on transactions. "developer_fee_percent": "1.0" // 1%. }' ``` ```json Response theme={null} { "id": "1a400dae-f7fc-4f75-8105-212a14d4132d", "status": "activated", "developer_fee_percent": "1.0", "customer_id": "23c2d200-4c00-4c5a-b31a-00d035d7e0ae", "created_at": "2025-07-04T22:10:34.564Z", "source_deposit_instructions": { "currency": "usd", "bank_name": "Lead Bank", "bank_address": "1801 Main St., Kansas City, MO 64108", "bank_routing_number": "101019644", "bank_account_number": "215268120000", "bank_beneficiary_name": "Ada Lovelace", "bank_beneficiary_address": "923 Folsom Street, 302, San Francisco, California 941070000, US", "payment_rail": "ach_push", "payment_rails": [ "ach_push", "wire" ] }, "destination": { "currency": "usdc", "payment_rail": "ethereum", "address": "0x3f5ce5fbfe3e9af3971dd833d26ba9b5c936f0be" } } ``` ```bash Request theme={null} curl --location --request POST 'https://api.bridge.xyz/v0/customers//virtual_accounts' \ --header 'Content-Type: application/json' \ --header 'Api-Key: ' \ --header 'Idempotency-Key: ' \ --data-raw '{ # The source object specifies a SEPA virtual IBAN. "source": { "currency": "eur", }, # The destination object instructs Bridge where to send the EURO deposits to. # Bridge will automatically handle converting and sending EURO to the crypto destination. "destination": { "payment_rail": "ethereum", "currency": "usdc", "address": "0x3f5CE5FBFe3E9af3971dD833D26BA9b5C936f0bE" }, # You can specifcy an optional developer fee to monetize on transactions. "developer_fee_percent": "1.0" // 1%. }' ``` ```json Response theme={null} { "id": "393c6358-4c19-4cb7-bbfa-d4a56be58309", "status": "activated", "developer_fee_percent": "1.0", "customer_id": "23c2d200-4c00-4c5a-b31a-00d035d7e0ae", "created_at": "2025-07-04T22:07:18.701Z", "source_deposit_instructions": { "currency": "eur", "iban": "IE90MODR14035307970528", "bic": "MODRIE00XXX", "account_holder_name": "Bridge Building Sp.z.o.o.", "bank_name": "Modulr Finance, Ireland Branch", "bank_address": "Floor 6, 2 Grand Canal Square, Dublin, Ireland", "payment_rail": "sepa", "payment_rails": [ "sepa" ] }, "destination": { "currency": "usdc", "payment_rail": "ethereum", "address": "0x3f5ce5fbfe3e9af3971dd833d26ba9b5c936f0be" } } ``` ```bash Request theme={null} curl --location --request POST 'https://api.bridge.xyz/v0/customers//virtual_accounts' \ --header 'Content-Type: application/json' \ --header 'Api-Key: ' \ --header 'Idempotency-Key: ' \ --data-raw '{ # The source object specifies a MXN virtual account. "source": { "currency": "mxn", }, # The destination object instructs Bridge where to send the MXN deposits to. # Bridge will automatically handle converting and sending MXN to the crypto destination. "destination": { "payment_rail": "ethereum", "currency": "usdc", "address": "0x3f5CE5FBFe3E9af3971dD833D26BA9b5C936f0bE" }, # You can specifcy an optional developer fee to monetize on transactions. "developer_fee_percent": "1.0" // 1%. }' ``` ```json Response theme={null} { "id": "35334433-dcee-48e8-bdc8-90171234ad00", "status": "activated", "developer_fee_percent": "1.0", "customer_id": "23c2d200-4c00-4c5a-b31a-00d035d7e0ae", "created_at": "2025-07-04T22:13:29.481Z", "source_deposit_instructions": { "currency": "mxn", "clabe": "568980546701071234", "account_holder_name": "Ada Lovelace", "payment_rails": [ "spei" ] }, "destination": { "currency": "usdc", "payment_rail": "ethereum", "address": "0x3f5ce5fbfe3e9af3971dd833d26ba9b5c936f0be" } } ``` ```bash Request theme={null} curl --location --request POST 'https://api.bridge.xyz/v0/customers//virtual_accounts' \ --header 'Content-Type: application/json' \ --header 'Api-Key: ' \ --header 'Idempotency-Key: ' \ --data-raw '{ "source": { "currency": "brl", }, # The destination object instructs Bridge where to send the BRL deposits to. # Bridge will automatically handle converting and sending USDC to the crypto destination. "destination": { "payment_rail": "ethereum", "currency": "usdc", "address": "0x3f5CE5FBFe3E9af3971dD833D26BA9b5C936f0bE" }, # You can specify an optional developer fee to monetize transactions. "developer_fee_percent": "1.0" // 1%. }' ``` ```json Response theme={null} { "id": "6e6ab621-6749-401f-b598-0c709c241696", "status": "activated", "developer_fee_percent": "0.0", "customer_id": "eeafff4b-2dbe-41f2-9444-a6e228aee975", "created_at": "2025-09-03T16:10:31.446Z", "source_deposit_instructions": { "currency": "brl", "br_code": "00020126770014br.gov.bcb.pix01366e6ab621-6749-401f-b598-0c709c2416960215Edson_Arantes5204000053039865802BR5914Bridge_Example6009Sao_Paulo622905256beca3e77fdd489289aa1daeb630416E9", "account_holder_name": "Edson Arantes do Nascimento", "payment_rails": [ "pix" ] }, "destination": { "currency": "usdc", "payment_rail": "ethereum", "address": "0x3f5CE5FBFe3E9af3971dD833D26BA9b5C936f0bE" } } ``` ```bash Request theme={null} curl --location --request POST 'https://api.bridge.xyz/v0/customers//virtual_accounts' \ --header 'Content-Type: application/json' \ --header 'Api-Key: ' \ --header 'Idempotency-Key: ' \ --data-raw '{ "source": { "currency": "gbp", }, # The destination object instructs Bridge where to send the GBP deposits to. # Bridge will automatically handle converting and sending USDC to the crypto destination. "destination": { "payment_rail": "ethereum", "currency": "usdc", "address": "0x3f5CE5FBFe3E9af3971dD833D26BA9b5C936f0bE" }, # You can specify an optional developer fee to monetize transactions. "developer_fee_percent": "1.0" // 1%. }' ``` ```json Response theme={null} { "id": "6e6ab621-6749-401f-b598-0c709c241696", "status": "activated", "developer_fee_percent": "0.0", "customer_id": "485c2b50-949c-412b-928a-f56fce42330d", "created_at": "2026-01-03T00:23:23.724Z", "source_deposit_instructions": { "currency": "brl", "account_number": "12345678", "sort_code": "123456", "account_holder_name": "Bridge Building Sp. Z.o.o.", "bank_name": "Banking Circle S.A.", "bank_address": "2 Boulevard de la Foire, L-1528 Luxembourg", "bank_beneficiary_name": "Bridge Building Sp. Z.o.o.", "bank_beneficiary_address": "2 Boulevard de la Foire, L-1528 Luxembourg", "payment_rails": [ "faster_payments" ] }, "destination": { "currency": "usdc", "payment_rail": "ethereum", "address": "0x3f5CE5FBFe3E9af3971dD833D26BA9b5C936f0bE" } } ``` ### Sharing Deposit Instructions Once a Virtual Account is created, use the `source_deposit_instructions` object in the response to share the fiat deposit details with your customer. Funds sent to those details will be automatically converted and delivered to the crypto destination you specified. ## Step 5: Create an external account Add and store a supplier's bank account details to send payments from the customer. You can add external fiat accounts through our [External account API](/api-reference/external-accounts/create-a-new-external-account) using the following request. ```bash Request expandable theme={null} curl --location 'https://api.bridge.xyz/v0/customers//external_accounts' \ --header 'Idempotency-Key: ea-7' \ --header 'Content-Type: application/json' \ --header 'Accept: application/json' \ --header 'Api-Key: ' \ --data '{ "currency": "usd", "account_type": "us", "bank_name": "Lead Bank", "account_name": "Ada Checking Account", "first_name": "Ada", "last_name": "Lovelace", "account_owner_type": "individual", // specifies an individual account "account_owner_name": "Ada Lovelace", "account": { "routing_number": "101019644", "account_number": "215268129123", "checking_or_savings": "checking" }, "address": { "street_line_1": "923 Folsom Street", "country": "USA", "state": "CA", "city": "San Francisco", "postal_code": "941070000" } }' ``` ```json Response expandable theme={null} { "id": "external-account-123", // external account id "customer_id": "23c2d462-4c69-4c5a-b31a-88d035d7e8ae", "created_at": "2025-07-05T19:03:50.819Z", "updated_at": "2025-07-05T19:03:51.251Z", "bank_name": "Lead Bank", "account_name": "Ada Checking Account", "account_owner_name": "Ada Lovelace", "active": true, "currency": "usd", "account_owner_type": "individual", "account_type": "us", "first_name": "Ada", "last_name": "Lovelace", "business_name": null, "account": { "last_4": "9123", "routing_number": "101019644", "checking_or_savings": "checking" }, "beneficiary_address_valid": true, "last_4": "9123" } ``` ```bash Request expandable theme={null} curl --location 'https://api.bridge.xyz/v0/customers//external_accounts' \ --header 'Idempotency-Key: ea-7' \ --header 'Content-Type: application/json' \ --header 'Accept: application/json' \ --header 'Api-Key: ' \ --data '{ "currency": "eur", "account_type": "iban", "bank_name": "Modulr Finance, Ireland Branch", "account_name": "GGCF Corporate", "first_name": "Ada", "last_name": "Lovelace", "iban": { "account_number": "IE04MODR99035512826162", "country": "IRL", "bic": "MODRIE22XXX" }, "address": { "street_line_1": "Floor 6, 2 Grand Canal Square, Dublin, Ireland", "country": "IRL", "city": "Dublin", "postal_code": "D02 A342" } }' ``` ```curl Response theme={null} { "id": "c8948ce6-26ac-4d37-a336-742f961a76f3", "customer_id": "23c2d400-4c69-4c5a-b31a-88d035d7e8ae", "created_at": "2025-07-05T18:45:50.728Z", "updated_at": "2025-07-05T18:45:51.373Z", "bank_name": "Modulr Finance, Ireland Branch", "account_name": "GGCF Corporate", "account_owner_name": "Ada Lovelace", "active": true, "currency": "eur", "account_owner_type": "individual", "account_type": "iban", "first_name": "Ada", "last_name": "Lovelace", "business_name": null, "iban": { "last_4": "6162", "bic": "MODRIE22XXX", "country": "IRL" } } ``` ```bash Request expandable theme={null} curl --location 'https://api.bridge.xyz/v0/customers/23c2d462-4c69-4c5a-b31a-88d035d7e8ae/external_accounts' \ --header 'Idempotency-Key: ea-6' \ --header 'Content-Type: application/json' \ --header 'Accept: application/json' \ --header 'Api-Key: ' \ --data '{ "currency": "mxn", "account_type": "clabe", "account_owner_name": "Ada Lovelace", "clabe": { "account_number": "626899715090851234" }, "account_name": "Ada Checking Account", "bank_name": "BBVA Bancomer", "first_name": "Ada", "last_name": "Lovelace", "account_owner_type": "individual", "address": { "street_line_1": "Av. Reforma", "city": "Mexico City", "state": "CDMX", "postal_code": "06600", "country": "MEX" } }' ``` ```json Response expandable theme={null} { "id": "2bb5b814-0128-49a8-977a-77b1bc1cdee2", "customer_id": "23c2d462-4c69-4c5a-b31a-88d035d7e8ae", "created_at": "2025-07-05T18:59:42.163Z", "updated_at": "2025-07-05T18:59:42.713Z", "bank_name": "BBVA Bancomer", "account_name": "Ada Checking Account", "account_owner_name": "Ada Lovelace", "active": true, "currency": "mxn", "account_owner_type": "individual", "account_type": "clabe", "first_name": "Ada", "last_name": "Lovelace", "business_name": null, "clabe": { "last_4": "1234" } } ``` ## Step 5: Make a payment Use the Transfers API to move funds from the customer’s wallet to a supplier’s bank account. You will need to call the API for each payment. ```bash Request expandable theme={null} curl --location --request POST 'https://api.bridge.xyz/v0/transfers' \ --header 'Api-Key: ' \ --header 'Idempotency-Key: ' \ --data-raw '{ "amount": "10.0", "on_behalf_of": "", "developer_fee": "0.5", "source": { "payment_rail": "bridge_wallet", "currency": "usdb", "bridge_wallet_id": "wallet_123" }, "destination": { "payment_rail": "ach", "currency": "usd", "external_account_id": "external-account-123" }, }' ``` # Dollar access Source: https://apidocs.bridge.xyz/get-started/guides/common-use-cases/dollar-access Enable customers globally to get paid, save and spend in USD or one of our many supported currencies by creating a virtual account and a wallet for each customer. Fiat deposits into the virtual account are converted to stablecoins and sent to the customer’s wallet. Dollar Access.png *** ## Step 1: Generate your API Keys Head over to [**dashboard.bridge.xyz**](https://dashboard.bridge.xyz/). Once logged in, click on the “API Keys” tab on the top menu bar and generate a new API key. Bridge will make your **API key available only once**, so make sure to **immediately copy and save the key safely and securely**. \ \ Your key is used to authenticate into our APIs and is highly sensitive. If it ever gets compromised, you can immediately revoke key access from our dashboard and generate a new key. ## Step 2: Onboard a customer Create a customer ID for each user who needs a USD or EUR account. Customers will need to accept our terms of service and complete KYC. Check out this [guide](/get-started/introduction/quick-start/create-your-first-customer) for a full in depth explanation on onboarding customers. The below example walks you through using a KYC link to onboard your customer. ```bash Request theme={null} curl --location --request POST 'https://api.bridge.xyz/v0/kyc_links' \ --header 'Content-Type: application/json' \ --header 'Api-Key: ' \ --header 'Idempotency-Key: ' \ --data-raw '{ "full_name": "John Doe", "email": "johndoe@example.com", "type": "individual" }' ``` ```json Response theme={null} { "id": "uuid", "full_name": "John Doe", "email": "johndoe@example.com", "type": "individual", // or "business" "kyc_link": "https://bridge.withpersona.com/verify?", "tos_link": "https://dashboard.bridge.xyz/accept-terms-of-service?", "kyc_status": "not_started", // or "under_review", "incomplete", "approved" or "rejected" "rejection_reasons": [], "tos_status": "pending", // or "approved" "created_at": "2025-07-16T18:28:25.970Z", "customer_id": "customer_id", "persona_inquiry_type": "gov_id_db" } ``` Guide the user through: 1. Visiting the `tos_link` and accepting terms of service 2. Completing identity verification via the `kyc_link` This process typically takes less than a minute and updates automatically once complete. ## Step 3: Create a wallet Create a wallet for the customer to hold stablecoins. The below example explains how to create a Bridge wallet associated with a customer object. ```bash Request theme={null} curl --request POST \ --url https://api.bridge.xyz/v0/customers//wallets \ --header 'Api-Key: ' \ --header 'Idempotency-Key: ' \ --header 'Content-Type: application/json' \ --data-raw '{ "chain": "solana" }' ``` ```json Response theme={null} { "id": "wallet_123", "chain": "solana", "address": "4oG1sWkP8vcrnhbkzZc1m9RTT2VUjZHKx92qiVFK7FuZ", "created_at": "2025-07-15T18:00:00Z" } ``` Use the `bridge_wallet_id` when referencing the wallet in other Bridge APIs. Check out this [guide](/get-started/guides/wallets/overview) for more information on using Bridge wallets. ## Step 4: Create a virtual account Use the [Virtual Accounts](/api-reference/virtual-accounts/create-a-virtual-account) API to provision permanent fiat deposit addresses for your customers. You define the `source` currency for the account and configure the `destination` to specify where Bridge should deliver the converted funds. Bridge handles the fiat-to-crypto conversion and sends the funds on-chain automatically. ```bash Request theme={null} curl --location --request POST 'https://api.bridge.xyz/v0/customers//virtual_accounts' \ --header 'Content-Type: application/json' \ --header 'Api-Key: ' \ --header 'Idempotency-Key: ' \ --data-raw '{ # The source object specifies a USD virtual account. "source": { "currency": "usd", }, # The destination object instructs Bridge where to send the USD deposits to. # Bridge will automatically handle converting and sending USD to the crypto destination. "destination": { "payment_rail": "ethereum", "currency": "usdc", "address": "0x3f5CE5FBFe3E9af3971dD833D26BA9b5C936f0bE" }, # You can specifcy an optional developer fee to monetize on transactions. "developer_fee_percent": "1.0" // 1%. }' ``` ```json Response theme={null} { "id": "1a400dae-f7fc-4f75-8105-212a14d4132d", "status": "activated", "developer_fee_percent": "1.0", "customer_id": "23c2d200-4c00-4c5a-b31a-00d035d7e0ae", "created_at": "2025-07-04T22:10:34.564Z", "source_deposit_instructions": { "currency": "usd", "bank_name": "Lead Bank", "bank_address": "1801 Main St., Kansas City, MO 64108", "bank_routing_number": "101019644", "bank_account_number": "215268120000", "bank_beneficiary_name": "Ada Lovelace", "bank_beneficiary_address": "923 Folsom Street, 302, San Francisco, California 941070000, US", "payment_rail": "ach_push", "payment_rails": [ "ach_push", "wire" ] }, "destination": { "currency": "usdc", "payment_rail": "ethereum", "address": "0x3f5ce5fbfe3e9af3971dd833d26ba9b5c936f0be" } } ``` ```bash Request theme={null} curl --location --request POST 'https://api.bridge.xyz/v0/customers//virtual_accounts' \ --header 'Content-Type: application/json' \ --header 'Api-Key: ' \ --header 'Idempotency-Key: ' \ --data-raw '{ # The source object specifies a SEPA virtual IBAN. "source": { "currency": "eur", }, # The destination object instructs Bridge where to send the EURO deposits to. # Bridge will automatically handle converting and sending EURO to the crypto destination. "destination": { "payment_rail": "ethereum", "currency": "usdc", "address": "0x3f5CE5FBFe3E9af3971dD833D26BA9b5C936f0bE" }, # You can specifcy an optional developer fee to monetize on transactions. "developer_fee_percent": "1.0" // 1%. }' ``` ```json Response theme={null} { "id": "393c6358-4c19-4cb7-bbfa-d4a56be58309", "status": "activated", "developer_fee_percent": "1.0", "customer_id": "23c2d200-4c00-4c5a-b31a-00d035d7e0ae", "created_at": "2025-07-04T22:07:18.701Z", "source_deposit_instructions": { "currency": "eur", "iban": "IE90MODR14035307970528", "bic": "MODRIE00XXX", "account_holder_name": "Bridge Building Sp.z.o.o.", "bank_name": "Modulr Finance, Ireland Branch", "bank_address": "Floor 6, 2 Grand Canal Square, Dublin, Ireland", "payment_rail": "sepa", "payment_rails": [ "sepa" ] }, "destination": { "currency": "usdc", "payment_rail": "ethereum", "address": "0x3f5ce5fbfe3e9af3971dd833d26ba9b5c936f0be" } } ``` ```bash Request theme={null} curl --location --request POST 'https://api.bridge.xyz/v0/customers//virtual_accounts' \ --header 'Content-Type: application/json' \ --header 'Api-Key: ' \ --header 'Idempotency-Key: ' \ --data-raw '{ # The source object specifies a MXN virtual account. "source": { "currency": "mxn", }, # The destination object instructs Bridge where to send the MXN deposits to. # Bridge will automatically handle converting and sending MXN to the crypto destination. "destination": { "payment_rail": "ethereum", "currency": "usdc", "address": "0x3f5CE5FBFe3E9af3971dD833D26BA9b5C936f0bE" }, # You can specifcy an optional developer fee to monetize on transactions. "developer_fee_percent": "1.0" // 1%. }' ``` ```json Response theme={null} { "id": "35334433-dcee-48e8-bdc8-90171234ad00", "status": "activated", "developer_fee_percent": "1.0", "customer_id": "23c2d200-4c00-4c5a-b31a-00d035d7e0ae", "created_at": "2025-07-04T22:13:29.481Z", "source_deposit_instructions": { "currency": "mxn", "clabe": "568980546701071234", "account_holder_name": "Ada Lovelace", "payment_rails": [ "spei" ] }, "destination": { "currency": "usdc", "payment_rail": "ethereum", "address": "0x3f5ce5fbfe3e9af3971dd833d26ba9b5c936f0be" } } ``` ```bash Request theme={null} curl --location --request POST 'https://api.bridge.xyz/v0/customers//virtual_accounts' \ --header 'Content-Type: application/json' \ --header 'Api-Key: ' \ --header 'Idempotency-Key: ' \ --data-raw '{ "source": { "currency": "brl", }, # The destination object instructs Bridge where to send the BRL deposits to. # Bridge will automatically handle converting and sending USDC to the crypto destination. "destination": { "payment_rail": "ethereum", "currency": "usdc", "address": "0x3f5CE5FBFe3E9af3971dD833D26BA9b5C936f0bE" }, # You can specify an optional developer fee to monetize transactions. "developer_fee_percent": "1.0" // 1%. }' ``` ```json Response theme={null} { "id": "6e6ab621-6749-401f-b598-0c709c241696", "status": "activated", "developer_fee_percent": "0.0", "customer_id": "eeafff4b-2dbe-41f2-9444-a6e228aee975", "created_at": "2025-09-03T16:10:31.446Z", "source_deposit_instructions": { "currency": "brl", "br_code": "00020126770014br.gov.bcb.pix01366e6ab621-6749-401f-b598-0c709c2416960215Edson_Arantes5204000053039865802BR5914Bridge_Example6009Sao_Paulo622905256beca3e77fdd489289aa1daeb630416E9", "account_holder_name": "Edson Arantes do Nascimento", "payment_rails": [ "pix" ] }, "destination": { "currency": "usdc", "payment_rail": "ethereum", "address": "0x3f5CE5FBFe3E9af3971dD833D26BA9b5C936f0bE" } } ``` ```bash Request theme={null} curl --location --request POST 'https://api.bridge.xyz/v0/customers//virtual_accounts' \ --header 'Content-Type: application/json' \ --header 'Api-Key: ' \ --header 'Idempotency-Key: ' \ --data-raw '{ "source": { "currency": "gbp", }, # The destination object instructs Bridge where to send the GBP deposits to. # Bridge will automatically handle converting and sending USDC to the crypto destination. "destination": { "payment_rail": "ethereum", "currency": "usdc", "address": "0x3f5CE5FBFe3E9af3971dD833D26BA9b5C936f0bE" }, # You can specify an optional developer fee to monetize transactions. "developer_fee_percent": "1.0" // 1%. }' ``` ```json Response theme={null} { "id": "6e6ab621-6749-401f-b598-0c709c241696", "status": "activated", "developer_fee_percent": "0.0", "customer_id": "485c2b50-949c-412b-928a-f56fce42330d", "created_at": "2026-01-03T00:23:23.724Z", "source_deposit_instructions": { "currency": "brl", "account_number": "12345678", "sort_code": "123456", "account_holder_name": "Bridge Building Sp. Z.o.o.", "bank_name": "Banking Circle S.A.", "bank_address": "2 Boulevard de la Foire, L-1528 Luxembourg", "bank_beneficiary_name": "Bridge Building Sp. Z.o.o.", "bank_beneficiary_address": "2 Boulevard de la Foire, L-1528 Luxembourg", "payment_rails": [ "faster_payments" ] }, "destination": { "currency": "usdc", "payment_rail": "ethereum", "address": "0x3f5CE5FBFe3E9af3971dD833D26BA9b5C936f0bE" } } ``` ### Sharing Deposit Instructions Once a Virtual Account is created, use the `source_deposit_instructions` object in the response to share the fiat deposit details with your customer. Funds sent to those details will be automatically converted and delivered to the crypto destination you specified. ## Step 5: Explore cards Enable users to spend their stablecoin balances locally. The below API example provision a card tied to a Bridge wallet. ```bash Request theme={null} curl --request POST \ --url https://api.bridge.xyz/v0/customers/customerID/card_accounts \ --header 'accept: application/json' \ --header 'content-type: application/json' \ --data '{ "currency": "usdb", "chain": "solana", "crypto_account": { "type": "bridge_wallet", "address": "4oG1sWkP8vcrnhbkzZc1m9RTT2VUjZHKx92qiVFK7FuZ" } }' ``` ### Retrieve card details Access card metadata, expiration, and access a secure image of the card. ```bash Request theme={null} curl -X GET 'https://api.bridge.xyz/v0/customers//card_accounts/' \ --header 'Api-Key: ' ``` ```json Response theme={null} { "id": "XXX-YYY", "status": "active", "card_image_url": "https://...", "card_details": { "last_4": "1264", "expiry": "10/24", "bin": "44325280" } } ``` You can now share these card details with your customer to **start spending!** Check our guide [here](/get-started/guides/cards/spend) for more information on setting up cards! # Payroll Source: https://apidocs.bridge.xyz/get-started/guides/common-use-cases/payroll Enable employers to pay employees and contractors globally by creating a wallet and virtual account for the employer and a wallet for each employee. Fiat deposits into the virtual account are converted to stablecoins and held in the employer’s wallet. Use the Transfers API to pay out funds from the employer to the employee. Payroll.png *** ## Step 1: Generate your API Keys Head over to [**dashboard.bridge.xyz**](https://dashboard.bridge.xyz/). Once logged in, click on the “API Keys” tab on the top menu bar and generate a new API key. Bridge will make your **API key available only once**, so make sure to **immediately copy and save the key safely and securely**. \ \ Your key is used to authenticate into our APIs and is highly sensitive. If it ever gets compromised, you can immediately revoke key access from our dashboard and generate a new key. ## Step 2: Onboard a customer Create a customer ID for each employer to manage payroll. Customers will need to accept our terms of service and complete KYC. Check out this [guide](/get-started/introduction/quick-start/create-your-first-customer) for a full in depth explanation on onboarding customers. The below example walks you through using a KYC link to onboard your customer. ```bash Request theme={null} curl --location --request POST 'https://api.bridge.xyz/v0/kyc_links' \ --header 'Content-Type: application/json' \ --header 'Api-Key: ' \ --header 'Idempotency-Key: ' \ --data-raw '{ "full_name": "John Doe", "email": "johndoe@example.com", "type": "individual" }' ``` ```json Response theme={null} { "id": "uuid", "full_name": "John Doe", "email": "johndoe@example.com", "type": "individual", // or "business" "kyc_link": "https://bridge.withpersona.com/verify?", "tos_link": "https://dashboard.bridge.xyz/accept-terms-of-service?", "kyc_status": "not_started", // or "under_review", "incomplete", "approved" or "rejected" "rejection_reasons": [], "tos_status": "pending", // or "approved" "created_at": "2025-07-16T18:28:25.970Z", "customer_id": "customer_id", "persona_inquiry_type": "gov_id_db" } ``` Guide the user through: 1. Visiting the `tos_link` and accepting terms of service 2. Completing identity verification via the `kyc_link` This process typically takes less than a minute and updates automatically once complete. ## Step 3: Create a wallet for the employer Create a wallet to hold the employer’s payroll funds. ```bash Request theme={null} curl --request POST \ --url https://api.bridge.xyz/v0/customers/{employer-customer-id}/wallets \ --header 'Api-Key: ' \ --header 'Idempotency-Key: ' \ --header 'Content-Type: application/json' \ --data '{ "chain": "solana" }' ``` ```json Response theme={null} { "id": "employer-wallet-id-123", "chain": "solana", "address": "0x353253250000000001340033", "created_at": "2024-09-01T02:03:04.567Z", "updated_at": "2024-09-01T02:03:04.567Z" } ``` ## Step 4: Create a wallet for an employee Create a wallet for each employee to get paid in stablecoins. ```bash Request theme={null} curl --request POST \ --url https://api.bridge.xyz/v0/customers/{employee-customer-id}/wallets \ --header 'Api-Key: ' \ --header 'Idempotency-Key: ' \ --header 'Content-Type: application/json' \ --data '{ "chain": "solana" }' ``` ```json Response theme={null} { "id": "employee-wallet-id-abc", "chain": "solana", "address": "0x444415153153500000120", "created_at": "2024-09-01T02:03:04.567Z", "updated_at": "2024-09-01T02:03:04.567Z" } ``` ## Step 5: Create a virtual account Create a USD or EUR account for the employer. Provide them with the bank instructions so they can deposit payroll. Deposits are converted to stablecoins and sent to their wallet. Use the [Virtual Accounts](/api-reference/virtual-accounts/create-a-virtual-account) API to provision permanent fiat deposit addresses for your customers. You define the `source` currency for the account and configure the `destination` to specify where Bridge should deliver the converted funds. Bridge handles the fiat-to-crypto conversion and sends the funds on-chain automatically. ```bash Request theme={null} curl --location --request POST 'https://api.bridge.xyz/v0/customers//virtual_accounts' \ --header 'Content-Type: application/json' \ --header 'Api-Key: ' \ --header 'Idempotency-Key: ' \ --data-raw '{ # The source object specifies a USD virtual account. "source": { "currency": "usd", }, # You can specify the employer's wallet as the destination to receive funds "destination": { "payment_rail": "solana", "currency": "usdc", "bridge_wallet_id": "employer-wallet-id-123" } }' ``` ## Step 6: Make a transfer Use the Transfers API to move funds from the employer’s wallet to the employee’s wallet. You will need to call the API for each employee. Use the [Transfers](/api-reference/transfers/create-a-transfer) API with the employer's `bridge_wallet` as the source and the employee's `bridge_wallet` as the destination. ```bash Request theme={null} curl --location --request POST 'https://api.bridge.xyz/v0/transfers' \ --header 'Api-Key: ' \ --header 'Idempotency-Key: ' \ --header 'Content-Type: application/json' \ --data-raw '{ "amount": "10.0", "on_behalf_of": "", "developer_fee": "0.0", "source": { "payment_rail": "bridge_wallet", "currency": "usdc", "bridge_wallet_id": "employer-wallet-id-123" }, "destination": { "payment_rail": "solana", "currency": "usdc", "bridge_wallet_id": "employee-wallet-id-abc" } }' ``` Bridge will then initiate a crypto transfer from between the two specified bridge wallets. # Remittances Source: https://apidocs.bridge.xyz/get-started/guides/common-use-cases/remittances Enable senders to pay recipients globally by creating a virtual account for the sender and a wallet for the recipient. Fiat deposits into the sender’s virtual account are converted to stablecoins and sent to the recipient’s wallet. Remittances.png *** ## Step 1: Generate your API Keys Head over to [**dashboard.bridge.xyz**](https://dashboard.bridge.xyz/). Once logged in, click on the “API Keys” tab on the top menu bar and generate a new API key. Bridge will make your **API key available only once**, so make sure to **immediately copy and save the key safely and securely**. \ \ Your key is used to authenticate into our APIs and is highly sensitive. If it ever gets compromised, you can immediately revoke key access from our dashboard and generate a new key. ## Step 2: Onboard a customer Create a customer ID for each sender initiating a payment. Customers will need to accept our terms of service and complete KYC. Check out this [guide](/get-started/introduction/quick-start/create-your-first-customer) for a full in depth explanation on onboarding customers. The below example walks you through using a KYC link to onboard your customer. ```bash Request theme={null} curl --location --request POST 'https://api.bridge.xyz/v0/kyc_links' \ --header 'Content-Type: application/json' \ --header 'Api-Key: ' \ --header 'Idempotency-Key: ' \ --data-raw '{ "full_name": "John Doe", "email": "johndoe@example.com", "type": "individual" }' ``` ```json Response theme={null} { "id": "uuid", "full_name": "John Doe", "email": "johndoe@example.com", "type": "individual", // or "business" "kyc_link": "https://bridge.withpersona.com/verify?", "tos_link": "https://dashboard.bridge.xyz/accept-terms-of-service?", "kyc_status": "not_started", // or "under_review", "incomplete", "approved" or "rejected" "rejection_reasons": [], "tos_status": "pending", // or "approved" "created_at": "2025-07-16T18:28:25.970Z", "customer_id": "customer_id", "persona_inquiry_type": "gov_id_db" } ``` Guide the user through: 1. Visiting the `tos_link` and accepting terms of service 2. Completing identity verification via the `kyc_link` This process typically takes less than a minute and updates automatically once complete. ## Step 3: Create a wallet Create a wallet for the recipient to receive funds from the sender. The below example explains how to create a Bridge wallet associated with a customer object. ```bash Request theme={null} curl --request POST \ --url https://api.bridge.xyz/v0/customers//wallets \ --header 'Api-Key: ' \ --header 'Idempotency-Key: ' \ --header 'Content-Type: application/json' \ --data-raw '{ "chain": "solana" }' ``` ```json Response theme={null} { "id": "wallet_123", "chain": "solana", "address": "4oG1sWkP8vcrnhbkzZc1m9RTT2VUjZHKx92qiVFK7FuZ", "created_at": "2025-07-15T18:00:00Z" } ``` Use the `bridge_wallet_id` when referencing the wallet in other Bridge APIs. Check out this [guide](/get-started/guides/wallets/overview) for more information on using Bridge wallets. ## Step 4: Create a virtual account Create a USD or EUR account for the sender. Provide them with the bank instructions so they can deposit funds. Deposits are converted to stablecoins and sent to their wallet. Use the [Virtual Accounts](/api-reference/virtual-accounts/create-a-virtual-account) API to provision permanent fiat deposit addresses for your customers. You define the `source` currency for the account and configure the `destination` to specify where Bridge should deliver the converted funds. Bridge handles the fiat-to-crypto conversion and sends the funds on-chain automatically. ```bash Request theme={null} curl --location --request POST 'https://api.bridge.xyz/v0/customers//virtual_accounts' \ --header 'Content-Type: application/json' \ --header 'Api-Key: ' \ --header 'Idempotency-Key: ' \ --data-raw '{ # The source object specifies a USD virtual account. "source": { "currency": "usd", }, # The destination object instructs Bridge where to send the USD deposits to. # Bridge will automatically handle converting and sending USD to the crypto destination. "destination": { "payment_rail": "ethereum", "currency": "usdc", "address": "0x3f5CE5FBFe3E9af3971dD833D26BA9b5C936f0bE" }, # You can specifcy an optional developer fee to monetize on transactions. "developer_fee_percent": "1.0" // 1%. }' ``` ```json Response theme={null} { "id": "1a400dae-f7fc-4f75-8105-212a14d4132d", "status": "activated", "developer_fee_percent": "1.0", "customer_id": "23c2d200-4c00-4c5a-b31a-00d035d7e0ae", "created_at": "2025-07-04T22:10:34.564Z", "source_deposit_instructions": { "currency": "usd", "bank_name": "Lead Bank", "bank_address": "1801 Main St., Kansas City, MO 64108", "bank_routing_number": "101019644", "bank_account_number": "215268120000", "bank_beneficiary_name": "Ada Lovelace", "bank_beneficiary_address": "923 Folsom Street, 302, San Francisco, California 941070000, US", "payment_rail": "ach_push", "payment_rails": [ "ach_push", "wire" ] }, "destination": { "currency": "usdc", "payment_rail": "ethereum", "address": "0x3f5ce5fbfe3e9af3971dd833d26ba9b5c936f0be" } } ``` ```bash Request theme={null} curl --location --request POST 'https://api.bridge.xyz/v0/customers//virtual_accounts' \ --header 'Content-Type: application/json' \ --header 'Api-Key: ' \ --header 'Idempotency-Key: ' \ --data-raw '{ # The source object specifies a SEPA virtual IBAN. "source": { "currency": "eur", }, # The destination object instructs Bridge where to send the EURO deposits to. # Bridge will automatically handle converting and sending EURO to the crypto destination. "destination": { "payment_rail": "ethereum", "currency": "usdc", "address": "0x3f5CE5FBFe3E9af3971dD833D26BA9b5C936f0bE" }, # You can specifcy an optional developer fee to monetize on transactions. "developer_fee_percent": "1.0" // 1%. }' ``` ```json Response theme={null} { "id": "393c6358-4c19-4cb7-bbfa-d4a56be58309", "status": "activated", "developer_fee_percent": "1.0", "customer_id": "23c2d200-4c00-4c5a-b31a-00d035d7e0ae", "created_at": "2025-07-04T22:07:18.701Z", "source_deposit_instructions": { "currency": "eur", "iban": "IE90MODR14035307970528", "bic": "MODRIE00XXX", "account_holder_name": "Bridge Building Sp.z.o.o.", "bank_name": "Modulr Finance, Ireland Branch", "bank_address": "Floor 6, 2 Grand Canal Square, Dublin, Ireland", "payment_rail": "sepa", "payment_rails": [ "sepa" ] }, "destination": { "currency": "usdc", "payment_rail": "ethereum", "address": "0x3f5ce5fbfe3e9af3971dd833d26ba9b5c936f0be" } } ``` ```bash Request theme={null} curl --location --request POST 'https://api.bridge.xyz/v0/customers//virtual_accounts' \ --header 'Content-Type: application/json' \ --header 'Api-Key: ' \ --header 'Idempotency-Key: ' \ --data-raw '{ # The source object specifies a MXN virtual account. "source": { "currency": "mxn", }, # The destination object instructs Bridge where to send the MXN deposits to. # Bridge will automatically handle converting and sending MXN to the crypto destination. "destination": { "payment_rail": "ethereum", "currency": "usdc", "address": "0x3f5CE5FBFe3E9af3971dD833D26BA9b5C936f0bE" }, # You can specifcy an optional developer fee to monetize on transactions. "developer_fee_percent": "1.0" // 1%. }' ``` ```json Response theme={null} { "id": "35334433-dcee-48e8-bdc8-90171234ad00", "status": "activated", "developer_fee_percent": "1.0", "customer_id": "23c2d200-4c00-4c5a-b31a-00d035d7e0ae", "created_at": "2025-07-04T22:13:29.481Z", "source_deposit_instructions": { "currency": "mxn", "clabe": "568980546701071234", "account_holder_name": "Ada Lovelace", "payment_rails": [ "spei" ] }, "destination": { "currency": "usdc", "payment_rail": "ethereum", "address": "0x3f5ce5fbfe3e9af3971dd833d26ba9b5c936f0be" } } ``` ```bash Request theme={null} curl --location --request POST 'https://api.bridge.xyz/v0/customers//virtual_accounts' \ --header 'Content-Type: application/json' \ --header 'Api-Key: ' \ --header 'Idempotency-Key: ' \ --data-raw '{ "source": { "currency": "brl", }, # The destination object instructs Bridge where to send the BRL deposits to. # Bridge will automatically handle converting and sending USDC to the crypto destination. "destination": { "payment_rail": "ethereum", "currency": "usdc", "address": "0x3f5CE5FBFe3E9af3971dD833D26BA9b5C936f0bE" }, # You can specify an optional developer fee to monetize transactions. "developer_fee_percent": "1.0" // 1%. }' ``` ```json Response theme={null} { "id": "6e6ab621-6749-401f-b598-0c709c241696", "status": "activated", "developer_fee_percent": "0.0", "customer_id": "eeafff4b-2dbe-41f2-9444-a6e228aee975", "created_at": "2025-09-03T16:10:31.446Z", "source_deposit_instructions": { "currency": "brl", "br_code": "00020126770014br.gov.bcb.pix01366e6ab621-6749-401f-b598-0c709c2416960215Edson_Arantes5204000053039865802BR5914Bridge_Example6009Sao_Paulo622905256beca3e77fdd489289aa1daeb630416E9", "account_holder_name": "Edson Arantes do Nascimento", "payment_rails": [ "pix" ] }, "destination": { "currency": "usdc", "payment_rail": "ethereum", "address": "0x3f5CE5FBFe3E9af3971dD833D26BA9b5C936f0bE" } } ``` ```bash Request theme={null} curl --location --request POST 'https://api.bridge.xyz/v0/customers//virtual_accounts' \ --header 'Content-Type: application/json' \ --header 'Api-Key: ' \ --header 'Idempotency-Key: ' \ --data-raw '{ "source": { "currency": "gbp", }, # The destination object instructs Bridge where to send the GBP deposits to. # Bridge will automatically handle converting and sending USDC to the crypto destination. "destination": { "payment_rail": "ethereum", "currency": "usdc", "address": "0x3f5CE5FBFe3E9af3971dD833D26BA9b5C936f0bE" }, # You can specify an optional developer fee to monetize transactions. "developer_fee_percent": "1.0" // 1%. }' ``` ```json Response theme={null} { "id": "6e6ab621-6749-401f-b598-0c709c241696", "status": "activated", "developer_fee_percent": "0.0", "customer_id": "485c2b50-949c-412b-928a-f56fce42330d", "created_at": "2026-01-03T00:23:23.724Z", "source_deposit_instructions": { "currency": "brl", "account_number": "12345678", "sort_code": "123456", "account_holder_name": "Bridge Building Sp. Z.o.o.", "bank_name": "Banking Circle S.A.", "bank_address": "2 Boulevard de la Foire, L-1528 Luxembourg", "bank_beneficiary_name": "Bridge Building Sp. Z.o.o.", "bank_beneficiary_address": "2 Boulevard de la Foire, L-1528 Luxembourg", "payment_rails": [ "faster_payments" ] }, "destination": { "currency": "usdc", "payment_rail": "ethereum", "address": "0x3f5CE5FBFe3E9af3971dD833D26BA9b5C936f0bE" } } ``` ### Sharing Deposit Instructions Once a Virtual Account is created, use the `source_deposit_instructions` object in the response to share the fiat deposit details with your customer. Funds sent to those details will be automatically converted and delivered to the crypto destination you specified. ## Step 5: Explore Cards Enable users to spend their stablecoin balances locally. The below API example provision a card tied to a Bridge wallet. ```bash Request theme={null} curl --request POST \ --url https://api.bridge.xyz/v0/customers/customerID/card_accounts \ --header 'accept: application/json' \ --header 'content-type: application/json' \ --data '{ "currency": "usdb", "chain": "solana", "crypto_account": { "type": "bridge_wallet", "address": "4oG1sWkP8vcrnhbkzZc1m9RTT2VUjZHKx92qiVFK7FuZ" } }' ``` ### Retrieve card details Access card metadata, expiration, and access a secure image of the card. ```bash Request theme={null} curl -X GET 'https://api.bridge.xyz/v0/customers//card_accounts/' \ --header 'Api-Key: ' ``` ```json Response theme={null} { "id": "XXX-YYY", "status": "active", "card_image_url": "https://...", "card_details": { "last_4": "1264", "expiry": "10/24", "bin": "44325280" } } ``` You can now share these card details with your customer to **start spending!** Check our guide [here](/get-started/guides/cards/spend) for more information on setting up cards! # Treasury management Source: https://apidocs.bridge.xyz/get-started/guides/common-use-cases/treasury-management Manage your customer’s treasury funds with USDB – a Bridge-issued stablecoin backed 1:1 by US dollars. USDB earns treasury yield, and that yield is shared with you. Create a virtual account and wallet to custody treasury funds. Fiat deposits into the virtual account are converted to stablecoins and held in the customer’s wallet. Use the Transfers API to enable customers to pay vendors. Treasury Mgmt.png *** ## Step 1: Generate your API Keys Head over to [**dashboard.bridge.xyz**](https://dashboard.bridge.xyz/). Once logged in, click on the “API Keys” tab on the top menu bar and generate a new API key. Bridge will make your **API key available only once**, so make sure to **immediately copy and save the key safely and securely**. \ \ Your key is used to authenticate into our APIs and is highly sensitive. If it ever gets compromised, you can immediately revoke key access from our dashboard and generate a new key. ## Step 2: Onboard a customer Create a customer ID for each business. Customers will need to accept our terms of service and complete KYC. Check out this [guide](/get-started/introduction/quick-start/create-your-first-customer) for a full in depth explanation on onboarding customers. The below example walks you through using a KYC link to onboard your customer. ```bash Request theme={null} curl --location --request POST 'https://api.bridge.xyz/v0/kyc_links' \ --header 'Content-Type: application/json' \ --header 'Api-Key: ' \ --header 'Idempotency-Key: ' \ --data-raw '{ "full_name": "John Doe", "email": "johndoe@example.com", "type": "individual" }' ``` ```json Response theme={null} { "id": "uuid", "full_name": "John Doe", "email": "johndoe@example.com", "type": "individual", // or "business" "kyc_link": "https://bridge.withpersona.com/verify?", "tos_link": "https://dashboard.bridge.xyz/accept-terms-of-service?", "kyc_status": "not_started", // or "under_review", "incomplete", "approved" or "rejected" "rejection_reasons": [], "tos_status": "pending", // or "approved" "created_at": "2025-07-16T18:28:25.970Z", "customer_id": "customer_id", "persona_inquiry_type": "gov_id_db" } ``` Guide the user through: 1. Visiting the `tos_link` and accepting terms of service 2. Completing identity verification via the `kyc_link` This process typically takes less than a minute and updates automatically once complete. ## Step 3: Create a wallet Create a wallet for your customer to hold treasury funds in USDB. The below example explains how to create a Bridge wallet associated with a customer object. ```bash Request theme={null} curl --request POST \ --url https://api.bridge.xyz/v0/customers//wallets \ --header 'Api-Key: ' \ --header 'Idempotency-Key: ' \ --header 'Content-Type: application/json' \ --data-raw '{ "chain": "solana" }' ``` ```json Response theme={null} { "id": "wallet_123", "chain": "solana", "address": "4oG1sWkP8vcrnhbkzZc1m9RTT2VUjZHKx92qiVFK7FuZ", "created_at": "2025-07-15T18:00:00Z" } ``` Use the `bridge_wallet_id` when referencing the wallet in other Bridge APIs. Check out this [guide](/get-started/guides/wallets/overview) for more information on using Bridge wallets. ## Step 4: Create a virtual account Create a USD or EUR account for the customer. Provide them with the bank instructions so they can receive payments. Deposits are converted to stablecoins and held in their wallet. Use the [Virtual Accounts](/api-reference/virtual-accounts/create-a-virtual-account) API to provision permanent fiat deposit addresses for your customers. You define the `source` currency for the account and configure the `destination` to specify where Bridge should deliver the converted funds. Bridge handles the fiat-to-crypto conversion and sends the funds on-chain automatically. ```bash Request theme={null} curl --location --request POST 'https://api.bridge.xyz/v0/customers//virtual_accounts' \ --header 'Content-Type: application/json' \ --header 'Api-Key: ' \ --header 'Idempotency-Key: ' \ --data-raw '{ # The source object specifies a USD virtual account. "source": { "currency": "usd", }, # The destination object instructs Bridge where to send the USD deposits to. # Bridge will automatically handle converting and sending USD to the crypto destination. "destination": { "payment_rail": "ethereum", "currency": "usdc", "address": "0x3f5CE5FBFe3E9af3971dD833D26BA9b5C936f0bE" }, # You can specifcy an optional developer fee to monetize on transactions. "developer_fee_percent": "1.0" // 1%. }' ``` ```json Response theme={null} { "id": "1a400dae-f7fc-4f75-8105-212a14d4132d", "status": "activated", "developer_fee_percent": "1.0", "customer_id": "23c2d200-4c00-4c5a-b31a-00d035d7e0ae", "created_at": "2025-07-04T22:10:34.564Z", "source_deposit_instructions": { "currency": "usd", "bank_name": "Lead Bank", "bank_address": "1801 Main St., Kansas City, MO 64108", "bank_routing_number": "101019644", "bank_account_number": "215268120000", "bank_beneficiary_name": "Ada Lovelace", "bank_beneficiary_address": "923 Folsom Street, 302, San Francisco, California 941070000, US", "payment_rail": "ach_push", "payment_rails": [ "ach_push", "wire" ] }, "destination": { "currency": "usdc", "payment_rail": "ethereum", "address": "0x3f5ce5fbfe3e9af3971dd833d26ba9b5c936f0be" } } ``` ```bash Request theme={null} curl --location --request POST 'https://api.bridge.xyz/v0/customers//virtual_accounts' \ --header 'Content-Type: application/json' \ --header 'Api-Key: ' \ --header 'Idempotency-Key: ' \ --data-raw '{ # The source object specifies a SEPA virtual IBAN. "source": { "currency": "eur", }, # The destination object instructs Bridge where to send the EURO deposits to. # Bridge will automatically handle converting and sending EURO to the crypto destination. "destination": { "payment_rail": "ethereum", "currency": "usdc", "address": "0x3f5CE5FBFe3E9af3971dD833D26BA9b5C936f0bE" }, # You can specifcy an optional developer fee to monetize on transactions. "developer_fee_percent": "1.0" // 1%. }' ``` ```json Response theme={null} { "id": "393c6358-4c19-4cb7-bbfa-d4a56be58309", "status": "activated", "developer_fee_percent": "1.0", "customer_id": "23c2d200-4c00-4c5a-b31a-00d035d7e0ae", "created_at": "2025-07-04T22:07:18.701Z", "source_deposit_instructions": { "currency": "eur", "iban": "IE90MODR14035307970528", "bic": "MODRIE00XXX", "account_holder_name": "Bridge Building Sp.z.o.o.", "bank_name": "Modulr Finance, Ireland Branch", "bank_address": "Floor 6, 2 Grand Canal Square, Dublin, Ireland", "payment_rail": "sepa", "payment_rails": [ "sepa" ] }, "destination": { "currency": "usdc", "payment_rail": "ethereum", "address": "0x3f5ce5fbfe3e9af3971dd833d26ba9b5c936f0be" } } ``` ```bash Request theme={null} curl --location --request POST 'https://api.bridge.xyz/v0/customers//virtual_accounts' \ --header 'Content-Type: application/json' \ --header 'Api-Key: ' \ --header 'Idempotency-Key: ' \ --data-raw '{ # The source object specifies a MXN virtual account. "source": { "currency": "mxn", }, # The destination object instructs Bridge where to send the MXN deposits to. # Bridge will automatically handle converting and sending MXN to the crypto destination. "destination": { "payment_rail": "ethereum", "currency": "usdc", "address": "0x3f5CE5FBFe3E9af3971dD833D26BA9b5C936f0bE" }, # You can specifcy an optional developer fee to monetize on transactions. "developer_fee_percent": "1.0" // 1%. }' ``` ```json Response theme={null} { "id": "35334433-dcee-48e8-bdc8-90171234ad00", "status": "activated", "developer_fee_percent": "1.0", "customer_id": "23c2d200-4c00-4c5a-b31a-00d035d7e0ae", "created_at": "2025-07-04T22:13:29.481Z", "source_deposit_instructions": { "currency": "mxn", "clabe": "568980546701071234", "account_holder_name": "Ada Lovelace", "payment_rails": [ "spei" ] }, "destination": { "currency": "usdc", "payment_rail": "ethereum", "address": "0x3f5ce5fbfe3e9af3971dd833d26ba9b5c936f0be" } } ``` ```bash Request theme={null} curl --location --request POST 'https://api.bridge.xyz/v0/customers//virtual_accounts' \ --header 'Content-Type: application/json' \ --header 'Api-Key: ' \ --header 'Idempotency-Key: ' \ --data-raw '{ "source": { "currency": "brl", }, # The destination object instructs Bridge where to send the BRL deposits to. # Bridge will automatically handle converting and sending USDC to the crypto destination. "destination": { "payment_rail": "ethereum", "currency": "usdc", "address": "0x3f5CE5FBFe3E9af3971dD833D26BA9b5C936f0bE" }, # You can specify an optional developer fee to monetize transactions. "developer_fee_percent": "1.0" // 1%. }' ``` ```json Response theme={null} { "id": "6e6ab621-6749-401f-b598-0c709c241696", "status": "activated", "developer_fee_percent": "0.0", "customer_id": "eeafff4b-2dbe-41f2-9444-a6e228aee975", "created_at": "2025-09-03T16:10:31.446Z", "source_deposit_instructions": { "currency": "brl", "br_code": "00020126770014br.gov.bcb.pix01366e6ab621-6749-401f-b598-0c709c2416960215Edson_Arantes5204000053039865802BR5914Bridge_Example6009Sao_Paulo622905256beca3e77fdd489289aa1daeb630416E9", "account_holder_name": "Edson Arantes do Nascimento", "payment_rails": [ "pix" ] }, "destination": { "currency": "usdc", "payment_rail": "ethereum", "address": "0x3f5CE5FBFe3E9af3971dD833D26BA9b5C936f0bE" } } ``` ```bash Request theme={null} curl --location --request POST 'https://api.bridge.xyz/v0/customers//virtual_accounts' \ --header 'Content-Type: application/json' \ --header 'Api-Key: ' \ --header 'Idempotency-Key: ' \ --data-raw '{ "source": { "currency": "gbp", }, # The destination object instructs Bridge where to send the GBP deposits to. # Bridge will automatically handle converting and sending USDC to the crypto destination. "destination": { "payment_rail": "ethereum", "currency": "usdc", "address": "0x3f5CE5FBFe3E9af3971dD833D26BA9b5C936f0bE" }, # You can specify an optional developer fee to monetize transactions. "developer_fee_percent": "1.0" // 1%. }' ``` ```json Response theme={null} { "id": "6e6ab621-6749-401f-b598-0c709c241696", "status": "activated", "developer_fee_percent": "0.0", "customer_id": "485c2b50-949c-412b-928a-f56fce42330d", "created_at": "2026-01-03T00:23:23.724Z", "source_deposit_instructions": { "currency": "brl", "account_number": "12345678", "sort_code": "123456", "account_holder_name": "Bridge Building Sp. Z.o.o.", "bank_name": "Banking Circle S.A.", "bank_address": "2 Boulevard de la Foire, L-1528 Luxembourg", "bank_beneficiary_name": "Bridge Building Sp. Z.o.o.", "bank_beneficiary_address": "2 Boulevard de la Foire, L-1528 Luxembourg", "payment_rails": [ "faster_payments" ] }, "destination": { "currency": "usdc", "payment_rail": "ethereum", "address": "0x3f5CE5FBFe3E9af3971dD833D26BA9b5C936f0bE" } } ``` ### Sharing Deposit Instructions Once a Virtual Account is created, use the `source_deposit_instructions` object in the response to share the fiat deposit details with your customer. Funds sent to those details will be automatically converted and delivered to the crypto destination you specified. ## Step 5: Create an external account Add and store a vendor’s bank account details to send payments from the customer. You can add external fiat accounts through our [External account API](/api-reference/external-accounts/create-a-new-external-account) using the following request. ```bash Request expandable theme={null} curl --location 'https://api.bridge.xyz/v0/customers//external_accounts' \ --header 'Idempotency-Key: ea-7' \ --header 'Content-Type: application/json' \ --header 'Accept: application/json' \ --header 'Api-Key: ' \ --data '{ "currency": "usd", "account_type": "us", "bank_name": "Lead Bank", "account_name": "Ada Checking Account", "first_name": "Ada", "last_name": "Lovelace", "account_owner_type": "individual", // specifies an individual account "account_owner_name": "Ada Lovelace", "account": { "routing_number": "101019644", "account_number": "215268129123", "checking_or_savings": "checking" }, "address": { "street_line_1": "923 Folsom Street", "country": "USA", "state": "CA", "city": "San Francisco", "postal_code": "941070000" } }' ``` ```json Response expandable theme={null} { "id": "external-account-123", // external account id "customer_id": "23c2d462-4c69-4c5a-b31a-88d035d7e8ae", "created_at": "2025-07-05T19:03:50.819Z", "updated_at": "2025-07-05T19:03:51.251Z", "bank_name": "Lead Bank", "account_name": "Ada Checking Account", "account_owner_name": "Ada Lovelace", "active": true, "currency": "usd", "account_owner_type": "individual", "account_type": "us", "first_name": "Ada", "last_name": "Lovelace", "business_name": null, "account": { "last_4": "9123", "routing_number": "101019644", "checking_or_savings": "checking" }, "beneficiary_address_valid": true, "last_4": "9123" } ``` ```bash Request expandable theme={null} curl --location 'https://api.bridge.xyz/v0/customers//external_accounts' \ --header 'Idempotency-Key: ea-7' \ --header 'Content-Type: application/json' \ --header 'Accept: application/json' \ --header 'Api-Key: ' \ --data '{ "currency": "eur", "account_type": "iban", "bank_name": "Modulr Finance, Ireland Branch", "account_name": "GGCF Corporate", "first_name": "Ada", "last_name": "Lovelace", "iban": { "account_number": "IE04MODR99035512826162", "country": "IRL", "bic": "MODRIE22XXX" }, "address": { "street_line_1": "Floor 6, 2 Grand Canal Square, Dublin, Ireland", "country": "IRL", "city": "Dublin", "postal_code": "D02 A342" } }' ``` ```curl Response theme={null} { "id": "c8948ce6-26ac-4d37-a336-742f961a76f3", "customer_id": "23c2d400-4c69-4c5a-b31a-88d035d7e8ae", "created_at": "2025-07-05T18:45:50.728Z", "updated_at": "2025-07-05T18:45:51.373Z", "bank_name": "Modulr Finance, Ireland Branch", "account_name": "GGCF Corporate", "account_owner_name": "Ada Lovelace", "active": true, "currency": "eur", "account_owner_type": "individual", "account_type": "iban", "first_name": "Ada", "last_name": "Lovelace", "business_name": null, "iban": { "last_4": "6162", "bic": "MODRIE22XXX", "country": "IRL" } } ``` ```bash Request expandable theme={null} curl --location 'https://api.bridge.xyz/v0/customers/23c2d462-4c69-4c5a-b31a-88d035d7e8ae/external_accounts' \ --header 'Idempotency-Key: ea-6' \ --header 'Content-Type: application/json' \ --header 'Accept: application/json' \ --header 'Api-Key: ' \ --data '{ "currency": "mxn", "account_type": "clabe", "account_owner_name": "Ada Lovelace", "clabe": { "account_number": "626899715090851234" }, "account_name": "Ada Checking Account", "bank_name": "BBVA Bancomer", "first_name": "Ada", "last_name": "Lovelace", "account_owner_type": "individual", "address": { "street_line_1": "Av. Reforma", "city": "Mexico City", "state": "CDMX", "postal_code": "06600", "country": "MEX" } }' ``` ```json Response expandable theme={null} { "id": "2bb5b814-0128-49a8-977a-77b1bc1cdee2", "customer_id": "23c2d462-4c69-4c5a-b31a-88d035d7e8ae", "created_at": "2025-07-05T18:59:42.163Z", "updated_at": "2025-07-05T18:59:42.713Z", "bank_name": "BBVA Bancomer", "account_name": "Ada Checking Account", "account_owner_name": "Ada Lovelace", "active": true, "currency": "mxn", "account_owner_type": "individual", "account_type": "clabe", "first_name": "Ada", "last_name": "Lovelace", "business_name": null, "clabe": { "last_4": "1234" } } ``` ## Step 6: Use the Transfers API Use the Transfers API to move funds from the customer’s wallet to a vendor’s bank account. You will need to call the API for each payment. ```bash Request expandable theme={null} curl --location --request POST 'https://api.bridge.xyz/v0/transfers' \ --header 'Api-Key: ' \ --header 'Idempotency-Key: ' \ --data-raw '{ "amount": "10.0", "on_behalf_of": "", "developer_fee": "0.5", "source": { "payment_rail": "bridge_wallet", "currency": "usdb", "bridge_wallet_id": "wallet_123" }, "destination": { "payment_rail": "ach", "currency": "usd", "external_account_id": "external-account-123" }, }' ``` # BRL integration guide Source: https://apidocs.bridge.xyz/get-started/guides/move-money/brl_pix_integration_guide To access BRL and the Pix payment rail, please reach out to our team at [sales@bridge.xyz](mailto:sales@bridge.xyz) ## Transaction Minimums and Limits We require a minimum transaction amount of **10 BRL** with no maximum limit. ## 🇧🇷 What we support * [Virtual Accounts](https://apidocs.bridge.xyz/platform/orchestration/virtual_accounts/virtual-account#brl) - Accept BRL via Pix payments from 1st and approved 3rd parties. * [Transfers](https://apidocs.bridge.xyz/platform/orchestration/transfers/transfer#create-transfer) - Receive BRL via Pix payins from 1st and approved 3rd parties, make payouts to any recipient. * [Liquidation Addresses](https://apidocs.bridge.xyz/platform/orchestration/liquidation_address/liquidation_address#multichain-%2B-multicurrency) - Offramps from stablecoin or crypto to BRL via Pix. * [Supported Countires](https://apidocs.bridge.xyz/platform/customers/compliance/supported-countries-list) - We support PIX on/offramps for customers in +100 countries. ## Related APIs * [Pix Endorsement](https://apidocs.bridge.xyz/platform/customers/customers/endorsements#pix-endorsement) required to use the BRL currency and Pix payment rail. If a customer already has the base endorsement, they should also have all of the info needed to grant the Pix endorsement. * **Important:** As of June 15, 2026 new requirements take into effect for the PIX endorsement. Please reference [BRL Migration Guide](https://apidocs.bridge.xyz/platform/customers/customers/brl-ramp-migration-guide) for more information. * Create a [BRL Virtual Account](https://apidocs.bridge.xyz/platform/orchestration/virtual_accounts/virtual-account#brl) to onramp funds using a unique account number * Create a [Pix External Account](https://apidocs.bridge.xyz/platform/orchestration/external-accounts/external-accounts-api#pix-key) to use as a [Transfer](https://apidocs.bridge.xyz/platform/orchestration/transfers/transfer#create-transfer) or [Liquidation Address](https://apidocs.bridge.xyz/platform/orchestration/liquidation_address/liquidation_address#multichain-%2B-multicurrency) offramp destination. We do not allow our BRL Virtual Accounts as an offramp destination. ## Logistics * **Onramp minimum 20 RBL** * **Offramp minimum 20 BRL** * Customer-specific volume limit of \$500k USD-equivalent per month, with the following enhanced KYC/B required to increase (contact account manager). * *Documentation should always be issued to the same legal entity that holds the account. If a document comes from a different entity within the corporate group (for example on financial capacity), it needs to clearly show the link between that entity and the account holder.* 1. Corporate bylaws/articles of incorporation (including consolidated amendments) 2. Ownership structure documentation (identifying all shareholders and percentages), plus ID and proof of address for each shareholder. If any shareholder is itself a legal entity, we'll need the same documentation for that entity as well. 3. Proof of address in the company's name 4. Target monthly volume, and proof of financial capacity matching the target volume (ex audited/signed financials: accountant certification, operational bank statements showing transaction flow, or a TPV report summarizing volume by period). * 1st and 3rd party payouts supported * 1st party payins supported, 3rd party payins supported from businesses. * Pix on/offramps complete in \~5 minutes however may take up to 30 minutes for transactions >\$50k. * **Non-Brazilian individual customers (determined by their tax ID)** can access BRL offramps (payouts) however do not have access to BRL onramps (virtual accounts / deposits). **Non-Brazilian business customers can access on and off ramps.** ## Best Practices: * We currently do not support BR Codes with static amounts. * When configuring an [External Account](https://apidocs.bridge.xyz/platform/orchestration/external-accounts/external-accounts-api#external-accounts)., ensure that all Pix Keys generated via EVP are entered in **lowercase**. ## KYC Requirements by Customer Type **Standard KYC individual** customers can provide any missing data either using our [Hosted KYC Link](https://apidocs.bridge.xyz/api-reference/customers/retrieve-a-hosted-kyc-link-for-an-existing-customer), or developers can submit directly via our [Customers API](https://apidocs.bridge.xyz/api-reference/customers/update-a-single-customer-object). | Likely Missing | How to collect | | :------------------------------------------------------------------------------ | :------------------------------------------------------------------------------- | | Tax ID
- For BR: Brazilian tax number (CPF)
- For Non-BR: Passport ID | KYC link or `identifying_information` with `type: cpf, passport, or national_id` | | Tax ID country | KYC link or `identifying_information` with `issuing_country` | | Phone number | KYC link or`phone `field | | Selfie | KYC link, or Customer API `liveness_check_selfies` field |
**Standard KYC business** customers can provide any missing data either using our [Hosted KYC Link](https://apidocs.bridge.xyz/api-reference/customers/retrieve-a-hosted-kyc-link-for-an-existing-customer), or developers can submit directly via our [Customers API](https://apidocs.bridge.xyz/api-reference/customers/update-a-single-customer-object). | Likely missing | How to collect | | :------------------------------------------------------------------------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Tax ID
- For BR: Brazilian tax number (CNPJ)
- For Non-BR: Any tax ID number | KYC link or `identifying_information` with `type: cnpj, ein or `[other available options](https://apidocs.bridge.xyz/api-reference/customers/create-a-customer#body-one-of-1-associated-persons-items-identifying-information)`.` | | Tax ID country | KYC link or `identifying_information` with `issuing_country` | | Phone number | KYC link or`phone `field | | Date of incorporation | KYC link or `incorporation_date` field | | UBO phone number (per UBO) | KYC link or `associated_persons.phone `field | | Business Formation Document | Customer API`business_formation `field | | Proof of Source of Funds Document | Customer API `proof_of_source_of_funds `field | | Business Address | Customer API `registered_address `field with `street_line_1,city, country` | | Proof of Address Document
- Utility bill, bank statement | Customer API `proof_of_address `field |
**Reliance individual** customers can provide any missing data either using our [Hosted KYC Link](https://apidocs.bridge.xyz/api-reference/customers/retrieve-a-hosted-kyc-link-for-an-existing-customer), or developers can submit directly via our [Customers API](https://apidocs.bridge.xyz/api-reference/customers/update-a-single-customer-object). | Required | How to collect | | :------------------------------------------------------------------------------ | :-------------------------------------------------------------------------------- | | Tax ID
- For BR: Brazilian tax number (CPF)
- For Non-BR: Passport ID | Customer API `identifying_information` with `type: cpf, passport, or national_id` | | Tax ID country | Customer API `identifying_information` with `issuing_country` | | Phone number | Customer API `phone` field | | Selfie | Customer API `liveness_check_selfies` field (array of base64 data URIs) | | Government ID image | Customer API `identifying_information` with `image_front` | Images (gov ID and selfie) must be JPEG, PNG, or HEIC format, minimum 200x200px, maximum 15MB.
**Reliance business** customers can provide any missing data either using our [Hosted KYC Link](https://apidocs.bridge.xyz/api-reference/customers/retrieve-a-hosted-kyc-link-for-an-existing-customer), or developers can submit directly via our [Customers API](https://apidocs.bridge.xyz/api-reference/customers/update-a-single-customer-object). | Required | How to collect | | :------------------------------------------------------------------------------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Tax ID
- For BR: Brazilian tax number (CNPJ)
- For Non-BR: Any tax ID number | Customer API `identifying_information` with `type: cnpj, ein or `[other available options](https://apidocs.bridge.xyz/api-reference/customers/create-a-customer#body-one-of-1-associated-persons-items-identifying-information)`.` | | Tax ID country | Customer API `identifying_information` with `issuing_country` | | Phone number | Customer API `phone` field | | Date of incorporation | Customer API `incorporation_date` field | | UBO phone number (per UBO) | [Associated Persons API](/api-reference/customers/associated-persons/update)`phone` field on each UBO | | UBO government ID image (per UBO) | [Associated Persons API](/api-reference/customers/associated-persons/update)`identifying_information` on each UBO with `image_front` | | UBO tax number (per UBO) | [Associated Persons API](/api-reference/customers/associated-persons/update)`identifying_information` on each UBO with type `cpf` | | Business Formation Document | Customer API`business_formation `field | | Proof of Source of Funds Document | Customer API `proof_of_source_of_funds `field | | Business Address | Customer API `registered_address `field with `street_line_1,city, country` | | Proof of Address Document
- Utility bill, bank statement | Customer API `proof_of_address `field
|
# COP integration guide Source: https://apidocs.bridge.xyz/get-started/guides/move-money/cop_integration_guide On and offramp with COP using Bre-b and Bank Transfer PSE/ACH To access COP and the Bre-b and Bank Transfer payment rails, please reach out to our team at [sales@bridge.xyz](mailto:sales@bridge.xyz) ## 🇨🇴 What we support * [Virtual Accounts](https://apidocs.bridge.xyz/platform/orchestration/virtual_accounts/virtual-account#cop) - Deposit COP via Bre-B and receive payments from 3rd party businesses. * [Transfers](https://apidocs.bridge.xyz/platform/orchestration/transfers/transfer#create-transfer) - Onramp COP via Bre-B and Bank Transfer (PSE/ACH) as a 1st party or from 3rd party businesses, offramp to any recipient. * [Liquidation Addresses](https://apidocs.bridge.xyz/platform/orchestration/liquidation_address/liquidation_address#multichain-%2B-multicurrency) - Offramps from stablecoin or crypto to COP via Bre-B and Bank Transfer. * [Supported Countries](https://apidocs.bridge.xyz/platform/customers/compliance/supported-countries-list) - We support COP on/offramps for customers in +100 countries. ## Related APIs * [COP Endorsement](https://apidocs.bridge.xyz/platform/customers/customers/endorsements#cop-endorsement) required to use the COP currency. If a customer already has the base endorsement, they should also have all of the info needed to grant the COP endorsement. * [COP Virtual Account](https://apidocs.bridge.xyz/platform/orchestration/virtual_accounts/virtual-account#cop) to onramp funds using a Bre-b key. * Create a [COP External Account](https://apidocs.bridge.xyz/platform/orchestration/external-accounts/external-accounts-api#cop-breb) to use as a [Transfer](https://apidocs.bridge.xyz/platform/orchestration/transfers/transfer#create-transfer) or [Liquidation Address](https://apidocs.bridge.xyz/platform/orchestration/liquidation_address/liquidation_address#multichain-%2B-multicurrency) offramp destination. ## Logistics * **Onramp minimum 100 COP** * **Offramp minimum 4000 COP** * No maximum * Bre-B transactions greater than 11,552,000 COP will be sent as a Bank Transfer. * 1st and 3rd party payouts supported. * 1st party payins supported, 3rd party payins supported from businesses. * COP Bre-b and Bank Transfers (PSE/ACH) complete in \~3 minutes however may take up to 30 minutes for larger values. ## **Request / Response Examples** ```bash Request expandable theme={null} curl --request POST \ --url https://api.bridge.xyz/v0/customers/#{request.customer_id}/external_accounts \ --header 'Api-Key: #{api_key}' \ --header 'Content-Type: application/json' \ --header 'Idempotency-Key: #{request.idempotency_key}' \ --data ' { "currency": "cop", "account_type": "bre_b", "account_owner_name": "First Last", "account_owner_type": "individual", "account": { "bre_b_key": "1234567890123456" } }' ``` ```json Response expandable theme={null} { "id": "bce9dbe4-bca7-42e0-9cc1-7482069019f1", "customer_id": "485c2b50-949c-412b-928a-f56fce42330d", "created_at": "2026-01-05T23:54:57.715Z", "updated_at": "2026-01-05T23:54:58.201Z", "account_owner_name": "Freddie Mercury", "active": true, "currency": "cop", "account_owner_type": "individual", "account_type": "bre_b", "account": { "bre_b_key": "1234567890123456" } ``` ```bash Request expandable theme={null} curl --request POST \ --url https://api.bridge.xyz/v0/customers/#{request.customer_id}/external_accounts \ --header 'Api-Key: #{api_key}' \ --header 'Content-Type: application/json' \ --header 'Idempotency-Key: #{request.idempotency_key}' \ --data ' { "currency": "cop", "account_type": "co_bank_transfer", "account_owner_name": "First Last", "first_name": "First Name", "last_name": "Last Name", "account_owner_type": "individual", "account": { "document_type": "cc", "account_number": "12345678910 "document_number": "1234567890", "bank_code": "1007", "account_type_detail": "savings", "phone_number": "+573001234567" } }' ``` ```json Response expandable theme={null} { "id": "bce9dbe4-bca7-42e0-9cc1-7482069019f1", "customer_id": "485c2b50-949c-412b-928a-f56fce42330d", "created_at": "2026-01-05T23:54:57.715Z", "updated_at": "2026-01-05T23:54:58.201Z", "account_owner_name": "First Last", "first_name": "First Name", "last_name": "Last Name", "active": true, "currency": "cop", "account_owner_type": "individual", "account_type": "co_bank_transfer", "account": { "document_type": "cc", "document_number": "1234567890", "bank_code": "1007", "account_type_detail": "savings", "phone_number": "+573001234567" } ``` ```bash Request expandable theme={null} curl --request POST \ --url https://api.bridge.xyz/v0/customers/#{request.customer_id}/virtual_accounts \ --header 'Api-Key: #{api_key}' \ --header 'Content-Type: application/json' \ --header 'Idempotency-Key: #{request.idempotency_key}' \ --data ' { "developer_fee_percent": "0.0", "source": { "currency": "cop" }, "destination": { "currency": "usdc", "payment_rail": "base", "address": "0xd0f43e6c8ee12ae4fe9d892c66c80dcb925f5d7c" } }' ``` ```curl Response theme={null} { "id": "65e93b85-ccf7-4c0b-a327-0cf80749e360", "status": "activated", "developer_fee_percent": "0.0", "customer_id": "485c2b50-949c-412b-928a-f56fce42330d", "created_at": "2026-01-03T00:23:23.724Z", "source_deposit_instructions": { "currency": "cop", "payment_rails": [ "bre_b" ] "bre_b_key": "12345678901234567890", "account_holder_name": "Bridge Developer Name" }, "destination": { "currency": "usdc", "payment_rail": "base", "address": "0xd0f43e6c8ee12ae4fe9d892c66c80dcb925f5d7c" } }' ``` ```bash Request expandable theme={null} curl --request POST \ --url https://api.bridge.xyz/v0/transfers \ --header 'Api-Key: #{api_key}' \ --header 'Content-Type: application/json' \ --header 'Idempotency-Key: #{request.idempotency_key}' \ --data ' { "developer_fee_percent": "0.0", "on_behalf_of": "485c2b50-949c-412b-928a-f56fce42330d", "amount": "20000", "source": { "currency": "cop", "payment_rail": "bre_b" }, "destination": { "payment_rail": "base", "currency": "usdc", "to_address": "0xd0f43e6c8ee12ae4fe9d892c66c80dcb925f5d7c" } }' ``` ```json Response expandable theme={null} { "id": "6ccbd781-8859-4944-8d88-66d8a0ff277b", "client_reference_id": null, "state": "awaiting_funds", "on_behalf_of": "485c2b50-949c-412b-928a-f56fce42330d", "currency": "cop", "amount": "20000", "developer_fee": "0.0", "source": { "payment_rail": "bre_b", "currency": "cop", }, "created_at": "2026-01-05T19:38:43.480Z", "updated_at": "2026-01-05T19:38:43.780Z", "destination": { "payment_rail": "base", "currency": "usdc", "to_address": "0xd0f43e6c8ee12ae4fe9d892c66c80dcb925f5d7c" }, "receipt": { "initial_amount": "20000", "developer_fee": "0.0", "exchange_fee": "0.0", "subtotal_amount": "20000", "gas_fee": "0.0" }, "developer_fee_percent": "0.0", "source_deposit_instructions": { "payment_rail": "bre_b", "currency": "cop", "amount": "20000", "deposit_message": "COP7depositmessage", "bre_b_key": "34567890", "account_holder_name": "Bridge Developer Name" } } ``` ```bash Request expandable theme={null} curl --request POST \ --url https://api.bridge.xyz/v0/transfers \ --header 'Api-Key: #{api_key}' \ --header 'Content-Type: application/json' \ --header 'Idempotency-Key: #{request.idempotency_key}' \ --data ' { "developer_fee_percent": "0.0", "on_behalf_of": "485c2b50-949c-412b-928a-f56fce42330d", "source": { "amount": "100", "currency": "usdc", "payment_rail": "bridge_wallet", "bridge_wallet_id": "bridge_wallet_id" }, "destination": { "currency": "cop", "payment_rail": "bre_b", "external_account_id": "bce9dbe4-bca7-42e0-9cc1-7482069019f1" "reference": "xxxxxxxxxxxx" // maximum 18 characters } }' ``` ```json Response expandable highlight={33-34} theme={null} { "id": "e94b1961-cf77-44db-a66f-07981f03fb1f", "client_reference_id": null, "state": "payment_submitted", "on_behalf_of": "485c2b50-949c-412b-928a-f56fce42330d", "currency": "usdc", "amount": "100", "developer_fee": "0.0", "source": { "payment_rail": "bridge_wallet", "currency": "usdc", "amount": "100", "from_address": "0xd0f43e6c8ee12ae4fe9d892c66c80dcb925f5d7c", "bridge_wallet_id": "d017bf1d-8372-4294-94ac-afd0cbc6357d" }, "created_at": "2026-01-06T17:29:22.796Z", "updated_at": "2026-01-06T17:29:22.874Z", "destination": { "payment_rail": "bre_b", "currency": "cop", "amount": "370000", "external_account_id": "bce9dbe4-bca7-42e0-9cc1-7482069019f1" }, "receipt": { "initial_amount": "100", "developer_fee": "0.0", "exchange_fee": "0.0", "subtotal_amount": "100", "gas_fee": "0.0", "final_amount": "370000", }, "created_at": "2020-01-01T00:00:00.000Z", "updated_at": "2020-01-02T00:00:00.000Z" } ``` ```bash Request expandable theme={null} curl --request POST \ --url https://api.bridge.xyz/v0/transfers \ --header 'Api-Key: #{api_key}' \ --header 'Content-Type: application/json' \ --header 'Idempotency-Key: #{request.idempotency_key}' \ --data ' { "developer_fee_percent": "0.0", "on_behalf_of": "#{request.customer_id}", "amount": "20000", "source": { "currency": "cop", "payment_rail": "co_bank_transfer", "co_bank_transfer": { "redirect_url": "https://example.com/pse/pay/abc123", "expiry_date": "2026-05-01T00:30:00.000Z", "sender_data":{ "full_name": "María López", "document_type": "cc", "document_number": "***7890", "email": "maria@example.com", "phone_number": "+573001234567" } } }, "destination": { "payment_rail": "base", "currency": "usdc", "to_address": "0xd0f43e6c8ee12ae4fe9d892c66c80dcb925f5d7c" } } ``` ```json Response expandable highlight={33-34} theme={null} { "id": "00000000-0000-0000-0000-000000000006", "state": "awaiting_funds", "on_behalf_of": "485c2b50-949c-412b-928a-f56fce42330d", "amount": "20000", "developer_fee": "0.0", "source": { "payment_rail": "co_bank_transfer", "currency": "cop", "co_bank_transfer": { "sender_data": { "full_name": "María López", "document_type": "cc", "document_number": "xxxxxxxx", "email": "maria@example.com", "phone_number": "+573xxxxxxxxxx" } } }, "destination": { "payment_rail": "base", "currency": "usdc", "to_address": "0xd0f43e6c8ee12ae4fe9d892c66c80dcb925f5d7c" }, "source_deposit_instructions": { "payment_rail": "co_bank_transfer", "amount": "20000", "currency": "cop", "start_url": "https://example.com/pse/pay/abc123", "redirect_url": "https://example.com/pse/pay/abc123", "expires_at": "2026-05-01T00:30:00.000Z", "account_holder_name": "Bridge Developer Name" }, "created_at": "2020-01-01T00:00:00.000Z", "updated_at": "2020-01-02T00:00:00.000Z" } ``` ```bash Request expandable theme={null} curl --request POST \ --url https://api.bridge.xyz/v0/transfers \ --header 'Api-Key: #{api_key}' \ --header 'Content-Type: application/json' \ --header 'Idempotency-Key: #{request.idempotency_key}' \ --data ' { "developer_fee_percent": "0.0", "on_behalf_of": "485c2b50-949c-412b-928a-f56fce42330d", "source": { "amount": "100", "currency": "usdc", "payment_rail": "bridge_wallet", "bridge_wallet_id": "d017bf1d-8372-4294-94ac-afd0cbc6357d" }, "destination": { "currency": "cop", "payment_rail": "co_bank_trasnfer", "external_account_id": "external_account_id" "reference": "xxxxxxxxxx" // maximum 18 characters } }' ``` ```json Response expandable highlight={33-34} theme={null} { "id": "e94b1961-cf77-44db-a66f-07981f03fb1f", "client_reference_id": null, "state": "payment_submitted", "on_behalf_of": "485c2b50-949c-412b-928a-f56fce42330d", "currency": "usdc", "amount": "100", "developer_fee": "0.0", "source": { "payment_rail": "bridge_wallet", "currency": "usdc", "amount": "100", "from_address": "0xd0f43e6c8ee12ae4fe9d892c66c80dcb925f5d7c", "bridge_wallet_id": "d017bf1d-8372-4294-94ac-afd0cbc6357d" }, "created_at": "2026-01-06T17:29:22.796Z", "updated_at": "2026-01-06T17:29:22.874Z", "destination": { "payment_rail": "co_bank_transfer", "currency": "cop", "amount": "370000", "external_account_id": "bce9dbe4-bca7-42e0-9cc1-7482069019f1", "reference": "xxxxxxxxxx" }, "receipt": { "initial_amount": "100", "developer_fee": "0.0", "exchange_fee": "0.0", "subtotal_amount": "100", "gas_fee": "0.0", "final_amount": "370000", }, "created_at": "2020-01-01T00:00:00.000Z", "updated_at": "2020-01-02T00:00:00.000Z" } ``` # Crypto Travel Rule Guide Source: https://apidocs.bridge.xyz/get-started/guides/move-money/crypto-travel-rule # Overview Global Travel Rule regulations require financial institutions and crypto providers to collect and share basic information about their customers for certain crypto transfers. For Bridge integrations, the practical rule is simple: if Bridge needs originator or beneficiary information for a crypto movement, your application will need to collect it and send it to Bridge to support Travel Rule compliance. Bridge stores and uses this data during compliance workflows, but your application is usually the system that knows: * who the customer is transacting with (“the counterparty”) * whether the wallet should be treated as `self_custodied`, `hosted`, or `external` * whether the counterparty remains the same for every movement on a route or varies for each transaction Official references: * U.S.: [31 CFR 1010.410(f)](https://www.ecfr.gov/current/title-31/subtitle-B/chapter-X/part-1010/section-1010.410) and [FinCEN virtual currency guidance](https://www.fincen.gov/system/files/2019-05/FinCEN%20Guidance%20CVC%20FINAL%20508.pdf) * E.U.: [Regulation (EU) 2023/1113](https://eur-lex.europa.eu/legal-content/EN/TXT/?uri=CELEX%3A32023R1113) This guide is about implementation decisions: when data is required, what data to collect, and where to send it. # Eligible Transactions You should determine whether Travel Rule data is required before funds move. As a developer integrating with Bridge, there are two separate checks to make: ## Amount requirements Crypto Travel Rule requirements depend on jurisdiction. Note that even if you are not yourself a regulated entity, Bridge is a regulated EU entity and MSB and is required to collect originator and beneficiary information for qualifying transactions. This means you will need to pass this data to Bridge as a condition of processing these flows. A transaction is **EEA-related (no threshold)** if any of the following is true: * You are an EEA-regulated CASP. This applies to all your transactions regardless of customer location or currency * The transaction has a EUR or EURC leg (e.g. EUR pay-in to a vIBAN, EUR payout, EURC conversion, etc.) regardless of the customer's location * The end customer is EEA-based, regardless of currency If any part of the transaction is serviced through Bridge EEA-regulated infrastructure (including SEPA or EURC services), EU Travel Rule requirements apply regardless of end-user residency. A transaction is **US-related (above USD 3,000)** if any of the following is true: * You are a US-regulated MSB/VASP. This applies to all your transactions above \$3,000 regardless of customer location or currency * The transaction has a USD or USDC leg, regardless of customer location * The end customer is US-based, regardless of currency | Developer type | Customer type | Flow | Travel Rule data required by Bridge? | | --------------------- | ------------------------ | --------------- | ------------------------------------ | | EEA-regulated CASP | Any | Any | Yes, all transactions, no threshold | | US-regulated MSB/VASP | Any | Any | Yes, above \$3,000 | | Unregulated | EEA customer | Any currency | Yes, no threshold | | Unregulated | US customer | Any currency | Yes, above \$3,000 | | Unregulated | Non-EEA | EUR or EURC leg | Yes, no threshold | | Unregulated | Non-EEA, non-US customer | USD or USDC leg | Yes, above \$3,000 | | Unregulated | Non-EEA, non-US customer | No USD/EUR leg | No | Ownership verification and attestation are required for any E.E.A.-related transaction exceeding €1,000 involving a `self_custodied` or `hosted` wallet tied to a Bridge customer. ## Source and flow requirements Source matters because Bridge may or may not receive Travel Rule data from the sending provider. If the source wallet belongs to another Crypto Asset Service Provider (CASP), that provider should send the required Travel Rule data to Bridge. In that case, you generally do not need to collect and submit the sender's data yourself. Otherwise, you should collect and submit Travel Rule data for: * incoming crypto from a self-custodied wallet * incoming crypto from any source where no crypto provider is transmitting Travel Rule data to Bridge * onramps where Bridge will send crypto to a destination wallet, because Bridge needs beneficiary information before payout In practice, this usually means: * collect **originator** data for inbound crypto deposits into Bridge * collect **beneficiary** data for outbound crypto payouts from Bridge, including onramps and withdrawals to destination wallets # Understanding the travel rule data Bridge accepts the same `travel_rule_data` shape whether you attach it on a reusable resource or submit it with the one-off endpoint. For eligible crypto deposits and withdrawals, we require originator information about the party sending the crypto and beneficiary information about the party receiving the crypto from either you or from another crypto-asset service provider (“CASP”). ```json theme={null} { "originator": { "name": "Jane Smith", "address": { "street_line_1": "123 Market St", "street_line_2": null, "city": "San Francisco", "state": "CA", "postal_code": "94105", "country": "USA" }, "identifying_information": { "type": "national_id", "number": "1234567890", "issuing_country": "USA" }, "birth_date": "2000-01-31", "place_of_birth": { "city": "San Francisco", "country": "USA" }, "wallet_type": "self_custodied", "wallet_attested_ownership_at": "2026-04-01T12:00:00Z" }, "beneficiary": { "is_self": true, "wallet_type": "external" } } ``` How `is_self` works: * Set `is_self: true` when that party is the same person or business as the Bridge customer on the resource. Bridge uses the verified customer name and address already on file instead of relying on `name` and `address` in the payload * Set `is_self: false` when that party differs from the Bridge customer. In this case, you need to provide the counterparty details including that party's `name` and `address` How wallet fields work: * `wallet_type: "external"` means the wallet is exchange-owned or a smart contract * `wallet_type: "self_custodied"` means the wallet is customer-owned * `wallet_type: "hosted"` means the wallet is developer-owned or developer-hosted For `self_custodied` and `hosted` wallets, you must validate wallet ownership before sending Travel Rule data. `wallet_attested_ownership_at` is required and should reflect when that ownership check was completed. # How to share travel rule data Bridge supports two ways to send Travel Rule data. You need to choose the one that matches how stable the counterparty is. ## 1. Attach `travel_rule_data` on the reusable resource Use the resource's `travel_rule_data` field on create or update for: * transfers * virtual accounts * liquidation addresses Use this option only when the same originator and beneficiary should apply to every future money movement through that resource. Good fits: * self-to-self routes * treasury flows * a fixed business counterparty * a route that is intentionally dedicated to one known sender or one known receiver Do not use this option when: * multiple senders may fund the same virtual account * multiple counterparties may use the same liquidation address * the destination wallet changes from movement to movement * you only learn the real counterparty after an event or drain exists ## 2. Submit one-off data with `POST /v0/travel_rule_data/:id` Use `POST /v0/travel_rule_data/:id` when the Travel Rule payload belongs to one specific money movement. This is the right choice when: * a reusable route can be used by different counterparties over time * you need to attach data to a specific transfer * you only know the sender after a virtual account event is created * you only know the relevant counterparty after a drain or bridge wallet event exists Current supported one-off resource IDs include: * transfer IDs * virtual account event IDs * bridge wallet event IDs * drain IDs The payload is the same `travel_rule_data` object shown above. ```bash theme={null} curl --location --request POST 'https://api.bridge.xyz/v0/travel_rule_data/' \ --header 'Api-Key: ' \ --header 'Content-Type: application/json' \ --data-raw '{ "originator": { "name": "Jane Smith", "address": { "street_line_1": "123 Market St", "street_line_2": null, "city": "San Francisco", "state": "CA", "postal_code": "94105", "country": "USA" }, "identifying_information": { "type": "national_id", "number": "1234567890", "issuing_country": "USA" }, "birth_date": "2000-01-31", "place_of_birth": { "city": "San Francisco", "country": "USA" }, "wallet_type": "self_custodied", "wallet_attested_ownership_at": "2026-04-01T12:00:00Z" }, "beneficiary": { "is_self": true, "wallet_type": "external" } }' ``` Decision rule: * if the parties are stable for every future use of the resource, attach `travel_rule_data` on create or update * if the parties are specific to one movement, use `POST /v0/travel_rule_data/:id` # Integration Checklist 1. Decide whether the movement is Travel Rule-eligible based on jurisdiction and amount. 2. Decide which side you need to populate: `originator`, `beneficiary`, or both. This is based on whether there is a crypto deposit and/or withdrawal involved and whether another crypto-asset service provider (“CASP”) already has the data. 3. Determine who is sending and receiving the funds. Use `is_self: true` if that party is the customer, and make sure the Bridge customer record already has the correct legal name and address. Otherwise use `is_self: false` and include the required identifying information. 4. Determine whether the wallet is `external`, `self_custodied`, or `hosted`. If the wallet is `self_custodied` or `hosted`, validate wallet ownership and send `wallet_attested_ownership_at` as the past timestamp when that check was completed. 5. Decide whether the counterparty is stable across all future uses of the resource. If the counterparty is stable, send `travel_rule_data` on the transfer, virtual account, or liquidation address create or update call. If the counterparty is movement-specific, wait until the relevant transfer, event, or drain exists and then call `POST /v0/travel_rule_data/:id`. # Related docs * [Transfers](/platform/orchestration/transfers/transfer) * [Source and destination updates](/platform/orchestration/transfers/transfer-updates) * [Virtual accounts](/platform/orchestration/virtual_accounts/virtual-account) * [Virtual account events](/platform/orchestration/virtual_accounts/virtual-account-events) * [Liquidation address](/platform/orchestration/liquidation_address/liquidation_address) * [Drains](/platform/orchestration/liquidation_address/drains) # FAQ Source: https://apidocs.bridge.xyz/get-started/guides/move-money/crypto-travel-rule-faq Frequently asked questions about Bridge's Crypto Travel Rule requirements ## Scope & Applicability The Travel Rule applies to on-chain crypto transactions where funds are sent on-chain to or from a wallet outside of Bridge's ecosystem. It does not apply to funds flows that stay within Bridge custody or fiat flows with no on-chain leg outside of Bridge. As a general rule, if the transaction involves moving crypto on-chain outside of Bridge's custody, the Travel Rule applies. | Jurisdiction | Threshold | | ------------ | ------------------------------------------------------------------------------------------------------------ | | **US** | > \$3,000 USD equivalent | | **EEA** | All EEA-related transactions (no minimum); wallet attestation required for EUR or EURC transactions > €1,000 | A transaction is EEA-related and subject to Travel Rule requirements with no minimum threshold if any of the following is true: * Bridge (or your entity) is an EEA-regulated CASP: applies to all your transactions regardless of customer location or currency * The transaction has a EUR or EURC leg (e.g., EUR pay-in to a vIBAN, EUR payout, EURC conversion): applies regardless of customer location * The end customer is EEA-based: applies regardless of currency The **€1,000 threshold applies only to wallet ownership attestation**, and only when the transaction has a EUR or EURC leg. All EEA-related transactions require Travel Rule data with no minimum threshold. Generally, the residential or legal (registered) address should be used. For businesses, EEA scope is determined by the business's registered address, not the residential addresses of individual UBOs or associated persons. **No.** If funds never leave Bridge's custody and no on-chain transfer is made to an external VASP or self-hosted wallet, there is no Travel Rule obligation. For example: * Fiat into a Bridge custodial wallet (onramp only, no outbound disbursement): **No Travel Rule data required** * Bridge wallet to Bridge wallet (internal transfer): **No Travel Rule data required** * Bridge wallet to fiat bank account (no on-chain leg): **No Travel Rule data required** **Yes.** You are permitted to attach `travel_rule_data` to any money movement even if it is not strictly required for that specific flow. This is a perfectly valid approach. ## Originator & Beneficiary: Identifying the Parties The **originator is whoever is actually sending the funds.** This may be your customer or a third party. The key distinction is whether the transfer is self-to-self or involves an identifiable third party: * **Self-to-self transfer** (your customer sends to themselves): Set `originator.is_self: true`. Bridge will automatically pull the originator's information from the customer's profile. * **Identifiable third-party originator** (a third party sends funds and their identity is known or obtainable): The third party is the originator. Where you are able to identify them (for example, on outbound transactions you initiate or inbound transfers where your customer knows the sender), you are expected to collect and submit their `name` and `address`. Bridge will work through its own resolution process internally and will reach out to you directly if additional information is needed. * **Unidentifiable originator** (funds arrive from an unknown source, e.g., open liquidation addresses): This is a distinct scenario with its own obligations and resolution framework. See the question below on unidentifiable originators. A **documented, good-faith effort** to collect originator data wherever possible is required. Where an originator cannot be identified, the obligation does not disappear. `is_self: true` means the person sending the funds *is* your customer sending to themselves. It is not a substitute for collecting third-party originator data when that data is obtainable. The **third party is the originator.** Where their identity is known or can be obtained (for instance, your customer knows the sender), you are expected to collect and submit their information. You do **not** need wallet ownership attestation for the third party. * A friend sends fiat to your customer's Virtual US Account and the customer can identify them: **Originator = the friend** (no attestation required) * A business partner deposits funds to your customer's Liquidation Address and the customer confirms who sent it: **Originator = the business partner** (no attestation required) Where the originator cannot be identified even after reasonable effort (such as with open liquidation addresses that accept funds from unknown senders), different obligations apply. See the question below on unidentifiable originators. * **Originator:** The third-party sender (their third-party information, collected from your customer) * **Beneficiary:** Your customer (the receiving party); use `is_self: true` Some product models involve liquidation addresses that accept inbound on-chain transfers from any sender, including parties unknown to both the developer and their customer. This is a recognized scenario with defined developer obligations. **1. Submit what you have.** You are required to submit originator data you can reasonably obtain. If your customer cannot identify the sender, you are not expected to produce information you do not have. If partial information is available (e.g., the customer knows a name but not an address), submit what you can. Bridge will work through its own resolution process on the back end and will reach out to you directly if additional information is needed. **2. Document your product model with Bridge.** If your use case structurally involves inbound transfers from unknown third parties (e.g., you operate open liquidation addresses), this should be communicated to Bridge. This documents that the scenario is known, intentional, and that your obligations as a partner are understood, including downstream AML responsibilities on your end-customer accounts. **3. Bridge will manage unresolvable cases on a risk basis.** For transfers above €1,000 where the originator cannot be identified, as well as any other transfers with missing required Travel Rule data, Bridge will take a risk-based approach to determine how those transfers are handled. Bridge will reach out to you directly if action or additional information is needed. The beneficiary is the **ultimate bank account holder**, not Bridge. If the bank account holder is the same person as your customer, use `is_self: true`. If it is a different person, provide the bank account holder's details as the beneficiary. * **Originator:** Your customer (who initiated the transfer). Set `is_self: true` on the originator and Bridge will pull their info from the customer profile. * **Beneficiary:** The third-party recipient (name, address, and `legal_entity_identifier` if a business) You collect the beneficiary's data from your customer. You do **not** need wallet ownership attestation from the third-party recipient. ## Required Fields This depends on whether the originator is your customer (self-to-self) or a third party. **Self-to-self (`originator.is_self: true`, where your customer is the sender):** * Set `is_self: true`. Bridge automatically pulls all originator data (name, address, `identifying_information`) from the customer's on-file profile. * You only need to provide the beneficiary if they are different from the customer. **Third-party originator (a third party is the sender):** For **individual third-party originators:** * `name` * `address` * `wallet_type` (if applicable; no attestation required) * `identifying_information` (ID number, DoB, etc.) when available For **business third-party originators:** * `name` * `address` * `legal_entity_identifier` (e.g., VAT number or other official business identifier) For **individual beneficiaries:** * `name` * `address` * `wallet_type` and `wallet_attested_ownership_at` (if applicable) For **business beneficiaries:** * `name` * `address` * `legal_entity_identifier` Date of birth and place of birth are **not** required at the beneficiary level. They are only needed for the originator when no physical ID is available. **No.** If you set `is_self: true` for the beneficiary (indicating the beneficiary is the same person as your customer), you do **not** need to provide the other beneficiary fields (`name`, `address`, `wallet_type`, `wallet_attested_ownership_at`). **Yes, for self-to-self transfers.** When `originator.is_self: true`, Bridge will automatically pull the originator's full profile (including `name`, `address`, and `identifying_information`) from the customer's profile, as long as you provide the beneficiary information (if the beneficiary is different from the customer). You do not need to re-submit data that was already collected at KYC/KYB onboarding. **For third-party originators**, Bridge has no profile on file for the third party. You are expected to take reasonable measures to obtain and submit their `name` and `address`. `identifying_information` (ID number, DoB, etc.) should be submitted if available. Any official government-issued business identifier, such as: * VAT registration number * EIN (US Employer Identification Number) * Company registration number * LEI (Legal Entity Identifier) ## wallet\_type, Attestation & Bridge Wallets | Value | Meaning | | ---------------- | -------------------------------------------------------------------------------- | | `hosted` | The wallet is custodied by you (the developer) on behalf of the customer | | `external` | The wallet is custodied by an external exchange or CASP (e.g., Coinbase, Kraken) | | `self_custodied` | The customer personally controls the wallet (e.g., MetaMask, Ledger) | `wallet_type` represents the custody arrangement, not the technology. It applies to the depositing wallet for inbound flows and the receiving wallet for outbound flows. **No.** Bridge-custodied wallets do not require attestation. You only need to note the wallet type as `hosted` (if you custody it) or you can omit attestation fields entirely for Bridge wallets. Attestation is required when: * The **sending wallet is self-hosted** (`self_custodied`) **AND** * The transaction is through Bridge's **EU entity** (EUR transaction) **AND** * The transaction exceeds **€1,000** in a single transaction or in several transactions which appear to be linked. For **US flows**, wallet attestation is **not required** when sending to or receiving from a self-hosted wallet. Attestation is **never** required for: * Bridge-custodied wallets * Third-party originators or beneficiaries (non-customers); collect their name and address, but no wallet attestation * Fiat-only flows **No.** Wallet ownership attestation is not required for third-party originators or recipients. When a third party is the originator, you collect their `name` and `address` from your customer, but no wallet attestation is needed. Attestation only applies to wallets owned by your own customers. Where your flow allows for it, a dropdown asking the customer to indicate the wallet type is sufficient. For example: "Was the sending wallet self-hosted, at an exchange, or hosted by a provider?" The customer (your platform's account holder) can provide this information. You do not need to independently verify it; the attestation obligation is out of scope for third-party originators. Where your flow does not allow you to collect this information, submit what you have and Bridge will work with you on the gaps. A signature challenge is the most common method, but Bridge does **not** require a specific method. Acceptable approaches include: * **Cryptographic signature challenge** (e.g., via WalletConnect, MetaMask personal signature) * **Micro-deposit / satoshi test** (send a small amount and verify the customer received it) * **Third-party vendor tools** that manage wallet verification Bridge will QA attestations on a sample basis to ensure they are captured and recorded accurately. Reach out if you would like vendor recommendations. **Not applicable.** These fields are specific to crypto wallets. For transactions where the destination or source is a fiat bank account, `wallet_type` and `wallet_attested_ownership_at` should be omitted. If the sending wallet is `external` (custodied by another CASP like Coinbase), you can declare `wallet_type: external` and that CASP is expected to transmit Travel Rule data directly to Bridge through standard VASP-to-VASP protocols. In practice, it is still best to submit the beneficiary information on your end regardless, to ensure Bridge has what it needs. ## Flow-Specific Scenarios | Flow | TR Required? | Submit What? | Notes | | ------------------------------------------------------------------------ | ---------------------- | ----------------------------------------------------------------------------------- | -------------------------------------------------------------------------- | | **Fiat into Bridge custodial wallet** (onramp, no outbound disbursement) | No | N/A | No on-chain transfer to external VASP | | **Fiat into Bridge custodial wallet, then disbursement** | Yes (disbursement leg) | Originator + beneficiary | TR applies to the disbursement on-chain leg | | **External/self-hosted wallet into Bridge wallet** (crypto deposit) | Yes | Originator (your customer or an identifiable third party) + beneficiary (`is_self`) | Wallet type of depositing wallet; attestation if self-hosted, EU, and >€1K | | **External VASP wallet (e.g., Coinbase) into Bridge wallet** | Yes | Beneficiary (`is_self` or beneficiary details) | Coinbase expected to send TR data; also submit beneficiary info | | **Bridge wallet to external/self-hosted wallet** (crypto payout) | Yes | Originator (your customer) + beneficiary info | No attestation needed for third-party recipient | | **Bridge wallet to fiat bank account** (offramp) | No on-chain TR | Beneficiary name if different from customer | No crypto wallet TR fields applicable | | **All-fiat flow** (no on-chain leg) | No | N/A | TR only applies to on-chain legs | | **Bridge wallet to Bridge wallet** (internal) | No | N/A | Stays within Bridge ecosystem | | **Bridge wallet to external PSP** (for downstream fiat payouts) | Yes | Originator + beneficiary (`is_self` if applicable) | Set `wallet_type: external`; `is_self` if user is the ultimate beneficiary | For these flows, you may not know a payment is happening in advance. In that case: * Funds will not be held or frozen while Travel Rule data is pending * You can submit the Travel Rule data after the deposit, referencing the event ID from the webhook * Bridge will reach out if data is missing and is not provided in a timely manner **No.** For offramps converting crypto to fiat: * If `is_self: true`, no other fields are required * If the beneficiary is a third party, provide `name` and `address`; `wallet_type` and `wallet_attested_ownership_at` are not applicable to fiat destinations ## Timing & API Integration The intent of the Travel Rule is for required data to travel with the payment. Depending on your flow, there are two ways to achieve this: 1. **Inline at creation:** Include `travel_rule_data` when creating a transfer, Virtual Account, or Liquidation Address 2. **One-off afterward:** Submit Travel Rule data separately via a POST to `/v0/travel_rule_data/{id}`, referencing the relevant resource ID (transfer ID, virtual account event ID, drain ID, etc.) The second option is especially useful for inbound flows (VA deposits, Liquidation Address pushes) where you cannot predict the payment in advance. Use the one-off POST endpoint: `POST /v0/travel_rule_data/{id}` where `{id}` is the resource ID of the relevant money movement (e.g., the transfer ID, virtual account event ID). See the [API reference](/api-reference/travel-rule/submit-travel-rule-data). **Yes.** For self-to-self transfers (where the originator and beneficiary are the same customer), you can use a reusable resource instead of submitting TR data on every individual transfer. ## Travel Rule Compliance Expectations and Enforcement Bridge will **not hold or freeze funds** due to missing Travel Rule data at the time of a transfer. However: 1. Bridge will reach out to you (the developer/partner) directly to collect the missing data 2. If data is not provided after outreach, Bridge will apply enhanced controls and may reject the transfer in case of increased risk. Bridge takes a risk-based approach with the goal of having complete Travel Rule data for all in-scope transactions. **Bridge will always reach out to you** (the developer/partner), not to your end customers. If Travel Rule data is missing, Bridge will contact you to resolve it. **No.** Bridge does not block or hold funds for lack of Travel Rule data at the time of the transaction. Funds will be immediately available in the user's wallet as normal. Controls are only imposed if data remains missing after Bridge reaches out. # EUR integration guide Source: https://apidocs.bridge.xyz/get-started/guides/move-money/eur-integration-guide On and offramp with EUR using SEPA Instant and SEPA Credit payments To access EUR and the SEPA payment rail, please reach out to our team at [sales@bridge.xyz](mailto:sales@bridge.xyz) ## 🇪🇺 What we support * [Virtual Accounts](https://apidocs.bridge.xyz/platform/orchestration/virtual_accounts/virtual-account#eur) - Deposit EUR using SEPA instant and SEPA credit payments using a unique virtual IBAN. * [Transfers](https://apidocs.bridge.xyz/platform/orchestration/transfers/transfer#create-transfer) - Onramp and offramps using memos. * [Liquidation Addresses](https://apidocs.bridge.xyz/platform/orchestration/liquidation_address/liquidation_address#multichain-%2B-multicurrency) - Offramp from stablecoin or crypto to EUR via SEPA. * [Supported Countries](https://apidocs.bridge.xyz/platform/customers/compliance/supported-countries-list) - We support EUR on & offramps for customers in +100 countries. ## Logistics * Onramps: 1PP & 3PP onramps supported. For 3PP deposits from individuals, please contact your account manager * Offramps: 1PP & 3PP onramps & offramps supported to both individuals and businesses. * **Support SEPA payments to & from IBANs issued in countries and territories:** Aland Islands, Albania, Andorra, Austria, Azores, Belgium, Bulgaria, Canary Islands, Ceuta, Croatia, Cyprus, Czech Republic, Denmark, Estonia, Finland, France, French Guiana, Germany, Gibraltar, Greece, Guadeloupe, Guernsey, Hungary, Iceland, Ireland, Isle of Man, Italy, Jersey, Latvia, Liechtenstein, Lithuania, Luxembourg, Madeira, Malta, Martinique, Mayotte, Melilla, Moldova, Monaco, Montenegro, Netherlands, North Macedonia, Norway, Poland, Portugal, Reunion, Romania, Saint Barthélemy, Saint Martin (French part), Saint Pierre and Miquelon, San Marino, Serbia, Slovakia, Slovenia, Spain, Sweden, Switzerland, United Kingdom, Vatican City. *** ## **Request / Response Examples** #### Related APIs * [SEPA Endorsement](https://apidocs.bridge.xyz/platform/customers/customers/endorsements#sepa-endorsement) required to use the EUR currency and SEPA payment rail. * Create a [EUR Virtual Account](https://apidocs.bridge.xyz/platform/orchestration/virtual_accounts/virtual-account#eur) to onramp funds using a unique IBAN. * Create a [EUR External Account](https://apidocs.bridge.xyz/platform/orchestration/external-accounts/external-accounts-api#eur-sepa) to use as a [Transfer](https://apidocs.bridge.xyz/platform/orchestration/transfers/transfer#create-transfer) or [Liquidation Address](https://apidocs.bridge.xyz/platform/orchestration/liquidation_address/liquidation_address#multichain-%2B-multicurrency) offramp destination. ```bash Request expandable theme={null} curl --request POST \ --url https://api.bridge.xyz/v0/customers/#{request.customer_id}/external_accounts \ --header 'Api-Key: #{api_key}' \ --header 'Content-Type: application/json' \ --header 'Idempotency-Key: 011235' \ --data ' { "currency": "eur", "bank_name": "Deutsche Bank", "account_owner_name": "Ada Lovelace", "first_name": "Ada", "last_name": "Lovelace", "account_owner_type": "individual", "account_type": "iban", "iban": { "account_number": "DE89370400440532013000", "bic": "DEUTDEDBFRA", "country": "DEU" }, "address": { "street_line_1": "Taunusanlage 12", "city": "Frankfurt", "postal_code": "60325", "country": "DEU" } }' ``` ```bash Request expandable theme={null} curl --request POST \ --url https://api.bridge.xyz/v0/customers/#{request.customer_id}/virtual_accounts \ --header 'Api-Key: #{api_key}' \ --header 'Content-Type: application/json' \ --header 'Idempotency-Key: #{request.idempotency_key}' \ --data ' { "developer_fee_percent": "0.0", "source": { "currency": "eur" }, "destination": { "currency": "usdc", "payment_rail": "tempo", "bridge_wallet_id": "bw_1234" } }' ``` ```bash Request expandable theme={null} curl --request POST \ --url https://api.bridge.xyz/v0/transfers \ --header 'Api-Key: #{api_key}' \ --header 'Content-Type: application/json' \ --header 'Idempotency-Key: 011235' \ --data ' { "developer_fee_percent": "0.0", "on_behalf_of": "#{request.customer_id}", "amount": "2.01", "source": { "currency": "eur", "payment_rail": "sepa" }, "destination": { "currency": "usdc", "payment_rail": "tempo", "bridge_wallet_id": "bw_1234" } }' ``` ```bash Request expandable theme={null} curl --request POST \ --url https://api.bridge.xyz/v0/transfers \ --header 'Api-Key: #{api_key}' \ --header 'Content-Type: application/json' \ --header 'Idempotency-Key: 011235' \ --data ' { "developer_fee_percent": "0.0", "on_behalf_of": "cust_1234", "source": { "currency": "usdc", "payment_rail": "bridge_wallet", "bridge_wallet_id": "bw_789" }, "destination": { "amount": "3.00", "currency": "eur", "payment_rail": "sepa", "external_account_id": "ea_5678", "reference": "abcdefghijklmnopqrstuvwxyzabcdefg" // SEPA reference remittance details } }' ``` # FX guide: convert from fiat to fiat Source: https://apidocs.bridge.xyz/get-started/guides/move-money/fiat_to_fiat Use Bridge's APIs to convert from one fiat currency to another using a method we call the **Stablecoin Sandwich.** ## What is a stablecoin sandwich? A stablecoin sandwich uses stablecoin as mechanism to convert between two fiat currencies. ![](https://files.readme.io/eeaa306977b407fb0e88e7f5fa35af9d1770427e257ddc824216f8bba0107d5e-image.png) ## Funds flow ![](https://files.readme.io/720124437d1fcadf40b8dc98ecb91ce916ade0d576d57682105e89cf57f614c3-image.png) *** ## One-time setup ![](https://files.readme.io/130fa3ff6edc181acd3604c45d7308a2d14a62e1e3bd73c0cb175d9d67763803-image.png) *** This wallet will hold stablecoins (USDC) used as the source for FX transfers. You can provision the wallet under your own customer id that you use for developing on Bridge. ```bash Request expandable theme={null} curl --location 'https://api.bridge.xyz/v0/customers/cust_alice/wallets' \ --header 'Api-Key: ' \ --header 'Idempotency-Key: w1' \ --header 'Content-Type: application/json' \ --data '{ "chain":"solana" }' ``` Use the returned wallet `id` in all future orchestration and payout requests. ```json Response expandable theme={null} { "id": "ec89f8d1-7d0d-47a1-b92f-96f5eb25600e", "chain": "base", "address": "0x58b34dc21b5253053f53cf5f143c421266441058", "tags": [], "created_at": "2025-07-05T00:45:02.206Z", "updated_at": "2025-07-05T00:45:02.206Z" } ``` This is where your USD deposits (via ACH or Wire) will land. Funds will be auto-converted to USDC into your Bridge Wallet. ```bash Request expandable theme={null} curl --location --request POST 'https://api.bridge.xyz/v0/customers/cust_alice/virtual_accounts' \ --header 'Content-Type: application/json' \ --header 'Api-Key: ' \ --header 'Idempotency-Key: ' \ --data-raw '{ "source": { "currency": "usd" }, "destination": { "payment_rail": "bridge_wallet", "currency": "usdc", "bridge_wallet_id": "wallet_id" } }' ``` ```json Response expandable theme={null} { "id": "1a400dae-f7fc-4f75-8105-212a14d4132d", "status": "activated", "customer_id": "cust_alice", "created_at": "2025-07-04T22:10:34.564Z", "source_deposit_instructions": { "currency": "usd", "bank_name": "Lead Bank", "bank_address": "1801 Main St., Kansas City, MO 64108", "bank_routing_number": "101019644", "bank_account_number": "215268120000", "bank_beneficiary_name": "Alice", "bank_beneficiary_address": "923 Folsom Street, 302, San Francisco, California 941070000, US", "payment_rail": "ach_push", "payment_rails": [ "ach_push", "wire" ] }, "destination": { "payment_rail": "bridge_wallet", "currency": "usdc", "bridge_wallet_id": "wallet_id" } } ``` Create an external account representing the recipient of the MXN funds. This only needs to be created once per recipient. ```bash Request expandable theme={null} curl --location 'https://api.bridge.xyz/v0/customers/23c2d462-4c69-4c5a-b31a-88d035d7e8ae/external_accounts' \ --header 'Idempotency-Key: ea-6' \ --header 'Content-Type: application/json' \ --header 'Accept: application/json' \ --header 'Api-Key: ' \ --data '{ "currency": "mxn", "account_owner_type": "individual", "first_name": "Carlos", "last_name": "Ramirez", "account_type": "clabe", "account_owner_name": "Carlos Ramirez", "bank_name": "BBVA Bancomer", "clabe": { "account_number": "626899715090851234" }, "account_name": "Carlos Personal Bank Account", "address": { "street_line_1": "Av. Reforma", "city": "Mexico City", "state": "CDMX", "postal_code": "06600", "country": "MEX" } }' ``` Now you're ready to FX! In step 1-3, you've created a virtual account that will receive USD deposits. With every USD deposit, we will forward those funds as USDC to your Bridge wallet. The last step is to go from USDC to MXN! **Important:** For crypto returns, use a **static return address** for the USDC leg. Avoid `refund_to_sender` to prevent returns going to an **omnibus wallet**. ```bash Request expandable theme={null} curl --location --request POST 'https://api.bridge.xyz/v0/transfers' \ --header 'Api-Key: ' \ --header 'Idempotency-Key: ' \ --data-raw '{ "on_behalf_of": "cust_alice", "amount": "1000.0", "source": { "currency": "usdc", "payment_rail": "bridge_wallet", "bridge_wallet_id": "wallet_id" }, "destination": { "currency": "mxn", "payment_rail": "spei", "external_account_id": "mxn_external_account_id" } }' ``` Bridge executes the FX conversion at market rate and delivers MXN via **SPEI**, an instant 24/7/365 payment rail in Mexico. ## Webhooks Bridge emits webhooks for every orchestration state: * `payment_initiated` * `payment_processed` * `cancelled` Use these to trigger business logic, notifications, or retries. ## Alternative methods * In the above example, we used a transfer to create one time FX payment. * If you want to automatically convert USD to MXN upon receiving a deposit, you can: * In Step 2, point your virtual account to a liquidation address. * Point the liquidation address to the destination external bank account. We design our APIs to be powerful and flexible lego blocks for developers to build a wide range of use cases. # Fixed outputs integration guide Source: https://apidocs.bridge.xyz/get-started/guides/move-money/fixed_outputs_integration_guide Fixed outputs provide the ability to specify a fixed amount in the destination currency when creating a Transfer in Bridge’s API. Bridge will determine the amount of source currency input required based on the current exchange rate. The source of a fixed output transfer can either be a Bridge wallet or an external customer wallet. **Supported Currency Pairs:** * USDC/USDB/USDT \<> EUR, MXN, BRL, GBP, COP, USDT ## Creating a Transfer **Request** ```text theme={null} POST https://api.bridge.xyz/v0/transfers { "on_behalf_of": "cust_alice", "source": { "currency": "usdc", "payment_rail": "bridge_wallet" // "ethereum" if sourcce is external wallet, "bridge_wallet_id": "wallet_id" // "from_address": "0x.." if source is external wallet }, "destination": { "currency": "eur", "payment_rail": "sepa", "external_account_id": "eur_external_account_id", "sepa_reference": "3fd33e83-5011-4425-b135-16a17d049fba", "amount": "850.0" } } ``` **Response** ```text theme={null} { "id": "euro_payout_transfer_id", "client_reference_id": null, "on_behalf_of": "cust_alice", "state": "pending", "currency": "usd", "amount": "1009.50", "source": { "payment_rail": "bridge_wallet", "currency": "usdc", "from_address": "bridge_wallet_address" }, "destination": { "payment_rail": "sepa", "currency": "eur", "external_account_id": "eur_external_account_id", "sepa_reference": "3fd33e83-5011-4425-b135-16a17d049fba", "amount": "850.0" }, "receipt": { "initial_amount": "1009.50", "developer_fee": "0.0", "exchange_fee": "0.0", "gas_fee": "0.0" }, "created_at": "2025-07-02T00:00:00.000Z", "updated_at": "2025-07-02T00:00:00.000Z" } ``` **Transfers API response and webhook payload for completed payout** ```text theme={null} { "id": "eur_transfer_id", "state": "payment_processed", "on_behalf_of": "cust_alice", "currency": "usd", "amount": "1009.50", "source": { "payment_rail": "bridge_wallet", "currency": "usdc", "from_address": "bridge_wallet_address" }, "destination": { "payment_rail": "sepa", "currency": "eur", "external_account_id": "eur_external_account_id", "sepa_reference": "3fd33e83-5011-4425-b135-16a17d049fba", "amount": "850.0" }, "created_at": "2025-07-06T04:26:04.350Z", "updated_at": "2025-07-06T04:26:08.726Z", "receipt": { "initial_amount": "1004.50",, "subtotal_amount": "1009.50", "converted_amount": "850.00, "final_amount": "850.00", "exchange_rate": "0.842001", "developer_exchange_fee": { "amount": "5.83", "currency": "eur" } } } ``` ## Fetching the exchange rate The [Exchange Rates API](https://apidocs.bridge.xyz/api-reference/exchange-rates/get-current-exchange-rate-between-two-currencies) provides a reference exchange rate for the requested currency pair including any Bridge fees taken out of the FX exchange. The response provides the rates in both directions for that currency pair. **Request** ```text theme={null} GET https://api.bridge.xyz/v0/exchange_rates?from=usd&to=mxn ``` **Response** ```text theme={null} { "midmarket_rate": "18.6556", "sell_rate": "18.5624", "buy_rate": "18.7488", } ```  Bridge provides three rates in the response: * **Mid market rate**: the reference exchange rate before any Bridge FX fees. Bridge uses this rate to calculate the effective rates below which include fees. * **Sell rate**: how much MXN output received for each 1 USD of input including fees (from → to) * **Buy rate**: how much MXN input required for each 1 USD of output including fees (to → from) ## Fixing the Source Amount By default, Bridge will calculate the source amount required for the destination amount including some padding to accommodate exchange rate fluctuations. When Bridge calculates the source amount, any funds received exceeding the minimum amount required for the destination amount will be distributed as a Developer Exchange Fee. Bridge also supports the developer calculating the source amount themselves to provide a `source.amount` in the Transfer creation request. By doing so, the developer can collect any funds received exceeding the source amount provided (and greater than the minimum amount required) for the destination amount as a Developer Exchange Fee. By default, when only `destination.amount` is specified, Bridge adds a 1% buffer to the calculated source amount to cover exchange rate fluctuations. Any excess funds are distributed as a Developer Exchange Fee. To override the buffer, specify both `source.amount` and `destination.amount`, calculated from the Exchange Rates API rate. By doing so, the developer can collect any funds received exceeding the source amount provided (and greater than the minimum amount required) for the destination amount as a Developer Exchange Fee. **Request** ```text theme={null} POST https://api.bridge.xyz/v0/transfers { "on_behalf_of": "cust_alice", "source": { "currency": "usdc", "payment_rail": "bridge_wallet", "bridge_wallet_id": "wallet_id", "amount": "1020.0" }, "destination": { "currency": "eur", "payment_rail": "sepa", "external_account_id": "eur_external_account_id", "sepa_reference": "3fd33e83-5011-4425-b135-16a17d049fba", "amount": "850.0" }, } ``` **Response** ```text theme={null} { "id": "euro_payout_transfer_id", "client_reference_id": null, "on_behalf_of": "cust_alice", "state": "pending", "currency": "usd", "amount": "1020.0", "source": { "payment_rail": "bridge_wallet", "currency": "usdc", "from_address": "bridge_wallet_address", "amount": "1020.0" }, "destination": { "payment_rail": "sepa", "currency": "eur", "external_account_id": "eur_external_account_id", "sepa_reference": "3fd33e83-5011-4425-b135-16a17d049fba", "amount": "850.0", "exchange_rate_spread": "1.04" // 1.04%. Calculated by Bridge from provided source/destination amounts }, "receipt": { "initial_amount": "1020.0", "developer_fee": "0.0", "exchange_fee": "0.0", "gas_fee": "0.0" }, "created_at": "2025-07-02T00:00:00.000Z", "updated_at": "2025-07-02T00:00:00.000Z" } ``` #### Transfer Creation Validations Bridge will calculate the amount required and fail early if the `source.amount` specified is insufficient to achieve the `destination.amount`: ```text theme={null} { "code": "invalid_parameters", "message": "Please resubmit the following parameters that are either missing or invalid", "source": { "location": "body", "key": { "amount": "must be at least 1009.50 USDC for destination amount of €850.00 EUR" } } } ``` ## Typical Flow Screenshot 2026 04 24 At 10 49 47 AM The 1% padding in the source amount will typically exceed any exchange rate variance. Excess funds are credited to the developer in a dedicated Fixed Outputs Excess Funds wallet. [This Bridge wallet can be created and used as a source or destination in Bridge’s Orchestration APIs](https://apidocs.bridge.xyz/platform/wallets/move-money#moving-money-using-orchestration), like any other Bridge wallet. In addition to the Developer Exchange Fee where variable fees can be applied through the spread on the exchange rate presented to the customer, the Developer Fee is a fixed amount expressed in USD. If a Developer Fee is specified in the Transfer creation request input, Bridge will also take this into account when calculating the required source amount: ```text theme={null} { "code": "invalid_parameters", "message": "Please resubmit the following parameters that are either missing or invalid", "source": { "location": "body", "key": { "amount": "must be at least 1030.00 USDC for destination amount of €850.00 EUR with developer fee of $10.00 USD" } } } ``` ## Unhappy Paths Flow These transfers behave similarly to a limit order. The 1% padding included in the source.amount is intended to cover typical FX variation. If the exchange rate moves from time of Transfer creation such that the amount of padding is now insufficient when the transfer is funded, Bridge will inform the developer the transfer is underfunded, requiring the developer to add more funds to allow this Transfer to complete at the desired destination amount. The Fixed Outputs Excess Funds wallet is a valid source for adding additional funds. The intent is that this account typically accumulates excess funds from source amount padding. In rare cases where the market is experiencing unusually high volatility, the developer can use this account to fund the deficit. ### Adding additional funds for an underfunded Transfer Screenshot 2026 04 24 At 10 49 11 AM **Underfunded Transfer API response and webhook payload** If the source funds are insufficient to provide the required source amount, Bridge updates the Transfer status to `underfunded` in the API and sends a webhook. ```text theme={null} { "id": "euro_payout_transfer_id", "client_reference_id": null, "on_behalf_of": "cust_alice", "state": "underfunded", "currency": "usd", "amount": "1004.50", "source": { "payment_rail": "bridge_wallet", "currency": "usdc", "from_address": "bridge_wallet_address" }, "destination": { "payment_rail": "sepa", "currency": "eur", "external_account_id": "eur_external_account_id", "sepa_reference": "3fd33e83-5011-4425-b135-16a17d049fba", "amount": "850.0", "exchange_rate_spread": "3.0" }, "additional_funding_instructions": { "destination": { "payment_rail": "bridge_transfer", "bridge_transfer_id": "euro_payout_transfer_id", }, "amount": "10.00" // minimum amount, can send more }, "receipt": { "initial_amount": "1004.50", "developer_fee": "0.0", "exchange_fee": "0.0", "gas_fee": "0.0" }, "created_at": "2025-07-02T00:00:00.000Z", "updated_at": "2025-07-02T00:00:00.000Z" } ``` To add additional funds, use the the additional funding instructions as the destination for a new Transfer: **Request** ```text theme={null} POST https://api.bridge.xyz/v0/transfers { "source": { "currency": "usdc", "payment_rail": "bridge_wallet", "bridge_wallet_id": "developer_exchange_fee_account", }, "destination": { "payment_rail": "bridge_transfer", "bridge_transfer_id": "euro_payout_transfer_id", }, "amount": "10.0" } ``` The Fixed Outputs Excess Funds wallet is only one example of a valid source for additional funds. Any valid orchestration source can also be used to add more funds: crypto rails, ACH, wire, prefunded accounts. The additional funding instructions can also be used to add more customer funds instead of developer funds to the Transfer. **Payload for completed Transfer when additional funds added** ```text theme={null} { "id": "eur_transfer_id", "state": "payment_processed", "on_behalf_of": "cust_alice", "currency": "usd", "amount": "1004.50", "source": { "payment_rail": "bridge_wallet", "currency": "usdc", "from_address": "bridge_wallet_address" }, "destination": { "payment_rail": "sepa", "currency": "eur", "external_account_id": "eur_external_account_id", "sepa_reference": "3fd33e83-5011-4425-b135-16a17d049fba", "amount": "850.0" }, "additional_funding": [ { "source_id": "addl_funds_transfer_id", "source_rail": "solana", "amount": "10.0", "currency": "usdc" } ], "created_at": "2025-07-06T04:26:04.350Z", "updated_at": "2025-07-06T04:26:08.726Z", "receipt": { "initial_amount": "1004.50",, "subtotal_amount": "1004.50", "converted_amount": "850.00", "final_amount": "850.00", "exchange_rate": "0.842001", "developer_exchange_fee" : { "amount": "5.83", "currency": "eur" } } } ``` `receipt.exchange_rate` is based on the original source input amount and provides the exchange rate from the customer’s perspective. It always matches (destination amount) / (*original* source amount). It does not take into account any additional funds added to address a funding shortfall. # GBP integration guide Source: https://apidocs.bridge.xyz/get-started/guides/move-money/gbp_fps_integration_guide On and offramp with GBP using Faster Payments To access GBP and the FPS payment rail, please reach out to our team at [sales@bridge.xyz](mailto:sales@bridge.xyz) ## 🇬🇧 What we support * [Virtual Accounts](https://apidocs.bridge.xyz/platform/orchestration/virtual_accounts/virtual-account#gbp) - Deposit GBP via Faster Payments and receive payments from 3rd party businesses. * [Transfers](https://apidocs.bridge.xyz/platform/orchestration/transfers/transfer#create-transfer) - Onramp GBP via Faster Payments as a 1st party or from 3rd party businesses, offramp to any recipient. * [Liquidation Addresses](https://apidocs.bridge.xyz/platform/orchestration/liquidation_address/liquidation_address#multichain-%2B-multicurrency) - Offramps from stablecoin or crypto to GBP via Faster Payments. * [Supported Countries](https://apidocs.bridge.xyz/platform/customers/compliance/supported-countries-list) - We support GBP on/offramps for customers in +100 countries. ## Related APIs * [Faster Payments Endorsement](https://apidocs.bridge.xyz/platform/customers/customers/endorsements#pix-endorsement) required to use the GBP currency and Faster Payments rail. If a customer already has the SEPA endorsement, they should also have all of the info needed to grant the Faster Payments endorsement. * Create a [GBP Virtual Account](https://apidocs.bridge.xyz/platform/orchestration/virtual_accounts/virtual-account#brl) to onramp funds using a unique account number * Create a [GBP External Account](https://apidocs.bridge.xyz/platform/orchestration/external-accounts/external-accounts-api#gbp-fps) to use as a [Transfer](https://apidocs.bridge.xyz/platform/orchestration/transfers/transfer#create-transfer) or [Liquidation Address](https://apidocs.bridge.xyz/platform/orchestration/liquidation_address/liquidation_address#multichain-%2B-multicurrency) offramp destination. ## Logistics * **Onramp minimum £2.00 GBP** * **Offramp minimum 3.00 of the source currency** * No maximum, transfers received or sent over £1M GBP will use the BACS payment rail. * 1st and 3rd party payouts supported * 1st party payins supported, 3rd party payins supported from businesses. * Faster Payments complete in \~5 minutes however may take up to 30 minutes for larger values. * BACS payments complete in 3 business days. ## **Request / Response Examples** ```bash Request expandable theme={null} curl --request POST \ --url https://api.bridge.xyz/v0/customers/#{request.customer_id}/external_accounts \ --header 'Api-Key: #{api_key}' \ --header 'Content-Type: application/json' \ --header 'Idempotency-Key: #{request.idempotency_key}' \ --data ' { "currency": "gbp", "bank_name": "Bank of England", "account_owner_name": "First Last", "first_name": "First", "last_name": "Last", "account_owner_type": "individual", "account": { "sort_code": "123456", "account_number": "34567890" }, "account_type": "gb" }' ``` ```json Response expandable theme={null} { "id": "bce9dbe4-bca7-42e0-9cc1-7482069019f1", "customer_id": "485c2b50-949c-412b-928a-f56fce42330d", "created_at": "2026-01-05T23:54:57.715Z", "updated_at": "2026-01-05T23:54:58.201Z", "bank_name": "Bank of England", "account_name": null, "account_owner_name": "Freddie Mercury", "active": true, "currency": "gbp", "account_owner_type": "individual", "account_type": "gb", "first_name": "Freddie", "last_name": "Mercury", "business_name": null, "account": { "sort_code": "123456", "account_number": "34567890" } ``` ```bash Request expandable theme={null} curl --request POST \ --url https://api.bridge.xyz/v0/customers/#{request.customer_id}/virtual_accounts \ --header 'Api-Key: #{api_key}' \ --header 'Content-Type: application/json' \ --header 'Idempotency-Key: #{request.idempotency_key}' \ --data ' { "developer_fee_percent": "0.0", "source": { "currency": "gbp" }, "destination": { "currency": "usdc", "payment_rail": "base", "bridge_wallet_id": "#{request.bridge_wallet_id}" } }' ``` ```curl Response theme={null} { "id": "65e93b85-ccf7-4c0b-a327-0cf80749e360", "status": "activated", "developer_fee_percent": "0.0", "customer_id": "485c2b50-949c-412b-928a-f56fce42330d", "created_at": "2026-01-03T00:23:23.724Z", "source_deposit_instructions": { "currency": "gbp", "account_number": "34567890", "sort_code": "123456", "account_holder_name": "Bridge Building Sp. Z.o.o.", "bank_name": "Banking Circle S.A.", "bank_address": "2 Boulevard de la Foire, L-1528 Luxembourg", "bank_beneficiary_name": "Bridge Building Sp. Z.o.o.", "bank_beneficiary_address": "2 Boulevard de la Foire, L-1528 Luxembourg", "payment_rails": [ "faster_payments" ] }, "destination": { "currency": "usdc", "payment_rail": "base", "address": "0xd0f43e6c8ee12ae4fe9d892c66c80dcb925f5d7c" } }' ``` ```bash Request expandable theme={null} curl --request POST \ --url https://api.bridge.xyz/v0/transfers \ --header 'Api-Key: #{api_key}' \ --header 'Content-Type: application/json' \ --header 'Idempotency-Key: #{request.idempotency_key}' \ --data ' { "developer_fee_percent": "0.0", "on_behalf_of": "#{request.customer_id}", "amount": "2.01", "source": { "currency": "gbp", "payment_rail": "faster_payments" }, "destination": { "currency": "usdc", "payment_rail": "base", "bridge_wallet_id": "#{request.bridge_wallet_id}" } }' ``` ```json Response expandable theme={null} { "id": "6ccbd781-8859-4944-8d88-66d8a0ff277b", "client_reference_id": null, "state": "awaiting_funds", "on_behalf_of": "485c2b50-949c-412b-928a-f56fce42330d", "currency": "gbp", "amount": "2.01", "developer_fee": "0.0", "source": { "payment_rail": "faster_payments", "currency": "gbp", "external_account_id": null }, "created_at": "2026-01-05T19:38:43.480Z", "updated_at": "2026-01-05T19:38:43.780Z", "destination": { "payment_rail": "base", "currency": "usdc", "to_address": "0xd0f43e6c8ee12ae4fe9d892c66c80dcb925f5d7c" }, "receipt": { "initial_amount": "2.01", "developer_fee": "0.0", "exchange_fee": "0.0", "subtotal_amount": "2.01", "gas_fee": "0.0" }, "developer_fee_percent": "0.0", "source_deposit_instructions": { "payment_rail": "faster_payments", "currency": "gbp", "amount": "2.01", "deposit_message": "BRGTPU5UDJWN4KW5PJM6", "account_number": "34567890", "sort_code": "123456", "bank_name": "Banking Circle S.A.", "bank_address": "2 Boulevard de la Foire, L-1528 Luxembourg" } } ``` ```bash Request expandable theme={null} curl --request POST \ --url https://api.bridge.xyz/v0/transfers \ --header 'Api-Key: #{api_key}' \ --header 'Content-Type: application/json' \ --header 'Idempotency-Key: #{request.idempotency_key}' \ --data ' { "developer_fee_percent": "0.0", "on_behalf_of": "#{request.customer_id}", "source": { "currency": "usdc", "payment_rail": "bridge_wallet", "bridge_wallet_id": "#{request.bridge_wallet_id}" }, "destination": { "amount": "3.00", "currency": "gbp", "payment_rail": "faster_payments", "external_account_id": "#{request.external_account_id}" "reference": "abcdefghijklmnopqr" // maximum 18 characters } }' ``` ```json Response expandable theme={null} { "id": "e94b1961-cf77-44db-a66f-07981f03fb1f", "client_reference_id": null, "state": "payment_submitted", "on_behalf_of": "485c2b50-949c-412b-928a-f56fce42330d", "currency": "usd", "amount": "4.12", "developer_fee": "0.0", "source": { "payment_rail": "bridge_wallet", "currency": "usdc", "amount": "4.12", "from_address": "0xd0f43e6c8ee12ae4fe9d892c66c80dcb925f5d7c", "bridge_wallet_id": "d017bf1d-8372-4294-94ac-afd0cbc6357d" }, "created_at": "2026-01-06T17:29:22.796Z", "updated_at": "2026-01-06T17:29:22.874Z", "destination": { "payment_rail": "faster_payments", "currency": "gbp", "amount": "3.0", "external_account_id": "bce9dbe4-bca7-42e0-9cc1-7482069019f1" }, "receipt": { "initial_amount": "4.12", "developer_fee": "0.0", "exchange_fee": "0.0", "subtotal_amount": "4.12", "gas_fee": "0.0" }, "developer_fee_percent": "0.0" } ``` # MXN integration guide Source: https://apidocs.bridge.xyz/get-started/guides/move-money/mxn-spei-integration-guide On and offramp with MXN using SPEI (Sistema de Pagos Electrónicos Interbancarios) To access MXN and the SPEI payment rail, please reach out to our team at [sales@bridge.xyz](mailto:sales@bridge.xyz) ## 🇲🇽 What we support * [Virtual Accounts](https://apidocs.bridge.xyz/platform/orchestration/virtual_accounts/virtual-account#mxn) - Deposit MXN via SPEI and receive payments from 3rd party businesses. * [Transfers](https://apidocs.bridge.xyz/platform/orchestration/transfers/transfer#create-transfer) - Onramp MXN via SPEI as a 1st party or from 3rd party businesses, offramp to any recipient. * [Liquidation Addresses](https://apidocs.bridge.xyz/platform/orchestration/liquidation_address/liquidation_address#multichain-%2B-multicurrency) - Offramp from stablecoin or crypto to MXN via SPEI. * [Supported Countries](https://apidocs.bridge.xyz/platform/customers/compliance/supported-countries-list) - We support MXN on/offramps for customers in +100 countries. ## Related APIs * [SPEI Endorsement](https://apidocs.bridge.xyz/platform/customers/customers/endorsements#spei-endorsement) required to use the MXN currency and SPEI payment rail. * Create an [MXN Virtual Account](https://apidocs.bridge.xyz/platform/orchestration/virtual_accounts/virtual-account#mxn) to onramp funds using a unique CLABE number. * Create an [MXN External Account](https://apidocs.bridge.xyz/platform/orchestration/external-accounts/external-accounts-api#mxn-spei) to use as a [Transfer](https://apidocs.bridge.xyz/platform/orchestration/transfers/transfer#create-transfer) or [Liquidation Address](https://apidocs.bridge.xyz/platform/orchestration/liquidation_address/liquidation_address#multichain-%2B-multicurrency) offramp destination. ## Transaction Minimums, Limits, Times * Refer our route explorer [here](/get-started/introduction/what-we-support/payment-routes). * No maximum * 1st and 3rd party payins and payouts supported * SPEI operates 24/7 and settles in seconds ## **Request / Response Examples** ```bash Request expandable theme={null} curl --request POST \ --url https://api.bridge.xyz/v0/customers/#{request.customer_id}/external_accounts \ --header 'Api-Key: #{api_key}' \ --header 'Content-Type: application/json' \ --header 'Idempotency-Key: #{request.idempotency_key}' \ --data ' { "currency": "mxn", "bank_name": "BBVA Mexico", "account_owner_name": "First Last", "first_name": "First", "last_name": "Last", "account_owner_type": "individual", "account_type": "clabe", "clabe": { "account_number": "012180015300000000" }, "address": { "street_line_1": "Paseo de la Reforma 510", "city": "Ciudad de Mexico", "state": "CMX", "postal_code": "06600", "country": "MEX" } }' ``` ```json Response expandable theme={null} { "id": "bce9dbe4-bca7-42e0-9cc1-7482069019f1", "customer_id": "485c2b50-949c-412b-928a-f56fce42330d", "created_at": "2026-01-05T23:54:57.715Z", "updated_at": "2026-01-05T23:54:58.201Z", "bank_name": "BBVA Mexico", "account_name": null, "account_owner_name": "First Last", "active": true, "currency": "mxn", "account_owner_type": "individual", "account_type": "clabe", "first_name": "First", "last_name": "Last", "business_name": null, "clabe": { "last_4": "0000" }, "address": { "street_line_1": "Paseo de la Reforma 510", "city": "Ciudad de Mexico", "state": "CMX", "postal_code": "06600", "country": "MEX" } } ``` ```bash Request expandable theme={null} curl --request POST \ --url https://api.bridge.xyz/v0/customers/#{request.customer_id}/virtual_accounts \ --header 'Api-Key: #{api_key}' \ --header 'Content-Type: application/json' \ --header 'Idempotency-Key: #{request.idempotency_key}' \ --data ' { "developer_fee_percent": "0.0", "source": { "currency": "mxn" }, "destination": { "currency": "usdc", "payment_rail": "base", "bridge_wallet_id": "#{request.bridge_wallet_id}" } }' ``` ```json Response expandable theme={null} { "id": "65e93b85-ccf7-4c0b-a327-0cf80749e360", "status": "activated", "developer_fee_percent": "0.0", "customer_id": "485c2b50-949c-412b-928a-f56fce42330d", "created_at": "2026-01-03T00:23:23.724Z", "source_deposit_instructions": { "currency": "mxn", "clabe": "646180115400000007", "account_holder_name": "Bridge Building S.A. de C.V.", "bank_name": "STP", "deposit_message": "BRGTPU5UDJWN4KW5PJM6", "payment_rails": [ "spei" ] }, "destination": { "currency": "usdc", "payment_rail": "base", "address": "0xd0f43e6c8ee12ae4fe9d892c66c80dcb925f5d7c" } } ``` ```bash Request expandable theme={null} curl --request POST \ --url https://api.bridge.xyz/v0/transfers \ --header 'Api-Key: #{api_key}' \ --header 'Content-Type: application/json' \ --header 'Idempotency-Key: #{request.idempotency_key}' \ --data ' { "developer_fee_percent": "0.0", "on_behalf_of": "#{request.customer_id}", "amount": "35.00", "source": { "currency": "mxn", "payment_rail": "spei" }, "destination": { "currency": "usdc", "payment_rail": "base", "bridge_wallet_id": "#{request.bridge_wallet_id}" } }' ``` ```json Response expandable theme={null} { "id": "6ccbd781-8859-4944-8d88-66d8a0ff277b", "client_reference_id": null, "state": "awaiting_funds", "on_behalf_of": "485c2b50-949c-412b-928a-f56fce42330d", "currency": "mxn", "amount": "35.00", "developer_fee": "0.0", "source": { "payment_rail": "spei", "currency": "mxn", "external_account_id": null }, "created_at": "2026-01-05T19:38:43.480Z", "updated_at": "2026-01-05T19:38:43.780Z", "destination": { "payment_rail": "base", "currency": "usdc", "to_address": "0xd0f43e6c8ee12ae4fe9d892c66c80dcb925f5d7c" }, "receipt": { "initial_amount": "35.00", "developer_fee": "0.0", "exchange_fee": "0.0", "subtotal_amount": "35.00", "gas_fee": "0.0" }, "developer_fee_percent": "0.0", "source_deposit_instructions": { "payment_rail": "spei", "currency": "mxn", "amount": "35.00", "deposit_message": "BRGTPU5UDJWN4KW5PJM6", "clabe": "646180115400000007", "bank_name": "STP" } } ``` ```bash Request expandable theme={null} curl --request POST \ --url https://api.bridge.xyz/v0/transfers \ --header 'Api-Key: #{api_key}' \ --header 'Content-Type: application/json' \ --header 'Idempotency-Key: #{request.idempotency_key}' \ --data ' { "developer_fee_percent": "0.0", "on_behalf_of": "#{request.customer_id}", "source": { "currency": "usdc", "payment_rail": "bridge_wallet", "bridge_wallet_id": "#{request.bridge_wallet_id}" }, "destination": { "amount": "35.00", "currency": "mxn", "payment_rail": "spei", "external_account_id": "#{request.external_account_id}", "spei_reference": "concepto de pago" // maximum 40 characters, alphanumeric and spaces only } }' ``` ```json Response expandable theme={null} { "id": "e94b1961-cf77-44db-a66f-07981f03fb1f", "client_reference_id": null, "state": "payment_submitted", "on_behalf_of": "485c2b50-949c-412b-928a-f56fce42330d", "currency": "mxn", "amount": "35.00", "developer_fee": "0.0", "source": { "payment_rail": "bridge_wallet", "currency": "usdc", "amount": "2.10", "from_address": "0xd0f43e6c8ee12ae4fe9d892c66c80dcb925f5d7c", "bridge_wallet_id": "d017bf1d-8372-4294-94ac-afd0cbc6357d" }, "created_at": "2026-01-06T17:29:22.796Z", "updated_at": "2026-01-06T17:29:22.874Z", "destination": { "payment_rail": "spei", "currency": "mxn", "amount": "35.00", "external_account_id": "bce9dbe4-bca7-42e0-9cc1-7482069019f1", "tracking_number": "021180040900000001" }, "receipt": { "initial_amount": "2.10", "developer_fee": "0.0", "exchange_fee": "0.0", "subtotal_amount": "2.10", "gas_fee": "0.0" }, "developer_fee_percent": "0.0" } ``` # Offramp with liquidation addresses Source: https://apidocs.bridge.xyz/get-started/guides/move-money/offramp_liquidation **Liquidation Addresses** are permanent on-chain addresses that auto-route incoming crypto to a fiat or crypto destination—enabling **crypto → fiat** or **crypto → crypto** conversions. When funds are sent (e.g. USDC), Bridge converts and forwards them based on the `destination_payment_rail`: * **Real-time rails** (e.g. wire, sepa, blockchains): funds are sent instantly * **Batch rails** (e.g. ach): funds are queued and processed daily *** ## Routing crypto deposits to a fiat destination You can create a liquidation address with a fiat destination (off ramp). ![](https://files.readme.io/3d2b2a30ff341b81b4b0aac0c8b185f2c7b9af672858ecf6456065de7e642a18-image.png) For fiat destinations, you need to first register your customer's external bank account with us. The following example walks through the option to create external bank accounts via the Bridge API. You also have the option to use Plaid to let your customers link bank accounts, please refer [External Accounts](/platform/orchestration/external-accounts/external-accounts-api) for more details. ```bash Request expandable theme={null} curl --location 'https://api.bridge.xyz/v0/customers//external_accounts' \ --header 'Idempotency-Key: ea-7' \ --header 'Content-Type: application/json' \ --header 'Accept: application/json' \ --header 'Api-Key: ' \ --data '{ "currency": "usd", "account_type": "us", "bank_name": "Lead Bank", "account_name": "Ada Checking Account", "first_name": "Ada", "last_name": "Lovelace", "account_owner_type": "individual", // specifies an individual account "account_owner_name": "Ada Lovelace", "account": { "routing_number": "101019644", "account_number": "215268129123", "checking_or_savings": "checking" }, "address": { "street_line_1": "923 Folsom Street", "country": "USA", "state": "CA", "city": "San Francisco", "postal_code": "941070000" } }' ``` ```json Response expandable theme={null} { "id": "039c270f-a038-40be-be7b-43f550ce0678", // external account id "customer_id": "23c2d462-4c69-4c5a-b31a-88d035d7e8ae", "created_at": "2025-07-05T19:03:50.819Z", "updated_at": "2025-07-05T19:03:51.251Z", "bank_name": "Lead Bank", "account_name": "Ada Checking Account", "account_owner_name": "Ada Lovelace", "active": true, "currency": "usd", "account_owner_type": "individual", "account_type": "us", "first_name": "Ada", "last_name": "Lovelace", "business_name": null, "account": { "last_4": "9123", "routing_number": "101019644", "checking_or_savings": "checking" }, "beneficiary_address_valid": true, "last_4": "9123" } ``` ```bash Request expandable theme={null} curl --location 'https://api.bridge.xyz/v0/customers/23c2d462-4c69-4c5a-b31a-88d035d7e8ae/external_accounts' \ --header 'Idempotency-Key: ea-5' \ --header 'Content-Type: application/json' \ --header 'Accept: application/json' \ --header 'Api-Key: ' \ --data '{ "currency": "eur", "account_type": "iban", "bank_name": "Modulr Finance, Ireland Branch", "account_owner_name": "Ada Lovelace", "iban": { "account_number": "IE26MODR99035507970528", "bic": "MODRIE22XXX", "country": "IRL" }, "address": { "street_line_1": "923 Folsom Street", "country": "USA", "state": "CA", "city": "San Francisco", "postal_code": "941070000" }, "account_name": "GGCF Corporate", "first_name": "Ada", "last_name": "Lovelace", "account_owner_type": "individual" }' ``` ```curl Response theme={null} { "id": "c8948ce6-26ac-4d37-a336-742f961a76f3", "customer_id": "23c2d400-4c69-4c5a-b31a-88d035d7e8ae", "created_at": "2025-07-05T18:45:50.728Z", "updated_at": "2025-07-05T18:45:51.373Z", "bank_name": "Modulr Finance, Ireland Branch", "account_name": "GGCF Corporate", "account_owner_name": "Ada Lovelace", "active": true, "currency": "eur", "account_owner_type": "individual", "account_type": "iban", "first_name": "Ada", "last_name": "Lovelace", "business_name": null, "iban": { "last_4": "0528", "bic": "MODRIE22XXX", "country": "IRL" } } ``` ```bash Request expandable theme={null} curl --location 'https://api.bridge.xyz/v0/customers/23c2d462-4c69-4c5a-b31a-88d035d7e8ae/external_accounts' \ --header 'Idempotency-Key: ea-6' \ --header 'Content-Type: application/json' \ --header 'Accept: application/json' \ --header 'Api-Key: ' \ --data '{ "currency": "mxn", "account_type": "clabe", "account_owner_name": "Ada Lovelace", "clabe": { "account_number": "626899715090851234" }, "account_name": "Ada Checking Account", "bank_name": "BBVA Bancomer", "first_name": "Ada", "last_name": "Lovelace", "account_owner_type": "individual", "address": { "street_line_1": "Av. Reforma", "city": "Mexico City", "state": "CDMX", "postal_code": "06600", "country": "MEX" } }' ``` ```json Response expandable theme={null} { "id": "2bb5b814-0128-49a8-977a-77b1bc1cdee2", "customer_id": "23c2d462-4c69-4c5a-b31a-88d035d7e8ae", "created_at": "2025-07-05T18:59:42.163Z", "updated_at": "2025-07-05T18:59:42.713Z", "bank_name": "BBVA Bancomer", "account_name": "Ada Checking Account", "account_owner_name": "Ada Lovelace", "active": true, "currency": "mxn", "account_owner_type": "individual", "account_type": "clabe", "first_name": "Ada", "last_name": "Lovelace", "business_name": null, "clabe": { "last_4": "1234" } } ``` With the liquidation address, you can configure * the chain and currency you want to receive funds on * the destination chain, currency, and details you want to send funds to * Make sure to configure the `return_address` so we know where to send funds to if your customer's transaction fails or is returned by the destination. ```bash Request expandable theme={null} curl --location 'https://api.bridge.xyz/v0/customers//liquidation_addresses' \ --header 'Content-Type: application/json' \ --header 'Accept: application/json' \ --header 'Idempotency-Key: 10' \ --header 'Api-Key: ' \ --data '{ "currency": "usdc", "chain": "ethereum", "external_account_id": "ad77b283-b000-4025-8197-023ea7e7d00", "destination_wire_message": "Wire payment for Ada Lovelace", "destination_payment_rail": "wire", "destination_currency": "usd" "return_address": "0x12343vrever323023fbverb94t24t23t" // very important to configure }' ``` You'll get a response containing the blockchain address we've created. ```json Response expandable theme={null} { "id": "5ef43832-cb43-4c64-8678-e87c518b364f", // unique Bridge identifier for the liquidation address "chain": "ethereum", "address": "0x27013f44e72fea1788a00602c8abaf7ef57725f1", // this is the liquidation address "currency": "usdc", "external_account_id": "ad77b283-b0de-4025-8197-023ea7e7d978", "customer_id": "23c2d462-4c69-4c5a-b31a-88d03", "destination_wire_message": "Wire payment for Ada Lovelace", "destination_payment_rail": "wire", "destination_currency": "usd", "created_at": "2025-07-05T00:10:05.670Z", "updated_at": "2025-07-05T00:10:05.670Z", "state": "active" } ``` *** ## Routing crypto deposits to a crypto destination You also have the option to create a liquidation address with a crypto destination (crypto to crypto) ```bash Request expandable theme={null} curl --location 'https://api.bridge.xyz/v0/customers/23c2d462-4c69-4c5a-b31a-88d035d7e8ae/liquidation_addresses' \ --header 'Content-Type: application/json' \ --header 'Accept: application/json' \ --header 'Idempotency-Key: 11' \ --header 'Api-Key: sk-live-5a0f22402efbc824139e5a7e719da2d5' \ --data '{ "currency": "usdt", "chain": "ethereum", "destination_payment_rail": "ethereum", "destination_currency": "usdc", "destination_address": "0x27013f44e72fea1788a00602", "return_address": "0x2700w1240xrw1200cva0394", }' ``` The response will contain the crypto address ready to start taking payments. ```json Response expandable theme={null} { "id": "24dc5860-c208-4ded-82ad-451cd88c6acd", "chain": "ethereum", "address": "0x50fba60922caa21375038824b4212f234v", "currency": "usdt", "customer_id": "23c2d462-4c69-4c5a-b31a-88d03", "destination_payment_rail": "ethereum", "destination_currency": "usdc", "destination_address": "0x27013f44e72fea1788a00602", "return_address": "0x2700w1240xrw1200cva0394", "created_at": "2025-07-05T00:17:04.779Z", "updated_at": "2025-07-05T00:17:04.779Z", "state": "active" } ``` *** ## Monitoring liquidation address payments ### Drain History When funds are deposited to a Liquidation Address, Bridge automatically “drains” those funds—converting and forwarding them to the configured destination. Each drain operation creates a **Drain Record**, which reflects the lifecycle of that individual payment. * You can retrieve the full drain history for a given liquidation address using the [Get drain history of a liquidation address](/api-reference/liquidation-addresses/get-drain-history-of-a-liquidation-address)) endpoint. * Bridge will also send you a **real time webhook** for new drains and state changes. ### Drain States The `state` field tracks the status of each drain through its lifecycle. Here are the possible values: | State | Description | | ------------------- | ----------------------------------------------------------------------------------------------------------------------------------------- | | `in_review` | The transaction is temporarily held for review. This usually clears automatically. If unresolved after 24 hours, Bridge will contact you. | | `funds_received` | Bridge has received crypto and is preparing the outgoing payment. | | `payment_submitted` | The outgoing payment has been sent. Confirmation pending (varies by payment rail). | | `payment_processed` | Payment successfully completed. Depending on the rail, metadata may include a `tx_hash`, `imad`, or `trace_number`. | | `undeliverable` | Bridge could not deliver the payment (e.g. invalid account or unsupported asset). | | `returned` | Payment was sent but later rejected and returned to Bridge. | | `refunded` | Funds that were returned have been re-sent to an alternative destination. | | `error` | A system or network issue prevented processing. Manual intervention may be required. | | `canceled` | The payment was canceled before submission—usually due to AML/EFE review or because it did not meet the minimum transfer threshold. | > Drains can only move forward (`funds_received` → `payment_submitted` → `payment_processed`) and cannot go backward. ### Fetching liquidation address drain history ```bash Request expandable theme={null} curl --request GET \ --url 'https://api.bridge.xyz/v0/customers//liquidation_addresses//drains' \ --header 'Api-Key: ' \ --header 'accept: application/json' ``` ```json Response expandable theme={null} [ { "id": "drain_123", "amount": "1.0", "currency": "usd", "state": "payment_processed", "created_at": "2023-05-05T19:39:14.316Z", "destination": { "payment_rail": "ethereum", "currency": "usdc", "to_address": "0xb5a18db2e404fd5d234f1bec969cb071bed86f82" }, "destination_tx_hash": "0x063834efe214f4199b1ad7181ce8c5ced3e15d271c8e866da7c89e86ee629cfb", "deposit_tx_hash": "0x39debb5d410baddbae5755a8bb98827722b05f5f0e29e428239bf30fc7af2891" }, { "id": "drain_456", "amount": "1.0", "currency": "usd", "state": "payment_processed", "created_at": "2023-05-04T18:39:14.316Z", "destination": { "payment_rail": "ethereum", "currency": "usdc", "to_address": "0xb5a18db2e404fd5d234f1bec969cb071bed86f82" }, "destination_tx_hash": "0x83f5ec78fdde7c48ad32cf2d7ec151fef578a0b6b123e37211a438521b234628", "deposit_tx_hash": "0xe6d166219539d0c875a7a4e0806f43ca117a3aaa42440cf875b6e3398fb09060" } ] ``` ## Learn more Learn more at at [Liquidation Addresses](/platform/orchestration/liquidation_address/liquidation_address)\ Configure fees via [Developer Fees](/platform/orchestration/fees-and-mins/devfees)\ View supported assets [here](/get-started/introduction/what-we-support/payment-routes) # Make recurring payments Source: https://apidocs.bridge.xyz/get-started/guides/move-money/recurring A **static template transfer** (AKA payment route in dashboard) that lets you generate reusable deposit instructions (like an ACH memo) that trigger a transfer automatically when funds are sent to Bridge. Your customers can continue to use the deposit instructions to send money as long as the static template remains active. ![](https://files.readme.io/90b7930e8ce414f975cccda396c27b11b574bc04d5d29bf43e54632d0faf7372-image.png) *** Use the [Create a transfer](/api-reference/transfers/create-a-transfer) endpoint and set `"static_template": true`. ```bash Request theme={null} curl --location --request POST 'https://api.bridge.xyz/v0/transfers' \ --header 'Api-Key: ' \ --header 'Idempotency-Key: ' \ --header 'Content-Type: application/json' \ --data-raw '{ "on_behalf_of": "cust_alice", "source": { "payment_rail": "sepa", "currency": "eur" }, "destination": { "payment_rail": "polygon", "currency": "usdc", "to_address": "0xdeadbeef" }, "features": { "static_template": true "allow_from_any_address": true // lets the deposit originate from any address } }' ``` The response object will contain deposit instructions. You can share these with your customers. Every time your customers send Bridge a deposit with the message `BRGEXAMPLEMEMO`, we will match it to this template, and **create a new transfer instance.** ```json Response expandable theme={null} { "id": "transfer_template_123", "state": "awaiting_funds", "on_behalf_of": "cust_alice", "source": { "payment_rail": "sepa", "currency": "eur" }, "destination": { "payment_rail": "polygon", "currency": "usdc", "to_address": "0xdeadbeef" }, // Share this with your customer "source_deposit_instructions": { "payment_rail": "sepa", "currency": "eur", "deposit_message": "BRGEXAMPLEMEMO", "iban": "IE57MODR99035505123456", "bic": "MODRIE22XXX", "account_holder_name": "Bridge Building Sp.z.o.o.", "bank_name": "Modulr Finance B.V.", "bank_address": "Strawinskylaan 4117, 1077 ZX Amsterdam, The Netherlands" }, "features": { "static_template": true, "flexible_amount": true }, "created_at": "2023-05-05T19:39:14.316Z", "updated_at": "2023-05-05T19:39:15.231Z" } ``` Each time funds match the template (e.g. via SEPA + deposit message), Bridge: * Creates a new Transfer instance * Processes the transfer automatically * Sends you a webhook * Makes it available to fetch at [Get all transfers](/api-reference/transfers/get-all-transfers) ### Fetching static template created transfers via API Use the template ID to list all matched transfers. ```bash Request expandable theme={null} curl --request GET \ --url 'https://api.bridge.xyz/v0/transfers?template_id=transfer_template_123' \ --header 'Api-Key: ' ``` Each resulting transfer instance is represented as a unique transfer object. ```json Response expandable theme={null} { "count": 2, "data": [ { "id": "transfer_instance_456", "state": "payment_processed", "on_behalf_of": "cust_alice", "amount": "1234.0", "source": { "payment_rail": "sepa", "currency": "eur", }, "destination": { "payment_rail": "polygon", "currency": "usdc", "to_address": "0xdeadbeef" }, "source_deposit_instructions": { "payment_rail": "sepa", "currency": "eur", "deposit_message": "BRGEXAMPLEMEMO", "iban": "IE57MODR99035505123456", "bic": "MODRIE22XXX", "account_holder_name": "Bridge Building Sp.z.o.o.", "bank_name": "Modulr Finance B.V.", "bank_address": "Strawinskylaan 4117, 1077 ZX Amsterdam, The Netherlands" }, "receipt": { "initial_amount": "1234.0", "developer_fee": "0.0", "exchange_fee": "0.0", "subtotal_amount": "1234.0", "url": "https://dashboard.bridge.xyz/transaction/4181f2d9-7647-4249-b340-068d6ebdf8a2/receipt/c571e913-1f94-457e-a158-4249526b847b", gas_fee: "0.0", final_amount: "1234.0", destination_tx_hash: "0x628ec487573fc503c3cad909bcd271d29a906257dc19a27db8cc82f213cf95e2", }, "features": { "static_template": true, "flexible_amount": true }, "created_at": "2024-10-06T19:39:14.316Z", "updated_at": "2024-10-06T19:39:15.231Z" }, { "id": "transfer_template_123", "state": "awaiting_funds", "on_behalf_of": "cust_alice", "source": { "payment_rail": "sepa", "currency": "eur", }, "destination": { "payment_rail": "polygon", "currency": "usdc", "to_address": "0xdeadbeef" }, "source_deposit_instructions": { "payment_rail": "sepa", "currency": "eur", "deposit_message": "BRGEXAMPLEMEMO", "iban": "IE57MODR99035505123456", "bic": "MODRIE22XXX", "account_holder_name": "Bridge Building Sp.z.o.o.", "bank_name": "Modulr Finance B.V.", "bank_address": "Strawinskylaan 4117, 1077 ZX Amsterdam, The Netherlands" }, "features": { "static_template": true, "flexible_amount": true }, "created_at": "2024-10-05T19:39:14.316Z", "updated_at": "2024-10-05T19:39:15.231Z" } ] } ``` ## Tips * Omit "amount" to make the template flexible (`flexible_amount: true`) * Use [Update a transfer](/api-reference/transfers/update-a-transfer) to modify template behavior (applies only to future deposits) * Static templates use **shared deposit instructions**, unlike Virtual Accounts, which are customer-specific # Supported Blockchains Source: https://apidocs.bridge.xyz/get-started/guides/move-money/supported-blockchains Reference guide for all blockchains supported by Bridge Bridge supports 10+ blockchains across EVM and non-EVM ecosystems. The `payment_rail` field in transfer, liquidation address, and virtual account requests is how you specify which chain to use. Check the [Route Explorer](https://apidocs.bridge.xyz/get-started/introduction/what-we-support/payment-routes#route-explorer) for the full list of supported currencies per chain. ## Chain-Specific Fields ### `blockchain_memo` * Stellar, Tron, and Tempo support an optional `blockchain_memo` field on the transfer `destination` object. This is a configurable field for sending memos to blockchain destinations. The memo can be used to add additional payment details to the transaction. * For Stellar deposits, a memo is a required field. It is returned in deposit instructions and **must be included by the sender.** ```json theme={null} { "destination": { "currency": "usdc", "payment_rail": "stellar", "to_address": "GBBD47IF6LWK7P7MDEVSCWR7DPUWV3NY3DTQEVFL4NAT4AQH3ZLLFLA5", "blockchain_memo": "4891237045" } } ``` ### `memoless_address` * For **Stellar deposit addresses**, Bridge returns a `memoless_address` alongside the standard `blockchain_memo`. This is a **Stellar muxed account address** (M-address) that encodes the routing memo directly into the address string itself, so your customers don't need to include a separate memo field when sending. # Tempo integration guide Source: https://apidocs.bridge.xyz/get-started/guides/move-money/tempo-integration-guide ## Overview [Tempo](https://docs.tempo.xyz/) is a general-purpose blockchain optimized for payments - designed for consistent gas fees, high throughput, and developer-first features that modern payment systems demand. Tempo has been built alongside design partners including **DoorDash**, **Anthropic**, and **Klarna**, shaping the chain around the needs of high-scale, real-world payment products. Bridge provides native Tempo support across our full product suite. If you're building on Tempo and need fiat on/off-ramps, stablecoin issuance, wallets, or payment infrastructure, you're in the right place. ## What we support * [Virtual Accounts](https://apidocs.bridge.xyz/platform/orchestration/virtual_accounts/virtual-account) - Set up fiat accounts that settle directly to Tempo. * [Transfers](https://apidocs.bridge.xyz/platform/orchestration/transfers/transfer) - Onramp via multiple fiat rails as a 1st party or from 3rd party businesses, offramp to any recipient. * [Liquidation Addresses](https://apidocs.bridge.xyz/platform/orchestration/liquidation_address/liquidation_address) - Auto-convert Tempo stablecoin deposits to fiat or other crypto * [Wallets](https://apidocs.bridge.xyz/platform/wallets/overview) - Provision and manage Tempo wallets for your users. * [Issuance](https://apidocs.bridge.xyz/platform/issuance/overview) - Mint and redeem custom stablecoins on Tempo. * [Cards](https://apidocs.bridge.xyz/platform/cards/overview/overview) (WIP) - Issue virtual and physical cards funded by Tempo stablecoin balances Cards on Tempo are currently in development. Reach out to [sales@bridge.xyz](mailto:sales@bridge.xyz) to join the early access list! ## Request/Response Examples ```text Request theme={null} curl --request POST \ --url https://api.bridge.xyz/v0/customers/INSERT_CUSTOMER_ID/wallets \ --header 'Api-Key: INSERT_TEST_KEY' \ --header 'Content-Type: application/json' \ --header 'Idempotency-Key: INSERT_IDEMPOTENCY_KEY' \ --data ' { "chain": "tempo" } ``` ```json Response theme={null} { "id": "40332a94-768d-495f-9f18-07286e6666666", "tags": [], "chain": "tempo", "address": "0xd31d9a3e463cb2e97678f3c1f88720b7c7eb01dd", "balances": [ { "chain": "tempo", "balance": "0.0", "currency": "eurc", "contract_address": "0x20c0000000000000000000001621e21f71cf12fb" }, { "chain": "tempo", "balance": "0.0", "currency": "usdc", "contract_address": "0x20c000000000000000000000b9537d11c60e8b50" } ], "created_at": "2026-03-09T19:06:40.805Z", "updated_at": "2026-03-09T19:06:40.805Z", "customer_id": "1e9ca0e3-f5d4-45d2-bfa5-07286e6665666" } ``` ```text Request theme={null} curl --request POST \ --url https://api.bridge.xyz/v0/customers/INSERT_CUSTOMER_ID/virtual_accounts \ --header 'Api-Key: INSERT_API_KEY' \ --header 'Content-Type: application/json' \ --header 'Idempotency-Key: INSERT_IDEMPOTENCY_KEY' \ --data ' { "developer_fee_percent": "0.0", "source": { "currency": "usd" }, "destination": { "currency": "usdc", "payment_rail": "tempo", "bridge_wallet_id": "INSERT_BRIDGE_WALLET_ID" } }' ``` ```json Response theme={null} { "id": "ee5dfe8b-da6e-4ef9-694e-8d4a5ac68d81", "status": "activated", "developer_fee_percent": "0.0", "customer_id": "1e9ca0e3-f5d4-45d2-bfa5-28682fc5cccc", "created_at": "2026-03-09T19:39:02.803Z", "source_deposit_instructions": { "currency": "usd", "bank_name": "Lead Bank", "bank_address": "1234 Main St., Kansas City, MO 64108", "bank_routing_number": "777777777", "bank_account_number": "777777777310", "bank_beneficiary_name": "John Doe", "bank_beneficiary_address": "123 White House, San Jose, California 951310000, US", "payment_rail": "ach_push", "payment_rails": [ "ach_push", "wire" ] }, "destination": { "currency": "usdc", "payment_rail": "tempo", "address": "0xe31d9a3e463cb2e97678f3c1f88720b7c7eb01ed" } } ``` ```text Request theme={null} curl --request POST \ --url https://api.bridge.xyz/v0/transfers \ --header 'Api-Key: INSERT_API_KEY' \ --header 'Content-Type: application/json' \ --header 'Idempotency-Key: INSERT_IDEMPOTENCY_KEY' \ --data ' { "developer_fee_percent": "0.0", "on_behalf_of": "INSERT_CUSTOMER_ID", "amount": "2.01", "source": { "currency": "usd", "payment_rail": "ach" }, "destination": { "currency": "usdc", "payment_rail": "tempo", "bridge_wallet_id": "#{request.bridge_wallet_id}" } }' ``` ```json Response theme={null} { "id": "6ccbd781-8859-4944-8d88-66d8a0ff277b", "client_reference_id": null, "state": "awaiting_funds", "on_behalf_of": "485c2b50-949c-412b-928a-f56fce42330d", "currency": "usd", "amount": "2.01", "developer_fee": "0.0", "source": { "payment_rail": "ach", "currency": "usd", "external_account_id": null }, "created_at": "2026-01-09T19:38:43.480Z", "updated_at": "2026-01-09T19:38:43.780Z", "destination": { "payment_rail": "tempo", "currency": "usdc", "to_address": "0xd0f43e6c8ee12ae4fe9d892c66c80dcb925f5d7c" }, "receipt": { "initial_amount": "2.01", "developer_fee": "0.0", "exchange_fee": "0.0", "subtotal_amount": "2.01", "gas_fee": "0.0" }, "developer_fee_percent": "0.0", "source_deposit_instructions": { "payment_rail": "ach_push", "amount": "2.01", "currency": "usd", "deposit_message": "YRRIJHASDJFOO", "bank_name": "Bank name", "bank_address": "Bank address", "bank_routing_number": "123456789", "bank_account_number": "1234567890", "bank_beneficiary_name": "Bank beneficiary", "bank_beneficiary_address": "Bank beneficiary address" } } ``` ```text Request theme={null} curl --request POST \ --url https://api.bridge.xyz/v0/transfers \ --header 'Api-Key: INSERT_API_KEY' \ --header 'Content-Type: application/json' \ --header 'Idempotency-Key: INSERT_IDEMPOTENCY_KEY' \ --data ' { "developer_fee_percent": "0.0", "on_behalf_of": "INSERT_CUSTOMER_ID", "source": { "currency": "usdc", "payment_rail": "bridge_wallet", "bridge_wallet_id": "INSERT_WALLET_ID" }, "destination": { "amount": "3.14", "currency": "usd", "payment_rail": "ach", "external_account_id": "INSERT_EXTERNAL_ACCOUNT_ID" "reference": "abcdefghijklmnopqr" // maximum 18 characters } }' ``` ```json Response theme={null} { "id": "e94b1961-cf77-44db-a66f-07981f03fb1f", "client_reference_id": null, "state": "payment_submitted", "on_behalf_of": "485c2b50-949c-412b-928a-f56fce42330d", "currency": "usd", "amount": "3.14", "developer_fee": "0.0", "source": { "payment_rail": "bridge_wallet", "currency": "usdc", "amount": "3.14", "from_address": "0xd0f43e6c8ee12ae4fe9d892c66c80dcb925f5d7c", "bridge_wallet_id": "d017bf1d-8372-4294-94ac-afd0cbc6357d" }, "created_at": "2026-01-06T17:29:22.796Z", "updated_at": "2026-01-06T17:29:22.874Z", "destination": { "payment_rail": "ach", "currency": "usd", "amount": "3.14", "external_account_id": "bce9dbe4-bca7-42e0-9cc1-7482069019f1" }, "receipt": { "initial_amount": "3.14", "developer_fee": "0.0", "exchange_fee": "0.0", "subtotal_amount": "3.14", "gas_fee": "0.0" }, "developer_fee_percent": "0.0" } ``` ```text Request theme={null} curl --request POST \ --url https://api.bridge.xyz/v0/customers/INSERT_CUSTOMER_ID/liquidation_addresses \ --header 'Api-Key: INSERT_API_KEY' \ --header 'Content-Type: application/json' \ --header 'Idempotency-Key: INSERT_IDEMPOTENCY_KEY' \ --data ' { "currency": "usdc", "chain": "tempo", "external_account_id": "INSERT_EXTERNAL_ACCOUNT_ID", "destination_ach_reference": "test", "destination_payment_rail": "ach", "destination_currency": "usd", "custom_developer_fee_percent": "0.1" } ' ``` ```json Response theme={null} { "id": "la_123", "chain": "tempo", "customer_id": "cust_123", "external_account_id": "ext_123", "address": "0x4d0280da2f2fDA5103914bCc5aad114743152A9c", "currency": "usdc", "state": "active", "created_at": "2025-11-22T21:31:30.515Z", "updated_at": "2025-11-22T21:31:30.515Z" } ``` ## Complimentary Integration Support We're offering **complimentary hands-on integration assistance** to a select cohort of developers building on Tempo. Our solutions engineering team will pair with you to get from zero to production as quickly as possible. [**Reach out to sales@bridge.xyz**](mailto:sales@bridge.xyz) to reserve your spot — space is limited. ## FAQ No. Bridge manages the Tempo network connection on your behalf. You interact exclusively with Bridge's dashboard and APIs. Minimal. Set blockchain as `tempo` in your API calls. Webhooks, error handling, idempotency — everything else stays the same. Explore supported payment routes [here](https://apidocs.bridge.xyz/get-started/introduction/what-we-support/payment-routes#route-explorer) in our docs! Cards on Tempo are coming soon. Contact [sales@bridge.xyz](mailto:sales@bridge.xyz) to join the early access list. *** # USD integration guide Source: https://apidocs.bridge.xyz/get-started/guides/move-money/usd-integration-guide On and offramp with USD using Wire, ACH, and Same Day ACH ## 🇺🇸 What we support * [Virtual Accounts](https://apidocs.bridge.xyz/platform/orchestration/virtual_accounts/virtual-account#usd) - Deposit USD via ACH or Wire and receive payments from 3rd party businesses. * [Transfers](https://apidocs.bridge.xyz/platform/orchestration/transfers/transfer#create-transfer) - Onramp USD via Wire, ACH, or Same Day ACH as a 1st party or from 3rd party businesses, offramp to any recipient. * [Liquidation Addresses](https://apidocs.bridge.xyz/platform/orchestration/liquidation_address/liquidation_address#multichain-%2B-multicurrency) - Offramp from stablecoin or crypto to USD via Wire or ACH. * [Supported Countries](https://apidocs.bridge.xyz/platform/customers/compliance/supported-countries-list) - We support USD on/offramps for customers in +100 countries. ## Logistics * **Virtual accounts are fully permitted to receive the following transactions.** 1. First-party payments where you are sending USD from your bank, fintech app, or brokerage account 2. Payroll payments from businesses 3. Third-party payment where a registered business sends USD from its bank account 4. Third-party payment from a family member’s bank account, where you share a surname 5. Third-party Person-to-Person payment for an amount less than \$4,000 6. Third party payments in most states except for New York and Texas * Refer [here](/platform/orchestration/more/cutoffs) for cutoffs and processing times. * Refer [here](/platform/orchestration/more/payment-tracking) for payment tracking identifiers. *** ## **Request / Response Examples** #### Related APIs * Create a [USD External Account](https://apidocs.bridge.xyz/platform/orchestration/external-accounts/external-accounts-api#usd) to use as a [Transfer](https://apidocs.bridge.xyz/platform/orchestration/transfers/transfer#create-transfer) or [Liquidation Address](https://apidocs.bridge.xyz/platform/orchestration/liquidation_address/liquidation_address#multichain-%2B-multicurrency) offramp destination. * Create a [USD Virtual Account](https://apidocs.bridge.xyz/platform/orchestration/virtual_accounts/virtual-account#usd) to onramp funds using a unique account and routing number. ```bash Request expandable theme={null} curl --request POST \ --url https://api.bridge.xyz/v0/customers/#{request.customer_id}/external_accounts \ --header 'Api-Key: #{api_key}' \ --header 'Content-Type: application/json' \ --header 'Idempotency-Key: #{request.idempotency_key}' \ --data ' { "currency": "usd", "account_type": "us", "bank_name": "Lead Bank", "account_name": "Ada Checking Account", "first_name": "Ada", "last_name": "Lovelace", "account_owner_type": "individual", // specifies an individual account "account_owner_name": "Ada Lovelace", "account": { "routing_number": "101019644", "account_number": "215268129123", "checking_or_savings": "checking" }, "address": { "street_line_1": "923 Folsom Street", "country": "USA", "state": "CA", "city": "San Francisco", "postal_code": "941070000" } }' ``` ```json Response expandable theme={null} { "id": "039c270f-a038-40be-be7b-43f550ce0678", // external account id "customer_id": "23c2d462-4c69-4c5a-b31a-88d035d7e8ae", "created_at": "2025-07-05T19:03:50.819Z", "updated_at": "2025-07-05T19:03:51.251Z", "bank_name": "Lead Bank", "account_name": "Ada Checking Account", "account_owner_name": "Ada Lovelace", "active": true, "currency": "usd", "account_owner_type": "individual", "account_type": "us", "first_name": "Ada", "last_name": "Lovelace", "business_name": null, "account": { "last_4": "9123", "routing_number": "101019644", "checking_or_savings": "checking" }, "beneficiary_address_valid": true, "last_4": "9123" } ``` ```bash Request expandable theme={null} curl --location --request POST 'https://api.bridge.xyz/v0/customers//virtual_accounts' \ --header 'Content-Type: application/json' \ --header 'Api-Key: ' \ --header 'Idempotency-Key: ' \ --data-raw '{ # The source object specifies a USD virtual account. "source": { "currency": "usd", }, # The destination object instructs Bridge where to send the USD deposits to. # Bridge will automatically handle converting and sending USD to the crypto destination. "destination": { "payment_rail": "ethereum", "currency": "usdc", "address": "0x3f5CE5FBFe3E9af3971dD833D26BA9b5C936f0bE" }, # You can specifcy an optional developer fee to monetize on transactions. "developer_fee_percent": "1.0" // 1%. }' ``` ```json Response expandable theme={null} { "id": "1a400dae-f7fc-4f75-8105-212a14d4132d", "status": "activated", "developer_fee_percent": "1.0", "customer_id": "23c2d200-4c00-4c5a-b31a-00d035d7e0ae", "created_at": "2025-07-04T22:10:34.564Z", "source_deposit_instructions": { "currency": "usd", "bank_name": "Lead Bank", "bank_address": "1801 Main St., Kansas City, MO 64108", "bank_routing_number": "101019644", "bank_account_number": "215268120000", "bank_beneficiary_name": "Ada Lovelace", "bank_beneficiary_address": "923 Folsom Street, 302, San Francisco, California 941070000, US", "payment_rail": "ach_push", "payment_rails": [ "ach_push", "wire" ] }, "destination": { "currency": "usdc", "payment_rail": "ethereum", "address": "0x3f5ce5fbfe3e9af3971dd833d26ba9b5c936f0be" } } ``` ```bash Request expandable theme={null} curl --request POST \ --url https://api.bridge.xyz/v0/transfers \ --header 'Api-Key: #{api_key}' \ --header 'Content-Type: application/json' \ --header 'Idempotency-Key: #{request.idempotency_key}' \ --data ' { "amount": "10.0", "on_behalf_of": "cust_alice", "developer_fee": "0.5", # source object tells Bridge where to expect deposits from. # can be fiat or crypto "source": { "payment_rail": "ach_push", "currency": "usd", }, # deposit object tells Bridge where to send funds to. # can also be fiat or crypto "destination": { "payment_rail": "ethereum", "currency": "usdc", "to_address": "0xdeadbeef", }, }' ``` ```json Response expandable theme={null} { "id": "transfer_123", "state": "awaiting_funds", "on_behalf_of": "cust_alice", "amount": "10.0", "developer_fee": "0.5", "source": { "payment_rail": "ach_push", "currency": "usd" }, "destination": { "payment_rail": "polygon", "currency": "usdc", "to_address": "0xdeadbeef" }, # Very important that your customer follows the source deposit instructions "source_deposit_instructions": { "bank_account_number": "123456789", # Bridge's bank account number to send deposits to "bank_routing_number": "101019644", # Bridge's bank account routing number # if the transfer requires a specific amount, it's important your customer includes # the exact amount expected. "amount": "10.0", "currency": "usd", "deposit_message": "BVI7depositmessage", # important that the deposit message is included }, "receipt": { "initial_amount": "10.0", "developer_fee": "0.5", "exchange_fee": "0.0", "final_amount": "9.5", "destination_tx_hash": "0xc0ffee", // A destination tx hash will appear after the transfer is complete }, "created_at": "2023-05-05T19:39:14.316Z", "updated_at": "2023-05-05T19:39:15.231Z" } ``` ```bash Request expandable theme={null} curl --location --request POST 'https://api.bridge.xyz/v0/transfers' \ --header 'Api-Key: ' \ --header 'Idempotency-Key: ' \ --data-raw '{ "amount": "10.0", "on_behalf_of": "cust_alice", "developer_fee": "0.5", # source object tells Bridge where to expect deposits from. # can be fiat or crypto "source": { # Note that we will not validate or reject payments when the payment_rail # is specificed as ach_same_day, but the deposit arrives via ACH or Wire. "payment_rail": "ach_same_day", "currency": "usd", }, # deposit object tells Bridge where to send funds to. # can also be fiat or crypto "destination": { "payment_rail": "ethereum", "currency": "usdc", "to_address": "0xdeadbeef", }, }' ``` ```bash Request expandable theme={null} curl --location --request POST 'https://api.bridge.xyz/v0/transfers' \ --header 'Api-Key: ' \ --header 'Idempotency-Key: ' \ --data-raw '{ "amount": "10.0", "on_behalf_of": "cust_alice", "developer_fee": "0.5", # source object tells Bridge where to expect deposits from. # can be fiat or crypto "source": { # Note that we will not validate or reject payments when the payment_rail # is specificed as wire, but the deposit arrives via ACH. "payment_rail": "wire", "currency": "usd", }, # deposit object tells Bridge where to send funds to. # can also be fiat or crypto "destination": { "payment_rail": "ethereum", "currency": "usdc", "to_address": "0xdeadbeef", }, }' ``` ```bash Request expandable theme={null} curl --request POST \ --url https://api.bridge.xyz/v0/transfers \ --header 'Api-Key: #{api_key}' \ --header 'Content-Type: application/json' \ --header 'Idempotency-Key: 01123' \ --data ' { "developer_fee_percent": "0.0", "on_behalf_of": "cust_1234", "source": { "currency": "usdc", "payment_rail": "bridge_wallet", "bridge_wallet_id": "bw_1234" }, "destination": { "amount": "3.00", "currency": "usd", "payment_rail": "wire", "external_account_id": "ea_1234", "wire_message": "Payment for Invoice #143509" } }' ``` ```bash Request expandable theme={null} curl --request POST \ --url https://api.bridge.xyz/v0/transfers \ --header 'Api-Key: #{api_key}' \ --header 'Content-Type: application/json' \ --header 'Idempotency-Key: 01123' \ --data ' { "developer_fee_percent": "0.0", "on_behalf_of": "cust_1234", "source": { "currency": "usdc", "payment_rail": "bridge_wallet", "bridge_wallet_id": "bw_1234" }, "destination": { "amount": "3.00", "currency": "usd", "payment_rail": "ach", "external_account_id": "ea_1234", // the US bank account to pay out to "ach_reference": "INV143509" // optional; appears on recipient statement, max 10 chars (A-Z, a-z, 0-9, spaces) } }' ``` ```bash Request expandable theme={null} curl --request POST \ --url https://api.bridge.xyz/v0/transfers \ --header 'Api-Key: #{api_key}' \ --header 'Content-Type: application/json' \ --header 'Idempotency-Key: 01123' \ --data ' { "developer_fee_percent": "0.0", "on_behalf_of": "cust_1234", "source": { "currency": "usdc", "payment_rail": "bridge_wallet", "bridge_wallet_id": "bw_1234" }, "destination": { "amount": "3.00", "currency": "usd", "payment_rail": "ach_same_day", // must be submitted before cutoff "external_account_id": "ea_1234", // the US bank account to pay out to "ach_reference": "INV143509" // optional; appears on recipient statement, max 10 chars (A-Z, a-z, 0-9, spaces) } }' ``` *** **To identify which rail a payment was actually received on,** use the `payment_received_rail` field on the Transfer source, or the `payment_rail` field on the Virtual Account source. Note that for **Transfers**, the `payment_rail` you specify at creation **reflects your intent** — not a guarantee. **The sending institution determines the actual rail used.** For example, a Transfer created with `payment_rail: wire` may ultimately arrive via ACH, in which case `payment_received_rail` will reflect `ach`. ## **ACH** * `payment_rail`: Use `ach` for outbound (offramp) transfers. Inbound (onramp) ACH pushed by the customer's bank uses the `ach_push` rail, which is also what appears in Virtual Account deposit instructions. * **`ach_reference`**: Optional reference included with an ACH offramp. Maximum 10 characters; allowed characters are `A–Z`, `a–z`, `0–9`, and spaces. Set this on the `destination` object. * `trace_number`: A unique 15-digit number assigned to each ACH transaction. Use this to uniquely identify ACH payments. * `description`: The ACH description set by the sender, configurable via API for offramps. For onramps, this is a read only field returned when available. * **`sender_name`** / **`sender_bank_routing_number`**: Sender identity fields returned read-only in onramp responses when available. *** ## **Same Day ACH** * `payment_rail`: `ach_same_day` * Same response fields as standard ACH (`trace_number`, `description`, `sender_name`, `ach_reference`). *** ## **Wire** * `payment_rail`: `wire` * **`wire_message`**: Optional memo included with the transfer. Up to 140 characters, validated as 4 lines of 35 characters each per the Fedwire standard. Set this on the `destination` object of an offramp transfer. * **`imad`**: The Input Message Accountability Data — a unique identifier assigned to each incoming Fedwire transaction. Returned read-only in onramp transfer responses and useful for reconciliation and tracing with your bank. * **`originator_name`** / **`originator_address`**: Name and address of the sender, returned read-only in onramp responses when available. * **`bank_beneficiary_name`** / **`bank_beneficiary_address`**: Beneficiary details returned read-only in onramp responses when available. *** ## **FedNow ⚡️** * **Maximum \$10,000,000 per onramp** (this is the FedNow network limit) * 1st and 3rd party payins and payouts supported * FedNow operates **24/7/365 and settles in seconds** * **Payment tracking identifiers**: FedNow onramps will include the following identifiers: * `end_to_end_id`: The end-to-end identifier assigned by the originator that travels with the payment across the FedNow network. Available across both the Transfers and Virtual Accounts APIs. * `transaction_id`: The unique transaction identifier assigned to the FedNow payment. Available across both the Transfers and Virtual Accounts APIs. * We may add more identifiers where helpful, as we roll out the program. * **Originator details**: FedNow onramps will include, if supplied: * `sender_name`: The name of the business or individual who initiated the transaction * `sender_bank_routing_number`: The routing number of the entity that initiated this transaction * **How to identify whether a deposit arrived via FedNow?** To identify which rail a payment was actually received on, use the `payment_received_rail` field on the Transfer source, or the `payment_rail` field on the Virtual Account source. For FedNow onramps, the `payment_received_rail` will be `fednow`. Please note you must clearly disclose fee details applicable to FedNow transfers (e.g., FedNow send/receive fees) in a way that is clear, concise, and accessible to your end users. # USDT Self Serve Trading Endpoints Source: https://apidocs.bridge.xyz/get-started/guides/move-money/usdt-self-serve-trading-endpoints For developers on a fixed rate for USDT trading, when the market rate dips below their fixed rate their USD trades pause until the market rate returns to be above their fixed rate. To provide developers with the autonomy to manage these stuck trades, we’ve added new endpoints to 1. View which transfer and liquidation address trades are stuck 2. View the estimated market rate these trades would execute at 3. Execute at market rate to complete the transaction. 4. Set a threshold that triggers market execution if the market rate drops below the fixed rate. With these endpoints, developers can take action directly or build workflows empowering their end users to do the same. ## **Get Stuck Trades** * Transfer: `/transfers/pending` * Liquidation Address: `/liquidation_addresses/drains/pending` * *To check the specific parameters required to source stuck trades from these endpoints, please reference [List Pending Transfers](https://apidocs.bridge.xyz/api-reference/transfers/list-transfers-with-pending-usdt-trades#list-transfers-with-pending-usdt-trades) and [List Pending Drains](https://apidocs.bridge.xyz/api-reference/liquidation-addresses/list-drains-with-pending-usdt-trades).* * Response: ```json theme={null} "exchange_details": { "fixed_rate": "0.999", // Fixed rate based on the developer bps fee. "estimated_market_rate": "0.99796", "updated_at": "2026-02-05T06:11:35Z"} ``` ## **Post Execute Trades** * Transfer: `/transfers/{transfer_id}/execute` * Liquidation Address: `/v0/customers/{customer-id}/liquidation_address/ea06c74c-b1ab-4f24-ba82-16fb950f9081/drains/218f5fc9-9c94-4a08-9f37-bd58688f8382/execute` * Response: ```json theme={null} "exchange_details": { "fixed_rate": "0.999", "traded_market_rate": "0.99796"} ``` * When executing a trade, it will take 1 minute to complete. During this period the response of the Transfer/Liqudiation Address Drain will include  “`trade_at_market”: true` ## **Get Responses For Each State** 1. **State: funds\_received** ```json theme={null} "exchange_details": { "fixed_rate": "0.999", "estimated_market_rate": "0.99796", "updated_at": "2026-02-05T06:11:35Z"} ``` 2. **State: funds\_received - After Post Execute Trade** ```json theme={null} "exchange_details": { "fixed_rate": "0.999", "estimated_market_rate": "0.99796", "trade_at_market": true} // indicates trade has been submitted and is pending ``` 3. **State: payment\_submitted** ```json theme={null} "exchange_details": { "fixed_rate": "0.999", "traded_market_rate": "0.99796"} ``` 4. **State: payment\_processed** ```json theme={null} "exchange_details": { "fixed_rate": "0.999", "traded_market_rate": "0.99796"} ``` ## **Market Rate Threshold Endpoint** This threshold is the range developers can set to automatically execute trades at market rate should the market rate dip below their fixed rate. \ Ex. if developers fixed rate is 10 bps (0.999), developer can set their threshold to 15 bps (0.9985): * Anything between 0.9985-0.999 will automatically execute at market rate (instead of being stuck and require manual execution). * If market rate dips beyond 15bps, trades will get stuck (and they will be available to execute at market). ### **Enable Threshold** * `/developer/trade_configurations` ```json theme={null} {"source_currency": "usdt", "destination_currency": "usd", "market_rate_configuration": { "market_rate_threshold": "0.9982", "enabled": true}} ``` * Response: ```json theme={null} {"source_currency": "usdt", "destination_currency": "usd", "fixed_rate": "0.999", "market_rate_configuration": { "market_rate_threshold": "0.9982", "enabled": true, "updated_at": "2026-02-11T03:30:00Z"}} ``` ### **Get Threshold** * `/developer/trade_configurations/usdt` * Response: ```json theme={null} {"data": [ {"source_currency": "usdt", "destination_currency": "usd", "fixed_rate": "0.999", "market_rate_configuration": { "market_rate_threshold": "0.9982", "enabled": true, "updated_at": "2026-02-11T03:30:00Z"}} ``` ### **Update/Disable Threshold** * `/developer/trade_configurations` ```json theme={null} {"source_currency": "usdt", "destination_currency": "usd", "market_rate_configuration": { "market_rate_threshold": "0.9982", "enabled": false}} ``` * Response: ```json theme={null} {"source_currency": "usdt", "destination_currency": "usd", "fixed_rate": "0.999", "market_rate_configuration": { "market_rate_threshold": "0.9982", "enabled": false, "updated_at": "2026-02-11T03:30:00Z"}} ``` ## **Notifications** While developers can monitor webhooks from  * `/transfers/pending ` * `/liquidation_addresses/drains/pending` should a developer want to be notified in their Bridge Slack channel, this can be enabled by requesting from their Account Manager. ## **Dashboard** When a developer has USDT trades that are stuck, we present them with task “Paused USDT transactions” on their Home view: Screenshot 2026 02 19 At 3 43 58 PM When clicking through the *Start* CTA of the task, developers are presented with actions to - 1. View/set depeg market rate threshold ([in Settings](https://dashboard.bridge.xyz/app/settings/organization/fixed-trade-rates)), 2. View/trade specific stuck trades at the market rate, 3. Trade all stuck trades at the market rate. Screenshot 2026 02 19 At 3 48 23 PM # Onramp with virtual accounts Source: https://apidocs.bridge.xyz/get-started/guides/move-money/virtualaccounts ## Overview Bridge ****virtual accounts are permanent, reusable fiat deposit addresses**** that convert incoming fiat into crypto and deliver it to your specified destination (e.g. a wallet address). They support multiple currencies and provide customers with local deposit details like account numbers and routing codes. For example, a USD virtual account gives your customer a U.S. account and routing number for ACH or wire transfers. **Supported Payment Rails** * **USD Virtual Accounts** - U.S. bank account and routing numbers issued in your customer’s name. * **EUR Virtual IBAN** - Euro-denominated IBANs for accepting SEPA payments. * **MXN Virtual Accounts** - CLABE account numbers for receiving SPEI (Mexico) payments. * **BRL Virtual Accounts** - BR codes for receiving PIX payments (only 1st party and 3rd party business payments supported). * **GBP Virtual Accounts** - Account number for receiving FPS payments (only 1st party and 3rd party business payments supported). * **COP Virtual Accounts (Beta)** - Bre-B key for receiving Bre-B payments (only 1st party and 3rd party business payments supported). Developers use virtual accounts to simplify global payments, custody stablecoins (e.g. USDB), and enable programmable flows. A common pattern: create a virtual account for a customer, route funds into a Bridge wallet, and earn yield. **Customers must be onboarded** and KYC/KYB-approved before creating virtual accounts. ![](https://files.readme.io/132dbb7a0c26b0bb79c8de61164c2db8535bd71816f6cd897f8030186fa91276-image.png) *** ## Step 1: Create a virtual account Use the [Virtual Accounts](/api-reference/virtual-accounts/create-a-virtual-account) API to provision permanent fiat deposit addresses for your customers. You define the `source` currency for the account and configure the `destination` to specify where Bridge should deliver the converted funds. Bridge handles the fiat-to-crypto conversion and sends the funds on-chain automatically. ```bash Request theme={null} curl --location --request POST 'https://api.bridge.xyz/v0/customers//virtual_accounts' \ --header 'Content-Type: application/json' \ --header 'Api-Key: ' \ --header 'Idempotency-Key: ' \ --data-raw '{ # The source object specifies a USD virtual account. "source": { "currency": "usd", }, # The destination object instructs Bridge where to send the USD deposits to. # Bridge will automatically handle converting and sending USD to the crypto destination. "destination": { "payment_rail": "ethereum", "currency": "usdc", "address": "0x3f5CE5FBFe3E9af3971dD833D26BA9b5C936f0bE" }, # You can specifcy an optional developer fee to monetize on transactions. "developer_fee_percent": "1.0" // 1%. }' ``` ```json Response theme={null} { "id": "1a400dae-f7fc-4f75-8105-212a14d4132d", "status": "activated", "developer_fee_percent": "1.0", "customer_id": "23c2d200-4c00-4c5a-b31a-00d035d7e0ae", "created_at": "2025-07-04T22:10:34.564Z", "source_deposit_instructions": { "currency": "usd", "bank_name": "Lead Bank", "bank_address": "1801 Main St., Kansas City, MO 64108", "bank_routing_number": "101019644", "bank_account_number": "215268120000", "bank_beneficiary_name": "Ada Lovelace", "bank_beneficiary_address": "923 Folsom Street, 302, San Francisco, California 941070000, US", "payment_rail": "ach_push", "payment_rails": [ "ach_push", "wire" ] }, "destination": { "currency": "usdc", "payment_rail": "ethereum", "address": "0x3f5ce5fbfe3e9af3971dd833d26ba9b5c936f0be" } } ``` ```bash Request theme={null} curl --location --request POST 'https://api.bridge.xyz/v0/customers//virtual_accounts' \ --header 'Content-Type: application/json' \ --header 'Api-Key: ' \ --header 'Idempotency-Key: ' \ --data-raw '{ # The source object specifies a SEPA virtual IBAN. "source": { "currency": "eur", }, # The destination object instructs Bridge where to send the EURO deposits to. # Bridge will automatically handle converting and sending EURO to the crypto destination. "destination": { "payment_rail": "ethereum", "currency": "usdc", "address": "0x3f5CE5FBFe3E9af3971dD833D26BA9b5C936f0bE" }, # You can specifcy an optional developer fee to monetize on transactions. "developer_fee_percent": "1.0" // 1%. }' ``` ```json Response theme={null} { "id": "393c6358-4c19-4cb7-bbfa-d4a56be58309", "status": "activated", "developer_fee_percent": "1.0", "customer_id": "23c2d200-4c00-4c5a-b31a-00d035d7e0ae", "created_at": "2025-07-04T22:07:18.701Z", "source_deposit_instructions": { "currency": "eur", "iban": "IE90MODR14035307970528", "bic": "MODRIE00XXX", "account_holder_name": "Bridge Building Sp.z.o.o.", "bank_name": "Modulr Finance, Ireland Branch", "bank_address": "Floor 6, 2 Grand Canal Square, Dublin, Ireland", "payment_rail": "sepa", "payment_rails": [ "sepa" ] }, "destination": { "currency": "usdc", "payment_rail": "ethereum", "address": "0x3f5ce5fbfe3e9af3971dd833d26ba9b5c936f0be" } } ``` ```bash Request theme={null} curl --location --request POST 'https://api.bridge.xyz/v0/customers//virtual_accounts' \ --header 'Content-Type: application/json' \ --header 'Api-Key: ' \ --header 'Idempotency-Key: ' \ --data-raw '{ # The source object specifies a MXN virtual account. "source": { "currency": "mxn", }, # The destination object instructs Bridge where to send the MXN deposits to. # Bridge will automatically handle converting and sending MXN to the crypto destination. "destination": { "payment_rail": "ethereum", "currency": "usdc", "address": "0x3f5CE5FBFe3E9af3971dD833D26BA9b5C936f0bE" }, # You can specifcy an optional developer fee to monetize on transactions. "developer_fee_percent": "1.0" // 1%. }' ``` ```json Response theme={null} { "id": "35334433-dcee-48e8-bdc8-90171234ad00", "status": "activated", "developer_fee_percent": "1.0", "customer_id": "23c2d200-4c00-4c5a-b31a-00d035d7e0ae", "created_at": "2025-07-04T22:13:29.481Z", "source_deposit_instructions": { "currency": "mxn", "clabe": "568980546701071234", "account_holder_name": "Ada Lovelace", "payment_rails": [ "spei" ] }, "destination": { "currency": "usdc", "payment_rail": "ethereum", "address": "0x3f5ce5fbfe3e9af3971dd833d26ba9b5c936f0be" } } ``` ```bash Request theme={null} curl --location --request POST 'https://api.bridge.xyz/v0/customers//virtual_accounts' \ --header 'Content-Type: application/json' \ --header 'Api-Key: ' \ --header 'Idempotency-Key: ' \ --data-raw '{ "source": { "currency": "brl", }, # The destination object instructs Bridge where to send the BRL deposits to. # Bridge will automatically handle converting and sending USDC to the crypto destination. "destination": { "payment_rail": "ethereum", "currency": "usdc", "address": "0x3f5CE5FBFe3E9af3971dD833D26BA9b5C936f0bE" }, # You can specify an optional developer fee to monetize transactions. "developer_fee_percent": "1.0" // 1%. }' ``` ```json Response theme={null} { "id": "6e6ab621-6749-401f-b598-0c709c241696", "status": "activated", "developer_fee_percent": "0.0", "customer_id": "eeafff4b-2dbe-41f2-9444-a6e228aee975", "created_at": "2025-09-03T16:10:31.446Z", "source_deposit_instructions": { "currency": "brl", "br_code": "00020126770014br.gov.bcb.pix01366e6ab621-6749-401f-b598-0c709c2416960215Edson_Arantes5204000053039865802BR5914Bridge_Example6009Sao_Paulo622905256beca3e77fdd489289aa1daeb630416E9", "account_holder_name": "Edson Arantes do Nascimento", "payment_rails": [ "pix" ] }, "destination": { "currency": "usdc", "payment_rail": "ethereum", "address": "0x3f5CE5FBFe3E9af3971dD833D26BA9b5C936f0bE" } } ``` ```bash Request theme={null} curl --location --request POST 'https://api.bridge.xyz/v0/customers//virtual_accounts' \ --header 'Content-Type: application/json' \ --header 'Api-Key: ' \ --header 'Idempotency-Key: ' \ --data-raw '{ "source": { "currency": "gbp", }, # The destination object instructs Bridge where to send the GBP deposits to. # Bridge will automatically handle converting and sending USDC to the crypto destination. "destination": { "payment_rail": "ethereum", "currency": "usdc", "address": "0x3f5CE5FBFe3E9af3971dD833D26BA9b5C936f0bE" }, # You can specify an optional developer fee to monetize transactions. "developer_fee_percent": "1.0" // 1%. }' ``` ```json Response theme={null} { "id": "6e6ab621-6749-401f-b598-0c709c241696", "status": "activated", "developer_fee_percent": "0.0", "customer_id": "485c2b50-949c-412b-928a-f56fce42330d", "created_at": "2026-01-03T00:23:23.724Z", "source_deposit_instructions": { "currency": "brl", "account_number": "12345678", "sort_code": "123456", "account_holder_name": "Bridge Building Sp. Z.o.o.", "bank_name": "Banking Circle S.A.", "bank_address": "2 Boulevard de la Foire, L-1528 Luxembourg", "bank_beneficiary_name": "Bridge Building Sp. Z.o.o.", "bank_beneficiary_address": "2 Boulevard de la Foire, L-1528 Luxembourg", "payment_rails": [ "faster_payments" ] }, "destination": { "currency": "usdc", "payment_rail": "ethereum", "address": "0x3f5CE5FBFe3E9af3971dD833D26BA9b5C936f0bE" } } ``` ### Sharing Deposit Instructions Once a Virtual Account is created, use the `source_deposit_instructions` object in the response to share the fiat deposit details with your customer. Funds sent to those details will be automatically converted and delivered to the crypto destination you specified. *** ## Step 2: Monitoring virtual account events Once a Virtual Account is created, your customer can start receiving fiat payments using the provided deposit instructions. Bridge automatically tracks the full lifecycle of each deposit—from the moment funds are received to the point they are delivered on-chain. Each event in this lifecycle is represented by a `VirtualAccountEvent`. ### Event Creation and Tracking Whenever a deposit is received, Bridge generates a `VirtualAccountEvent` with a unique `id`. You can: * Fetch historical events using the [Virtual Account Activity](/api-reference/virtual-accounts/virtual-account-activity) API. * Receive **real-time webhook notifications** when: * A new deposit is received. * The status of an event changes (e.g. funds delivered, refund issued). Each `VirtualAccountEvent` includes detailed information about the deposit, source, status, and destination. ### Virtual account event types Below are the different types of virtual account events you may receive. You can identify the type of each event by checking the `type` field in the virtual account event object. | Type | Description | | ------------------- | --------------------------------------------------------------------- | | `funds_received` | Bridge received funds via ACH or wire. | | `payment_submitted` | Bridge submitted the crypto payment. | | `payment_processed` | Payment confirmed on-chain. Final state. | | `funds_scheduled` | (ACH only) Incoming funds are in transit with estimated arrival date. | | `in_review` | Transaction is under manual review. | | `refunded` | Funds could not be delivered and were refunded to the sender. | | `account_update` | Virtual Account was updated (e.g. new destination address). | | `deactivation` | Virtual Account was deactivated. | | `reactivation` | Virtual Account was reactivated. | | `microdeposit` | Microdeposit verification detected. Funds are never onramped. | All transaction-triggered events include a `deposit_id` field. This id is unique for each transaction that Bridge receives through this Virtual Account and can be used to link separate events to the same source transaction. ### Fetching virtual account activity ```bash Request expandable theme={null} curl --location 'https://api.bridge.xyz/v0/customers//virtual_accounts//history' \ --header 'Accept: application/json' \ --header 'Api-Key: ' ``` ```json Response expandable theme={null} { "count": 10, // Total number of events returned "data": [ { "id": "3686be0e-468c-e3ad-1dcd-b4a41b8b7632", // Unique ID of the event "type": "payment_processed", // Event type: payment_processed means funds were delivered on chain "currency": "usd", // Event source currency "created_at": "2025-07-01T12:00:00Z", // Timestamp when the payment was processed. "customer_id": "84325ad9-1c8f-5794-3738-373b980d466f", "virtual_account_id": "4707fbec-f5a0-39d1-55d5-83fa18e1e49f", "amount": "1500.0", // Deposited amount "developer_fee_amount": "0.0", // Amount held for developer fees "exchange_fee_amount": "0.0", // Exchange fees "subtotal_amount": "1500.0", // Source amount after subtracting dev and exchange fees "gas_fee": "0.0", // On-chain gas fee charged when sending crypto "deposit_id": "ce898006-6347-f8b5-4e52-45185ba66e65", // ID of the deposit associated with this event "source": { "payment_rail": "ach_push", // Rail the funds arrived on (e.g., ach_push, wire) "description": "Mock ACH Description 00", // Free-text description from the bank "sender_name": "Sender 00", // Name of the sender provided by their bank "sender_bank_routing_number": "00000000", // Sender's bank routing number "trace_number": "000000000000000" // ACH trace number }, "destination_tx_hash": "0xabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcd0", // Blockchain tx hash // we include a receipt object to share transaction details with your customer "receipt": { "initial_amount": "1500.0", // Amount received before fees "developer_fee": "0.0", "exchange_fee": "0.0", "subtotal_amount": "1500.0", "url": "https://dashboard.bridge.xyz/transaction/mock_tx_0/receipt/mock_receipt_0", "gas_fee": "0.0", "final_amount": "1500.0", // final amount after subtracting any gas fees "destination_tx_hash": "0xabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcd0" } }, { "id": "e8d43469-efcc-90e2-c64d-6c50c8e8912f", "type": "funds_received", // Event indicating fiat funds have arrived "currency": "usdc", "created_at": "2025-07-02T12:00:00Z", "customer_id": "5b6575f9-d3e4-79d1-ed7d-62c02ab14af3", "virtual_account_id": "9c132b3f-476e-5eaf-4e17-fed4b06dd93e", "amount": "1500.0", "developer_fee_amount": "0.0", "exchange_fee_amount": "0.0", "subtotal_amount": "1500.0", "gas_fee": "0.0", "deposit_id": "3f8dc835-c994-67f1-3221-77b1060ed2f7", "source": { "payment_rail": "ach_push", "description": "Mock ACH Description 01", "sender_name": "Sender 01", "sender_bank_routing_number": "00000001", "trace_number": "000000000000001" } } // ... additional records omitted for brevity ... ] } ``` ## Learn More Refer [Virtual Accounts](/platform/orchestration/virtual_accounts/virtual-account) for more detailed documentation. # Send wallet funds to a crypto address Source: https://apidocs.bridge.xyz/get-started/guides/wallets/crypto-to-crypto Bridge wallets are secure, custodial crypto wallets that let you send and receive stablecoins with ease. Once you've provisioned a wallet for your customer or company, you can send and receive funds using orchestration API. You must use Bridge’s orchestration APIs to move funds. **Do not attempt to send directly** from the wallet address. ![](https://files.readme.io/bcd6a3bfe25913355630174c61719239120611cd39ded4ffb188eaecd2a7bb07-image.png) *** ```bash Request expandable theme={null} curl --request POST \ --url https://api.bridge.xyz/v0/customers//wallets \ --header 'Api-Key: ' \ --header 'Idempotency-Key: ' \ --header 'Content-Type: application/json' \ --data-raw '{ "chain": "solana" }' ``` ```json Response expandable theme={null} { "id": "wallet_123", "chain": "solana", "address": "the-blockchain-address", "created_at": "2024-09-01T02:03:04.567Z", "updated_at": "2024-09-01T02:03:04.567Z" } ``` Note the `id` returned — this is your `bridge_wallet_id`. Use the [Transfers](/api-reference/transfers/create-a-transfer) API with `bridge_wallet` as the source. ```bash Request expandable theme={null} curl --location --request POST 'https://api.bridge.xyz/v0/transfers' \ --header 'Api-Key: ' \ --header 'Idempotency-Key: ' \ --header 'Content-Type: application/json' \ --data-raw '{ "amount": "10.0", "on_behalf_of": "", "developer_fee": "0.0", "source": { "payment_rail": "bridge_wallet", "currency": "usdb", "bridge_wallet_id": "wallet_123" }, "destination": { "payment_rail": "ethereum", "currency": "usdc", "to_address": "0xdeadbeef..." } }' ``` ```json Response expandable theme={null} { "id": "transfer_abc", "amount": "10.0", ... "source": { "payment_rail": "bridge_wallet", "currency": "usdb", "bridge_wallet_id": "wallet_123" }, "destination": { "payment_rail": "ethereum", "currency": "usdc", "to_address": "0xdeadbeef" }, } ``` This will initiate a crypto transfer from your Bridge wallet to the specified blockchain address. Use the Transfer ID returned in the response to monitor progress via the [Get a transfer](/api-reference/transfers/get-a-transfer) endpoint or by listening to webhooks -- learn more at [Setting up webhooks](/get-started/introduction/quick-start/setting-up-webhooks). ```curl Request expandable theme={null} curl --request GET \ --url https://api.bridge.xyz/v0/transfers/ \ --header 'Api-Key: ' ``` # Send wallet funds to a fiat external account Source: https://apidocs.bridge.xyz/get-started/guides/wallets/offramp This guide walks you through how to offramp funds from a Bridge-managed wallet to an external fiat account (e.g. a customer’s bank account) using the Transfers API. ## Prerequisites Before you start, make sure you have * A Bridge wallet with sufficient balance * A verified customer (via KYC or business onboarding) * External account created *** Use [Create a transfer](/api-reference/transfers/create-a-transfer) endpoint to move funds from a Bridge wallet to a fiat destination. ```bash Request expandable theme={null} curl --location --request POST 'https://api.bridge.xyz/v0/transfers' \ --header 'Api-Key: ' \ --header 'Idempotency-Key: ' \ --header 'Content-Type: application/json' \ --data-raw '{ "amount": "100.00", "on_behalf_of": "cust_12345", // id of the customer who owns the wallet and ext. account "source": { "payment_rail": "bridge_wallet", "currency": "usdb", "bridge_wallet_id": "wallet_abc123" // id of the bridge wallet with funds }, "destination": { "payment_rail": "ach", "currency": "usd", "external_account_id": "ext_account_xyz789" // id of the customer bank account } }' ``` You can query the [Get a transfer](/api-reference/transfers/get-a-transfer) endpoint or listen to webhook events to retrieve the transfer details: ```bash Request expandable theme={null} curl --location --request GET 'https://api.bridge.xyz/v0/transfers/transfer_xyz' \ --header 'Api-Key: ' \ --header 'accept: application/json' ``` ```json Response expandable theme={null} { "id": "transfer_xyz", "state": "payment_processed", "amount": "100.00", "source": { ... }, "destination": { "payment_rail": "ach", "currency": "usd", "external_account_id": "ext_account_xyz789" }, ... } ``` Common states: * `awaiting_funds`: waiting for source balance * `payment_submitted`: funds handed off to banking partner * `payment_processed`: funds delivered to external account # Related Docs * [Transfers](/platform/orchestration/transfers/transfer) * [External Accounts](/platform/orchestration/external-accounts/external-accounts-api) * [Wallets](/platform/wallets/overview) * [Setting up webhooks](/get-started/introduction/quick-start/setting-up-webhooks) # Send fiat deposits to your wallet Source: https://apidocs.bridge.xyz/get-started/guides/wallets/onramp This guide walks you through creating a crypto wallet for a customer, then linking it to a virtual account so fiat deposits (e.g. ACH, SEPA) are automatically converted and delivered to the wallet as stablecoins. ![](https://files.readme.io/d051ccd62a78c5556e3401e032c74ee265918ddd1aa35e45263bbb434b1253d3-image.png) *** Create a new Bridge-managed crypto wallet for your customer. This wallet will hold funds (e.g. USDB) and can earn yield. ```bash Request expandable theme={null} curl --request POST \ --url https://api.bridge.xyz/v0/customers//wallets \ --header 'Api-Key: ' \ --header 'Idempotency-Key: ' \ --header 'Content-Type: application/json' \ --data-raw '{ "chain": "solana" }' ``` ```json Response expandable theme={null} { "id": "wallet_abc123", "chain": "solana", "address": "4oG1sWkP8vcrnhbkzZc1m9RTT2VUjZHKx92qiVFK7FuZ", "created_at": "2025-07-15T18:00:00Z" } ``` Use the `bridge_wallet_id` (wallet\_abc123 above) when referencing the wallet in other Bridge APIs. Now, link the wallet to a virtual account. Any fiat deposits into the account will be automatically converted to USDB and delivered to the wallet. ```bash Request expandable theme={null} curl --request POST \ --url https://api.bridge.xyz/v0/customers//virtual_accounts \ --header 'Api-Key: ' \ --header 'Idempotency-Key: ' \ --header 'Content-Type: application/json' \ --data-raw '{ "source": { "currency": "usd" }, "destination": { "payment_rail": "solana", "currency": "usdb", "bridge_wallet_id": "wallet_abc123" } }' ``` ```json Response expandable theme={null} { "id": "va_123", "status": "activated", "customer_id": "cust_alice", "source_deposit_instructions": { "currency": "usd", "bank_beneficiary_name": "Alice Customer", "bank_name": "Lead Bank", "bank_address": "1801 Main St., Kansas City, MO 64108", "bank_routing_number": "101019644", "bank_account_number": "123456789", "payment_rails": ["ach_push", "wire"], }, "destination": { "bridge_wallet_id": "wallet_abc123", "currency": "usdb" } } ``` Share the virtual account details (account and routing number) with your customer. When they send a fiat deposit, Bridge will: * Match the payment * Convert it to stablecoin (e.g. USDB) * Deliver it to the linked wallet Use this API to check wallet balances and confirm the funds have landed. ```bash Request expandable theme={null} curl --request GET --url --header 'Api-Key: ' --header 'accept: application/json' ``` ```json Response expandable theme={null} { "id": "uuid", "chain": "solana", "address": "the-blockchain-address", "created_at": "2024-09-01T02:03:04.567Z", "updated_at": "2024-09-01T02:03:04.567Z", "balances": [ { "balance": "123.456789", "currency": "usdb", "chain": "solana", "contract_address": "ENL66PGy8d8j5KNqLtCcg4uidDUac5ibt45wbjH9REzB", } ] } ``` # Custodial wallets Source: https://apidocs.bridge.xyz/get-started/guides/wallets/overview Bridge offers fully managed, compliant custody for stablecoins with no third-party integrations required. Using Bridge wallets, you can: * Create wallets for your customers or your business. * Transfer stablecoins in and out using orchestration APIs. * Query balances and transfer history. * Tag and organize wallets as needed. Before creating wallets, make sure you have onboarded your customer and finished any required KYC/KYB or endorsements. Learn more at [wallets](/platform/wallets/overview). # Welcome Source: https://apidocs.bridge.xyz/get-started/introduction/overview ## Introduction Welcome to **Bridge**, the seamless way to integrate stablecoin payments into your product. Bridge lets you move money with internet speed and global reach — across fiat rails and stablecoins. Whether you're building global payment flows, launching a card product, or managing wallets, Bridge offers a composable set of APIs to power seamless money movement. This guide is designed to help you navigate our APIs, avoid common integration pitfalls, and get to market faster. ## What you can build with Bridge * **Send & receive payments**\ Move funds globally using fiat rails, stablecoins, or supported digital assets. * **Virtual accounts**\ Instantly issue USD, EUR, and MXN deposit accounts for your users with local bank details. * **Custody funds**\ Provision custodial wallets to hold stablecoin balances securely. * **Issue stablecoins**\ Launch your own branded stablecoin or use USDB to earn rewards on held balances. * **Issue stablecoin-backed cards**\ Enable users to spend from their stablecoin balances with Visa-powered virtual and physical cards. *** ## Get started Here’s a quick guide to help you find what you need: Get up and running with our API in minutes. Explore starter core use cases for moving money using orchestration, wallets, cards, and more. More detailed documentation on the developer platform. Detailed endpoint documentation with request/response schemas. Read more about recent feature improvements and launches. ## Key platform components The Bridge developer platform includes flexible and simple APIs to power your use cases. Easily onboard users with KYC/KYB flows and manage identity lifecycle. APIs to send, receive, and convert between fiat and stablecoins. Power on ramps, off ramps, and crypto to crypto payments using transfers. Custody funds for your customers or your company, initiate transfers, and check balances with secure custodial wallets. Launch your own branded stablecoin and earn on-chain rewards on balances held in Bridge-issued stablecoins. Issue branded Visa cards that work online, in-store, and through mobile wallets. Customers can spend directly from stablecoin balances. ## Getting Help We're excited to have you build with us! If you have questions, run into issues, or just want to say hi, you can contact us at [support@bridge.xyz](mailto:support@bridge.xyz) or visit our [Support Page](https://support.bridge.xyz/) # Create your first payment Source: https://apidocs.bridge.xyz/get-started/introduction/quick-start/create-a-one-time-payment This guide will walk you through sending a one-time payment using Bridge's Transfer API. ## Transfer API The Transfer API enable conversion between fiat and crypto across supported currencies and rails. There are three primary transfer types: * **Fiat → Crypto (aka onramps)**: Convert traditional fiat currency to cryptocurrency * **Crypto → Crypto**: Exchange between different cryptocurrencies * **Crypto → Fiat (aka offramps)**: Convert cryptocurrency to traditional fiat currency Here are the key concepts to a transfer: * **Source**: Origin of funds (Bridge wallet, customer crypto wallet, bank account) * **Destination**: Endpoint for funds transfer * **On Behalf Of**: Customer identifier for compliance * **Amount**: Transfer amount (can be flexible) ### Transfer Flow ![](https://files.readme.io/ab382eeec27e9c69149e4fbb3e16d0e0a1f60ba6deb472e2171e9b6f39bc1ad3-image.png) For detailed information, see [Transfers](/platform/orchestration/transfers/transfer). *** ## Step 1: Create a transfer Let's create a transfer for an onramp from a USD ACH deposit to a USDC Ethereum address. ```bash Request expandable theme={null} curl --location --request POST 'https://api.bridge.xyz/v0/transfers' \ --header 'Api-Key: ' \ --header 'Idempotency-Key: ' \ --data-raw '{ "on_behalf_of": "cust_alice", "source": { "payment_rail": "ach_push", "currency": "usd", }, "destination": { "payment_rail": "ethereum", "currency": "usdc", "to_address": "0xdeadbeef", }, "features": { "flexible_amount": true // allows for any deposit amount } }' ``` ```json Response expandable theme={null} { "id": "transfer_123", "state": "awaiting_funds", "on_behalf_of": "cust_alice", "source": { "payment_rail": "ach_push", "currency": "usd" }, "destination": { "payment_rail": "ethereum", "currency": "usdc", "to_address": "0xdeadbeef" }, "source_deposit_instructions": { "payment_rails": ["ach_push","wire"], "currency": "usd", "deposit_message": "BRGEXAMPLEMEMO", "currency": "usd", "bank_beneficiary_name": "Test Beneficiary", "bank_routing_number": "123456789", "bank_account_number": "987654321", "bank_name": "Test Bank" }, "features": { "flexible_amount": true }, "created_at": "2023-05-05T19:39:14.316Z", "updated_at": "2023-05-05T19:39:15.231Z" } ``` You can share the source deposit instructions with your customer. Your customer will then need to initiate an ACH deposit with: * the source deposit routing number: `123456789` * the source deposit account number: `987654321` * with the a deposit message as: `BRGEXAMPLEMEMO` Once Bridge receives these funds, we'll look for the deposit message to find the payment. ## Step 2: Monitor Transfer Status When Bridge receives the deposit, we'll transition the transfer state to `funds_received`. The transfer status when it's delivered is `payment_processed`. You can pull the transfer status from the API or listen to webhooks to watch the transfer transition. View the full breakdown of transfer states [here](/platform/orchestration/transfers/transfer-states). ### Fetching Transfers status via API You can use the [Get a transfer](/api-reference/transfers/get-a-transfer) endpoint to fetch the latest Transfer status. ```bash Request expandable theme={null} curl --request GET \ --url 'https://api.bridge.xyz/v0/transfer_123' \ --header 'accept: application/json' ``` ```json Response expandable theme={null} { "count": 2, "data": [ { "summary": "A successful onramp transfer object", "value": { "id": "transfer_456", "client_reference_id": "client_transfer_id_456", "state": "funds_received", // transfer state "on_behalf_of": "cust_alice", "amount": "500.25", "developer_fee": "0.0", "source": { "payment_rail": "ach", "currency": "usd", "external_account_id": "ext_123" }, "destination": { "payment_rail": "ethereum", "currency": "usdc", "to_address": "0x71C7656EC7ab88b098defB751B7401B5f6d8976F" }, "receipt": { "initial_amount": "500.25", "developer_fee": "0.0", "exchange_fee": "0.0", "subtotal_amount": "500.25", "gas_fee": "0.0", "final_amount": "500.25", "destination_tx_hash": "0xdeadbeef", "url": "https://dashboard.bridge.xyz/transaction/00000000-0000-0000-0000-000000000000/receipt/00000000-0000-0000-0000-000000000000" }, "created_at": "2020-01-02T00:00:00.000Z", "updated_at": "2020-01-03T00:00:00.000Z" } } ] } ``` ```json Response expandable theme={null} { "count": 2, "data": [ { "summary": "A successful onramp transfer object", "value": { "id": "transfer_456", "client_reference_id": "client_transfer_id_456", "state": "payment_processed", // transfer state "on_behalf_of": "cust_alice", "amount": "500.25", "developer_fee": "0.0", "source": { "payment_rail": "ach", "currency": "usd", "external_account_id": "ext_123" }, "destination": { "payment_rail": "ethereum", "currency": "usdc", "to_address": "0x71C7656EC7ab88b098defB751B7401B5f6d8976F" }, "receipt": { "initial_amount": "500.25", "developer_fee": "0.0", "exchange_fee": "0.0", "subtotal_amount": "500.25", "gas_fee": "0.0", "final_amount": "500.25", "destination_tx_hash": "0xdeadbeef", "url": "https://dashboard.bridge.xyz/transaction/00000000-0000-0000-0000-000000000000/receipt/00000000-0000-0000-0000-000000000000" }, "created_at": "2020-01-02T00:00:00.000Z", "updated_at": "2020-01-03T00:00:00.000Z" } } ] } ``` ### Advanced: Monitoring using webhooks You can set up webhooks to receive real-time notifications about transfer status changes. See [guide](/get-started/introduction/quick-start/setting-up-webhooks) for more details on setting up webhooks. ```json Example webhook: payment_processed expandable theme={null} { "api_version": "v0", "event_id": "wh_t8TAhPPYrRV2v8Asi9ed3sw", "event_developer_id": "371983-uery-1238-1238971", "event_category": "transfer", "event_type": "updated.status_transitioned", "event_object_id": "fecffc8b-ed5e-48ae-bd24-b36268330b32", "event_object_status": "payment_processed", "event_object": { "id": "transfer_abc123", "state": "payment_processed", "amount": "50.0", "currency": "usd", "developer_fee": "0.0", "client_reference_id": null, "on_behalf_of": "cust_alice", "source": { "currency": "usdb", "payment_rail": "bridge_wallet", "bridge_wallet_id": "wallet_alice_usdb" }, "destination": { "currency": "usdb", "payment_rail": "solana", "to_address": "9uYxZmV1KxJn7oVPW6bLUhF3cGQsk8vvMf1sQdPE6K4" }, "receipt": { "url": "https://dashboard.bridge.xyz/transaction/transfer_abc123/receipt/receipt_xyz456", "gas_fee": "0.0", "exchange_fee": "0.0", "developer_fee": "0.0", "initial_amount": "50.0", "subtotal_amount": "50.0", "final_amount": "50.0", "destination_tx_hash": "3gJH6oXpZUNgC1QLh8mXNPF92LtLKzHZj5eHuQrdQAgB" }, "created_at": "2025-07-15T23:55:39.411Z", "updated_at": "2025-07-15T23:55:58.645Z" }, "event_object_changes": { "state": [ "payment_submitted", "payment_processed" ] }, "event_created_at": "2024-02-01T04:32:28.978Z" } ``` *** ## Best Practices 1. **Clear Instructions**: Provide customers with clear, step-by-step deposit instructions, including deposit messages 2. **Error Handling**: Plan for various failure scenarios and customer communication 3. **Testing**: Always test with small amounts before processing larger transfers ## Next Steps After successfully creating your first transfer: 1. **Implement Webhook Processing**: Set up comprehensive webhook handling for all transfer events 2. **Customer Communication**: Build flows to notify customers of transfer status changes 3. **Error Recovery**: Implement processes to handle failed transfers ## Additional Resources * [Transfers](/platform/orchestration/transfers/transfer) * [Make recurring payments using saved payment routes](/get-started/guides/move-money/recurring) * [Setting up webhooks](/get-started/introduction/quick-start/setting-up-webhooks) # Onboard your first customer Source: https://apidocs.bridge.xyz/get-started/introduction/quick-start/create-your-first-customer Bridge customers represent users of your business who can send and receive money. There are two types: * **Individual customers**: Personal users with personal information * **Business customers**: Companies with business information and beneficial owners ### Key Terms * **KYC (Know Your Customer)**: Identity verification process required for compliance * **Endorsements**: Approval for specific payment rails (USD, EUR, MXN) * **Terms of Service**: Legal agreement customers must accept *** ## Method 1: Using KYC Links (Quick Start - Recommended) Bridge provides a **hosted onboarding flows** so you don’t have to build your own KYC UI. This is the fastest way to onboard customers. ![](https://files.readme.io/44bcd17e95746a1ad3e6079f783410f2eed51a01318df77aa0c1bb130a00101a-image.png) Use the `/kyc_links` endpoint to generate links for TOS acceptance and KYC verification ```bash Request expandable theme={null} curl --location --request POST 'https://api.bridge.xyz/v0/kyc_links' \ --header 'Content-Type: application/json' \ --header 'Api-Key: ' \ --header 'Idempotency-Key: ' \ --data-raw '{ "full_name": "John Doe", "email": "johndoe@example.com", "type": "individual" }' ``` ```json Response expandable theme={null} { "id": "uuid", "full_name": "John Doe", "email": "johndoe@example.com", "type": "individual", // or "business" "kyc_link": "https://bridge.withpersona.com/verify?", "tos_link": "https://dashboard.bridge.xyz/accept-terms-of-service?", "kyc_status": "not_started", // or "under_review", "incomplete", "approved" or "rejected" "rejection_reasons": [], "tos_status": "pending", // or "approved" "created_at": "2025-07-16T18:28:25.970Z", "customer_id": "customer_id", "persona_inquiry_type": "gov_id_db" } ``` Guide the user through: 1. Visiting the `tos_link` and accepting terms of service 2. Completing identity verification via the `kyc_link` This process typically takes less than a minute and updates automatically once complete. More about KYC Links here: [KYC Links for New Customers](/platform/customers/customers/kyclinks) ## Method 2: Direct API Integration (More Control) Prefer to control the onboarding UI? You can collect and submit customer data directly to Bridge. ![](https://files.readme.io/32e86521c9fbdfa9557c8688268f60ea354a3c0de96a5808ecef5fedca5325b3-image.png) Create U.S. based customer: ```bash Request expandable theme={null} curl --location --request POST 'https://api.bridge.xyz/v0/customers' \ --header 'Content-Type: application/json' \ --header 'Api-Key: ' \ --header 'Idempotency-Key: ' \ --data-raw '{ "type": "individual", "first_name": "John", "last_name": "Doe", "email": "email@example.com", "residential_address": { "street_line_1": "123 Main St", "city": "New York City", "subdivision": "New York", "postal_code": "10001", "country": "USA" }, "birth_date": "2007-01-01", "signed_agreement_id": "d536a227-06d3-4de1-acd3-8b5131730480", "identifying_information": [ { "type": "ssn", "issuing_country": "usa", "number": "xxx-xx-xxxx" }, { "type": "drivers_license", "issuing_country": "usa", "number": "xxxxxxxxxxxxx", "image_front": "data:image/jpg;base64,...", "image_back": "data:image/jpg;base64,..." } ] } ``` A customer endorsement activates a customer to use a specific payment rail. Most flows automatically request a "base" endorsement when creating a customer. Endorsements represent an approval of a customer to onboard and transact with Bridge. To onboard a customer and enable them to take actions on Bridge, the customer must provide their KYC information and accept the terms of service for the required endorsement type. ## Checking Customer Endorsement Status ```bash Request expandable theme={null} curl --request GET \ --url https://api.bridge.xyz/v0/customers/{customerID} \ --header 'accept: application/json' ``` Example of an approved customer ```json Response expandable theme={null} { "id": '1', ... "endorsements": [ { "name": "base", "status": "approved", "additionalRequirements": [], "requirements": { "complete": [ "first_name", "last_name", "tax_identification_number", "email_address", "date_of_birth", "accepted_risk_region", "address_of_residence", "terms_of_service_v1" ], "pending": [], "missing": null, "issues": [], }, }, ], } ``` Example of an incomplete customer ```json expandable theme={null} { "id": "cust_1", ... "endorsements": [ { "name": "base", "status": "incomplete", "requirements": { "complete": [ "first_name", "last_name", "tax_identification_number", "email_address", "date_of_birth", "accepted_risk_region", "address_of_residence" ], "pending": [], "missing": { "all_of": [ "terms_of_service_v1", "sanctions_screen" ] }, "issues": [] }, }, ] } ``` Learn more about endorsements here: [Endorsements](/platform/customers/customers/endorsements) ## What's next? After creating your first customer: 1. **Test the complete flow** in your development environment 2. **Handle edge cases** like rejections and additional requirements 1. For detailed rejection reasons, see the [Rejection Reasons](/platform/customers/customers/rejection_reasons) 2. To increase customer limits, see the [Additional Requirements for Existing Customers](/platform/customers/customers/add_req) 3. **Set up webhooks** to receive real-time status updates for customers 1. See [Setting up webhooks](/get-started/introduction/quick-start/setting-up-webhooks) for setting up your first webhook 4. **Review security practices** to protect customer data Learn more at [Customers](/platform/customers/overview). # Get set up with Bridge Source: https://apidocs.bridge.xyz/get-started/introduction/quick-start/get-set-up-with-bridge ### Step 1: Create a Bridge account **Are you an existing developer?** Head over to [dashboard.bridge.xyz](https://dashboard.bridge.xyz) to login to your Bridge Dashboard. **Do you want to get started?** [Contact sales](https://www.bridge.xyz/requestfreedemo). ### Step 2: Create your API keys Once logged in, click on the "API Keys" tab on the top menu bar and generate a new API key. Safely store your API keys Bridge will make your **API key available only once**, so make sure to **immediately copy and save the key safely and securely**. Your key is used to authenticate into our APIs and is highly sensitive. If it ever gets compromised, you can immediately revoke key access from our dashboard and generate a new key. #### Creating scoped API keys programmatically In addition to the Dashboard, you can create **scoped API keys** via the API. Scoped keys are restricted to a subset of permissions and are useful for limiting what a key can do — for example, granting only `customer:read` access to a read-only service. Use `POST /v0/api_keys` with an unrestricted key or a key that holds the `api_key:create` scope: ```bash theme={null} curl -X POST https://api.bridge.xyz/v0/api_keys \ -H "Api-Key: " \ -H "Content-Type: application/json" \ -d '{ "name": "Customer service key", "scopes": ["customer:read", "customer:create"] }' ``` The `name` field is optional (up to 100 characters) and lets you label a key so you can identify its purpose later. The `value` in the response is the plaintext secret — it is returned **only once**, so store it immediately. Up to 500 scoped keys may exist per developer. To inspect the scopes on the key making a request, call `GET /v0/api_keys/whoami`. ### Step 3: Follow our guides and start moving money. [**Create your first customer**](/get-started/introduction/quick-start/create-your-first-customer) - This guide walks you through creating your first customer and getting them verified [**Create a one-time payment**](/get-started/introduction/quick-start/create-a-one-time-payment) - This guide walks you through moving funds onchain through a bank [**Setting up webhooks**](/get-started/introduction/quick-start/setting-up-webhooks) - This guide walks you through setting up and using Bridge webhooks to handle customer events in your application. # Platform overview Source: https://apidocs.bridge.xyz/get-started/introduction/quick-start/overview Bridge APIs are modular building blocks that let you create fast, flexible, and compliant payment experiences. Whether you’re collecting fiat, moving stablecoins, or issuing cards, our APIs are designed to support your unique use case — across fiat and crypto. This guide outlines the **core product categories**, what each product does, and **when you should use them**. *** ## 🔁 Orchestration: Move money Bridge orchestration APIs power your fiat and crypto flows. Go from fiat to crypto (onramps), crypto to fiat (offramps), and crypto to crypto. | Product | Description | Use when you need to... | | :---------------------------- | :-------------------------------------------------------------------------------------------------------------- | :------------------------------------------------------------------------------- | | **Virtual Accounts** | **Unique fiat deposit addresses** (USD, EUR, MXN, BRL, GBP, and more!) issued to your customers. | Collect fiat bank transfers - especially for recurring deposits. | | **Transfers** | **One-time fiat or stablecoin transfers**. Supports onramps, offramps, and crypto-to-crypto flows. | When you need to send or receive money programmatically - either fiat or crypto. | | **Static Template Transfers** | **Reusable transfer instructions** for **recurring**, template-based transfers. AKA payment routes in dashboard | Let customers make recurring payments. | | **Liquidation Addresses** | **On-chain addresses** that auto-forward to a crypto or fiat destination. | Accept crypto at fixed addresses and automatically route or convert funds. | | **Prefunded Accounts** | Load fiat into Bridge-managed balances for instant offramps. | **Guarantee fast withdrawals** without waiting for inbound deposits to settle. | *** ## 👜 Wallets: Custody crypto Bridge offers secure custodial wallets that allow you to hold and transfer stablecoins — with full compliance built-in. You can provision wallets for your customers or even for yourself to help with treasury management. | **Product** | **Description** | **Use When You Need To...** | | :----------------- | :------------------------------------------------------------------------- | ---------------------------------------------- | | **Bridge Wallets** | Custodial wallets for managing crypto on behalf of users or your business. | Custody crypto and power stablecoin transfers. | *** ## 💳 Cards: Spend stablecoins anywhere Let users spend their stablecoin balances globally using virtual Visa cards. | **Product** | **Description** | **Use When You Need To...** | | :---------- | :-------------------------------------------------------- | :------------------------------------------------------------------------------------------------- | | **Cards** | Issue virtual cards linked to Bridge or external wallets. | When you want to enable customers to spend stablecoin balances anywhere Visa is accepted globally. | *** ## 🪙 Issuance: Create or use stablecoins Use Bridge’s stablecoin (USDB) or launch your own branded version. | **Product** | **Description** | **Use When You Need To...** | | :---------------------------- | :----------------------------------------------------------------- | :------------------------------------------------------------ | | **USDB / Custom Stablecoins** | Mint USDB or branded stablecoins that earn yield on held balances. | Offer branded stablecoins, or earn yield on reserve balances. | *** ## 👤 Customers: Onboarding & compliance Bridge provides built-in tools to onboard and manage your users with full KYC/KYB compliance. | **Product** | **Description** | **Use When You Need To...** | | :---------------------- | :------------------------------------------------------------------------- | :--------------------------------------------------------------------------------- | | **Customer Onboarding** | Verify identity and onboard customers across financial rails and products. | Onboard users to new payment products and need to satisfy compliance requirements. | # Set up a sandbox environment Source: https://apidocs.bridge.xyz/get-started/introduction/quick-start/setting-up-sandbox Bridge has a sandbox environment for you to quickly begin testing your integration without having to move real money. To access this sandbox, you must first reach out to [support@bridge.xyz](mailto:support@bridge.xyz) to get onboarded with a Developer account within Bridge. Afterwards, you'll be able to generate sandbox API keys ## Step 1: Generate a Sandbox Key **Note that only dashboard admins have access to both sandbox and prod API keys.** \ Please ask your dashboard admin for access if you don't have it * Go to [https://dashboard.bridge.xyz/](https://dashboard.bridge.xyz/) and log in with your email. * Then, ensure the "Sandbox" toggle is turned on (blue). * Then, hit the button to generate a sandbox key. * Sandbox keys should be prefixed with `sk-test`. ## Step 2: Hit an API Bridge's sandbox is currently functional with the customer creation and KYC process. For example, here is how you can create a Bridge customer. **Note that the sandbox base url is** [https://api.sandbox.bridge.xyz](https://api.sandbox.bridge.xyz) ```bash expandable theme={null} curl --location --request POST 'https://api.sandbox.bridge.xyz/v0/customers' \ --header 'Content-Type: application/json' \ --header 'Api-Key: ' \ --header 'Idempotency-Key: ' \ --data-raw '{ "first_name": "John", "last_name": "Doe", "email": "johndoe@johndoe.com", "address": { "street_line_1": "123 Washington St", "street_line_2": "Apt 2F", "city": "San Francisco", "state": "CA", "postal_code": "10001", "country": "USA" }, "birth_date": "1989-09-09", "tax_identification_number": "111-11-1111", "phone": "+15555555555", "signed_agreement_id": "", "type": "individual" }' ``` We recommend the following steps to get a sense of how to use Bridge: * Create a customer * Call `POST /v0/customers/{customer_id}/simulate_kyc_approval` to approve them * Fetch that customer and verify `kyc_status` is `approved` * Create fake liquidation addresses, transfers and fiat deposit instructions (Note: there is no real money movement in Sandbox) ## Differences with Production Sandbox differs from production in a few key areas. We highly recommend using the Sandbox only to test API request/response schemas and Production itself for any other kind of testing. **Onboarding/KYC** * Customers must be created via the API; they cannot be created using kyc links. * Customers require a simulated KYC/KYB approval. After creating a customer, call `POST /v0/customers/{customer_id}/simulate_kyc_approval` to approve them and enable money movement. * Sandbox is subject to arbitrary rate limits; we may drop your requests anytime. * The signed agreement ID in production cannot be arbitrary * While in production you can have multiple users under the same Developer Account, in Sandbox each of those users will be scoped under their own unique Developer Account. In particular, changes made by one user in the sandbox won't be visible to other users **even if those users share a developer account in production**. **Payments** * There is no real money movement in Sandbox. * Plaid does not work in Sandbox. * There is no testnet support in Sandbox. * Virtual Accounts, Static Memos, Liquidation Addresses, and Transfers are created with dummy data. * There are no payments-related webhooks fired in sandbox. **Wallets** * You can create and test Bridge wallets in Sandbox. See [Sandbox integration](/platform/wallets/sandbox) for details. * Use the `simulate_deposit` endpoint to add funds to wallets in Sandbox. * Sandbox wallets don't interact with the blockchain and use fake addresses. Stablecoin Issuance is only supported in Production. If you have suggests for how to improve our sandbox experience, please reach out to us at [support@bridge.xyz](mailto:support@bridge.xyz), thanks! # Configure webhooks Source: https://apidocs.bridge.xyz/get-started/introduction/quick-start/setting-up-webhooks Bridge webhooks allow you to receive real-time notifications when events occur in your Bridge account. This guide covers creating, implementing, testing, and enabling webhooks using Bridge's REST API. ## Prerequisites * A Bridge account with API access * Bridge API credentials (API key) * HTTPS endpoint with valid X.509 certificate * Development environment with your preferred language (Ruby, Node.js, Python, or Go) *** ## Step 1: Create a New Webhook First, create a webhook endpoint using the Bridge API. The webhook will be created in `disabled` state initially. ```bash Request expandable theme={null} curl --request POST \ --url https://api.bridge.xyz/v0/webhooks \ --header 'Api-Key: ' \ --header 'Content-Type: application/json' \ --header 'Idempotency-Key: ' \ --data '{ "url": "", "event_epoch": "webhook_creation", "event_categories": [ "customer", "kyc_link", "transfer" ] }' ``` ```json Response expandable theme={null} { "id": "webhook_abc123", "status": "disabled", "url": "https://your-domain.com/webhooks/bridge", "events": ["customer", "kyc_link", "transfer"], "created_at": "2024-01-15T10:30:00Z" } ``` Save the `webhook_id` from the response - you'll need it for testing and enabling the webhook. ## Step 2: Implement the Webhook Handler Create an endpoint that can receive and process Bridge webhook events with proper timestamp validation, refer [Webhook Event Signature Verification](/platform/additional-information/webhooks/signature). Bridge webhook signatures use the format: `X-Webhook-Signature: t=,v0=` ```python expandable theme={null} from flask import Flask, request, jsonify from typing import Dict, Any, Optional, Union import json import base64 import time from cryptography.hazmat.primitives import hashes, serialization from cryptography.hazmat.primitives.asymmetric import padding from cryptography.exceptions import InvalidSignature app = Flask(__name__) class WebhookEvent: def __init__(self, data: Dict[str, Any]): self.api_version: str = data['api_version'] self.event_id: str = data['event_id'] self.event_category: str = data['event_category'] self.event_type: str = data['event_type'] self.event_object: Dict[str, Any] = data['event_object'] self.event_object_changes: Optional[Dict[str, Any]] = data.get('event_object_changes') self.event_created_at: str = data['event_created_at'] class SignatureVerificationResult: def __init__(self, is_valid: bool, error: Optional[str] = None): self.is_valid = is_valid self.error = error WEBHOOK_PUBLIC_KEY = """-----BEGIN PUBLIC KEY----- your_webhook_public_key_here -----END PUBLIC KEY-----""" def verify_webhook_signature(payload: bytes, signature_header: str, public_key_pem: str) -> SignatureVerificationResult: try: # Parse signature header signature_parts = signature_header.split(',') timestamp = next((part.split('=', 1)[1] for part in signature_parts if part.startswith('t=')), None) signature = next((part.split('=', 1)[1] for part in signature_parts if part.startswith('v0=')), None) if not timestamp or not signature: return SignatureVerificationResult(False, 'Missing timestamp or signature') # Check timestamp (reject events older than 10 minutes) current_time = int(time.time() * 1000) if current_time - int(timestamp) > 600000: return SignatureVerificationResult(False, 'Timestamp too old') # Create and digest signed payload signed_payload = f"{timestamp}.{payload.decode()}" digester = hashlib.sha256(signed_payload.encode()) # Verify signature public_key = serialization.load_pem_public_key(public_key_pem.encode()) signature_bytes = base64.b64decode(signature) public_key.verify( signature_bytes, digester.digest(), padding.PKCS1v15(), hashes.SHA256() ) return SignatureVerificationResult(True) except InvalidSignature: return SignatureVerificationResult(False, 'Invalid signature') except Exception as e: return SignatureVerificationResult(False, f'Signature verification failed: {e}') def handle_webhook_event(event: WebhookEvent) -> None: if event.event_type == 'customer.created': print(f"New customer created: {event.event_object.get('id')}") elif event.event_type == 'customer.updated': print(f"Customer updated: {event.event_object.get('id')}") elif event.event_type == 'transfer.created': print(f"Transfer created: {event.event_object.get('id')}") else: print(f"Unhandled event type: {event.event_type}") @app.route('/webhooks/bridge', methods=['POST']) def handle_webhook(): payload = request.get_data() signature_header = request.headers.get('X-Webhook-Signature') if not signature_header: return jsonify({'error': 'Missing signature header'}), 400 verification = verify_webhook_signature(payload, signature_header, WEBHOOK_PUBLIC_KEY) if not verification.is_valid: print(f"Signature verification failed: {verification.error}") return jsonify({'error': 'Invalid signature'}), 400 try: event_data = json.loads(payload) event = WebhookEvent(event_data) handle_webhook_event(event) return jsonify({'received': True}) except Exception as e: print(f"Failed to parse webhook event: {e}") return jsonify({'error': 'Invalid JSON'}), 400 if __name__ == '__main__': app.run(port=3000, debug=True) ``` ```typescript expandable theme={null} import express, { Request, Response } from 'express'; import crypto from 'crypto'; const app = express(); interface WebhookEvent { api_version: string; event_id: string; event_category: string; event_type: string; event_object: Record; event_object_changes?: Record; event_created_at: string; } interface SignatureVerificationResult { isValid: boolean; error?: string; } const WEBHOOK_PUBLIC_KEY = `-----BEGIN PUBLIC KEY----- your_webhook_public_key_here -----END PUBLIC KEY-----`; app.use('/webhooks/bridge', express.raw({ type: 'application/json' })); function verifyWebhookSignature( payload: Buffer, signatureHeader: string, publicKey: string ): SignatureVerificationResult { try { // Parse signature header const signatureParts = signatureHeader.split(','); const timestamp = signatureParts.find(part => part.startsWith('t='))?.split('=')[1]; const signature = signatureParts.find(part => part.startsWith('v0='))?.split('=')[1]; if (!timestamp || !signature) { return { isValid: false, error: 'Missing timestamp or signature' }; } // Check timestamp (reject events older than 10 minutes) const currentTime = Date.now(); if (currentTime - parseInt(timestamp) > 600000) { return { isValid: false, error: 'Timestamp too old' }; } // Create signed payload const signedPayload = `${timestamp}.${payload.toString()}`; // Create a SHA256 digest of the signed payload const digest = crypto.createHash('sha256').update(signedPayload).digest(); // Verify signature const verifier = crypto.createVerify('RSA-SHA256'); verifier.update(digest); const isValid = verifier.verify(publicKey, signature, 'base64'); return { isValid }; } catch (error) { return { isValid: false, error: `Verification failed: ${error.message}` }; } } function handleWebhookEvent(event: WebhookEvent): void { switch (event.event_type) { case 'customer.created': console.log(`New customer created: ${event.event_object.id}`); break; case 'customer.updated': console.log(`Customer updated: ${event.event_object.id}`); break; case 'transfer.created': console.log(`Transfer created: ${event.event_object.id}`); break; default: console.log(`Unhandled event type: ${event.event_type}`); } } app.post('/webhooks/bridge', (req: Request, res: Response) => { const payload = req.body as Buffer; const signatureHeader = req.headers['x-webhook-signature'] as string; if (!signatureHeader) { return res.status(400).json({ error: 'Missing signature header' }); } const verification = verifyWebhookSignature(payload, signatureHeader, WEBHOOK_PUBLIC_KEY); if (!verification.isValid) { console.error('Signature verification failed:', verification.error); return res.status(400).json({ error: 'Invalid signature' }); } try { const event: WebhookEvent = JSON.parse(payload.toString()); handleWebhookEvent(event); res.status(200).json({ received: true }); } catch (error) { console.error('Failed to parse webhook event:', error); res.status(400).json({ error: 'Invalid JSON' }); } }); app.listen(3000, () => console.log('Webhook server listening on port 3000')); ``` ```ruby expandable theme={null} # typed: strict require 'sinatra' require 'json' require 'openssl' require 'base64' require 'sorbet-runtime' class WebhookHandler extend T::Sig class WebhookEvent < T::Struct prop :api_version, String prop :event_id, String prop :event_category, String prop :event_type, String prop :event_object, T::Hash[String, T.untyped] prop :event_object_changes, T.nilable(T::Hash[String, T.untyped]) prop :event_created_at, String end class SignatureVerificationResult < T::Struct prop :is_valid, T::Boolean prop :error, T.nilable(String) end WEBHOOK_PUBLIC_KEY = T.let("""-----BEGIN PUBLIC KEY----- your_webhook_public_key_here -----END PUBLIC KEY-----""", String) sig { params(payload: String, signature_header: String, public_key_pem: String).returns(SignatureVerificationResult) } def self.verify_webhook_signature(payload, signature_header, public_key_pem) # Parse signature header: t=timestamp,v0=signature signature_parts = signature_header.split(',') timestamp = signature_parts.find { |part| part.start_with?('t=') }&.split('=', 2)&.last signature = signature_parts.find { |part| part.start_with?('v0=') }&.split('=', 2)&.last return SignatureVerificationResult.new(is_valid: false, error: 'Missing timestamp or signature') unless timestamp && signature # Check timestamp (reject events older than 10 minutes) current_time = Time.now.to_i * 1000 if current_time - timestamp.to_i > 600_000 return SignatureVerificationResult.new(is_valid: false, error: 'Timestamp too old') end # Create signed payload: timestamp.payload signed_payload = "#{timestamp}.#{payload}" begin # Verify signature public_key = OpenSSL::PKey::RSA.new(public_key_pem) signature_bytes = Base64.decode64(signature) is_valid = public_key.verify(OpenSSL::Digest::SHA256.new, signature_bytes, signed_payload) SignatureVerificationResult.new(is_valid: is_valid) rescue => e SignatureVerificationResult.new(is_valid: false, error: "Signature verification failed: #{e.message}") end end sig { params(event: WebhookEvent).void } def self.handle_webhook_event(event) case event.event_type when 'customer.created' puts "New customer created: #{event.event_object['id']}" when 'customer.updated' puts "Customer updated: #{event.event_object['id']}" when 'transfer.created' puts "Transfer created: #{event.event_object['id']}" else puts "Unhandled event type: #{event.event_type}" end end end post '/webhooks/bridge' do payload = request.body.read signature_header = request.env['HTTP_X_WEBHOOK_SIGNATURE'] unless signature_header status 400 return { error: 'Missing signature header' }.to_json end verification = WebhookHandler.verify_webhook_signature(payload, signature_header, WebhookHandler::WEBHOOK_PUBLIC_KEY) unless verification.is_valid puts "Signature verification failed: #{verification.error}" status 400 return { error: 'Invalid signature' }.to_json end begin event_data = JSON.parse(payload) event = WebhookHandler::WebhookEvent.new( api_version: T.cast(event_data['api_version'], String), event_id: T.cast(event_data['event_id'], String), event_category: T.cast(event_data['event_category'], String), event_type: T.cast(event_data['event_type'], String), event_object: T.cast(event_data['event_object'], T::Hash[String, T.untyped]), event_object_changes: T.cast(event_data['event_object_changes'], T.nilable(T::Hash[String, T.untyped])), event_created_at: T.cast(event_data['event_created_at'], String) ) WebhookHandler.handle_webhook_event(event) status 200 { received: true }.to_json rescue => e puts "Failed to parse webhook event: #{e.message}" status 400 { error: 'Invalid JSON' }.to_json end end ``` ```java expandable theme={null} import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.web.bind.annotation.*; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.annotation.JsonProperty; import java.security.KeyFactory; import java.security.MessageDigest; import java.security.PublicKey; import java.security.Signature; import java.security.spec.X509EncodedKeySpec; import java.util.Base64; import java.util.HashMap; import java.util.Map; @SpringBootApplication @RestController public class WebhookHandler { private static final String WEBHOOK_PUBLIC_KEY = """ -----BEGIN PUBLIC KEY----- your_webhook_public_key_here -----END PUBLIC KEY----- """; static class WebhookEvent { @JsonProperty("api_version") public String apiVersion; @JsonProperty("event_id") public String eventId; @JsonProperty("event_category") public String eventCategory; @JsonProperty("event_type") public String eventType; @JsonProperty("event_object") public Map eventObject; @JsonProperty("event_object_changes") public Map eventObjectChanges; @JsonProperty("event_created_at") public String eventCreatedAt; } static class SignatureVerificationResult { public boolean isValid; public String error; public SignatureVerificationResult(boolean isValid, String error) { this.isValid = isValid; this.error = error; } } @PostMapping("/webhooks/bridge") public ResponseEntity> handleWebhook( @RequestBody String payload, @RequestHeader(value = "X-Webhook-Signature", required = false) String signatureHeader) { if (signatureHeader == null) { Map error = new HashMap<>(); error.put("error", "Missing signature header"); return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(error); } SignatureVerificationResult verification = verifyWebhookSignature(payload, signatureHeader, WEBHOOK_PUBLIC_KEY); if (!verification.isValid) { System.err.println("Signature verification failed: " + verification.error); Map error = new HashMap<>(); error.put("error", "Invalid signature"); return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(error); } try { ObjectMapper mapper = new ObjectMapper(); WebhookEvent event = mapper.readValue(payload, WebhookEvent.class); handleWebhookEvent(event); Map response = new HashMap<>(); response.put("received", true); return ResponseEntity.ok(response); } catch (Exception e) { System.err.println("Failed to parse webhook event: " + e.getMessage()); Map error = new HashMap<>(); error.put("error", "Invalid JSON"); return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(error); } } private void handleWebhookEvent(WebhookEvent event) { switch (event.eventType) { case "customer.created": System.out.println("New customer created: " + event.eventObject.get("id")); break; case "customer.updated": System.out.println("Customer updated: " + event.eventObject.get("id")); break; case "transfer.created": System.out.println("Transfer created: " + event.eventObject.get("id")); break; default: System.out.println("Unhandled event type: " + event.eventType); } } private SignatureVerificationResult verifyWebhookSignature(String payload, String signatureHeader, String publicKeyPem) { try { // Parse signature header String[] parts = signatureHeader.split(","); String timestamp = null; String signature = null; for (String part : parts) { if (part.startsWith("t=")) { timestamp = part.substring(2); } else if (part.startsWith("v0=")) { signature = part.substring(3); } } if (timestamp == null || signature == null) { return new SignatureVerificationResult(false, "Missing timestamp or signature"); } // Check timestamp (reject events older than 10 minutes) long currentTime = System.currentTimeMillis(); long eventTime = Long.parseLong(timestamp); if (currentTime - eventTime > 600000) { return new SignatureVerificationResult(false, "Timestamp too old"); } // Create signed payload String signedPayload = timestamp + "." + payload; // Parse public key String publicKeyContent = publicKeyPem .replace("-----BEGIN PUBLIC KEY-----", "") .replace("-----END PUBLIC KEY-----", "") .replaceAll("\\s", ""); byte[] keyBytes = Base64.getDecoder().decode(publicKeyContent); X509EncodedKeySpec spec = new X509EncodedKeySpec(keyBytes); KeyFactory keyFactory = KeyFactory.getInstance("RSA"); PublicKey publicKey = keyFactory.generatePublic(spec); MessageDigest digest = MessageDigest.getInstance("SHA-256"); byte[] dataDigest = digest.digest(signedPayload.getBytes()); // Verify signature Signature sig = Signature.getInstance("SHA256withRSA"); sig.initVerify(publicKey); sig.update(dataDigest); byte[] signatureBytes = Base64.getDecoder().decode(signature); boolean isValid = sig.verify(signatureBytes); return new SignatureVerificationResult(isValid, null); } catch (Exception e) { return new SignatureVerificationResult(false, "Signature verification failed: " + e.getMessage()); } } public static void main(String[] args) { SpringApplication.run(WebhookHandler.class, args); } } ``` ```go expandable theme={null} // Go (Gin) package main import ( "crypto" "crypto/rsa" "crypto/sha256" "crypto/x509" "encoding/base64" "encoding/json" "encoding/pem" "fmt" "net/http" "strconv" "strings" "time" "github.com/gin-gonic/gin" ) const WEBHOOK_PUBLIC_KEY = `-----BEGIN PUBLIC KEY----- your_webhook_public_key_here -----END PUBLIC KEY-----` type WebhookEvent struct { Type string `json:"type"` Data map[string]interface{} `json:"data"` } func verifyWebhookSignature(payload []byte, signatureHeader, publicKeyPEM string) bool { // Parse signature header parts := strings.Split(signatureHeader, ",") var timestamp, signature string for _, part := range parts { if strings.HasPrefix(part, "t=") { timestamp = strings.TrimPrefix(part, "t=") } else if strings.HasPrefix(part, "v0=") { signature = strings.TrimPrefix(part, "v0=") } } if timestamp == "" || signature == "" { return false } // Check timestamp (reject events older than 10 minutes) ts, err := strconv.ParseInt(timestamp, 10, 64) if err != nil { fmt.Printf("Failed to parse timestamp: %v\n", err) return false } currentTime := time.Now().UnixNano() / int64(time.Millisecond) if currentTime-ts > 600000 { fmt.Println("Timestamp too old") return false } // Create signed payload signedPayload := fmt.Sprintf("%s.%s", timestamp, string(payload)) // Parse public key block, _ := pem.Decode([]byte(publicKeyPEM)) if block == nil { fmt.Println("Failed to parse PEM public key") return false } publicKey, err := x509.ParsePKIXPublicKey(block.Bytes) if err != nil { fmt.Printf("Failed to parse public key: %v\n", err) return false } rsaPublicKey, ok := publicKey.(*rsa.PublicKey) if !ok { fmt.Println("Public key is not RSA") return false } // Decode signature signatureBytes, err := base64.StdEncoding.Strict().DecodeString(signature) if err != nil { fmt.Printf("Failed to decode signature: %v\n", err) return false } // Hash the signed payload, twice hashed := sha256.Sum256([]byte(signedPayload)) hashed = sha256.Sum256(hashed[:]) // Verify signature err = rsa.VerifyPKCS1v15(rsaPublicKey, crypto.SHA256, hashed[:], signatureBytes) if err != nil { fmt.Printf("Signature verification failed: %v\n", err) return false } return true } func handleWebhook(c *gin.Context) { payload, err := c.GetRawData() if err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": "Failed to read payload"}) return } signatureHeader := c.GetHeader("X-Webhook-Signature") if !verifyWebhookSignature(payload, signatureHeader, WEBHOOK_PUBLIC_KEY) { c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid signature"}) return } var event WebhookEvent if err := json.Unmarshal(payload, &event); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid JSON"}) return } switch event.Type { case "customer.created": fmt.Printf("New customer created: %v\n", event.Data["id"]) case "customer.updated": fmt.Printf("Customer updated: %v\n", event.Data["id"]) } c.JSON(http.StatusOK, gin.H{"received": true}) } func main() { r := gin.Default() r.POST("/webhooks/bridge", handleWebhook) fmt.Println("Webhook server listening on port 3000") r.Run(":3000") } ``` ## Step 3: Test the Webhook Before enabling your webhook, test it to ensure it's working correctly. ### Send a Test Event ```bash expandable theme={null} # Send a test event to your webhook curl --request POST \ --url https://api.bridge.xyz/v0/webhooks/{webhookID}/send \ --header 'Api-Key: ' \ --header 'Content-Type: application/json' \ --header 'Idempotency-Key: ' \ --data '{ "event_id": "" }' ``` ### Check Webhook Logs ```bash expandable theme={null} # View webhook delivery logs curl --request GET \ --url https://api.bridge.xyz/v0/webhooks/{webhookID}/logs \ --header 'Api-Key: ' ``` ### List upcoming webhook events ```bash expandable theme={null} # Retrieve upcoming events for the webhook curl --request GET \ --url https://api.bridge.xyz/v0/webhooks/{webhookID}/events \ --header 'Api-Key: ' ``` ## Step 4: Enable the Webhook Once you've tested your webhook and confirmed it's working, enable it to start receiving live events. ```bash Request expandable theme={null} curl --request PUT \ --url https://api.bridge.xyz/v0/webhooks/{webhookID} \ --header 'Api-Key: ' \ --header 'Content-Type: application/json' \ --data '{ "url": "https://your-domain.com/webhooks/bridge", "status": "active", "event_categories": [ "customer" ] }' ``` ```json Response expandable theme={null} { "id": "wep_123", "url": "https://your-domain.com/webhooks/bridge", "status": "active", "public_key": "-----BEGIN PUBLIC KEY-----\\nFJJ3hFnaPLmxxG4a5w0BAQEFAAOCAQ8AMIIBCgKCAQEAtYhc6PV2LOs/nqDRHi0B\\nMKTsdMLHtg58a1NDxaYfw4IZJ3hpy1qIFUgt5X0HhCYZE0Y40MyLGIejPyitEjYw\\ni9/aE+9F/PN+btqN7OK6cVuF9s/R9cZCtNc27UdTQXrUO5T8GXNAMmRr0KFh8yPv\\nfIgpoZn5ZhnyRbZpDvrxHzLmcZJFAX8Ca+KZLzgGVybEqJtP6fKAT0zrrUS1z44s\\nRDOLiXl543cRAmBnUyrT6cXiNz/PNbm4zRK5Nx7LGxBFrCWQCao4Yi8hrwWsnHxg\\n0Tcy3UyZhAcgL6ydVJfLD5x58Ri4BN32WPBtgSSO6JxZZwCiX0d1BOgq7+eNgmzN\\nJQIDAQAB\\n-----END PUBLIC KEY-----\\n", "event_categories": [ "customer", "liquidation_address", "virtual_account", "virtual_account.activity", "card_account", "card_transaction", "card_withdrawal", "posted_card_account_transaction" ] } ``` Your webhook is now active and will receive live events from Bridge! ## Best Practices ### General 1. **Return 200 status quickly** to avoid timeouts 2. **Implement idempotency** to handle duplicate events 3. **Gracefully handle non-breaking changes (new fields, non-schema changes)** to prevent disruptions to your integration 4. **Log webhook events** for debugging and monitoring ### Security 1. **Always verify webhook signatures** to ensure events are from Bridge 2. **Use HTTPS endpoints** with valid certificates 3. **Store webhook secrets securely** (use environment variables) ## Common Event Types * `customer.created` - New customer registration * `customer.updated` - Customer information changes * `payment.succeeded` - Successful payment processing * `payment.failed` - Failed payment attempt * `subscription.created` - New subscription * `subscription.cancelled` - Subscription cancellation ## Troubleshooting * **Check webhook logs** for delivery status and error messages * **Verify your endpoint URL** is accessible and returns 200 * **Ensure signature verification** is implemented correctly * **Check for certificate issues** on your HTTPS endpoint * **Monitor response times** to avoid timeout issues ## Next Steps * Review the [Webhooks](/platform/additional-information/webhooks/overview) documentation for more details * Implement proper error handling and retry logic * Set up monitoring and alerting for webhook failures * Consider implementing webhook replay functionality for critical events This completes your webhook integration with Bridge. Your application will now receive real-time notifications for customer events and can respond accordingly. # Supported blockchains and fiat rails Source: https://apidocs.bridge.xyz/get-started/introduction/what-we-support/payment-routes Supported currencies, rails, and which currency pairs can be converted The following stablecoins and blockchains are supported across all Bridge APIs. Interested in support for other assets or blockchains? **Contact us directly** to discuss integration. ### Important * ⚠️ Deposits sent to **unsupported asset/blockchain pairs** or to **incorrect addresses** may be **irretrievable and permanently lost**. * Make sure that you are sending amounts above the **transaction minimum**, learn more about how minimums are enforced [here](/platform/orchestration/fees-and-mins/mins). Refer the below table for supported payment routes and transaction minimums. * **USDC & EURC are the only stablecoins supported for users in the EEA** due to regulatory restrictions ### **Supported fiat rails** * ACH (USD) * FedNow (USD) * Wire (USD) * SEPA (EUR) * SPEI (MXN) * Pix (BRL) * Faster Payments (GBP) * Bre-B & Bank Transfer (COP) * and more coming soon! ### **Route Explorer** Below, you will find all the routes we support. You can use the filters to search for the routes you are interested in. # index Source: https://apidocs.bridge.xyz/index

Build with Bridge.

Bridge provides modern payments infrastructure to move money with stablecoins and fiat rails, custody funds via wallets, issue your own stablecoin, and provision globally accepted cards — at the speed and scale of the internet.

Get started →

Quickstart guides

Use a virtual account to accept deposits in USD, EUR, GBP, MXN, and more with a unique account & routing number. Easily create onramps, offramps, and crypto to crypto transfers using our orchestration APIs. Provision a card backed by stablecoins and spend anywhere in the world. Custody funds in a wallet. Use it to send, receive, or hold stablecoins. Issue your own stablecoin and start earning yield.

Resources

Reach out to our team for help with integration or technical issues. Click here to request a demo! Watch our interactive demo to see Bridge in action.
# FAQ guidance for your users Source: https://apidocs.bridge.xyz/platform/additional-information/faq Bridge requires its developers to include the following FAQs in their support pages. These are common questions that users ask from support channels. Anything enclosed in \[], such as \[support\_email], must be filled out based on the developer. We do not require you to use our exact copy as long as the questions are covered. Translations in other languages such as Spanish are accepted as well. ## **Common Payment Questions** #### **I have a question about a payment. How can I contact support?** Reach out to \[developer\_name] at \[support\_email], \[phone\_number] or \[social\_media\_handles]. Please avoid contacting our banking partners directly, as they are not best suited to help you. #### **My funds are missing or have not landed in my account.** Contact us at \[support\_email]/\[support\_phone]/\[whatsapp] and we will investigate. If you have sent funds from your bank account, request a Trace ID for an ACH payment or an IMAD for a wire from your bank. Providing this information will help us track down the transaction faster. #### **When will the funds land in the account?** Next-day ACH transactions can take 1-3 days to arrive in your account. Same-day ACH transactions sent before 4 pm EST will arrive at their destination on the same day.\ Wires can take a few hours to process, but they will be processed the same day as long as they are received before 5 p.m. EST. #### **What is the minimum amount that I can send or receive?** As a developer, you can modify the language depending on the type of payment. Refer [here](https://apidocs.bridge.xyz/docs/transaction-costs) for documentation on minimum transaction amounts. #### **Where do I input the memo when making a payment?** Memos can be entered in the Memo or reference field when creating the ACH or Wire.\ For JP Morgan Chase, the correct field is called “Message to Recipient.”\ For Mercury, the correct field is called “Message to Recipient.” We recommend reaching out to your bank if you are not sure where the memo should go ## **My bank doesn’t recognize the Routing Number for the payment. What should I do?** The correct routing numbers for Lead Bank are 101019644 for virtual accounts and 101206101 for most memo-based payments. Both can be found on FRB Services' website at [frbservices.org](http://frbservices.org). The American Bankers Association (ABA) also provides an online lookup tool for routing numbers, which can be accessed here. If you encounter any errors, please contact your bank's support and inform them that these routing numbers are listed on the websites mentioned above and should be recognized to support wire and ACH payments. ## **Virtual Account FAQs** If you are utilizing Bridge Virtual Accounts, we require the following questions to be covered in your FAQs. #### **Does \[developer\_name] provide SWIFT codes or account numbers to its Customers?** Virtual accounts with \[developer\_name] do not currently support SWIFT payments, only ACH and US domestic wires. #### **My bank did a microdeposit to my virtual account. How do I get the amounts for the microdeposits?** Notifications for Microdeposits made to virtual accounts are sent to \[email, SMS, push notification]. It can take up to 1 day for the microdeposits to arrive. #### **I am being asked for a 3-letter code by Plaid that was sent to my virtual account. Where can I find this code?** The 3 letter code is included as part of the descriptor of the microdeposit. #### **What types of transactions can I receive in my virtual account?** **Virtual accounts are fully permitted to receive the following transactions for non-US residents.** 1. First-party payments where you are sending USD from your bank, fintech app, or brokerage account 2. Third-party payment where a registered business sends USD from its bank account 3. Third-party payment from a family member’s bank account, where you share a surname 4. Third-party Person-to-Person payment for an amount less than \$4,000 **The following types of transactions are fully permitted to be received by virtual accounts for US residents.** 1. First-party payments where you are sending USD from your bank, fintech app, or brokerage account 2. Payroll payments from businesses 3. Third party payments in most states except for a few, please refer [here](/platform/orchestration/more/rail-specific) # Precision and rounding Source: https://apidocs.bridge.xyz/platform/additional-information/precision When interacting with Bridge’s APIs, it's important to understand how we handle **rounding, fees, and fractional cent precision** to ensure your payments are processed smoothly and your customer receives the expected amount. *** ## Key Policies * **Whole cent enforcement**\ Bridge only processes amounts that can be expressed in **whole U.S. cents**.\ Even if the stablecoin supports more than two decimal places, Bridge will **truncate** the amount to the nearest cent. * **Fractional Cents Are Discarded**\ Any fractional cent (e.g., `$100.119999`) will be **ignored**, not processed or refunded. * **Rounding Ensures Sufficient Balance** * Bridge will round fractional cent values in such a way to ensure that there will always be sufficient balance available to process your transaction. * Bridge will always round in such a way to guarantee at least the minimum amount of fees that are owed to all parties, whether they be our developers or to Bridge. ### Example Calculation Let’s say you want to offramp **\$100,100.119999 USDT** with a **10 bps developer fee (0.1%)**: 1. **Bridge truncates to whole cents**:\ Note that USDT, like many other stablecoins, has 6 digits of precision. However, because Bridge only supports whole cents, we will first truncate this amount down to \$100,100.11.\ `$100,100.119999 → rounded down to $100,100.11` 2. **Bridge calculates developer fee**:\ `0.1% of $100,100.11 = $100.10011 → rounded up to $100.11` 3. **Customer receives**:\ `$100,100.11 - $100.11 = $100,000.00` Therefore, the amount that Bridge will send to the destination is \$100,000.00. ## Working backwards from desired output If you want your customer to receive a **clean, round-dollar output**, use this formula: `Input Amount = Output Amount / 0.999 ` Then **round up** to the nearest cent to ensure fees are covered. ### 📐 Reference Table These examples assume **no developer fee** and only standard Bridge exchange fees. | **Input Amount** | **Output Amount** | | :--------------- | :---------------- | | \$100.11 | \$100.00 | | \$200.21 | \$200.00 | | \$500.51 | \$500.00 | | \$1,001.01 | \$1,000.00 | | \$100,100.11 | \$100,000.00 | | \$500,500.51 | \$500,000.00 | # Pricing Source: https://apidocs.bridge.xyz/platform/additional-information/pricing Please reach out to [sales@bridge.xyz](mailto:sales@bridge.xyz) to discuss pricing. # Receipts Source: https://apidocs.bridge.xyz/platform/additional-information/receipts Bridge is required to send receipts for transactions processed through our system. These receipts include transaction amount, fees and Bridge legal disclosures. When you're integrating, we will work with your team to customize these receipts to match your branding. # Webhooks Source: https://apidocs.bridge.xyz/platform/additional-information/webhooks/overview Bridge's [Webhooks API](/api-reference/webhooks) lets developers manage webhook endpoints that are subscribed to webhook events for real-time updates instead of relying on API polling for a faster, more efficient, and better overall experience. Webhook endpoints require you to provide a `url` with the https scheme and a valid X.509 certificate. When your endpoint is created, a `PKI public key` in `PEM` format will be assigned to it and shared with you. Refer to [Webhook Event Signature Verification](/platform/additional-information/webhooks/signature) for details on how to verify the authenticity of incoming events. When your endpoint is active, Bridge will deliver events with `POST` with the `application/json` content type. The endpoint should return a 200 status to Bridge as quickly as possible to avoid timeouts and retries on the Bridge side. ## **Implementation Flow** A typical flow to implement Bridge webhooks within your application may like the following 1. Make a [POST request to /webhooks](/api-reference/webhooks/create-a-webhook-endpoint) to create your endpoint in the `disabled` state. 2. Implement your application's logic for [Webhook Event Signature Verification](/platform/additional-information/webhooks/signature). 3. [Get upcoming webhook events](/api-reference/webhooks/list-upcoming-events) and [send events](/api-reference/webhooks/send-event) to test the logic for receiving events from bridge. You can [view event delivery logs](/api-reference/webhooks/view-logs) to debug any issues 4. After verifying your webhook functionality, enable it using [PUT /webhooks](/api-reference/webhooks/update-a-webhook) **Note**: Webhooks can also be created, updated, and deleted in the Bridge Dashboard. ## **Webhook States** The webhook status refers to the current state of a webhook. There are several possible states that a webhook can be in, including: * `disabled` - This is the initial state of all newly created webhooks. Events will not automatically be delivered to the endpoint in this state. We recommend testing the webhook from this state using (see [POST /send documentation](/api-reference/webhooks/send-event)). You can update the webhook to `active` using [PUT /webhooks](/api-reference/webhooks/update-a-webhook). Webhooks must be disabled in order to change their URL * `active` - Bridge will automatically deliver events to your webhook. Automatic delivery of events can be paused by updating the webhook to `disabled` using [PUT /webhooks](/api-reference/webhooks/update-a-webhook) * `deleted`- This state is only visible as the result of a [DELETE /webhooks](/api-reference/webhooks/delete-a-webhook) request. This state is not considered a valid status input of [PUT /webhooks](/api-reference/webhooks/update-a-webhook). Webhooks in this state will no longer be accessible from subsequent API requests. ## **FAQ** * **Q: How do retries work?** If your endpoint is unavailable when Bridge attempts to deliver a webhook, Bridge will automatically retry with exponential backoff for up to two days. # Webhook event signature verification Source: https://apidocs.bridge.xyz/platform/additional-information/webhooks/signature For each event delivery, Bridge will include a webhook signature header in the HTTP request for event authenticity verification * The header name is`X-Webhook-Signature` ; * The header value format is `t=,v0=` , where the timestamp is in milliseconds; To verify the signature, follow these steps: 1. Parse the signature header to extract the `timestamp` and `base64 encoded signature` 2. Join `timestamp` with the `raw http request body data` with a dot (`.`), and generate a `SHA256` digest; 3. Perform a strict base64 decoding on the `based64 encoded signature` to get the `decoded signature`; 4. Verify the signature using the per-endpoint `public key`, `digest` (from Step 2), and `decoded signature` (from Step 3 **To avoid replay attacks** Bridge advises the receiving endpoint to disregard events that are older than a few minutes, e.g. 10 minutes, and return a 400 status to request retries. For each event delivery retry, Bridge generates a new timestamp. Check out the guide [here](/get-started/introduction/quick-start/setting-up-webhooks) to see sample code setting up webhooks. # Event structure Source: https://apidocs.bridge.xyz/platform/additional-information/webhooks/structure Bridge now supports webhook events for the following categories: * `customer` * `kyc_link` * `liquidation_address.drain` * `static_memo.activity` * `transfer` * `virtual_account.activity` * `bridge_wallet.activity` * `card_account` * `card_transaction` * `posted_card_account_transaction` * `card_withdrawal` * `external_acccount` Additional event categories will be added soon.\ \ **💬 Feedback welcome** — Let us know which event types you'd like to see prioritized next. ## Supported Event Types | **Category** | **Supported Event Types** | | :-------------------------------- | :------------------------------------------------------------- | | `customer` | `created`, `updated`, `updated.status_transitioned`, `deleted` | | `kyc_link` | `created`, `updated`, `updated.status_transitioned` | | `liquidation_address.drain` | `created`, `updated`, `updated.status_transitioned` | | `static_memo.activity` | `created`, `updated` | | `transfer` | `created`, `updated`, `updated.status_transitioned` | | `virtual_account.activity` | `created`, `updated` | | `bridge_wallet.activity` | `created`, `updated` | | `card_account` | `created`, `updated`, `updated.status_transitioned` | | `card_transaction` | `created`, `updated`, `updated.status_transitioned` | | `posted_card_account_transaction` | `created` | | `external_acccount` | `created`, `updated` | ## Event Object Schema Each webhook payload includes: | **Field** | **Description** | | :--------------------- | :--------------------------------------------------------------------------------------------------- | | `api_version` | Current version of Bridge APIs (`v0`). | | `event_id` | Globally unique event identifier. Useful as an idempotency key. | | `event_category` | Category of the event (e.g., `virtual_account.activity`). | | `event_type` | Formatted as `.`. | | `event_object_id` | Same value as `event_object.id` (duplicated for easy access). | | `event_object_status` | Optional. Populated when the object has a concept of status (e.g., `kyc_status`, `transfer_status`). | | `event_object` | The full resource data, matching the structure in Bridge's API reference. | | `event_object_changes` | Diffs from the previous event (only present on updates). | | `event_created_at` | Timestamp of the event in ISO 8601 format. | ### Event Object Schema Reference The `event_object` field contains the full resource data, matching the structure returned by corresponding API endpoints. **Webhooks and API responses use identical rendering logic**, ensuring schema consistency. | Event Category | Schema Documentation | | --------------------------- | ------------------------------------------------------------------------------------------------------------------ | | `transfer` | [Transfer API Reference](/platform/orchestration/transfers/transfer) | | `virtual_account.activity` | [Virtual Account Activity](/platform/orchestration/virtual_accounts/virtual-account-events) | | `customer` | [Customer API Reference](/platform/customers/customers/api) | | `kyc_link` | [KYC Link API Reference](/platform/customers/customers/kyclinks) | | `liquidation_address.drain` | [Liquidation Address](/platform/orchestration/liquidation_address/liquidation_address) | | `static_memo.activity` | [Static Memo Activity](/platform/orchestration/more/staticmemos) | | `bridge_wallet.activity` | [Bridge Wallet transaction history API](/api-reference/bridge-wallets/get-transaction-history-for-a-bridge-wallet) | | `external_acccount` | [External Account API Reference](/api-reference/external-accounts/retrieve-an-external-account-object) | ## Supported Mutation Types Each event can have the following mutation types: * `created` * `updated` * `updated.status_transitioned` *(for state transitions like KYC or Transfer status)* * `deleted` *(if applicable)* ## **Examples** For cards-related webhook events, see the scenarios outlined in [this](https://apidocs.bridge.xyz/platform/cards/overview/webhooks) cards-specific webhook scenarios page. ### Transfers ```json theme={null} { "api_version": "v0", "event_id": "wh_123abc456def", "event_developer_id": "dev_111aaa222bbb333ccc", "event_category": "transfer", "event_type": "created", "event_object_id": "tr_abc123xyz789", "event_object_status": "awaiting_funds", "event_object": { "id": "tr_abc123xyz789", "state": "awaiting_funds", "amount": "1500.00", "currency": "usd", "developer_fee": "0.0", "client_reference_id": null, "on_behalf_of": "cust_alice", "source": { "currency": "usdc", "from_address": "0x1111111111111111111111111111111111111111", "payment_rail": "polygon" }, "destination": { "currency": "usd", "payment_rail": "ach", "external_account_id": "external-account-123" }, "receipt": { "gas_fee": "0.0", "exchange_fee": "0.0", "developer_fee": "0.0", "initial_amount": "1500.00", "subtotal_amount": "1500.00", "final_amount": "1500.00" }, "created_at": "2025-07-22T11:26:55.000Z", "updated_at": "2025-07-22T11:26:56.000Z" }, "event_object_changes": {}, "event_created_at": "2025-07-22T11:26:00.000Z" } ``` ```json theme={null} { "api_version": "v0", "event_id": "wh_789xyz654mno", "event_developer_id": "dev_444ddd555eee666fff", "event_category": "transfer", "event_type": "updated.status_transitioned", "event_object_id": "tr_xyz789abc123", "event_object_status": "funds_received", "event_object": { "id": "tr_xyz789abc123", "state": "funds_received", "amount": "1.00", "currency": "usd", "developer_fee": "0.0", "client_reference_id": null, "on_behalf_of": "cust_bob", "source": { "currency": "usdb", "payment_rail": "bridge_wallet", "bridge_wallet_id": "wallet_bob_usdb" }, "destination": { "currency": "usdb", "payment_rail": "solana", "to_address": "9uYxZmV1KxJn7oVPW6bLUhF3cGQsk8vvMf1sQdPE6K4" }, "receipt": { "gas_fee": "0.0", "exchange_fee": "0.0", "developer_fee": "0.0", "initial_amount": "1.00", "subtotal_amount": "1.00", "final_amount": "1.00", "destination_tx_hash": "4gJH6oXpZUNgC1QLh8mXNPF92LtLKzHZj5eHuQrdQAgB" }, "created_at": "2025-06-11T21:27:00.000Z", "updated_at": "2025-06-11T21:27:01.000Z" }, "event_object_changes": { "state": ["payment_submitted", "funds_received"] }, "event_created_at": "2025-06-11T21:27:00.000Z" } ``` ```json theme={null} { "api_version": "v0", "event_id": "wh_789ghi012jkl", "event_developer_id": "dev_111aaa222bbb333ccc", "event_category": "transfer", "event_type": "updated.status_transitioned", "event_object_id": "tr_abc123xyz789", "event_object_status": "in_review", "event_object": { "id": "tr_abc123xyz789", "state": "in_review", "amount": "1500.00", "currency": "usd", "developer_fee": "0.0", "client_reference_id": null, "on_behalf_of": "cust_alice", "source": { "currency": "usdc", "from_address": "0x1111111111111111111111111111111111111111", "payment_rail": "polygon" }, "destination": { "currency": "usd", "payment_rail": "ach", "external_account_id": "external-account-123" }, "receipt": { "gas_fee": "0.0", "exchange_fee": "0.0", "developer_fee": "0.0", "initial_amount": "1500.00", "subtotal_amount": "1500.00", "final_amount": "1500.00" }, "created_at": "2025-07-22T11:26:55.000Z", "updated_at": "2025-07-22T11:28:10.000Z" }, "event_object_changes": { "state": ["awaiting_funds", "in_review"] }, "event_created_at": "2025-07-22T11:28:10.000Z" } ``` ```json theme={null} { "api_version": "v0", "event_id": "wh_t96YqUFLXfXxqJewhzz92qn", "event_developer_id": "f1959d8d-798e-418d-bd69-8d556ade827b", "event_sequence": 801, "event_category": "transfer", "event_type": "transfer.updated", "event_object_id": "37f16b41-85d2-4db3-96be-f305cb246b15", "event_object_status": "payment_submitted", "event_object": { "id": "37f16b41-85d2-4db3-96be-f305cb246b15", "state": "payment_submitted", "amount": "0.01", "source": { "currency": "usdc", "from_address": "41myj7T7vHPQ17SQFJdbJ35JrrYAgHzH1raFd9S8PvsM", "payment_rail": "bridge_wallet", "bridge_wallet_id": "9a5ac57a-ce6c-4419-86f5-8cf3adc91292" }, "receipt": { "gas_fee": "0.0", "exchange_fee": "0.0", "final_amount": "0.01", "developer_fee": "0.0", "initial_amount": "0.01", "subtotal_amount": "0.01", "destination_tx_hash": "3DrJCtEmQNaXA1VKLfihJn3MAHsfEwb2UALf6V3LvjutXadweMCmWUDoQzNiXT1d2UZBVbHwsmxLDaMUf3UgPpYX" }, "currency": "usd", "created_at": "2026-05-26T14:50:33.310Z", "updated_at": "2026-05-26T14:50:42.868Z", "destination": { "currency": "usdc", "to_address": "92ZfgbCPwvBTBSJUJoQJTQ7kr4M1wayi8d2FzHVfiXcV", "payment_rail": "solana" }, "on_behalf_of": "8570375f-125c-4913-9da5-3a33c029a060", "developer_fee": "0.0", "client_reference_id": "963d82b7-4773-446d-a9dc-741a4309b7ba" }, "event_object_changes": { "receipt": [ { "gas_fee": "0.0", "exchange_fee": "0.0", "final_amount": "0.01", "developer_fee": "0.0", "initial_amount": "0.01", "subtotal_amount": "0.01" }, { "gas_fee": "0.0", "exchange_fee": "0.0", "final_amount": "0.01", "developer_fee": "0.0", "initial_amount": "0.01", "subtotal_amount": "0.01", "destination_tx_hash": "3DrJCtEmQNaXA1VKLfihJn3MAHsfEwb2UALf6V3LvjutXadweMCmWUDoQzNiXT1d2UZBVbHwsmxLDaMUf3UgPpYX" } ], "updated_at": [ "2026-05-26T14:50:36.344Z", "2026-05-26T14:50:42.868Z" ] }, "event_created_at": "2026-05-26T14:50:43.149Z" } ``` ```json theme={null} { "api_version": "v0", "event_id": "wh_t8TAhPPYrRV2v8Asi9ed3sw", "event_developer_id": "371983-uery-1238-1238971", "event_category": "transfer", "event_type": "updated.status_transitioned", "event_object_id": "fecffc8b-ed5e-48ae-bd24-b36268330b32", "event_object_status": "payment_processed", "event_object": { "id": "transfer_abc123", "state": "payment_processed", "amount": "50.0", "currency": "usd", "developer_fee": "0.0", "client_reference_id": null, "on_behalf_of": "cust_alice", "source": { "currency": "usdb", "payment_rail": "bridge_wallet", "bridge_wallet_id": "wallet_alice_usdb" }, "destination": { "currency": "usdb", "payment_rail": "solana", "to_address": "9uYxZmV1KxJn7oVPW6bLUhF3cGQsk8vvMf1sQdPE6K4" }, "receipt": { "url": "https://dashboard.bridge.xyz/transaction/transfer_abc123/receipt/receipt_xyz456", "gas_fee": "0.0", "exchange_fee": "0.0", "developer_fee": "0.0", "initial_amount": "50.0", "subtotal_amount": "50.0", "final_amount": "50.0", "destination_tx_hash": "3gJH6oXpZUNgC1QLh8mXNPF92LtLKzHZj5eHuQrdQAgB" }, "created_at": "2025-07-15T23:55:39.411Z", "updated_at": "2025-07-15T23:55:58.645Z" }, "event_object_changes": { "state": [ "payment_submitted", "payment_processed" ] }, "event_created_at": "2024-02-01T04:32:28.978Z" } ``` ```json theme={null} { "api_version": "v0", "event_id": "wh_345cde678fgh", "event_developer_id": "dev_111aaa222bbb333ccc", "event_category": "transfer", "event_type": "updated.status_transitioned", "event_object_id": "tr_abc123xyz789", "event_object_status": "kyc_required", "event_object": { "id": "tr_abc123xyz789", "state": "kyc_required", "amount": "1500.00", "currency": "usd", "developer_fee": "0.0", "client_reference_id": null, "on_behalf_of": "cust_alice", "source": { "currency": "usdc", "from_address": "0x1111111111111111111111111111111111111111", "payment_rail": "polygon" }, "destination": { "currency": "usd", "payment_rail": "ach", "external_account_id": "external-account-123" }, "receipt": { "gas_fee": "0.0", "exchange_fee": "0.0", "developer_fee": "0.0", "initial_amount": "1500.00", "subtotal_amount": "1500.00", "final_amount": "1500.00" }, "kyc_link": "https://bridge.withpersona.com/verify?inquiry-template-id=itmpl_abc&fields[em ail]=alice@example.com", "created_at": "2025-07-22T11:26:55.000Z", "updated_at": "2025-07-22T11:27:05.000Z" }, "event_object_changes": { "state": ["awaiting_funds", "kyc_required"] }, "event_created_at": "2025-07-22T11:27:05.000Z" } ``` ```json theme={null} { "api_version": "v0", "event_id": "wh_456def789ghi", "event_developer_id": "dev_111aaa222bbb333ccc", "event_category": "transfer", "event_type": "updated.status_transitioned", "event_object_id": "tr_abc123xyz789", "event_object_status": "kyc_in_review", "event_object": { "id": "tr_abc123xyz789", "state": "kyc_in_review", "amount": "1500.00", "currency": "usd", "developer_fee": "0.0", "client_reference_id": null, "on_behalf_of": "cust_alice", "source": { "currency": "usdc", "from_address": "0x1111111111111111111111111111111111111111", "payment_rail": "polygon" }, "destination": { "currency": "usd", "payment_rail": "ach", "external_account_id": "external-account-123" }, "receipt": { "gas_fee": "0.0", "exchange_fee": "0.0", "developer_fee": "0.0", "initial_amount": "1500.00", "subtotal_amount": "1500.00", "final_amount": "1500.00" }, "created_at": "2025-07-22T11:26:55.000Z", "updated_at": "2025-07-22T11:35:00.000Z" }, "event_object_changes": { "state": ["kyc_required", "kyc_in_review"] }, "event_created_at": "2025-07-22T11:35:00.000Z" } ``` ```json theme={null} { "api_version": "v0", "event_id": "wh_567efg890hij", "event_developer_id": "dev_111aaa222bbb333ccc", "event_category": "transfer", "event_type": "updated.status_transitioned", "event_object_id": "tr_abc123xyz789", "event_object_status": "developer_kyb_required", "event_object": { "id": "tr_abc123xyz789", "state": "developer_kyb_required", "amount": "1500.00", "currency": "usd", "developer_fee": "0.0", "client_reference_id": null, "on_behalf_of": "cust_alice", "source": { "currency": "usdc", "from_address": "0x1111111111111111111111111111111111111111", "payment_rail": "polygon" }, "destination": { "currency": "usd", "payment_rail": "ach", "external_account_id": "external-account-123" }, "receipt": { "gas_fee": "0.0", "exchange_fee": "0.0", "developer_fee": "0.0", "initial_amount": "1500.00", "subtotal_amount": "1500.00", "final_amount": "1500.00" }, "created_at": "2025-07-22T11:26:55.000Z", "updated_at": "2025-07-22T11:27:02.000Z" }, "event_object_changes": { "state": ["awaiting_funds", "developer_kyb_required"] }, "event_created_at": "2025-07-22T11:27:02.000Z" } ``` ```json theme={null} { "api_version": "v0", "event_id": "wh_678fgh901ijk", "event_developer_id": "dev_111aaa222bbb333ccc", "event_category": "transfer", "event_type": "updated.status_transitioned", "event_object_id": "tr_abc123xyz789", "event_object_status": "underfunded", "event_object": { "id": "tr_abc123xyz789", "state": "underfunded", "amount": "1500.00", "currency": "usd", "developer_fee": "0.0", "client_reference_id": null, "on_behalf_of": "cust_alice", "source": { "currency": "usdc", "from_address": "0x1111111111111111111111111111111111111111", "payment_rail": "polygon" }, "destination": { "currency": "usd", "payment_rail": "ach", "external_account_id": "external-account-123" }, "receipt": { "gas_fee": "0.0", "exchange_fee": "0.0", "developer_fee": "0.0", "initial_amount": "1200.00", "subtotal_amount": "1200.00", "final_amount": "1200.00" }, "created_at": "2025-07-22T11:26:55.000Z", "updated_at": "2025-07-22T11:27:10.000Z" }, "event_object_changes": { "state": ["awaiting_funds", "underfunded"] }, "event_created_at": "2025-07-22T11:27:10.000Z" } ``` ```json theme={null} { "api_version": "v0", "event_id": "wh_789ghi012jkl", "event_developer_id": "dev_111aaa222bbb333ccc", "event_category": "transfer", "event_type": "updated.status_transitioned", "event_object_id": "tr_abc123xyz789", "event_object_status": "undeliverable", "event_object": { "id": "tr_abc123xyz789", "state": "undeliverable", "amount": "1500.00", "currency": "usd", "developer_fee": "0.0", "client_reference_id": null, "on_behalf_of": "cust_alice", "source": { "currency": "usdc", "from_address": "0x1111111111111111111111111111111111111111", "payment_rail": "polygon" }, "destination": { "currency": "usd", "payment_rail": "ach", "external_account_id": "external-account-123" }, "receipt": { "gas_fee": "0.0", "exchange_fee": "0.0", "developer_fee": "0.0", "initial_amount": "1500.00", "subtotal_amount": "1500.00", "final_amount": "1500.00" }, "created_at": "2025-07-22T11:26:55.000Z", "updated_at": "2025-07-22T11:45:00.000Z" }, "event_object_changes": { "state": ["payment_submitted", "undeliverable"] }, "event_created_at": "2025-07-22T11:45:00.000Z" } ``` ```json theme={null} { "api_version": "v0", "event_id": "wh_890hij123klm", "event_developer_id": "dev_111aaa222bbb333ccc", "event_category": "transfer", "event_type": "updated.status_transitioned", "event_object_id": "tr_abc123xyz789", "event_object_status": "error", "event_object": { "id": "tr_abc123xyz789", "state": "error", "amount": "1500.00", "currency": "usd", "developer_fee": "0.0", "client_reference_id": null, "on_behalf_of": "cust_alice", "source": { "currency": "usdc", "from_address": "0x1111111111111111111111111111111111111111", "payment_rail": "polygon" }, "destination": { "currency": "usd", "payment_rail": "ach", "external_account_id": "external-account-123" }, "receipt": { "gas_fee": "0.0", "exchange_fee": "0.0", "developer_fee": "0.0", "initial_amount": "1500.00", "subtotal_amount": "1500.00", "final_amount": "1500.00" }, "created_at": "2025-07-22T11:26:55.000Z", "updated_at": "2025-07-22T11:50:00.000Z" }, "event_object_changes": { "state": ["in_review", "error"] }, "event_created_at": "2025-07-22T11:50:00.000Z" } ``` ```json theme={null} { "api_version": "v0", "event_id": "wh_901ijk234lmn", "event_developer_id": "dev_111aaa222bbb333ccc", "event_category": "transfer", "event_type": "updated.status_transitioned", "event_object_id": "tr_abc123xyz789", "event_object_status": "canceled", "event_object": { "id": "tr_abc123xyz789", "state": "canceled", "amount": "1500.00", "currency": "usd", "developer_fee": "0.0", "client_reference_id": null, "on_behalf_of": "cust_alice", "source": { "currency": "usdc", "from_address": "0x1111111111111111111111111111111111111111", "payment_rail": "polygon" }, "destination": { "currency": "usd", "payment_rail": "ach", "external_account_id": "external-account-123" }, "receipt": { "gas_fee": "0.0", "exchange_fee": "0.0", "developer_fee": "0.0", "initial_amount": "1500.00", "subtotal_amount": "1500.00", "final_amount": "1500.00" }, "created_at": "2025-07-22T11:26:55.000Z", "updated_at": "2025-07-22T11:40:00.000Z" }, "event_object_changes": { "state": ["awaiting_funds", "canceled"] }, "event_created_at": "2025-07-22T11:40:00.000Z" } ``` ```json theme={null} { "api_version": "v0", "event_id": "wh_012jkl345mno", "event_developer_id": "dev_111aaa222bbb333ccc", "event_category": "transfer", "event_type": "updated.status_transitioned", "event_object_id": "tr_abc123xyz789", "event_object_status": "deactivated", "event_object": { "id": "tr_abc123xyz789", "state": "deactivated", "amount": "1500.00", "currency": "usd", "developer_fee": "0.0", "client_reference_id": null, "on_behalf_of": "cust_alice", "source": { "currency": "usdc", "from_address": "0x1111111111111111111111111111111111111111", "payment_rail": "polygon" }, "destination": { "currency": "usd", "payment_rail": "ach", "external_account_id": "external-account-123" }, "receipt": { "gas_fee": "0.0", "exchange_fee": "0.0", "developer_fee": "0.0", "initial_amount": "1500.00", "subtotal_amount": "1500.00", "final_amount": "1500.00" }, "created_at": "2025-07-22T11:26:55.000Z", "updated_at": "2025-07-22T12:00:00.000Z" }, "event_object_changes": { "state": ["awaiting_funds", "deactivated"] }, "event_created_at": "2025-07-22T12:00:00.000Z" } ``` ```json theme={null} { "api_version": "v0", "event_id": "wh_123klm456nop", "event_developer_id": "dev_111aaa222bbb333ccc", "event_category": "transfer", "event_type": "updated.status_transitioned", "event_object_id": "tr_abc123xyz789", "event_object_status": "missing_return_policy", "event_object": { "id": "tr_abc123xyz789", "state": "missing_return_policy", "amount": "1500.00", "currency": "usd", "developer_fee": "0.0", "client_reference_id": null, "on_behalf_of": "cust_alice", "source": { "currency": "usdc", "from_address": "0x1111111111111111111111111111111111111111", "payment_rail": "polygon" }, "destination": { "currency": "usd", "payment_rail": "ach", "external_account_id": "external-account-123" }, "receipt": { "gas_fee": "0.0", "exchange_fee": "0.0", "developer_fee": "0.0", "initial_amount": "1500.00", "subtotal_amount": "1500.00", "final_amount": "1500.00" }, "created_at": "2025-07-22T11:26:55.000Z", "updated_at": "2025-07-22T11:32:00.000Z" }, "event_object_changes": { "state": ["payment_processed", "missing_return_policy"] }, "event_created_at": "2025-07-22T11:32:00.000Z" } ``` ```json theme={null} { "api_version": "v0", "event_id": "wh_234lmn567opq", "event_developer_id": "dev_111aaa222bbb333ccc", "event_category": "transfer", "event_type": "updated.status_transitioned", "event_object_id": "tr_abc123xyz789", "event_object_status": "returned", "event_object": { "id": "tr_abc123xyz789", "state": "returned", "amount": "1500.00", "currency": "usd", "developer_fee": "0.0", "client_reference_id": null, "on_behalf_of": "cust_alice", "source": { "currency": "usdc", "from_address": "0x1111111111111111111111111111111111111111", "payment_rail": "polygon" }, "destination": { "currency": "usd", "payment_rail": "ach", "external_account_id": "external-account-123" }, "receipt": { "gas_fee": "0.0", "exchange_fee": "0.0", "developer_fee": "0.0", "initial_amount": "1500.00", "subtotal_amount": "1500.00", "final_amount": "1500.00" }, "created_at": "2025-07-22T11:26:55.000Z", "updated_at": "2025-07-23T09:00:00.000Z" }, "event_object_changes": { "state": ["payment_processed", "returned"] }, "event_created_at": "2025-07-23T09:00:00.000Z" } ``` ```json theme={null} { "api_version": "v0", "event_id": "wh_345mno678pqr", "event_developer_id": "dev_111aaa222bbb333ccc", "event_category": "transfer", "event_type": "updated.status_transitioned", "event_object_id": "tr_abc123xyz789", "event_object_status": "refund_in_flight", "event_object": { "id": "tr_abc123xyz789", "state": "refund_in_flight", "amount": "1500.00", "currency": "usd", "developer_fee": "0.0", "client_reference_id": null, "on_behalf_of": "cust_alice", "source": { "currency": "usdc", "from_address": "0x1111111111111111111111111111111111111111", "payment_rail": "polygon" }, "destination": { "currency": "usd", "payment_rail": "ach", "external_account_id": "external-account-123" }, "receipt": { "gas_fee": "0.0", "exchange_fee": "0.0", "developer_fee": "0.0", "initial_amount": "1500.00", "subtotal_amount": "1500.00", "final_amount": "1500.00" }, "created_at": "2025-07-22T11:26:55.000Z", "updated_at": "2025-07-23T09:05:00.000Z" }, "event_object_changes": { "state": ["returned", "refund_in_flight"] }, "event_created_at": "2025-07-23T09:05:00.000Z" } ``` ```json theme={null} { "api_version": "v0", "event_id": "wh_456nop789qrs", "event_developer_id": "dev_111aaa222bbb333ccc", "event_category": "transfer", "event_type": "updated.status_transitioned", "event_object_id": "tr_abc123xyz789", "event_object_status": "refunded", "event_object": { "id": "tr_abc123xyz789", "state": "refunded", "amount": "1500.00", "currency": "usd", "developer_fee": "0.0", "client_reference_id": null, "on_behalf_of": "cust_alice", "source": { "currency": "usdc", "from_address": "0x1111111111111111111111111111111111111111", "payment_rail": "polygon" }, "destination": { "currency": "usd", "payment_rail": "ach", "external_account_id": "external-account-123" }, "receipt": { "gas_fee": "0.0", "exchange_fee": "0.0", "developer_fee": "0.0", "initial_amount": "1500.00", "subtotal_amount": "1500.00", "final_amount": "1500.00" }, "created_at": "2025-07-22T11:26:55.000Z", "updated_at": "2025-07-23T09:20:00.000Z" }, "event_object_changes": { "state": ["refund_in_flight", "refunded"] }, "event_created_at": "2025-07-23T09:20:00.000Z" } ``` ```json theme={null} { "api_version": "v0", "event_id": "wh_567opq890rst", "event_developer_id": "dev_111aaa222bbb333ccc", "event_category": "transfer", "event_type": "updated.status_transitioned", "event_object_id": "tr_abc123xyz789", "event_object_status": "refund_failed", "event_object": { "id": "tr_abc123xyz789", "state": "refund_failed", "amount": "1500.00", "currency": "usd", "developer_fee": "0.0", "client_reference_id": null, "on_behalf_of": "cust_alice", "source": { "currency": "usdc", "from_address": "0x1111111111111111111111111111111111111111", "payment_rail": "polygon" }, "destination": { "currency": "usd", "payment_rail": "ach", "external_account_id": "external-account-123" }, "receipt": { "gas_fee": "0.0", "exchange_fee": "0.0", "developer_fee": "0.0", "initial_amount": "1500.00", "subtotal_amount": "1500.00", "final_amount": "1500.00" }, "created_at": "2025-07-22T11:26:55.000Z", "updated_at": "2025-07-23T09:20:00.000Z" }, "event_object_changes": { "state": ["refund_in_flight", "refund_failed"] }, "event_created_at": "2025-07-23T09:20:00.000Z" } ``` ### Bridge Wallet Activity To receive Bridge Wallet activity events, create or update a webhook endpoint subscribed to `bridge_wallet.activity`. Bridge Wallet activity webhooks deliver the same object returned by the [Bridge Wallet transaction history API](/api-reference/bridge-wallets/get-transaction-history-for-a-bridge-wallet). ```json theme={null} { "api_version": "v0", "event_id": "wh_wallet_123", "event_developer_id": "dev_111aaa222bbb333ccc", "event_category": "bridge_wallet.activity", "event_type": "bridge_wallet.activity.created", "event_object_id": "bwe_123", "event_object_status": null, "event_object": { "id": "bwe_123", "bridge_wallet_id": "bw_123", "amount": "50.000000", "available_balance": "1050.000000", "currency": "usdc", "type": "deposit", "source": { "currency": "usd", "payment_rail": "ach" }, "destination": { "currency": "usdc", "payment_rail": "ethereum", "tx_hash": "0xdeadbeef" }, "payment_route": { "type": "drain", "customer_id": "cust_123", "drain_id": "drain_123", "liquidation_address_id": "la_123", "liquidation_address_address": "0x1111111111111111111111111111111111111111" }, "created_at": "2025-01-01T00:00:00.000Z" }, "event_object_changes": {}, "event_created_at": "2025-01-01T00:00:00.000Z" } ``` ```json theme={null} { "api_version": "v0", "event_id": "wh_wallet_456", "event_developer_id": "f1959d8d-798e-418d-bd69-8d556ade827b", "event_sequence": 621, "event_category": "bridge_wallet.activity", "event_type": "bridge_wallet.activity.updated", "event_object_id": "808c20d4-3b83-440c-88d4-140fd2ba4015", "event_object_status": null, "event_object": { "id": "808c20d4-3b83-440c-88d4-140fd2ba4015", "type": "undeliverable", "amount": "0.01", "currency": "usdc", "source": { "payment_rail": "solana", "currency": "usdc" }, "destination": { "payment_rail": "bridge_wallet", "currency": "usdc" }, "payment_route": { "type": "transfer", "customer_id": "8570375f-125c-4913-9da5-3a33c029a060", "transfer_id": "232d9152-e2dc-4057-9775-ea3a9e32b5f7" }, "bridge_wallet_id": "9a5ac57a-ce6c-4419-86f5-8cf3adc91292", "available_balance": "4.46", "created_at": "2026-04-29T17:26:49.601Z" }, "event_object_changes": {}, "event_created_at": "2026-04-29T17:27:04.308Z" } ``` ### Virtual Accounts Below is a creation event for a Virtual Account Activity event object ```json theme={null} { "api_version": "v0", "event_id": "wh_t8TAhPPYrRV2v8Asi9ed3sw", "event_developer_id": "371983-uery-1238-1238971", "event_category": "virtual_account.activity", "event_type": "virtual_account.activity.created", "event_object_id": "fecffc8b-ed5e-48ae-bd24-b36268330b32", "event_object_status": null, "event_object": { "id": "fecffc8b-ed5e-48ae-bd24-b36268330b32", "type": "payment_submitted", "amount": "1970.0", "source": { "description": "EXAMPLE TRANSACTION Brown-Beer Arnoldo Schimmel MD 01202024", "sender_name": "Brown-Beer", "payment_rail": "ach_push", "sender_bank_routing_number": "023883013" }, "gas_fee": "0.0", "currency": "usdc", "created_at": "2024-02-01T04:31:43.342Z", "deposit_id": "c7fab38f-7b65-42d3-bc8d-a694cd1901c1", "customer_id": "6ed47d9c-03be-420c-8699-369707ca02e9", "subtotal_amount": "1970.0", "virtual_account_id": "22033ca5-a991-476c-ade9-911d10f0ece6", "exchange_fee_amount": "10.0", "developer_fee_amount": "20.0" }, "event_object_changes": { }, "event_created_at": "2024-02-01T04:32:28.978Z" } ``` ```json theme={null} { "api_version": "v0", "event_id": "wh_t8trBtrPEqeFYLrQD9Zjog4", "event_category": "virtual_account.activity", "event_type": "virtual_account.activity.updated", "event_object_id": "fecffc8b-ed5e-48ae-bd24-b36268330b32", "event_object_status": null, "event_object": { "id": "fecffc8b-ed5e-48ae-bd24-b36268330b32", "type": "payment_submitted", "amount": "1970.0", "source": { "description": "EXAMPLE TRANSACTION Brown-Beer Arnoldo Schimmel MD 01202024", "sender_name": "Brown-Beer", "payment_rail": "ach_push", "sender_bank_routing_number": "023883013" }, "gas_fee": "0.0", "currency": "usdc", "created_at": "2024-02-01T04:31:43.342Z", "deposit_id": "c7fab38f-7b65-42d3-bc8d-a694cd1901c1", "customer_id": "6ed47d9c-03be-420c-8699-369707ca02e9", "subtotal_amount": "1970.0", "virtual_account_id": "22033ca5-a991-476c-ade9-911d10f0ece6", "destination_tx_hash": "0xa7de792daa970f89cdb36dbce93026d10942ea24", "exchange_fee_amount": "10.0", "developer_fee_amount": "20.0" }, "event_object_changes": { "destination_tx_hash": [ null, "0xa7de792daa970f89cdb36dbce93026d10942ea24" ] }, "event_created_at": "2024-02-01T04:34:13.763Z" } ``` ### Customers Initial creation via a KYC link before the customer has taken any action. ```json theme={null} { "api_version": "v0", "event_id": "wh_2tEL5NVw3dkEpLRJz4dS8gqWYX1", "event_developer_id": "b2f58e14-3c8d-4a1e-9b7a-1234567890ab", "event_sequence": 1, "event_category": "customer", "event_type": "customer.created", "event_object_id": "c_2tEKzQmNvR9xJfPdL8mY4hsBk3A", "event_object_status": "not_started", "event_object": { "id": "c_2tEKzQmNvR9xJfPdL8mY4hsBk3A", "first_name": "Jane", "last_name": "Doe", "email": "jane.doe@example.com", "type": "individual", "status": "not_started", "persona_inquiry_type": "gov_id_db", "has_accepted_terms_of_service": false, "client_reference_id": null, "tos_link": "https://dashboard.bridge.xyz/tos/c_2tEKzQmNvR9xJfPdL8mY4hsBk3A", "rejection_reasons": [], "endorsements": [ { "name": "base", "status": "incomplete", "requirements": { "complete": [], "pending": [], "missing": { "id_verification": "Identity verification required" }, "issues": [] } } ], "future_requirements_due": [], "created_at": "2025-11-19T21:14:58.328Z", "updated_at": "2025-11-19T21:14:58.328Z" }, "event_object_changes": {}, "event_created_at": "2025-11-19T21:14:58.328Z" } ``` Customer has started KYC but hasn't finished. ```json theme={null} { "api_version": "v0", "event_id": "wh_3fGH7NPq5eLmRTKwV2xB9jrZYc4", "event_developer_id": "b2f58e14-3c8d-4a1e-9b7a-1234567890ab", "event_sequence": 2, "event_category": "customer", "event_type": "customer.updated.status_transitioned", "event_object_id": "c_2tEKzQmNvR9xJfPdL8mY4hsBk3A", "event_object_status": "incomplete", "event_object": { "id": "c_2tEKzQmNvR9xJfPdL8mY4hsBk3A", "first_name": "Jane", "last_name": "Doe", "email": "jane.doe@example.com", "type": "individual", "status": "incomplete", "persona_inquiry_type": "gov_id_db", "has_accepted_terms_of_service": false, "client_reference_id": null, "tos_link": "https://dashboard.bridge.xyz/tos/c_2tEKzQmNvR9xJfPdL8mY4hsBk3A", "rejection_reasons": [], "endorsements": [ { "name": "base", "status": "incomplete", "requirements": { "complete": ["government_id"], "pending": ["selfie_verification"], "missing": {}, "issues": [] } } ], "future_requirements_due": [], "created_at": "2025-11-19T21:14:58.328Z", "updated_at": "2025-11-19T21:22:14.105Z" }, "event_object_changes": { "status": ["not_started", "incomplete"] }, "event_created_at": "2025-11-19T21:22:14.105Z" } ``` Customer must complete an additional questionnaire before proceeding. ```json theme={null} { "api_version": "v0", "event_id": "wh_8rST1UVw4XYz5ABc6DEf7GHijkl", "event_developer_id": "b2f58e14-3c8d-4a1e-9b7a-1234567890ab", "event_sequence": 3, "event_category": "customer", "event_type": "customer.updated.status_transitioned", "event_object_id": "c_2tEKzQmNvR9xJfPdL8mY4hsBk3A", "event_object_status": "awaiting_questionnaire", "event_object": { "id": "c_2tEKzQmNvR9xJfPdL8mY4hsBk3A", "first_name": "Jane", "last_name": "Doe", "email": "jane.doe@example.com", "type": "individual", "status": "awaiting_questionnaire", "persona_inquiry_type": "gov_id_db", "has_accepted_terms_of_service": true, "client_reference_id": null, "tos_link": null, "rejection_reasons": [], "endorsements": [ { "name": "base", "status": "incomplete", "requirements": { "complete": ["government_id", "selfie_verification"], "pending": ["questionnaire"], "missing": {}, "issues": [] } } ], "future_requirements_due": [], "created_at": "2025-11-19T21:14:58.328Z", "updated_at": "2025-11-19T21:48:09.761Z" }, "event_object_changes": { "status": ["incomplete", "awaiting_questionnaire"] }, "event_created_at": "2025-11-19T21:48:09.761Z" } ``` Business customer has completed KYB but verification of ultimate beneficial owners (UBOs) is still pending. ```json theme={null} { "api_version": "v0", "event_id": "wh_6pQR9STu2VWx3YZa4BCd5EFg6HIj", "event_developer_id": "b2f58e14-3c8d-4a1e-9b7a-1234567890ab", "event_sequence": 3, "event_category": "customer", "event_type": "customer.updated.status_transitioned", "event_object_id": "c_7bXNpRmLqD4kJfWvA2sY9hcTz8E", "event_object_status": "awaiting_ubo", "event_object": { "id": "c_7bXNpRmLqD4kJfWvA2sY9hcTz8E", "first_name": "Acme Corp", "last_name": null, "email": "kyb@example.com", "type": "business", "status": "awaiting_ubo", "persona_inquiry_type": "business", "has_accepted_terms_of_service": true, "client_reference_id": null, "tos_link": null, "rejection_reasons": [], "endorsements": [ { "name": "base", "status": "incomplete", "requirements": { "complete": ["business_verification"], "pending": ["ubo_verification"], "missing": {}, "issues": [] } } ], "future_requirements_due": [], "created_at": "2025-11-19T21:14:58.328Z", "updated_at": "2025-11-19T21:55:30.214Z" }, "event_object_changes": { "status": ["incomplete", "awaiting_ubo"] }, "event_created_at": "2025-11-19T21:55:30.214Z" } ``` Customer completed KYC submission; awaiting manual review. ```json theme={null} { "api_version": "v0", "event_id": "wh_5kPQ2XRw8nBdSfLmC7vJ4tzNhe9", "event_developer_id": "b2f58e14-3c8d-4a1e-9b7a-1234567890ab", "event_sequence": 3, "event_category": "customer", "event_type": "customer.updated.status_transitioned", "event_object_id": "c_2tEKzQmNvR9xJfPdL8mY4hsBk3A", "event_object_status": "under_review", "event_object": { "id": "c_2tEKzQmNvR9xJfPdL8mY4hsBk3A", "first_name": "Jane", "last_name": "Doe", "email": "jane.doe@example.com", "type": "individual", "status": "under_review", "persona_inquiry_type": "gov_id_db", "has_accepted_terms_of_service": true, "client_reference_id": null, "tos_link": null, "rejection_reasons": [], "endorsements": [ { "name": "base", "status": "incomplete", "requirements": { "complete": ["government_id", "selfie_verification"], "pending": [], "missing": {}, "issues": [] } } ], "future_requirements_due": [], "created_at": "2025-11-19T21:14:58.328Z", "updated_at": "2025-11-19T21:35:42.917Z" }, "event_object_changes": { "status": ["incomplete", "under_review"], "has_accepted_terms_of_service": [false, true] }, "event_created_at": "2025-11-19T21:35:42.917Z" } ``` Customer passed KYC and is fully active. ```json theme={null} { "api_version": "v0", "event_id": "wh_9mRS4VTx1oCeWgNqA6uK8yzBpf2", "event_developer_id": "b2f58e14-3c8d-4a1e-9b7a-1234567890ab", "event_sequence": 4, "event_category": "customer", "event_type": "customer.updated.status_transitioned", "event_object_id": "c_2tEKzQmNvR9xJfPdL8mY4hsBk3A", "event_object_status": "approved", "event_object": { "id": "c_2tEKzQmNvR9xJfPdL8mY4hsBk3A", "first_name": "Jane", "last_name": "Doe", "email": "jane.doe@example.com", "type": "individual", "status": "approved", "persona_inquiry_type": "gov_id_db", "has_accepted_terms_of_service": true, "client_reference_id": null, "tos_link": null, "rejection_reasons": [], "endorsements": [ { "name": "base", "status": "approved", "requirements": { "complete": ["government_id", "selfie_verification"], "pending": [], "missing": {}, "issues": [] } } ], "future_requirements_due": [], "created_at": "2025-11-19T21:14:58.328Z", "updated_at": "2025-11-19T22:01:08.443Z" }, "event_object_changes": { "status": ["under_review", "approved"] }, "event_created_at": "2025-11-19T22:01:08.443Z" } ``` Customer failed KYC. Includes rejection reasons. ```json theme={null} { "api_version": "v0", "event_id": "wh_7nWD6YUz3qAfXhMrE5tP1bcLjk8", "event_developer_id": "b2f58e14-3c8d-4a1e-9b7a-1234567890ab", "event_sequence": 4, "event_category": "customer", "event_type": "customer.updated.status_transitioned", "event_object_id": "c_2tEKzQmNvR9xJfPdL8mY4hsBk3A", "event_object_status": "rejected", "event_object": { "id": "c_2tEKzQmNvR9xJfPdL8mY4hsBk3A", "first_name": "Jane", "last_name": "Doe", "email": "jane.doe@example.com", "type": "individual", "status": "rejected", "persona_inquiry_type": "gov_id_db", "has_accepted_terms_of_service": true, "client_reference_id": null, "tos_link": null, "rejection_reasons": [ { "reason": "id_verification_failed", "message": "We were unable to verify your identity. Please ensure your government-issued ID is valid and the photo is clear." } ], "endorsements": [ { "name": "base", "status": "revoked", "requirements": { "complete": [], "pending": [], "missing": {}, "issues": [ "id_verification_failed" ] } } ], "future_requirements_due": [], "created_at": "2025-11-19T21:14:58.328Z", "updated_at": "2025-11-19T22:05:31.762Z" }, "event_object_changes": { "status": ["under_review", "rejected"] }, "event_created_at": "2025-11-19T22:05:31.762Z" } ``` Customer account has been paused, typically due to an active compliance flag. ```json theme={null} { "api_version": "v0", "event_id": "wh_2mNO5PQr8STu9VWx1YZa3BCde4F", "event_developer_id": "b2f58e14-3c8d-4a1e-9b7a-1234567890ab", "event_sequence": 5, "event_category": "customer", "event_type": "customer.updated.status_transitioned", "event_object_id": "c_2tEKzQmNvR9xJfPdL8mY4hsBk3A", "event_object_status": "paused", "event_object": { "id": "c_2tEKzQmNvR9xJfPdL8mY4hsBk3A", "first_name": "Jane", "last_name": "Doe", "email": "jane.doe@example.com", "type": "individual", "status": "paused", "persona_inquiry_type": "gov_id_db", "has_accepted_terms_of_service": true, "client_reference_id": null, "tos_link": null, "rejection_reasons": [], "endorsements": [ { "name": "base", "status": "approved", "requirements": { "complete": ["government_id", "selfie_verification"], "pending": [], "missing": {}, "issues": [] } } ], "future_requirements_due": [], "created_at": "2025-11-19T21:14:58.328Z", "updated_at": "2025-11-20T10:12:44.882Z" }, "event_object_changes": { "status": ["approved", "paused"] }, "event_created_at": "2025-11-20T10:12:44.882Z" } ``` Customer account has been permanently closed. ```json theme={null} { "api_version": "v0", "event_id": "wh_9vWX3YZa6BCd7EFg8HIj1JKlmno", "event_developer_id": "b2f58e14-3c8d-4a1e-9b7a-1234567890ab", "event_sequence": 6, "event_category": "customer", "event_type": "customer.updated.status_transitioned", "event_object_id": "c_2tEKzQmNvR9xJfPdL8mY4hsBk3A", "event_object_status": "offboarded", "event_object": { "id": "c_2tEKzQmNvR9xJfPdL8mY4hsBk3A", "first_name": "Jane", "last_name": "Doe", "email": "jane.doe@example.com", "type": "individual", "status": "offboarded", "persona_inquiry_type": "gov_id_db", "has_accepted_terms_of_service": true, "client_reference_id": null, "tos_link": null, "rejection_reasons": [], "endorsements": [ { "name": "base", "status": "revoked", "requirements": { "complete": [], "pending": [], "missing": {}, "issues": [] } } ], "future_requirements_due": [], "created_at": "2025-11-19T21:14:58.328Z", "updated_at": "2025-11-20T11:03:22.119Z" }, "event_object_changes": { "status": ["paused", "offboarded"] }, "event_created_at": "2025-11-20T11:03:22.119Z" } ``` ### KYC Links ```json theme={null} { "api_version": "v0", "event_id": "wh_tmyqyd9q5nsVJazfux9EiQC", "event_category": "kyc_link", "event_type": "kyc_link.updated.status_transitioned", "event_object_id": "3694522e-6bed-4660-a803-f599b50c7691", "event_object_status": "incomplete", "event_object": { "id": "3694522e-6bed-4660-a803-f599b50c7691", "type": "individual", "email": "danyka+wintheiser@quigley.xyz", "kyc_link": "", "tos_link": "", "full_name": "Danyka Wintheiser", "created_at": "2024-02-09T16:48:11.531Z", "kyc_status": "incomplete", "tos_status": "approved", "customer_id": null, "persona_inquiry_type": "gov_id_db" }, "event_object_changes": { "kyc_status": [ "not_started", "incomplete" ], "tos_status": [ "pending", "approved" ] }, "event_created_at": "2024-02-09T17:00:43.709Z" } ``` # Customizing card art Source: https://apidocs.bridge.xyz/platform/cards/additional/customizing This page is part of the legacy Bridge Cards API. For new integrations, use the [consumer issuing guide](/platform/cards/overview/stripe-issuing) instead. # **Overview** Developers can customize the card art for the virtual in-app card, as well as for mobile wallets (Apple Pay and Google Pay). Card art is subject to bank partner and Visa approval. Please reach out to your Bridge program manager to get the latest version of our guidelines. ## **Mobile Wallet** Card art must fit within certain specifications and requires approval from Visa, the digital wallet provider (Google Pay and Apple Pay), and the issuing bank. 1. **Mobile Wallet Card Design** Create two templates for the Mobile Wallet card: * One blank template (with your logo and card network logo) * One template with the last four of the PAN populated **Requirements:** * PNG format * 1536 x 969 pixels * Image must include your logo and card network logo * Please add “DEBIT” above the Visa logo in all CAPS. Use at least 11-point type, maintain a clear space of 3.0mm above the Visa Brand Mark * Image *must not* contain these elements: * Embossed attributes * Transparency overlays * Magstripe * EMV chip faceplate or contacts * Hologram * Rounded corners * Shading or three-dimensional effects * Labels for "Member since," expiry date, or cardholder name * Miniature BIN under the PAN * White or other color background behind the image * Specify RGB values (255, 255, 255) for when the image cannot be rendered: * Card background, when the image cannot be rendered * Foreground, for the last four digits of the PAN * Label, for text on the front of the card 2. **Mobile Wallet App Icon** This is used for push notifications in the wallet to identify your program for transaction data. * PNG format * 100 x 100 pixels 3. **Short description of the program** This will be your company/product name, which will be displayed in the wallet and used for push notifications. * 32 characters max ## **Virtual Card - In App and Web** **Digital card design** This is the card art that will show up in your app. Unlike a physical card, a digital card has only one side, which displays the cardholder name, PAN, expiry, and CVV or CVC, as well as the chosen artwork. For virtual cards, follow these instructions to create the card template: 1. Create two templates for the digital card: 1. One blank template 2. One template with all information populated: PAN, expiry, and CVV or CVC 2. Once you have designed the templates, submit to Bridge for compliance approval ***Blank card template:*** aa4d859c3d2663cc5768a2fcd77d7f0dde5aa2d53c27dd0204749676fd1452ab-Bridge_Card_Art_Default_.jpg ***Card image with full PAN, name, expiry, and CVV:*** ad3aab26757db4b504d5b7de8cb7b1fccbfc4d6c1ff220681344ef0778431441-Bridge_Card_Art_Default_-_completed_.jpg **A digital card template must fulfill these requirements:** * JPG or PNG file format (PNG is preferred) * 500 x 315 pixels * A label and space for the expiration date * A label and space for the CVV or CVC * Horizontal orientation **Additional card elements that can be configured:** * Font – Galileo offers a variety of fonts. See [Supported Fonts](https://docs.galileo-ft.com/pro/page/supported-fonts) for the list * Font color * Font size * Lower-case letters and font mixing are not supported * X/Y coordinates for data elements * Spaces to use in between each card number chunk **Note:** * For MVP, we will render the image of the card above in the app * As a fast follow in H1 2025, we will enable developers to create more customized ways to reveal sensitive card data (e.g., tap to reveal, copy details, etc) # Fees Source: https://apidocs.bridge.xyz/platform/cards/additional/fees Configure fees on card transactions to generate additional revenue This page is part of the legacy Bridge Cards API. For new integrations, use the [consumer issuing guide](/platform/cards/overview/stripe-issuing) instead. ## **Overview** Bridge allows you to configure fees on card transactions, enabling you to generate additional revenue beyond interchange share. These fees are automatically calculated and deducted from your customers' wallets at the time of each card transaction. There are two types of fees you can configure: | **Fee Type** | **Description** | **When Applied** | | :-------------- | :-------------------------------------------------------------------------------- | :--------------------------------------------------------------- | | Transaction Fee | A percentage-based fee, fixed fee, or both applied to the transaction amount | All transactions, configurable for domestic and/or international | | FX Fee | A percentage-based premium on the exchange rate for foreign currency transactions | Transactions where currency conversion occurs | Fees are included in the terms accepted by end users when they sign up for a card. The fee amounts are disclosed to customers as part of the card program terms. ## **Fee Types** ### Transaction Fees Transaction fees are surcharges applied to the transaction amount. You can configure transaction fees as: * **Percentage-based only**: A percentage of the transaction amount (e.g., 1%) * **Fixed amount only**: A flat fee per transaction (e.g., `$0.30`) * **Both percentage and fixed**: A combination of percentage plus fixed amount (e.g., 1% + `$0.30`) Fixed fees are charged once per transaction, regardless of how many authorizations occur. For example, if a transaction has an incremental authorization (where the merchant increases the amount after the initial auth), the fixed fee is only applied once on the initial authorization—not on each subsequent incremental auth. You can configure different fee rates for: * **International transactions**: Transactions where the merchant is located outside the card's country of issuance * **Domestic transactions**: Transactions where the merchant is in the same country as the card's country of issuance ### FX Fees FX fees are percentage-based premiums applied to the exchange rate provided by the card network whenever currency conversion occurs. When a cardholder makes a purchase in a currency different from their card's currency (e.g., a USD cardholder purchasing in EUR, GBP, or JPY), the transaction is converted using the network's exchange rate plus your configured FX fee percentage. For example, if the network's exchange rate is 1.10 USD/EUR and you have a 1.5% FX fee configured, the effective exchange rate applied to the transaction would be approximately 1.0835 USD/EUR. ## **Configuring Fees** Fee configurations are set up during your onboarding process with Bridge. To configure or modify your fee structure: 1. Contact the Bridge team to discuss your desired fee configuration 2. Specify your fee rates for each applicable fee type 3. Bridge will configure your fee settings Fee configurations apply globally across all card accounts for your integration. Per-customer fee customization is not currently supported. Changes to fee configurations require Bridge approval and should be infrequent. ### Configuration Options | **Setting** | **Description** | **Example** | | :----------------------------------------- | :-------------------------------------------- | :----------------------- | | International transaction fee (percentage) | Percentage fee for international transactions | 1.00% (100 basis points) | | International transaction fee (fixed) | Fixed amount for international transactions | `$0.30` | | Domestic transaction fee (percentage) | Percentage fee for domestic transactions | 0.50% (50 basis points) | | Domestic transaction fee (fixed) | Fixed amount for domestic transactions | `$0.25` | | FX premium | Percentage fee applied to the exchange rate | 1.50% (150 basis points) | You can configure percentage fees, fixed fees, or both for each transaction type. For example, you might set international transactions to `1% + $0.30`, while domestic transactions have only a `$0.25` fixed fee. ## **How Fees Are Applied** When a card transaction is authorized, Bridge calculates the applicable fees and includes them in the total amount debited from the cardholder's wallet. The fee calculation happens as follows: 1. The card network sends the transaction authorization request with the transaction amount 2. Bridge determines if the transaction is domestic or international 3. If applicable, Bridge applies the transaction fee percentage and any fixed fee 4. For transactions where currency conversion occurs, Bridge applies the FX premium to the exchange rate 5. The total amount (transaction amount + fees) is debited from the cardholder's wallet Fees are typically applied at the time of authorization. This means the fee amount is included in the hold placed on the cardholder's balance when the transaction is first approved. ## **Fees in Webhooks** Fee information is included in `card_transaction` webhook events. The `fees` object provides a complete breakdown of all fees applied to a transaction. ### Fee Object Structure The fee information is included at the top level of the transaction webhook payload: ```json expandable theme={null} { "id": "b3f589e1-f66b-5cf7-c24b-4c9addb593b", "fees": { "transaction_fee": { "fee_amount": "-0.5", "fee_config": { "fixed_fee_amount": "0.5" }, "is_international": false }, "total_fee_amount": "-0.5" }, "amount": "-0.99", "status": "approved", "category": "purchase", "currency": "usd", "created_at": "2025-12-17T15:48:30.490Z", "updated_at": "2025-12-17T15:50:18.547Z", "customer_id": "2e4ab8ed-58b5-552g-ac08-67771c25e072", "authorized_at": "2025-12-17T15:48:30.497Z", "merchant_name": "ECOMMERCE STORE", "status_reason": "approved", "billing_amount": "-0.99", "card_account_id": "d742b7g5-61be-5b33-bd75-45c9bbe4c2ea", "original_amount": "-0.99", "merchant_location": "SAN JOSE, CA", "authorization_infos": [ { "fees": { "transaction_fee": { "fee_amount": "-0.5", "fee_config": { "fixed_fee_amount": "0.5" }, "is_international": false }, "total_fee_amount": "-0.5" }, "amount": "-0.99", "wallet": "other", "account": { "last_4": "4821" }, "network": "visa", "currency": "usd", "merchant": { "state": "CA", "country": "USA", "category": "department_stores", "description": "ECOMMERCE STORE SAN JOSE CA", "postal_code": "951260000", "category_code": "5311" }, "auth_type": "auth", "recurring": false, "created_at": "2025-12-17T15:48:30.000Z", "customer_id": "2e4ab8ed-58b5-552g-ac08-67771c25e072", "card_present": false, "entry_method": "card_not_present", "international": false, "status_reason": "approved", "billing_amount": "-0.99", "transaction_id": "b3f589e1-f66b-5cf7-c24b-4c9addb593b", "approval_status": "approved", "card_account_id": "d742b7g5-61be-5b33-bd75-45c9bbe4c2ea", "cashback_amount": "0.00", "authorization_id": "g13d8g27-814f-6494-95c9-f6a32ca16g22", "partial_supported": false, "verification_data": { "cvv_check": "match", "pin_check": "no_pin_passed", "address_check": "mismatch", "address_postal_code_check": "mismatch" }, "local_transaction_details": { "amount": "-0.99", "currency": "usd", "exchange_rate": "1.0" } } ], "merchant_category_code": "5311", "transaction_description": "ECOMMERCE STORE SAN JOSE CA" } ``` ### Fee Fields Reference | **Field** | **Description** | | :------------------------------------------------------------ | :------------------------------------------------------------------------------ | | `fees.total_fee_amount` | The total fee amount deducted from the cardholder's wallet for this transaction | | `fees.fx_fee.fee_amount` | The fee amount attributable to the FX premium | | `fees.fx_fee.local_currency` | The original currency of the transaction at the merchant | | `fees.fx_fee.is_international` | Whether the transaction was classified as international | | `fees.fx_fee.original_exchange_rate` | The exchange rate provided by the card network before the FX premium | | `fees.fx_fee.effective_exchange_rate` | The exchange rate applied after adding the FX premium | | `fees.fx_fee.fee_config.percentage_fee_basis_points` | Your configured FX fee rate in basis points | | `fees.transaction_fee.fee_amount` | The fee amount from the transaction fee | | `fees.transaction_fee.is_international` | Whether the transaction was classified as international | | `fees.transaction_fee.fee_config.percentage_fee_basis_points` | Your configured transaction fee rate in basis points | | `fees.transaction_fee.fee_config.fixed_fee_amount` | Your configured fixed fee amount per transaction | ### Webhook Scenarios with Fees Below are examples of card transaction webhooks showing how fees appear in different scenarios. #### Successful Transaction with Fees A successful transaction can go through multiple stages: initial authorization, preauth completion, and settlement. The fee is charged at the initial authorization and persists through the transaction lifecycle. In these examples, the fee is calculated as: 1% of `$1.11` (`$0.01`) + `$0.10` fixed fee = `$0.11`. When a card transaction is first approved, the fee is calculated and included: ```json expandable theme={null} { "api_version": "v0", "event_id": "wh_t6svpKfUvYmRxQRBL7wMvsg", "event_developer_id": "6cd7ec7c-6857-45d9-9eff-607577a5f382", "event_sequence": 22100, "event_category": "card_transaction", "event_type": "card_transaction.created", "event_object_id": "0ad0f797-9805-4c3a-8fa0-c77a1be52e4b", "event_object_status": "approved", "event_object": { "id": "0ad0f797-9805-4c3a-8fa0-c77a1be52e4b", "fees": { "transaction_fee": { "fee_amount": "-0.11", "fee_config": { "percentage_fee_basis_points": 100, "fixed_fee_amount": "0.1" }, "is_international": false }, "total_fee_amount": "-0.11" }, "amount": "-1.11", "status": "approved", "category": "purchase", "currency": "usd", "created_at": "2025-10-09T15:01:58.478Z", "updated_at": "2025-10-09T15:02:01.638Z", "customer_id": "af6071ae-2e83-45ed-8f01-2174db6a617e", "authorized_at": "2025-10-09T15:01:58.497Z", "merchant_name": "ECOMMERCE.COM", "status_reason": "approved", "billing_amount": "-1.11", "card_account_id": "9ae899d5-fef2-488a-8321-e6447f52196d", "original_amount": "-1.11", "merchant_location": "+14155557142, WAUS", "authorization_infos": [ { "fees": { "transaction_fee": { "fee_amount": "-0.11", "fee_config": { "percentage_fee_basis_points": 100, "fixed_fee_amount": "0.1" }, "is_international": false }, "total_fee_amount": "-0.11" }, "amount": "-1.11", "wallet": "other", "account": { "last_4": "3111" }, "network": "visa", "currency": "usd", "merchant": { "state": "WA", "country": "USA", "category": "computer_software_stores", "description": "ECOMMERCE.COM +14155557142 WAUS", "postal_code": "98117", "category_code": "5734" }, "auth_type": "auth", "recurring": false, "created_at": "2025-10-09T15:01:58.000Z", "fee_amount": "0.00", "customer_id": "af6071ae-2e83-45ed-8f01-2174db6a617e", "card_present": false, "entry_method": "card_not_present", "international": false, "status_reason": "approved", "billing_amount": "-1.11", "transaction_id": "0ad0f797-9805-4c3a-8fa0-c77a1be52e4b", "approval_status": "approved", "card_account_id": "9ae899d5-fef2-488a-8321-e6447f52196d", "cashback_amount": "0.00", "authorization_id": "d9d534a0-87d8-506d-a0bb-12725ffc4599", "partial_supported": false, "verification_data": { "cvv_check": "match", "pin_check": "no_pin_passed", "address_check": "not_provided", "address_postal_code_check": "not_provided" }, "local_transaction_details": { "amount": "-1.11", "currency": "usd", "exchange_rate": "1.0" } } ], "merchant_category_code": "5734", "transaction_description": "ECOMMERCE.COM +14155557142 WAUS" }, "event_object_changes": {}, "event_created_at": "2025-10-09T15:02:02.791Z" } ``` At preauth completion, the `authorization_infos` array contains both the preauth\_completion and original auth. The top-level `fees` shows the total fee, while each authorization shows its individual fee (the preauth\_completion shows `0.0` since the fee was already charged on the initial auth): ```json expandable theme={null} { "api_version": "v0", "event_id": "wh_t2mA7ae7KNJy232Y1kADhLR", "event_developer_id": "6cd7ec7c-6857-45d9-9eff-607577a5f382", "event_sequence": 22164, "event_category": "card_transaction", "event_type": "card_transaction.updated", "event_object_id": "0ad0f797-9805-4c3a-8fa0-c77a1be52e4b", "event_object_status": "approved", "event_object": { "id": "0ad0f797-9805-4c3a-8fa0-c77a1be52e4b", "fees": { "transaction_fee": { "fee_amount": "-0.11", "fee_config": { "percentage_fee_basis_points": 100, "fixed_fee_amount": "0.1" }, "is_international": false }, "total_fee_amount": "-0.11" }, "amount": "-1.11", "status": "approved", "category": "purchase", "currency": "usd", "created_at": "2025-10-09T15:01:58.478Z", "updated_at": "2025-10-10T00:18:10.345Z", "customer_id": "af6071ae-2e83-45ed-8f01-2174db6a617e", "authorized_at": "2025-10-09T15:01:58.497Z", "merchant_name": "ECOMMERCE.COM", "status_reason": "approved", "billing_amount": "-1.11", "card_account_id": "9ae899d5-fef2-488a-8321-e6447f52196d", "original_amount": "-1.11", "merchant_location": "+14155137142, WAUS", "authorization_infos": [ { "fees": { "transaction_fee": { "fee_amount": "0.0", "fee_config": { "percentage_fee_basis_points": 100, "fixed_fee_amount": "0.1" }, "is_international": false }, "total_fee_amount": "0.0" }, "amount": "-1.11", "wallet": "other", "account": { "last_4": "3111" }, "network": "visa", "currency": "usd", "merchant": { "state": "WA", "country": "USA", "category": "computer_software_stores", "description": "ECOMMERCE.COM +14155557142 WAUS", "postal_code": "98117", "category_code": "5734" }, "auth_type": "preauth_completion", "recurring": false, "created_at": "2025-10-10T00:18:05.000Z", "fee_amount": "0.00", "customer_id": "af6071ae-2e83-45ed-8f01-2174db6a617e", "card_present": false, "entry_method": "card_not_present", "international": true, "status_reason": "approved", "billing_amount": "-1.11", "transaction_id": "0ad0f797-9805-4c3a-8fa0-c77a1be52e4b", "approval_status": "approved", "card_account_id": "9ae899d5-fef2-488a-8321-e6447f52196d", "cashback_amount": "0.00", "authorization_id": "b31da99c-6013-5e35-974c-eb75705c680e", "partial_supported": false, "verification_data": { "cvv_check": "not_provided", "pin_check": "no_pin_passed", "address_check": "not_provided", "address_postal_code_check": "not_provided" }, "local_transaction_details": { "amount": "-1.11", "currency": "usd", "exchange_rate": "1.0" }, "original_authorization_id": "d9d534a0-87d8-506d-a0bb-12725ffc4599" }, { "fees": { "transaction_fee": { "fee_amount": "-0.11", "fee_config": { "percentage_fee_basis_points": 100, "fixed_fee_amount": "0.1" }, "is_international": false }, "total_fee_amount": "-0.11" }, "amount": "-1.11", "wallet": "other", "account": { "last_4": "6360" }, "network": "visa", "currency": "usd", "merchant": { "state": "WA", "country": "USA", "category": "computer_software_stores", "description": "ECOMMERCE.COM +14155557142 WAUS", "postal_code": "98117", "category_code": "5734" }, "auth_type": "auth", "recurring": false, "created_at": "2025-10-09T15:01:58.000Z", "fee_amount": "0.00", "customer_id": "af6071ae-2e83-45ed-8f01-2174db6a617e", "card_present": false, "entry_method": "card_not_present", "international": false, "status_reason": "approved", "billing_amount": "-1.11", "transaction_id": "0ad0f797-9805-4c3a-8fa0-c77a1be52e4b", "approval_status": "approved", "card_account_id": "9ae899d5-fef2-488a-8321-e6447f52196d", "cashback_amount": "0.00", "authorization_id": "d9d534a0-87d8-506d-a0bb-12725ffc4599", "partial_supported": false, "verification_data": { "cvv_check": "match", "pin_check": "no_pin_passed", "address_check": "not_provided", "address_postal_code_check": "not_provided" }, "local_transaction_details": { "amount": "-1.11", "currency": "usd", "exchange_rate": "1.0" } } ], "merchant_category_code": "5734", "transaction_description": "ECOMMERCE.COM +14155557142 WAUS" }, "event_object_changes": { "updated_at": [ ... ], "authorization_infos": [ ... ] }, "event_created_at": "2025-10-10T00:18:10.954Z" } ``` When the transaction settles, the fee information persists unchanged: ```json expandable theme={null} { "api_version": "v0", "event_id": "wh_tgX252cKCHQcBHhwf7XjTZd", "event_developer_id": "6cd7ec7c-6857-45d9-9eff-607577a5f382", "event_sequence": 22178, "event_category": "card_transaction", "event_type": "card_transaction.updated.status_transitioned", "event_object_id": "0ad0f797-9805-4c3a-8fa0-c77a1be52e4b", "event_object_status": "settled", "event_object": { "id": "0ad0f797-9805-4c3a-8fa0-c77a1be52e4b", "fees": { "transaction_fee": { "fee_amount": "-0.11", "fee_config": { "percentage_fee_basis_points": 100, "fixed_fee_amount": "0.1" }, "is_international": false }, "total_fee_amount": "-0.11" }, "amount": "-1.11", "status": "settled", "category": "purchase", "currency": "usd", "created_at": "2025-10-09T15:01:58.478Z", "updated_at": "2025-10-10T17:08:18.750Z", "customer_id": "af6071ae-2e83-45ed-8f01-2174db6a617e", "authorized_at": "2025-10-09T15:01:58.497Z", "merchant_name": "ECOMMERCE.COM", "status_reason": "approved", "billing_amount": "-1.11", "card_account_id": "9ae899d5-fef2-488a-8321-e6447f52196d", "original_amount": "-1.11", "merchant_location": "+14155557142, WAUS", "authorization_infos": [ { "fees": { "transaction_fee": { "fee_amount": "0.0", "fee_config": { "percentage_fee_basis_points": 100, "fixed_fee_amount": "0.1" }, "is_international": false }, "total_fee_amount": "0.0" }, "amount": "-1.11", "wallet": "other", "account": { "last_4": "3111" }, "network": "visa", "currency": "usd", "merchant": { "state": "WA", "country": "USA", "category": "computer_software_stores", "description": "ECOMMERCE.COM +14155557142 WAUS", "postal_code": "98117", "category_code": "5734" }, "auth_type": "preauth_completion", "recurring": false, "created_at": "2025-10-10T00:18:05.000Z", "fee_amount": "0.00", "customer_id": "af6071ae-2e83-45ed-8f01-2174db6a617e", "card_present": false, "entry_method": "card_not_present", "international": true, "status_reason": "approved", "billing_amount": "-1.11", "transaction_id": "0ad0f797-9805-4c3a-8fa0-c77a1be52e4b", "approval_status": "approved", "card_account_id": "9ae899d5-fef2-488a-8321-e6447f52196d", "cashback_amount": "0.00", "authorization_id": "b31da99c-6013-5e35-974c-eb75705c680e", "partial_supported": false, "verification_data": { "cvv_check": "not_provided", "pin_check": "no_pin_passed", "address_check": "not_provided", "address_postal_code_check": "not_provided" }, "local_transaction_details": { "amount": "-1.11", "currency": "usd", "exchange_rate": "1.0" }, "original_authorization_id": "d9d534a0-87d8-506d-a0bb-12725ffc4599" }, { "fees": { "transaction_fee": { "fee_amount": "-0.11", "fee_config": { "percentage_fee_basis_points": 100, "fixed_fee_amount": "0.1" }, "is_international": false }, "total_fee_amount": "-0.11" }, "amount": "-1.11", "wallet": "other", "account": { "last_4": "6360" }, "network": "visa", "currency": "usd", "merchant": { "state": "WA", "country": "USA", "category": "computer_software_stores", "description": "ECOMMERCE.COM +14155557142 WAUS", "postal_code": "98117", "category_code": "5734" }, "auth_type": "auth", "recurring": false, "created_at": "2025-10-09T15:01:58.000Z", "fee_amount": "0.00", "customer_id": "af6071ae-2e83-45ed-8f01-2174db6a617e", "card_present": false, "entry_method": "card_not_present", "international": false, "status_reason": "approved", "billing_amount": "-1.11", "transaction_id": "0ad0f797-9805-4c3a-8fa0-c77a1be52e4b", "approval_status": "approved", "card_account_id": "9ae899d5-fef2-488a-8321-e6447f52196d", "cashback_amount": "0.00", "authorization_id": "d9d534a0-87d8-506d-a0bb-12725ffc4599", "partial_supported": false, "verification_data": { "cvv_check": "match", "pin_check": "no_pin_passed", "address_check": "not_provided", "address_postal_code_check": "not_provided" }, "local_transaction_details": { "amount": "-1.11", "currency": "usd", "exchange_rate": "1.0" } } ], "merchant_category_code": "5734", "transaction_description": "ECOMMERCE.COM +14155557142 WAUS" }, "event_object_changes": { "status": [ "approved", "settled" ], "updated_at": ... }, "event_created_at": "2025-10-10T17:08:20.362Z" } ``` ##### Over Capture and Under Capture The preauth completion amount can differ from the original authorization amount. This happens when merchants capture more (over capture) or less (under capture) than the initially authorized amount. When this occurs, the fee adjusts based on the final captured amount. When a merchant captures more than the original authorization (e.g., original auth was `$10.00` but final capture is `$12.00`), an additional fee is charged for the difference. The top-level `fees` reflects the updated total fee based on the captured amount: ```json expandable theme={null} { "api_version": "v0", "event_id": "wh_t2mA7ae7KNJy232Y1kADhLR", "event_developer_id": "6cd7ec7c-6857-45d9-9eff-607577a5f382", "event_sequence": 22164, "event_category": "card_transaction", "event_type": "card_transaction.updated", "event_object_id": "0ad0f797-9805-4c3a-8fa0-c77a1be52e4b", "event_object_status": "approved", "event_object": { "id": "0ad0f797-9805-4c3a-8fa0-c77a1be52e4b", "fees": { "transaction_fee": { "fee_amount": "-0.22", "fee_config": { "percentage_fee_basis_points": 100, "fixed_fee_amount": "0.1" }, "is_international": false }, "total_fee_amount": "-0.22" }, "amount": "-12.00", "status": "approved", "category": "purchase", "currency": "usd", "created_at": "2025-10-09T15:01:58.478Z", "updated_at": "2025-10-10T00:18:10.345Z", "customer_id": "af6071ae-2e83-45ed-8f01-2174db6a617e", "authorized_at": "2025-10-09T15:01:58.497Z", "merchant_name": "ECOMMERCE.COM", "status_reason": "approved", "billing_amount": "-12.00", "card_account_id": "9ae899d5-fef2-488a-8321-e6447f52196d", "original_amount": "-10.00", "merchant_location": "+14155137142, WAUS", "authorization_infos": [ { "fees": { "transaction_fee": { "fee_amount": "-0.02", "fee_config": { "percentage_fee_basis_points": 100, "fixed_fee_amount": "0.1" }, "is_international": false }, "total_fee_amount": "-0.02" }, "amount": "-12.00", "wallet": "other", "account": { "last_4": "3111" }, "network": "visa", "currency": "usd", "merchant": { "state": "WA", "country": "USA", "category": "computer_software_stores", "description": "ECOMMERCE.COM +14155557142 WAUS", "postal_code": "98117", "category_code": "5734" }, "auth_type": "preauth_completion", "recurring": false, "created_at": "2025-10-10T00:18:05.000Z", "fee_amount": "0.00", "customer_id": "af6071ae-2e83-45ed-8f01-2174db6a617e", "card_present": false, "entry_method": "card_not_present", "international": false, "status_reason": "approved", "billing_amount": "-12.00", "transaction_id": "0ad0f797-9805-4c3a-8fa0-c77a1be52e4b", "approval_status": "approved", "card_account_id": "9ae899d5-fef2-488a-8321-e6447f52196d", "cashback_amount": "0.00", "authorization_id": "b31da99c-6013-5e35-974c-eb75705c680e", "partial_supported": false, "verification_data": { "cvv_check": "not_provided", "pin_check": "no_pin_passed", "address_check": "not_provided", "address_postal_code_check": "not_provided" }, "local_transaction_details": { "amount": "-12.00", "currency": "usd", "exchange_rate": "1.0" }, "original_authorization_id": "d9d534a0-87d8-506d-a0bb-12725ffc4599" }, { "fees": { "transaction_fee": { "fee_amount": "-0.20", "fee_config": { "percentage_fee_basis_points": 100, "fixed_fee_amount": "0.1" }, "is_international": false }, "total_fee_amount": "-0.20" }, "amount": "-10.00", "wallet": "other", "account": { "last_4": "6360" }, "network": "visa", "currency": "usd", "merchant": { "state": "WA", "country": "USA", "category": "computer_software_stores", "description": "ECOMMERCE.COM +14155557142 WAUS", "postal_code": "98117", "category_code": "5734" }, "auth_type": "auth", "recurring": false, "created_at": "2025-10-09T15:01:58.000Z", "fee_amount": "0.00", "customer_id": "af6071ae-2e83-45ed-8f01-2174db6a617e", "card_present": false, "entry_method": "card_not_present", "international": false, "status_reason": "approved", "billing_amount": "-10.00", "transaction_id": "0ad0f797-9805-4c3a-8fa0-c77a1be52e4b", "approval_status": "approved", "card_account_id": "9ae899d5-fef2-488a-8321-e6447f52196d", "cashback_amount": "0.00", "authorization_id": "d9d534a0-87d8-506d-a0bb-12725ffc4599", "partial_supported": false, "verification_data": { "cvv_check": "match", "pin_check": "no_pin_passed", "address_check": "not_provided", "address_postal_code_check": "not_provided" }, "local_transaction_details": { "amount": "-10.00", "currency": "usd", "exchange_rate": "1.0" } } ], "merchant_category_code": "5734", "transaction_description": "ECOMMERCE.COM +14155557142 WAUS" }, "event_object_changes": { "amount": ["-10.00", "-12.00"], "updated_at": [...], "authorization_infos": [...] }, "event_created_at": "2025-10-10T00:18:10.954Z" } ``` In this example, the original auth was `$10.00` with a fee of `$0.20` (1% of `$10` + `$0.10` fixed). The over capture of `$12.00` adds an additional percentage fee of `$0.02` (1% of the extra `$2.00`), bringing the total fee to `$0.22`. The fixed fee is not charged again. When a merchant captures less than the original authorization (e.g., original auth was `$10.00` but final capture is `$8.00`), a portion of the percentage fee is refunded. The fixed fee is not refunded: ```json expandable theme={null} { "api_version": "v0", "event_id": "wh_t2mA7ae7KNJy232Y1kADhLR", "event_developer_id": "6cd7ec7c-6857-45d9-9eff-607577a5f382", "event_sequence": 22164, "event_category": "card_transaction", "event_type": "card_transaction.updated", "event_object_id": "0ad0f797-9805-4c3a-8fa0-c77a1be52e4b", "event_object_status": "approved", "event_object": { "id": "0ad0f797-9805-4c3a-8fa0-c77a1be52e4b", "fees": { "transaction_fee": { "fee_amount": "-0.18", "fee_config": { "percentage_fee_basis_points": 100, "fixed_fee_amount": "0.1" }, "is_international": false }, "total_fee_amount": "-0.18" }, "amount": "-8.00", "status": "approved", "category": "purchase", "currency": "usd", "created_at": "2025-10-09T15:01:58.478Z", "updated_at": "2025-10-10T00:18:10.345Z", "customer_id": "af6071ae-2e83-45ed-8f01-2174db6a617e", "authorized_at": "2025-10-09T15:01:58.497Z", "merchant_name": "ECOMMERCE.COM", "status_reason": "approved", "billing_amount": "-8.00", "card_account_id": "9ae899d5-fef2-488a-8321-e6447f52196d", "original_amount": "-10.00", "merchant_location": "+14155137142, WAUS", "authorization_infos": [ { "fees": { "transaction_fee": { "fee_amount": "0.02", "fee_config": { "percentage_fee_basis_points": 100, "fixed_fee_amount": "0.1" }, "is_international": false }, "total_fee_amount": "0.02" }, "amount": "-8.00", "wallet": "other", "account": { "last_4": "3111" }, "network": "visa", "currency": "usd", "merchant": { "state": "WA", "country": "USA", "category": "computer_software_stores", "description": "ECOMMERCE.COM +14155557142 WAUS", "postal_code": "98117", "category_code": "5734" }, "auth_type": "preauth_completion", "recurring": false, "created_at": "2025-10-10T00:18:05.000Z", "fee_amount": "0.00", "customer_id": "af6071ae-2e83-45ed-8f01-2174db6a617e", "card_present": false, "entry_method": "card_not_present", "international": false, "status_reason": "approved", "billing_amount": "-8.00", "transaction_id": "0ad0f797-9805-4c3a-8fa0-c77a1be52e4b", "approval_status": "approved", "card_account_id": "9ae899d5-fef2-488a-8321-e6447f52196d", "cashback_amount": "0.00", "authorization_id": "b31da99c-6013-5e35-974c-eb75705c680e", "partial_supported": false, "verification_data": { "cvv_check": "not_provided", "pin_check": "no_pin_passed", "address_check": "not_provided", "address_postal_code_check": "not_provided" }, "local_transaction_details": { "amount": "-8.00", "currency": "usd", "exchange_rate": "1.0" }, "original_authorization_id": "d9d534a0-87d8-506d-a0bb-12725ffc4599" }, { "fees": { "transaction_fee": { "fee_amount": "-0.20", "fee_config": { "percentage_fee_basis_points": 100, "fixed_fee_amount": "0.1" }, "is_international": false }, "total_fee_amount": "-0.20" }, "amount": "-10.00", "wallet": "other", "account": { "last_4": "6360" }, "network": "visa", "currency": "usd", "merchant": { "state": "WA", "country": "USA", "category": "computer_software_stores", "description": "ECOMMERCE.COM +14155557142 WAUS", "postal_code": "98117", "category_code": "5734" }, "auth_type": "auth", "recurring": false, "created_at": "2025-10-09T15:01:58.000Z", "fee_amount": "0.00", "customer_id": "af6071ae-2e83-45ed-8f01-2174db6a617e", "card_present": false, "entry_method": "card_not_present", "international": false, "status_reason": "approved", "billing_amount": "-10.00", "transaction_id": "0ad0f797-9805-4c3a-8fa0-c77a1be52e4b", "approval_status": "approved", "card_account_id": "9ae899d5-fef2-488a-8321-e6447f52196d", "cashback_amount": "0.00", "authorization_id": "d9d534a0-87d8-506d-a0bb-12725ffc4599", "partial_supported": false, "verification_data": { "cvv_check": "match", "pin_check": "no_pin_passed", "address_check": "not_provided", "address_postal_code_check": "not_provided" }, "local_transaction_details": { "amount": "-10.00", "currency": "usd", "exchange_rate": "1.0" } } ], "merchant_category_code": "5734", "transaction_description": "ECOMMERCE.COM +14155557142 WAUS" }, "event_object_changes": { "amount": ["-10.00", "-8.00"], "updated_at": [...], "authorization_infos": [...] }, "event_created_at": "2025-10-10T00:18:10.954Z" } ``` In this example, the original auth was `$10.00` with a fee of `$0.20` (1% of `$10` + `$0.10` fixed). The under capture of `$8.00` refunds `$0.02` of the percentage fee (1% of the `$2.00` difference), bringing the total fee to `$0.18`. The fixed fee (`$0.10`) is not refunded. #### Incremental Authorization with Fees When a transaction has an incremental authorization (e.g., adding a tip at a restaurant), the fixed fee is only charged once on the initial authorization. Subsequent incremental authorizations only apply the percentage fee to the additional amount. In the initial auth, the fee is calculated as: 1% of `$7.34` (`$0.07`) + `$0.10` fixed fee = `$0.17`. When an incremental authorization is added, only the percentage fee (1%) applies to the additional amount—the fixed fee is not charged again. The initial authorization includes both the percentage fee and the fixed fee: ```json expandable theme={null} { "api_version": "v0", "event_id": "wh_trD8QwHKEMY5YukFYKsDbRc", "event_developer_id": "d0556c4f-405d-4d4d-8e2c-1ea8859baa33", "event_sequence": 269516, "event_category": "card_transaction", "event_type": "card_transaction.created", "event_object_id": "6128b59d-6a6c-483b-ae6d-57b92edd3c33", "event_object_status": "approved", "event_object": { "id": "6128b59d-6a6c-483b-ae6d-57b92edd3c33", "fees": { "transaction_fee": { "fee_amount": "-0.17", "fee_config": { "percentage_fee_basis_points": 100, "fixed_fee_amount": "0.1" }, "is_international": false }, "total_fee_amount": "-0.17" }, "amount": "-7.34", "status": "approved", "category": "purchase", "currency": "usd", "created_at": "2025-10-22T13:47:56.982Z", "updated_at": "2025-10-22T13:47:59.262Z", "customer_id": "15ff6495-9947-4b18-8b46-319668cbd69a", "authorized_at": "2025-10-22T13:47:56.995Z", "merchant_name": "SQ *BRIDGE CAFE", "status_reason": "approved", "billing_amount": "-6.12", "card_account_id": "44a2f5c1-9f26-4bed-a6e3-601533148e6f", "original_amount": "-7.34", "merchant_location": "San Francisco, CAUS", "authorization_infos": [ { "fees": { "transaction_fee": { "fee_amount": "-0.17", "fee_config": { "percentage_fee_basis_points": 100, "fixed_fee_amount": "0.1" }, "is_international": false }, "total_fee_amount": "-0.17" }, "amount": "-7.34", "wallet": "other", "account": { "last_4": "8739" }, "network": "visa", "currency": "usd", "merchant": { "state": "CA", "country": "USA", "category": "eating_places_restaurants", "description": "SQ *BRIDGE CAFE San FranciscoCAUS", "postal_code": "94105", "category_code": "5812" }, "auth_type": "auth", "recurring": false, "created_at": "2025-10-22T13:47:56.000Z", "fee_amount": "0.00", "customer_id": "15ff6495-9947-4b18-8b46-319668cbd69a", "card_present": true, "entry_method": "contactless", "international": false, "status_reason": "approved", "billing_amount": "-6.12", "transaction_id": "6128b59d-6a6c-483b-ae6d-57b92edd3c33", "approval_status": "approved", "card_account_id": "44a2f5c1-9f26-4bed-a6e3-601533148e6f", "cashback_amount": "0.00", "authorization_id": "7502d7ae-a36f-5aca-8497-c4a7789452d4", "partial_supported": false, "verification_data": { "cvv_check": "match", "pin_check": "no_pin_passed", "address_check": "not_provided", "address_postal_code_check": "not_provided" }, "local_transaction_details": { "amount": "-6.12", "currency": "usd", "exchange_rate": "1.0" } } ], "merchant_category_code": "5812", "transaction_description": "SQ *BRIDGE CAFE San FranciscoCAUS" }, "event_object_changes": {}, "event_created_at": "2025-10-22T13:48:00.087Z" } ``` When an additional amount is authorized (e.g., a tip), only the percentage fee applies to that amount. The incremental auth entry in `authorization_infos` shows the additional fee (`-0.01` = 1% of `$1.06`), while the top-level `fees` shows the updated total (`-0.18` = original `$0.17` + additional `$0.01`): ```json expandable theme={null} { "api_version": "v0", "event_id": "wh_tnx8GPnonE2Fk7maYZ1vku5", "event_developer_id": "d0556c4f-405d-4d4d-8e2c-1ea8859baa33", "event_sequence": 269518, "event_category": "card_transaction", "event_type": "card_transaction.updated.status_transitioned", "event_object_id": "6128b59d-6a6c-483b-ae6d-57b92edd3c33", "event_object_status": "incremental_auth_approved", "event_object": { "id": "6128b59d-6a6c-483b-ae6d-57b92edd3c33", "fees": { "transaction_fee": { "fee_amount": "-0.18", "fee_config": { "percentage_fee_basis_points": 100, "fixed_fee_amount": "0.1" }, "is_international": false }, "total_fee_amount": "-0.18" }, "amount": "-8.4", "status": "incremental_auth_approved", "category": "purchase", "currency": "usd", "created_at": "2025-10-22T13:47:56.982Z", "updated_at": "2025-10-22T13:48:05.284Z", "customer_id": "15ff6495-9947-4b18-8b46-319668cbd69a", "authorized_at": "2025-10-22T13:47:56.995Z", "merchant_name": "SQ *BRIDGE CAFE", "status_reason": "approved", "billing_amount": "-7.0", "card_account_id": "44a2f5c1-9f26-4bed-a6e3-601533148e6f", "original_amount": "-7.34", "merchant_location": "San Francisco, CAUS", "authorization_infos": [ { "fees": { "transaction_fee": { "fee_amount": "-0.01", "fee_config": { "percentage_fee_basis_points": 100, "fixed_fee_amount": "0.1" }, "is_international": false }, "total_fee_amount": "-0.01" }, "amount": "-1.06", "wallet": "other", "account": { "last_4": "8739" }, "network": "visa", "currency": "usd", "merchant": { "state": "CA", "country": "USA", "category": "eating_places_restaurants", "description": "SQ *BRIDGE CAFE San FranciscoCAUS", "postal_code": "94105", "category_code": "5812" }, "auth_type": "incremental_auth", "recurring": false, "created_at": "2025-10-22T13:48:00.000Z", "fee_amount": "0.00", "customer_id": "15ff6495-9947-4b18-8b46-319668cbd69a", "card_present": false, "entry_method": "card_not_present", "international": false, "status_reason": "approved", "billing_amount": "-0.88", "transaction_id": "6128b59d-6a6c-483b-ae6d-57b92edd3c33", "approval_status": "approved", "card_account_id": "44a2f5c1-9f26-4bed-a6e3-601533148e6f", "cashback_amount": "0.00", "authorization_id": "6b9ca2a5-09e3-5a25-9108-accd9ac32533", "partial_supported": false, "verification_data": { "cvv_check": "not_provided", "pin_check": "no_pin_passed", "address_check": "not_provided", "address_postal_code_check": "not_provided" }, "local_transaction_details": { "amount": "-0.88", "currency": "usd", "exchange_rate": "1.0" }, "original_authorization_id": "7502d7ae-a36f-5aca-8497-c4a7789452d4" }, { "fees": { "transaction_fee": { "fee_amount": "-0.17", "fee_config": { "percentage_fee_basis_points": 100, "fixed_fee_amount": "0.1" }, "is_international": false }, "total_fee_amount": "-0.17" }, "amount": "-7.34", "wallet": "other", "account": { "last_4": "8739" }, "network": "visa", "currency": "usd", "merchant": { "state": "CA", "country": "USA", "category": "eating_places_restaurants", "description": "SQ *BRIDGE CAFE San FranciscoCAUS", "postal_code": "94105", "category_code": "5812" }, "auth_type": "auth", "recurring": false, "created_at": "2025-10-22T13:47:56.000Z", "fee_amount": "0.00", "customer_id": "15ff6495-9947-4b18-8b46-319668cbd69a", "card_present": true, "entry_method": "contactless", "international": false, "status_reason": "approved", "billing_amount": "-6.12", "transaction_id": "6128b59d-6a6c-483b-ae6d-57b92edd3c33", "approval_status": "approved", "card_account_id": "44a2f5c1-9f26-4bed-a6e3-601533148e6f", "cashback_amount": "0.00", "authorization_id": "7502d7ae-a36f-5aca-8497-c4a7789452d4", "partial_supported": false, "verification_data": { "cvv_check": "match", "pin_check": "no_pin_passed", "address_check": "not_provided", "address_postal_code_check": "not_provided" }, "local_transaction_details": { "amount": "-6.12", "currency": "usd", "exchange_rate": "1.0" } } ], "merchant_category_code": "5812", "transaction_description": "SQ *BRIDGE CAFE San FranciscoCAUS" }, "event_object_changes": { "amount": [ "-7.34", "-8.4" ], "status": [ "approved", "incremental_auth_approved" ], "updated_at": [ "2025-10-22T13:47:59.262Z", "2025-10-22T13:48:05.284Z" ], "billing_amount": [ "-6.12", "-7.0" ], "authorization_infos": [ ... ] }, "event_created_at": "2025-10-22T13:48:06.116Z" } ``` #### Authorization Reversal with Fee Refund When a transaction is reversed before settlement, fees may be refunded depending on your configuration. In this example, fees are refunded and the `fees` object shows a net total of `0.0`: ```json expandable theme={null} { "api_version": "v0", "event_id": "wh_tw4T3wMJKXZ6Enc7VWrY6Zw", "event_developer_id": "3c2a733c-e59d-4b0e-b302-2ab5b4472a38", "event_sequence": 9458340, "event_category": "card_transaction", "event_type": "card_transaction.updated.status_transitioned", "event_object_id": "726ca19d-27c7-42cc-bf3b-ab2426b958d8", "event_object_status": "reversed", "event_object": { "id": "726ca19d-27c7-42cc-bf3b-ab2426b958d8", "fees": { "transaction_fee": { "fee_amount": "0.0", "fee_config": { "percentage_fee_basis_points": 100, "fixed_fee_amount": "0.1" }, "is_international": false }, "total_fee_amount": "0.0" }, "amount": "0.0", "status": "reversed", "category": "purchase", "currency": "usd", "created_at": "2025-10-27T19:25:01.108Z", "updated_at": "2025-10-27T19:26:27.163Z", "customer_id": "15ff6495-9947-4b18-8b46-319668cbd69a", "authorized_at": "2025-10-27T19:25:01.128Z", "merchant_name": "ROCKET RIDES SAN FRANCISCOCAUS", "status_reason": "approved", "billing_amount": "0.0", "card_account_id": "665f8d7c-00fd-4e88-a9aa-64d68e988b80", "original_amount": "-4.0", "merchant_location": "SAN FRANCISCO, CAUS", "authorization_infos": [ { "fees": { "transaction_fee": { "fee_amount": "0.14", "fee_config": { "percentage_fee_basis_points": 100, "fixed_fee_amount": "0.1" }, "is_international": false }, "total_fee_amount": "0.14" }, "amount": "4.0", "wallet": "other", "account": { "last_4": "3405" }, "network": "visa", "currency": "usd", "merchant": { "state": "CA", "country": "USA", "category": "miscellaneous_recreation_services", "description": "ROCKET RIDES SAN FRANCISCOCAUS", "postal_code": "941030000", "category_code": "7999" }, "auth_type": "reversal", "recurring": false, "created_at": "2025-10-27T19:26:26.000Z", "fee_amount": "0.00", "customer_id": "15ff6495-9947-4b18-8b46-319668cbd69a", "card_present": false, "entry_method": "card_not_present", "international": false, "status_reason": "approved", "billing_amount": "4.0", "transaction_id": "726ca19d-27c7-42cc-bf3b-ab2426b958d8", "approval_status": "approved", "card_account_id": "665f8d7c-00fd-4e88-a9aa-64d68e988b80", "cashback_amount": "0.00", "authorization_id": "c5d1cf2b-31aa-5fa7-91e9-c29619cc8f94", "partial_supported": false, "verification_data": { "cvv_check": "not_provided", "pin_check": "no_pin_passed", "address_check": "not_provided", "three_d_secure_check": "authenticated", "address_postal_code_check": "not_provided" }, "local_transaction_details": { "amount": "4.0", "currency": "usd", "exchange_rate": "1.0" }, "original_authorization_id": "f76cc7da-3c76-5b62-8499-ac7fd2677f49" }, { "fees": { "transaction_fee": { "fee_amount": "-0.14", "fee_config": { "percentage_fee_basis_points": 100, "fixed_fee_amount": "0.1" }, "is_international": false }, "total_fee_amount": "-0.14" }, "amount": "-4.0", "wallet": "other", "account": { "last_4": "3405" }, "network": "visa", "currency": "usd", "merchant": { "state": "CA", "country": "USA", "category": "miscellaneous_recreation_services", "description": "ROCKET RIDES SAN FRANCISCOCAUS", "postal_code": "941030000", "category_code": "7999" }, "auth_type": "auth", "recurring": false, "created_at": "2025-10-27T19:25:00.000Z", "fee_amount": "0.00", "customer_id": "15ff6495-9947-4b18-8b46-319668cbd69a", "card_present": false, "entry_method": "card_not_present", "international": false, "status_reason": "approved", "billing_amount": "-4.0", "transaction_id": "726ca19d-27c7-42cc-bf3b-ab2426b958d8", "approval_status": "approved", "card_account_id": "665f8d7c-00fd-4e88-a9aa-64d68e988b80", "cashback_amount": "0.00", "authorization_id": "f76cc7da-3c76-5b62-8499-ac7fd2677f49", "partial_supported": false, "verification_data": { "cvv_check": "not_provided", "pin_check": "no_pin_passed", "address_check": "not_provided", "three_d_secure_check": "authenticated", "address_postal_code_check": "not_provided" }, "local_transaction_details": { "amount": "-4.0", "currency": "usd", "exchange_rate": "1.0" } } ], "merchant_category_code": "7999", "transaction_description": "ROCKET RIDES SAN FRANCISCOCAUS" }, "event_object_changes": { "status": ["approved", "reversed"], "amount": ["-4.0", "0.0"], "billing_amount": ["-4.0", "0.0"] }, "event_created_at": "2025-10-27T19:26:27.804Z" } ``` The `authorization_infos` array contains both the original authorization (with negative fee) and the reversal (with positive fee, returning the fee to the cardholder). The top-level `fees.total_fee_amount` shows the net fee of `0.0`. #### Authorization Expiration with Fee Refund Authorizations can expire if the merchant does not complete the transaction within a certain time period (e.g., a hotel hold that is never settled). When an authorization expires, fees are **always refunded** to the cardholder. When a card transaction is first approved, the fee is calculated and charged: ```json expandable theme={null} { "api_version": "v0", "event_id": "wh_t6peG8KvbTfHRKJXK2vdaU3", "event_developer_id": "e2551449-d309-4b8f-8035-47323545d024", "event_sequence": 10190914, "event_category": "card_transaction", "event_type": "card_transaction.created", "event_object_id": "5a0662c4-eee0-4d31-a659-3b7ef5927c78", "event_object_status": "approved", "event_object": { "id": "5a0662c4-eee0-4d31-a659-3b7ef5927c78", "fees": { "transaction_fee": { "fee_amount": "-0.20", "fee_config": { "percentage_fee_basis_points": 100, "fixed_fee_amount": "0.1" }, "is_international": true }, "total_fee_amount": "-0.20" }, "amount": "-10.00", "status": "approved", "category": "purchase", "currency": "usd", "created_at": "2025-11-19T04:44:06.191Z", "updated_at": "2025-11-19T04:46:17.629Z", "customer_id": "6398ddae-a6a5-4f88-8086-e5b21f3ab6a0", "authorized_at": "2025-11-19T04:44:06.208Z", "merchant_name": "CENTRAL LIMA, PE", "status_reason": "approved", "billing_amount": "-10.00", "card_account_id": "ce2b71b9-1179-4d9d-b644-690a4f7d935f", "original_amount": "-10.00", "merchant_location": "LIMA, PE", "authorization_infos": [ { "fees": { "transaction_fee": { "fee_amount": "-0.20", "fee_config": { "percentage_fee_basis_points": 100, "fixed_fee_amount": "0.1" }, "is_international": true }, "total_fee_amount": "-0.20" }, "amount": "-10.00", "wallet": "other", "account": { "last_4": "7471" }, "network": "visa", "currency": "usd", "merchant": { "country": "PER", "category": "eating_places_restaurants", "description": "CENTRAL LIMA, PE", "category_code": "5812" }, "auth_type": "auth", "recurring": false, "created_at": "2025-11-19T04:44:05.000Z", "fee_amount": "0.00", "customer_id": "6398ddae-a6a5-4f88-8086-e5b21f3ab6a0", "card_present": true, "entry_method": "contactless", "international": true, "status_reason": "approved", "billing_amount": "-10.00", "transaction_id": "5a0662c4-eee0-4d31-a659-3b7ef5927c78", "approval_status": "approved", "card_account_id": "ce2b71b9-1179-4d9d-b644-690a4f7d935f", "cashback_amount": "0.00", "authorization_id": "ac95da35-b154-42d7-8b74-646981a549f8", "partial_supported": false, "verification_data": { "cvv_check": "match", "pin_check": "no_pin_passed", "address_check": "not_provided", "address_postal_code_check": "not_provided" }, "local_transaction_details": { "amount": "-33.33", "currency": "pen", "exchange_rate": "0.3" } } ], "merchant_category_code": "5812", "transaction_description": "CENTRAL LIMA, PE" }, "event_object_changes": {}, "event_created_at": "2025-11-19T04:46:19.881Z" } ``` In this example, the fee is calculated as: 1% of `$10.00` (`$0.10`) + `$0.10` fixed fee = `$0.20`. When the authorization expires without being settled, the fee is fully refunded. The `fees.total_fee_amount` becomes `0.0`: ```json expandable theme={null} { "api_version": "v0", "event_id": "wh_tv5skiJkqZ2dSGay4rfsDFK", "event_developer_id": "e2551449-d309-4b8f-8035-47323545d024", "event_sequence": 10265365, "event_category": "card_transaction", "event_type": "card_transaction.updated.status_transitioned", "event_object_id": "5a0662c4-eee0-4d31-a659-3b7ef5927c78", "event_object_status": "expired", "event_object": { "id": "5a0662c4-eee0-4d31-a659-3b7ef5927c78", "fees": { "transaction_fee": { "fee_amount": "0.0", "fee_config": { "percentage_fee_basis_points": 100, "fixed_fee_amount": "0.1" }, "is_international": true }, "total_fee_amount": "0.0" }, "amount": "0.0", "status": "expired", "category": "purchase", "currency": "usd", "created_at": "2025-11-19T04:44:06.191Z", "updated_at": "2025-11-21T09:00:21.221Z", "customer_id": "6398ddae-a6a5-4f88-8086-e5b21f3ab6a0", "authorized_at": "2025-11-19T04:44:06.208Z", "merchant_name": "CENTRAL LIMA, PE", "status_reason": "approved", "billing_amount": "0.0", "card_account_id": "ce2b71b9-1179-4d9d-b644-690a4f7d935f", "original_amount": "-10.00", "merchant_location": "LIMA, PE", "authorization_infos": [ { "fees": { "transaction_fee": { "fee_amount": "0.20", "fee_config": { "percentage_fee_basis_points": 100, "fixed_fee_amount": "0.1" }, "is_international": true }, "total_fee_amount": "0.20" }, "amount": "10.00", "wallet": "other", "account": { "last_4": "7471" }, "network": "visa", "currency": "usd", "merchant": { "country": "PER", "category": "eating_places_restaurants", "description": "CENTRAL LIMA, PE", "category_code": "5812" }, "auth_type": "expiration", "recurring": false, "created_at": "2025-11-21T09:00:21.000Z", "fee_amount": "0.00", "customer_id": "6398ddae-a6a5-4f88-8086-e5b21f3ab6a0", "card_present": true, "entry_method": "contactless", "international": true, "status_reason": "approved", "billing_amount": "10.00", "transaction_id": "5a0662c4-eee0-4d31-a659-3b7ef5927c78", "approval_status": "approved", "card_account_id": "ce2b71b9-1179-4d9d-b644-690a4f7d935f", "cashback_amount": "0.00", "authorization_id": "1d4fedc2-6e6b-4781-ae5d-c85fe6ccbdcf", "partial_supported": false, "verification_data": { "cvv_check": "match", "pin_check": "no_pin_passed", "address_check": "not_provided", "address_postal_code_check": "not_provided" }, "local_transaction_details": { "amount": "33.33", "currency": "pen", "exchange_rate": "0.3" }, "original_authorization_id": "ac95da35-b154-42d7-8b74-646981a549f8" }, { "fees": { "transaction_fee": { "fee_amount": "-0.20", "fee_config": { "percentage_fee_basis_points": 100, "fixed_fee_amount": "0.1" }, "is_international": true }, "total_fee_amount": "-0.20" }, "amount": "-10.00", "wallet": "other", "account": { "last_4": "7471" }, "network": "visa", "currency": "usd", "merchant": { "country": "PER", "category": "eating_places_restaurants", "description": "CENTRAL LIMA, PE", "category_code": "5812" }, "auth_type": "auth", "recurring": false, "created_at": "2025-11-19T04:44:05.000Z", "fee_amount": "0.00", "customer_id": "6398ddae-a6a5-4f88-8086-e5b21f3ab6a0", "card_present": true, "entry_method": "contactless", "international": true, "status_reason": "approved", "billing_amount": "-10.00", "transaction_id": "5a0662c4-eee0-4d31-a659-3b7ef5927c78", "approval_status": "approved", "card_account_id": "ce2b71b9-1179-4d9d-b644-690a4f7d935f", "cashback_amount": "0.00", "authorization_id": "ac95da35-b154-42d7-8b74-646981a549f8", "partial_supported": false, "verification_data": { "cvv_check": "match", "pin_check": "no_pin_passed", "address_check": "not_provided", "address_postal_code_check": "not_provided" }, "local_transaction_details": { "amount": "-33.33", "currency": "pen", "exchange_rate": "0.3" } } ], "merchant_category_code": "5812", "transaction_description": "CENTRAL LIMA, PE" }, "event_object_changes": { "status": [ "approved", "expired" ], "amount": [ "-10.00", "0.0" ], "billing_amount": [ "-10.00", "0.0" ], "updated_at": [ "2025-11-19T04:46:17.629Z", "2025-11-21T09:00:21.221Z" ] }, "event_created_at": "2025-11-21T09:00:22.241Z" } ``` When an authorization expires, the `authorization_infos` array contains both the original auth (with negative fee amount) and the expiration entry (with positive fee amount, returning the fee). The top-level `fees.total_fee_amount` shows the net fee of `0.0`, meaning the full fee was refunded. #### Denied Transactions Fees are **not charged** on denied transactions. The `fees` object will not appear in webhook payloads for denied transactions. #### Refunds After Settlement For refunds that occur after a transaction has settled (merchant credits), fees from the original transaction are **not returned** to the cardholder. The `fees` object will not appear in refund transaction webhooks. ## **Fees on Card Statements** When transaction fees are enabled for your integration, card statements will surface fee information in two places: ### Statement Summary The statement summary section includes a **Transaction Fees** row that shows the total transaction fees charged during the statement period. This row only appears when fees are enabled. | **Field** | **Description** | | :--------------- | :-------------------------------------------------------------------------------- | | Transaction Fees | The sum of all per-transaction developer fees charged during the statement period | ### Activities Table The activities table adds a **Transaction Fee** column next to each transaction entry. This column shows: * The fee amount for that specific transaction (e.g., `-$1.50`) * A dash (`-`) for transactions that have no associated fee ### How Statement Fees Are Calculated Transaction fees on the statement are derived from the settled fee amount recorded on each posted transaction. They are included in the running balance calculation, meaning the statement's starting and ending balances account for both transaction amounts and their associated fees. ## **Fees and Refunds** When a transaction is refunded or reversed, the handling of fees depends on your configuration and the type of refund: | **Scenario** | **Fee Behavior** | | :---------------------------------------- | :-------------------------------------------------------------------- | | Auth reversal (refund before settlement) | Fee refund behavior is configurable per developer | | Auth expiration | Fees are always refunded to the cardholder | | Merchant credit (refund after settlement) | Fees from the original transaction are not returned to the cardholder | Fee refund behavior for your integration is configured by Bridge during onboarding. Contact the Bridge team if you need to understand or modify how fees are handled for refunds. ## **Fees Payout** Card transaction fees you collect are automatically withheld from each transaction and set aside in a ledger reserved for you. Fees are settled and **paid out monthly on the 5th of each month** to your configured external account. ### Payout Details | **Detail** | **Description** | | :--------------- | :----------------------------------------------------------------------------- | | Payout frequency | Monthly, on the 5th of each month | | Payout currency | Same as the card's base currency (regardless of original transaction currency) | ### Configuring Your Payout Account To receive your fee payouts, you need to configure an external account using the [Configure a fee External Account API](/api-reference/developers/configure-a-fee-external-account). This is the bank account where Bridge will deposit your monthly fee payouts. # Freezing a card account Source: https://apidocs.bridge.xyz/platform/cards/additional/freezing This page is part of the legacy Bridge Cards API. For new integrations, use the [consumer issuing guide](/platform/cards/overview/stripe-issuing) instead. ## **Overview** If you are concerned about fraud, or if a user loses their card, you may want to freeze or un-freeze their card to prevent new authorizations from coming in.\ Note: Even if frozen, cards can still receive transaction events, such as settlements, refunds, or “forced” transactions. ## **Freezing a card** ```bash theme={null} curl -X POST ' --header 'Content-Type: application/json' \ --header 'Api-Key: ' \ -d initiator="customer" \ -d reason="lost_or_stolen" ``` ## **Unfreezing a card** ```bash theme={null} curl -X POST ' --header 'Content-Type: application/json' \ --header 'Api-Key: ' \ -d initiator="customer" ``` # Marketing, UX and compliance Source: https://apidocs.bridge.xyz/platform/cards/additional/marketing This page is part of the legacy Bridge Cards API. For new integrations, use the [consumer issuing guide](/platform/cards/overview/stripe-issuing) instead. To offer the Bridge card product to your customers, your marketing, user interfaces and servicing procedures must adhere to the guidelines and applicable laws and regulations. Please reach out to your Bridge program manager to get the latest version of our guidelines. # In-app mobile wallet provisioning Source: https://apidocs.bridge.xyz/platform/cards/additional/mobile-wallet-provisioning This page is part of the legacy Bridge Cards API. For new integrations, use the [consumer issuing guide](/platform/cards/overview/stripe-issuing) instead. *Push provisioning* enables customers to add cards directly to Apple Pay or Google Pay without manually typing in the card details. When issuing cards with Bridge, the Bridge team will set this up and make sure that your users have a seamless mobile wallet integration with minimal lift from you. Bridge's Cards API provides a [mobile wallet push provisioning request](/api-reference/cards/create-a-mobile-wallet-push-provisioning-request) endpoint that will provide the necessary information to add a card to a mobile wallet. Below, we'll discuss the details of the process specific to each wallet provider. ## Apple Pay ### Overview For Apple Pay, your mobile app first communicates with Apple's servers to retrieve the necessary certificates to encrypt the card details, then sends them to Bridge to retrieve the encrypted card details, and uses it to complete the provisioning process. At a high level, you can think of the process as the following: 1. Your cardholder requests to add their card to the mobile wallet from within your mobile app. 2. Your mobile app calls Apple via the [PassKit](https://developer.apple.com/documentation/passkit) API to generate the certificates, keys, and other data required to encrypt the card details. 3. Your application passes this information through your backend to Bridge, which will encrypt the card details using the provided certificates and keys, and return the encrypted payload to you. 4. You provide the encrypted payload provided by Bridge via PassKit. 5. Your mobile wallet decrypts the payload, validates it, tokenizes it with the card network, and activates it. ### Requirements Your app must have the `com.apple.developer.payment-pass-provisioning` entitlement in order to enable adding cards to Apple Pay wallets. You can request this entitlement with Apple following [this guide](https://applepaydemo.apple.com/wallet-extensions#allowListing). When testing this flow, ensure that you are testing with a production card in the production environment. Additionally, ensure that you are testing your app with this flow through TestFlight, as side-loading doesn't work with in-app provisioning. ### Integration guide Within your app, create a `PKAddPaymentPassRequestConfiguration` to configure how the card will be displayed, using `ECC_V2` as the encryption scheme. Use this to initialize a `PKAddPaymentPassViewController` to display the flow for adding the card to Apple Pay. As the user interacts with the flow, the controller will handle requesting Apple Servers for the necessary certificates, which will then get passed back to the `generateRequestWithCertificateChain` method. In your implementation of the `generateRequestWithCertificateChain` method, the arguments will contain a list of `certificates`, a `nonce`, and a `nonceSignature`. From the list of certificates, you will take the leaf certificate (the first item), and a subordinate certificate (the second item). You can use the following snippet as a rough reference implementation in your `PKAddPaymentPassViewControllerDelegate` for extracting the necessary details and encoding them in base64: ```swift theme={null} extension AddCardToWalletViewController: PKAddPaymentPassViewControllerDelegate { func addPaymentPassViewController(_ controller: PKAddPaymentPassViewController, generateRequestWithCertificateChain certificates: [Data], nonce: Data, nonceSignature: Data, completionHandler handler: @escaping (PKAddPaymentPassRequest) -> Void) { // Extract leaf and subordinate certificates - both must exist guard certificates.count >= 2 else { print("Error: Expected at least 2 certificates (leaf and subordinate)") ... } let leafCert = certificates[0].base64EncodedString() let subordinateCert = certificates[1].base64EncodedString() // This is what the request should look like when it gets to Bridge's // POST /card_accounts/{cardAccountID}/create_mobile_wallet_provisioning_request endpoint // Just a mock example -- don't directly call Bridge's endpoint from your mobile app! let pushProvisioningDetailsJSON: [String: Any] = [ "wallet_provider": "apple_pay", "apple_pay": [ "encoding": "base64", "leaf_cert": leafCert, "subordinate_cert": subordinateCert, "nonce": nonce.base64EncodedString(), "nonce_signature": nonceSignature.base64EncodedString() ] ] ... ``` Pass these details to your backend, and then to the Bridge [mobile wallet push provisioning request](/api-reference/cards/create-a-mobile-wallet-push-provisioning-request) endpoint, like so: ```json theme={null} { "wallet_provider": "apple_pay", "apple_pay": { "encoding": "base64", "leaf_cert": "MIIFjTCCA3WgAwIBAgIIWq7uC...", "subordinate_cert": "MIIFozCCA4ugAwIBAgIBATANBg...", "nonce": "dGhpcyBpcyBhIG5vbmNl", "nonce_signature": "MEUCIQDxl9V7oV8k3R..." } } ``` The response will contain the encrypted card details like so: ```json theme={null} { "wallet_provider": "apple_pay", "apple_pay": { "activation_data": "MBPAC-1-FK-123456.1--TDEA-8BF92C1D4291C91F35EFF127C1F9ABC12348DFED4E", "encrypted_pass_data": "F92C1D45EFF127F9C1D45EF2C1D45EFF127F92F127F92C1D45EFF127==", "ephemeral_public_key": "0499a6f42e83e27830f7f8994a4f150a78cdb9b7507bc5d28cbfbf8cc3ef0af68b780ffb562c936e60cb10db69192017089e3b73c83fcf0ebdf2c06b613c3f88b7" } } ``` You can then use the `activation_data`, `encrypted_pass_data`, and `ephemeral_public_key` to create the `PKAddPaymentPassRequest` to complete the provisioning. ## Google Pay For Google Pay, you can integrate Google's private [Android Push Provisioning API](https://developers.google.com/pay/issuers/apis/push-provisioning/android/integration-steps). You can follow [this guide](https://support.google.com/console/answer/15157842?hl=en) to request access to the API. Google Pay will provide the wallet account ID and device ID that is needed to pass into the mobile wallet provisioning request. # Managing PINs Source: https://apidocs.bridge.xyz/platform/cards/additional/pins This page is part of the legacy Bridge Cards API. For new integrations, use the [consumer issuing guide](/platform/cards/overview/stripe-issuing) instead. ## **Overview** Personal Identification Numbers (PINs) are an important security control and help keep your user's funds safe and card program low-risk. By providing an easy to use PIN management flow you can keep your users safe and ensure that transactions are not blocked. ### **Security Considerations** PINs are sensitive data, so we take special caution to never transmit directly through your servers In order to address both security and regulatory concerns (PCI) all PIN operations are mediated via time-limited, single-use URLs surfaced in hosted frames. ## **PIN Management Operations** As of date, Bridge only offers a single PIN management operation: * **Update Card PIN:** Allows customers to securely set or change their card PIN. Note that they cannot view their PIN in this flow. ### **Updating a Card PIN** To allow a customer to update their PIN you will need to request a signed URL from the Bridge API, and then use that URL to render an iframe in your application or a webview. To do so, you should use the [Create Card PIN Update URL](/api-reference/cards/create-card-pin-update-url) API to request a signed URL which your user can use to kick off a PIN editing session. ```bash theme={null} curl -x POST https\://\/card_accounts/\/pin -H "Content-Type: application/json" -H "Api-Key: YOUR_API_KEY" ``` You should then embed this URL via an iframe tag ```html theme={null}