API reference
The b-paid API lets your systems pay other businesses that have a b-paid account, and see the payments you send and receive. It is a REST API: each kind of object has its own URL, requests and responses are JSON, and it uses the standard HTTP methods and status codes. To make your first calls, follow the quickstart.
Set up API access
Section titled “Set up API access”- Sign up at b-paid.com, and verify your business in the b-paid app.
- Email b-paid support at support@b-paid.com and ask them to turn on API access for your b-paid account.
- In the b-paid web app, open Developers and select Create API key under Sandbox API keys. Owners, Admins and users with the Developer role can do this.
- Follow the quickstart.
API keys
Section titled “API keys”An API key pays from the b-paid account you create it in. If your business has more than one b-paid account, create keys in the one you want to pay from. On the Developers page, create keys under Live API keys or Sandbox API keys:
- A live key moves real money.
- A sandbox key works only in the sandbox, where no real money moves.
Each API key has two values, Primary and Secondary. Both work: send either one in the X-Api-Key header. Select Show keys to see them.
Keep your API keys secret: anyone with a live key can send payments from your account. Don’t put keys in client-side code or check them into source control.
Rotate an API key
Section titled “Rotate an API key”Each API key has two values so you can rotate it without downtime:
- Switch your systems to the other value, for example from Primary to Secondary.
- Select Regenerate on the value you stopped using. Its old value stops working at once.
If a key may have been exposed, regenerate both values.
Revoke an API key to stop both of its values at once. A revoked key can’t be restored.
Making requests
Section titled “Making requests”All requests must be made over HTTPS. Send every request to https://api.b-paid.com, with an API key in the X-Api-Key header. A live API key runs the request live, and a sandbox key runs it in the sandbox. Send request bodies as JSON, with Content-Type: application/json.
curl https://api.b-paid.com/v1/account \ --header "X-Api-Key: <your API key>"Accounts and bpids
Section titled “Accounts and bpids”Every b-paid account has a bpid: a public id, such as ACC-ONE-000-BZ, that others use to pay it. Your account’s id, and a payment’s source_account_id and destination_account_id, are bpids. To pay a business, ask the business for its bpid, which it can find in the b-paid app under Settings. Find your own there, or with Retrieve your account.
Ids, amounts and times
Section titled “Ids, amounts and times”Treat ids, including bpids, as opaque strings.
Amounts are integers in cents (USD): 145000 is $1,450.00. One payment can be at most $999,999.99 (99999999). You pay from your available balance: the money in your account that isn’t set aside for scheduled payments. Retrieve your account returns it as available_balance. You add money to your account in the b-paid app.
Times are in UTC, in ISO 8601, with up to 7 decimal places of seconds, for example 2026-09-22T17:42:08.1234567Z.
Scheduled payments and quick pay
Section titled “Scheduled payments and quick pay”To pay on a due date instead of now, send net_terms_days: the number of days from when you create the payment until it is due, 1 to 180. 30 pays 30 days from now. The payment’s scheduled_for is its due date. Until then its status is scheduled, and its amount is set aside from your available balance. You can cancel a payment only while its status is scheduled.
Quick pay is a discount you offer the recipient for being paid before the due date. To offer it, send quick_pay_percent with net_terms_days, for example 2.5 for 2.5% off amount. The discount gets smaller each day, down to 0 on the due date. The recipient accepts the offer in the b-paid app. The payment is then paid at once, at the discounted amount, and its amount_paid shows what was paid. quick_pay_percent on Create a payment has the full rules and an example.
Pagination
Section titled “Pagination”List payments returns payments newest first, one page at a time. Each page has its payments in data, and a next_cursor. To get the next page, send next_cursor as cursor, with the same filters as the first request. When there are no more payments, next_cursor is null. The default and maximum page size is 100; set a smaller one with limit.
b-paid doesn’t send webhooks. To find new payments, list payments with created_at.on_or_after set a few minutes before the newest created_at you have, and skip the ids you already have. To follow a payment until it is complete, failed or canceled, retrieve it.
Errors
Section titled “Errors”The b-paid API uses standard HTTP status codes: 2xx means success, 4xx means a problem with the request, and 5xx means a problem on our side.
Error responses are JSON objects in the RFC 9457 problem details format, sent as application/problem+json. A 5xx may arrive without a body, so decide what to do from the HTTP status first. Use type, a stable identifier for the kind of error, to handle errors in your code. title and detail are human-readable and may change.
{ "status": 400, "type": "invalid_parameters_error", "title": "One or more request parameters are invalid.", "detail": "net_terms_days must be between 1 and 180."}status(integer, always): The HTTP status, the same as the response’s.type(string, always): The kind of error, from the list below. New types may be added, so give your code a fallback for types it doesn’t recognize.title(string, always): A short, human-readable summary of the error type.detail(string): A human-readable explanation of this error and how to fix it, when there is more to say than thetitle.resource_id(string): Onidempotency_key_already_used_error, the id of the payment the key created.retry_after(integer): Onrate_limited_error, the seconds to wait before retrying, the same as theRetry-Afterheader.
Other fields may be added. Ignore any you don’t recognize.
Every response has a Request-Id header. When you contact b-paid support at support@b-paid.com about a request, include its Request-Id.
Error types
Section titled “Error types”Each error type, sorted by HTTP status:
invalid_parameters_error(400): A field or query parameter is missing, unknown or invalid, or theIdempotency-Keyheader is invalid. Nothing was created.invalid_api_key_error(401): The API key is missing, unknown or revoked.insufficient_permissions_error(403): API access isn’t turned on for your account. Ask b-paid support to turn it on.verification_required_error(403): Your business isn’t verified yet. Finish verifying it in the b-paid app.api_method_not_found_error(404): No endpoint exists at this path for this method, or the endpoint is sandbox-only and you sent a live key.object_not_found_error(404): Your account has no object with this id. Live and sandbox objects are separate, so an id from one is not found with a key for the other.idempotency_key_already_used_error(409): TheIdempotency-Keywas already used for a different payment.resource_idis that payment’s id.invalid_operation_error(409): The object’s current state doesn’t allow this, for example canceling a payment that is alreadycomplete.unsupported_media_type_error(415): The body was not sent asapplication/json.rate_limited_error(429): You went over the rate limit.internal_server_error(500): An unexpected error occurred on our side.service_unavailable_error(503): The b-paid API is temporarily unavailable.
Retrying
Section titled “Retrying”A 429 is always safe to retry: wait the number of seconds in the Retry-After header first. Fix any other 4xx before you send the request again.
After a 5xx, a timeout or a network error on Create a payment, you don’t know whether the payment was created. Send the same request again with the same Idempotency-Key: that never pays twice.
Idempotent requests
Section titled “Idempotent requests”Idempotency lets you retry a request without paying twice. It helps when a request fails or times out and you don’t know whether the payment was created.
When you create a payment, send an Idempotency-Key header: a unique value you choose for that payment, such as a UUID, of 1 to 200 ASCII characters. If you send the request again with the same key, you get back the payment the first request created, with the header Idempotent-Replayed: true, instead of a new payment.
Use a new key for every new payment. If you send a used key with a different amount, destination_account_id, net_terms_days or quick_pay_percent, you get 409 idempotency_key_already_used_error, with the id of the payment the key created in resource_id. To find the payment a key created, list payments with idempotency_key.
A 400 creates no payment and doesn’t use up the key: fix the request, then send it again with the same key. To try a failed payment again, send a new key.
This example pays SIM-PAY-002-BZ, a sandbox test account:
curl https://api.b-paid.com/v1/payments \ --header "X-Api-Key: <your API key>" \ --header "Idempotency-Key: <a new UUID>" \ --header "Content-Type: application/json" \ --data '{"amount": 145000, "destination_account_id": "SIM-PAY-002-BZ"}'Rate limits
Section titled “Rate limits”Your b-paid account can make 6 requests per second with live keys, and another 6 per second with sandbox keys. All of your API keys share these limits.
Over the limit, you get 429 rate_limited_error: wait the number of seconds in the Retry-After header, then retry. When the b-paid API is busy, you can get a 429 below your limit too. Handle it the same way.
Sandbox
Section titled “Sandbox”The sandbox lets you build and test your integration without moving real money. Send requests to the same base URL, https://api.b-paid.com, with a sandbox API key. Live and sandbox data are separate.
The endpoints marked “Sandbox:” simulate what others do, such as paying you. They work only with a sandbox key.
Your sandbox account has your bpid and its own balance, which starts at $0.00. To add money, call Sandbox: Receive a payment: the test account SIM-PAY-001-BZ pays you the amount you choose.
In the sandbox you can pay only these test accounts. Paying any other bpid returns 400 invalid_parameters_error.
destination_account_id |
Effect |
|---|---|
SIM-PAY-001-BZ to SIM-PAY-010-BZ |
The payment is complete. |
SIM-PAY-101-BZ |
The money leaves your balance at once. The payment stays pending for 10 to 15 minutes, then is complete. |
To get a failed payment, pay more than your available balance.
A scheduled payment is paid on its due date, as with a live key. The shortest term is 1 day, and the sandbox can’t skip ahead. To accept a quick pay offer as the recipient, call Sandbox: Accept a quick pay offer.
Sandbox payments send no emails or notifications, and don’t appear in the b-paid app.
OpenAPI
Section titled “OpenAPI”This reference also exists in OpenAPI 3.0.