Skip to main content

Introduction

This document is a guide to help your team evaluate and implement the ach_debit transfer type. It covers what the ach_debit functionalities are, how to get set up, and the key steps to go from initial testing to production. Use it as a reference while you integrate. When making POST requests Brale requires an Idempotency-Key header to be included and used on retries. Read more about idempotency keys in Brale. Using ach-debits required your business to be fully onboarded, and branded ach_debits are a premium feature.
  • Testnet Environment
    • If users wants to first test the below endpoints on testnet, they will need to create API credentials that are scoped to testnet - please follow the below link for more information:
  • Production Environment
    • Partners can leverage mainnet APIs by using their mainnet API keys generated in the Brale Portal.

End Customer Account Creation

  • Here is an example of how to get your account_id
    curl --request GET \
      --url https://api.brale.xyz/accounts \
      --header "Authorization: Bearer ${ACCESS_TOKEN}"
    
  • Managed account model: where Partner’s end users can create an account under Partner account, where Partner will have access to those accounts. This will allow end users to view their account and transaction history for all onramp operations executed. The Partner will be able to execute onramp operations on behalf of the end users as well.
  • The following request is an example of how to create a Plaid Token that you will need to use next section when setting up addresses for funding your transactions. Specifically, you will want to store the link_token as this is the plaid token you will need to use in subsequent requests.
  • Native mobile app considerations (Plaid Link): Because Brale manages the Plaid client configuration, mobile Plaid OAuth is not fully self-serve. You must submit your platform-specific values to Brale so they can be whitelisted before mobile Plaid OAuth will work. Your backend should create the link_token. Your mobile app uses the link_token to initialize Plaid Link. iOS:
    • Provide Brale with your iOS redirect URI. This must be an HTTPS universal link (e.g., https://example.com/plaid-redirect). Custom URL schemes are not supported for Plaid OAuth on iOS.
    • Your app must be configured for Universal Links so the redirect returns the user to your app after they complete the bank login.
    Android:
    • Provide Brale with your Android package name (android_package_name, i.e., the applicationId from your app’s build configuration).
    • The package name you submit must exactly match your app’s configuration. A mismatch will prevent Plaid from redirecting back to your app.
    Brale must whitelist your iOS redirect URI and/or Android package name before mobile Plaid OAuth will function. Contact Brale to submit these values.
    Troubleshooting: user completes bank login but is not returned to the app If the user finishes the Plaid/bank login flow but lands in Safari (iOS) or is not redirected back to your app (Android), check the following:
    • Brale whitelist not completed — confirm Brale has approved your redirect URI or package name.
    • iOS Universal Link misconfigured — verify your app’s Associated Domains entitlement and apple-app-site-association file are set up correctly.
    • Android package name mismatch — ensure the android_package_name submitted to Brale matches your app’s applicationId.
    • App configuration does not match the submitted value — double-check that the value registered with Brale exactly matches what your app is using at runtime.
curl --request POST \
  --url https://api.brale.xyz/accounts/{account_id}/plaid/link_token \
  --header 'Authorization: Bearer <token>' \
  --header 'Content-Type: application/json' \
  --data '
{
  "legal_name": "John Doe",
  "email_address": "user@example.com",
  "phone_number": "+1234567890",
  "date_of_birth": "1990-01-01"
}
'
Response Body Example:
{
  "link_token": "link-sandbox-123456789",
  "expiration": "2024-01-01T12:00:00Z",
  "callback_url": "https://customer.com/webhooks/plaid-updates"
}
  • Your backend should call the endpoint indicated by callback_url (which is the Brale “register account” step) and pass the public_token (and your webhook URL, if applicable). This registers the bank account inside Brale and returns an address_id for subsequent transfers.

Setup addresses (Funding)

  • If the user wants to connect a financial institution to fund their stablecoin with, they will need to create an external address for it. The same goes for funding stablecoins with existing digital assets from an external wallet. When transferring to an external address (on-chain wallet or off-chain bank account), use:
  • POST /accounts/{account_id}/addresses/external
  • Include an Idempotency-Key header and a JSON body. Examples: On-chain wallet (e.g., Solana) request body example:
    {
      "name": "User Solana Wallet",
      "address": "7xKXtg...",
      "transfer_types": ["solana"]
    }
    
    Off-chain bank account request example:
    • Partner will need to create a form that requests this information from end users to provide the below data
    • Once the below data has been recorded, Brale will generate a “Address ID” that corresponds to the financial institution OR the external wallet, and for any future debit operations we will reference the “Address ID”. Create off-chain external address:
    curl --request POST \
      --url https://api.brale.xyz/accounts/{account_id}/addresses/external \
      --header 'Authorization: Bearer <token>' \
      --header 'Content-Type: application/json' \
      --header 'Idempotency-Key: <idempotency-key>' \
      --data '
    {
      "name": "Operating Account (ACH Debit)",
      "transfer_types": [
        "ach_debit"
      ],
      "plaid_token": "PUBLIC_TOKEN_EXCHANGED_WITH_BRALE"
    }
    '
    

Requesting Mint/On-ramping

  • At this stage your end users’ accounts should already be connected, where Brale will execute debits and mint to desired stablecoins from the process below:
  • You will need to call the following below endpoints with the relevant data to be able to execute a swap or a transfer. POST https://api.brale.xyz/accounts/account_id/transfers
    • USDC to SBC request body example:
    {
      "amount": {
        "value": "100",
        "currency": "USD"
      },
      "source": {
        "address_id": "2VcUIonJeVQzFoBuC7LdFT0dRe4",
        "value_type": "USDC",
        "transfer_type": "Solana"
      },
      "destination": {
        "address_id": "2VcUIonJeVQzFoBuC7LdFT0dRe4",
        "value_type": "SBC",
        "transfer_type": "Solana"
      }
    }
    
    {
      "amount": {
        "value": "1",
        "currency": "USD"
      },
      "source": {
        "address_id": "2VcUIonJeVQzFoBuC7LdFT0dRe4", // address_id is the primitive, even for onchain sources
        "value_type": "USD",
        "transfer_type": "ach_debit"
      },
      "destination": {
        "address_id": "34yGFQf7tP1HJCPAWNGaN4rh4nX",
        "value_type": "SBC",
        "transfer_type": "polygon"
      },
      "brand": { "account_id": "34lCJZ2bxbPAzB3ou67Md01veUo" }
    }