Skip to main content
Accounts are represented by account_id values, which are assigned to verified entities. If you have an API Key and Secret, your application has its own account_id. You can also create additional account_id values for your business clients or for individual end users. Two shapes are supported today:
  • Business, custodial (KYB) — the existing behavior. The account holds one or more Brale-custodied (type=internal) on-chain wallets, can originate transfers, and can hold off-chain bank Addresses.
  • Individual, transactional (KYC) — a natural person verified with KYC. The account holds no custody at Brale, cannot originate on-chain transfers, and only receives value through external destination addresses. See Individual accounts.
Which shape you get is controlled by three optional dimension fields on POST /accounts. Omitting them all preserves today’s business/KYB behavior. See Account types for the full matrix. Each account_id (business, custodial) is associated with one or more custodial (type=internal) onchain wallets, which are represented by address_id values. Off-chain bank accounts are also represented as Addresses (using address_id). Individual, transactional accounts have no internal addresses. The legacy financial_institution_id is deprecated — new integrations should use address_id and the Addresses resource instead. The account_id is used in the request URL across many Brale API endpoints to scope the request to a specific application or client. To KYB and approve a business account, we collect key details such as business name and EIN. To KYC an individual account, we collect the person’s legal name, date of birth, address, and government identifier. For more information, see our Compliance Requirements. If additional details are required, Brale will notify you with the steps to complete verification.
Business customers can also self onboard at https://app.brale.xyz/signup. Individual accounts are managed entirely through the API — there is no end-user dashboard for them.

Account dimensions

POST /accounts accepts three optional discriminator fields: Only three combinations are accepted: Any other combination is rejected with 422 unsupported_account_combination. The rejection is permanent, so it is safe for clients to cache the error against an idempotency key.
Omitting all three dimension fields produces exactly today’s behavior. Existing integrations that create business accounts do not need to change.
For a fuller discussion of when to choose each combination, see Account types.

Creating a business account

You are required to pass in business information, controller information, and ultimate beneficial owner information. POST https://api.brale.xyz/accounts
Request

Presenting the Brale End-User Agreement

Partners must show the exact Brale End-User Agreement (EUA) to their end users before calling POST /accounts and capture consent. The most recent version is hosted at https://brale.xyz/legal/end-user-agreement.

Business account — Required vs. Optional Fields

Creating an individual account

On the individual path, set entity_type to individual and account_type to transactional. The individual object and tos_attestation are required. Business-only fields (business_name, ein, website, business_controller, beneficial_owners) must not be sent — they are rejected on this path. POST https://api.brale.xyz/accounts
Request
The created account’s name is derived from the individual’s first and last name.

Individual account — Required vs. Optional Fields

Identity types

One identity is submitted per individual. Use SSN9 for a US taxpayer, or the matching document type for a non-US individual. The region column is guidance on which value to send, not a separate validation: any value in this list is accepted, and the individual’s jurisdiction comes from individual.country.

Creating a non-US individual account

Non-US individuals are supported. individual.address.state is optional and free-form, and the postal code accepts any format, so only the identity type and country change. Omit state for countries that have no state or province:
Request

What a transactional account cannot do

Transactional accounts are inbound by design. The following constraints are enforced, not conventional:
  • No Brale-custodied wallets, ever. A transactional account has no automatic custodial wallet at creation and cannot hold internal (type=internal) addresses.
  • External addresses are destination-only. An external address on a transactional account can receive value but cannot be the source of a transfer.
  • The account cannot originate an on-chain transfer. An attempt returns 422 with type compatible_address_not_found. Checking the address balance first does not predict this, because the constraint is about the address role, not funds.
  • Automations from a transactional account may only target external destinations. A Brale-custodied destination is rejected.
The supported shape today is inbound: the account receives value on chain and can be the destination of an on-ramp. See Individual accounts for the end-to-end workflow.

Common Errors when creating Accounts

Individual path errors

Account Status

Brale will review the Account and return a status field denoting the customer’s verification status (KYB for business accounts, KYC for individual accounts). If the customer is in a pending status, you will need to wait for the customer to be verified before creating or linking addresses or bank accounts. GET https://api.brale.xyz/accounts/:id
Response

Account Statuses

Verification

Account verification is asynchronous. After creating an account, Brale reviews the submitted information — KYB for business accounts, KYC for individual accounts. The lifecycle and webhook events are identical in shape across both. Two integration patterns are supported. Proactive (at onboarding): Stage documents, then either pass doc_submission_ids when creating the account or link them later. Reactive (documents requested during review): When Brale needs additional documents, subscribe to the account.verification.documents_required webhook event (see Webhook Events). The payload lists each required document (document_kind, display_name, person_label, status). Stage the files, then link them. Alternatively, poll required documents.
When verification succeeds, Brale emits account.verification.completed and the account status transitions to complete. When it is declined, Brale emits account.verification.rejected and status becomes rejected. A decline is terminal. The account will not reach complete on its own and uploading further documents does not reopen it, so do not keep polling a rejected account. Contact Brale if you believe a decline is incorrect.

Using Account ID in every request

All resources in the Brale API (Addresses, Financial Institutions, Transfers, Automations, etc.) are scoped to specific accounts. Supply the ID in the path, never in the body.
Every endpoint that contains {account_id} must be called by including the account ID in the path. E.g. GET https://api.brale.xyz/accounts/2Js1YFqlfxgNqC2KTPEjrWIwKU7/addresses. Do not send the account ID in the body or query string.