Create an account
POST /v1/accounts · scope connected_accounts:write · full field reference →
contact_email is the only required field.
-
countrydefaults to your platform’s country, and decides which requirements the account is given. -
entity_typeisindividualorcompany. Any other value is rejected with400. -
configurationnames the personas (merchant,recipient) the account is being created for, each as its own key. Nothing is applied for you, so name at least one persona and request at least one capability under it; don’t create an account without both. Sending"configuration": {}is rejected with422 VALIDATION_ERROR, since an empty object is never what you mean. Naming a persona with nocapabilitiesunder it is not itself a capability request; nest capabilities under it, or leavecapabilitiesout of a persona entirely to request everything that persona allows. -
Every capability lives inside
configuration.<persona>.capabilities, so naming one always names the persona it belongs to in the same request.card_collectionbelongs tomerchant;payoutsandtransfersbelong torecipient. Nesting a capability under the wrong persona fails with400 capability_configuration_mismatch: it is never silently corrected. In sandbox, whatever is granted is grantedactiveimmediately rather thanpending_review; see Testing. -
Send
"capabilities": {}under a persona when you want to apply it and request nothing yet, for a platform that creates the account now and collects requirements later. -
responsibilities.fees.collectordecides who takes the Bachs processing fee on this account’s direct charges.bachs(the default) means the fee comes out of the charge, so the account settles net.platformmeans you absorb it: the fee is debited from your balance and the account settles gross. It is fixed at creation and cannot be changed afterwards, and it is returned on every read of the account.platformhas no effect on a destination charge. There the account is the counterparty being paid out of a sale that is yours, so there is no fee of theirs for you to absorb; the setting is read but does not apply, and the charge settles as it otherwise would. Set it for accounts that sell in their own name.
An account can start out recipient-only and be given
merchant later: POST /v1/accounts/{account_id} takes the same configuration shape, so naming merchant there applies it the same way naming it at creation would. See Update an account.responsibilities and the account settles net, which is what most platforms want. Take the fee on only when you mean to pay it:
payouts, transfers and conversions are the recipient capabilities, the ones any account needs just to hold and move money it has received. card_collection and the other payment-method capabilities are merchant capabilities: what gives an account the ability to accept payments in the first place. Name both personas in configuration if the account needs to do both. See Capabilities for what each capability permits and how the two groups relate.
Bachs creates a service user to own the account and sends onboarding correspondence to contact_email. An account cannot create other accounts of its own; that returns 403.
Treat the account id as an opaque string. New accounts are prefixed
acct_, and accounts created before that convention are unprefixed. Store what the API returns and send it back unchanged rather than validating its shape.Act on behalf of an account
Send the account id inX-Account-Id. The request runs as that account.
- The header works on any API-key endpoint, not only Connect ones.
- Naming an account you do not own returns
403— your key authenticates fine, it is just not authorized for that account. A non-existent id and another platform’s id return the same403, so the header cannot probe which ids are real. See Acting as an account. - The account’s own capabilities still apply. A restricted
payoutscapability blocks the withdrawal whether you call it or the account does.
Update an account
POST /v1/accounts/{account_id} · scope connected_accounts:write · full field reference →
One write path. Set the account’s contact details, request capabilities, and supply requirement values in a single call. Omitted keys are left alone.
display_nameandcontact_emailchange what you set at creation.configurationrequests capabilities, and cannot withdraw one. See Capabilities. It is the same shape as creation: naming a persona as a key is what applies it, if the account does not already have it, whether or not you nest a capability under itscapabilities.conversionsabove works becauserecipientis either already applied or gets applied by this same call. Unlike creation, a persona named here withcapabilitiesleft out never blanket-requests: it only applies the persona.fieldscarries requirement values, keyed the way the account’s requirements name them. See Requirements.balance_currenciessets which currencies the account holds. See below.
Currencies the account holds
Holding a currency decides what an account settles in, not what it can charge in. A checkout can be priced in any supported currency, held or not, and converts on the way to the balance. This is true for one-time and recurring (subscription) checkouts alike: a subscription priced in a currency the account does not hold still bills each cycle and settles the proceeds into the account’s settlement currency (USD unless it holds the priced currency). A new account holds only USD, so give it a currency when you want its takings to stay in that currency rather than convert. Not every currency Bachs collects in can be held as a balance. Balance currencies lists the ones that can. Asking for any other is refused with400, and the error names the set that is accepted.
true to add a currency and false to remove one. Omit the field and nothing changes. USD is always held, cannot be removed, and does not appear in the response.
This only applies to an account that takes its own payments. An account that is paid through transfers receives whatever currency you send it, and holds it from that point.
A partial fields submission is never rejected for being partial. Everything valid is saved, and whatever is still missing or invalid comes back in the requirements block of the same response, so you can save an account holder’s progress as they fill in a form.
Persons
/v1/accounts/{account_id}/persons · scope connected_accounts:read / connected_accounts:write
The people behind an account: its representative, its beneficial owners, its directors. A company account needs its representative and every owner at or above the ownership threshold; an individual account has exactly one person.
relationship carries all of them on the same person rather than repeating them across separate collections.
On edit, keys you omit are left alone; sending a key as null clears it. So {"last_name": "Obi-Nwosu"} renames without touching anything else, and naming one relationship flag does not reset the rest.
Requirement keys are anchored to the person: persons.per_3a91c0d7.id_document names exactly who needs to re-upload. Removing a person removes the requirements that were only about them.
The representative cannot be removed, because nothing would ask for a replacement and the account would stall. Make another person the representative first.
id_number_provided) rather than echoing it, and never carries how the person was verified.
Read an account
GET /v1/accounts/{account_id} · scope connected_accounts:read · full field reference →
Returns the account with its capabilities, configuration, responsibilities, and requirements blocks. configuration is keyed by persona (merchant, recipient) and, on a single-account read, reads as {} when none apply rather than null. List items do not carry it and return null, the same way they do for capabilities and requirements. responsibilities reads as { "fees": { "collector": "bachs" } } unless the platform took the fee on at creation. GET /v1/accounts lists your accounts.
Fields with a standing rejection are listed in requirements.errors, each with the field key and a reason written for the account holder. Like the rest of requirements, they are only on a single-account read, so an index screen built from GET /v1/accounts cannot flag accounts needing attention; read the account to know.
Nothing outstanding in requirements does not mean a capability is active. Gate features on the capability’s status. See Capabilities.
include
requirements.values is not returned by default, since it needs a further resource load. Ask for it when you want to read back what has already been submitted:
requirements.values and requirements.persons. Sensitive fields are listed as provided and never echoed back.
Comma-separated or repeated (?include=a,b and ?include=a&include=b are the same). An unknown value returns 400 invalid_include rather than being ignored, so a typo does not leave you waiting for a block that never arrives. Anything not asked for is absent from the response rather than null, since null could not be told apart from genuinely empty.
Errors
Account endpoints return the standard error envelope. Common cases:FORBIDDEN(403), yourconnectcapability is not active. See Become a platform.NOT_FOUND(404), the account id is not one of your accounts.VALIDATION_ERROR(422), a field failed validation; inspecterrors[].invalid_configuration(400),configurationnames a persona that does not exist. Valid keys aremerchantandrecipient.

