> ## Documentation Index
> Fetch the complete documentation index at: https://docs.bachs.io/llms.txt
> Use this file to discover all available pages before exploring further.

> ## Agent Instructions
> Money is always a decimal string at the currency's precision (for example "29.00"), paired with an ISO 4217 currency field. Never use minor units.
> Build against the sandbox first: base URL https://sandbox-api.bachs.io with sk_sandbox_ keys. Production is https://api.bachs.io with sk_live_ keys; going live is a key swap.
> Treat webhooks (for example collection.succeeded) as the source of truth for fulfilment, never client-side events or redirects.
> Subscriptions are created by completing a checkout for a recurring product. There is no direct create-subscription endpoint.
> IDs carry resource prefixes (cust_, prod_, sub_, chk_, inv_, ref_) and timestamps are ISO 8601 UTC.

# How Bachs works

> The mental model behind every Bachs integration: who is involved, how a payment moves from checkout to payout, which currencies sit where, and how the sandbox relates to live.

Bachs is the payments and billing platform for African internet businesses and the customers they serve anywhere: one API and one dashboard for checkout, subscriptions, payouts and sub accounts. This page gives you the model that every guide builds on.

## The three parties

Every flow on Bachs involves the same three parties.

* **You**, the business. You create products, create checkouts, receive webhooks, hold a balance and withdraw from it.
* **Your customer.** They pay at checkout with a card, a bank transfer, mobile money or crypto, in their own currency. All payment methods are available through a single checkout, and your customer sees only the methods relevant to their currency and location.
* **Bachs.** It renders the hosted checkout, processes the payment, holds the funds in your Bachs balance, and sends the money to your payout destination when you ask.

Your customer pays in their currency, you settle in yours, and Bachs carries the conversion between the two.

## The flow of a payment

A one-time sale moves through five objects: a product, a checkout session, a payment, your balance and a payout.

```mermaid theme={"dark"}
sequenceDiagram
    participant C as Customer
    participant A as Your server
    participant B as Bachs
    A->>B: Create a checkout session (product_cart or pricing)
    B-->>A: checkout_url
    A-->>C: Redirect to checkout_url
    C->>B: Pays on the hosted page
    B-->>C: Redirect to success_url
    B->>A: Webhook: collection.succeeded or checkout.completed
    A->>A: Verify the signature, fulfil the order once
    B->>B: Funds land in your balance
    A->>B: Create a payout
    B->>A: Webhook: payout.paid or payout.failed
```

1. **Product.** One thing you sell, from your catalog. A checkout is priced with a `product_cart` of catalog products, or with a raw `pricing` amount when you have no product to reference.
2. **Checkout session.** It ties a price to a customer and returns a hosted `checkout_url`. Bachs resolves pricing, handles currency conversion, selects payment methods and processes the payment. You send the customer to the URL and listen for the result.
3. **Payment.** When the checkout is paid, Bachs redirects the customer to your `success_url` and sends `checkout.completed` and `collection.succeeded` to your webhook endpoint. Either can arrive first: fulfil the order on whichever arrives first, once. A free checkout sends only `checkout.completed`.
4. **Balance.** Funds collected through Bachs are held in your Bachs balance.
5. **Payout.** A payout moves money from your balance to your own bank account or wallet. You save a destination, get a quote if the currencies differ, create the payout, then track `payout.paid` or `payout.failed`. An accepted payout is not proof of completion.

> [!WARNING]
>
> The webhook is the signal to fulfil, never the redirect. Redirects can be lost if the customer closes the tab. Treat the webhook as the source of truth, verify its signature before trusting it, and use the event `id` to deduplicate, because delivery is at least once.

## Three currency sets

Collection currencies and withdrawal currencies are separate. What you can collect from customers is not the same as what you can withdraw. A third set matters as well: the currencies an account can **hold** as a balance, which is narrower than either of the other two.

| Set | What it means | Today |
| - | - | - |
| Collection currencies | What your customer can pay in at checkout. | USD and NGN by card, NGN by bank transfer, nine local currencies by mobile money, and crypto. |
| Balance currencies | What you can hold money in. | USD and NGN. USD is always held and cannot be turned off. |
| Withdrawal currencies | What you can send to your own bank account or wallet. | NGN, GHS, KES, TZS, UGX, GBP, USD, CAD, EUR, plus USDT and USDC. |

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 at the rate quoted on the charge. On the way out, international bank and mobile money withdrawals draw from your USD balance, and a payout in another currency needs a conversion quote, created before you send it, that fixes the source and destination amounts. You are never forced to convert.

## Sandbox and live

Bachs runs two separate deployments with the same API. Endpoints, request structure and response shapes are identical; only the base URL and the keys change.

| Environment | Base URL | Keys |
| - | - | - |
| Sandbox | `https://sandbox-api.bachs.io` | `sk_sandbox_...` |
| Live | `https://api.bachs.io` | `sk_live_...` |

API keys are environment-specific, so a key only works against its own URL. Nothing is shared between the two, not balances, customers, payout destinations, webhook endpoints or API keys. Sandbox payments are simulated, succeed by default, and send the same webhooks as production, so you can test your handler against every outcome before anything real moves.

Sandbox keys are available the moment you sign up. Live keys need account verification, which happens once and covers your product, your identity and your withdrawal account. Most reviews finish within 48 hours. Once you are verified, going live means swapping your API keys.

## Read next

> [card] [Pay-ins and withdrawals](https://docs.bachs.io/for-you/payins-payouts.md)
>
> How customers pay you, and how you receive your funds.

> [card] [Payment statuses](https://docs.bachs.io/guides/payments/statuses.md)
>
> Understand payment charge statuses, what each one means, and how substatuses add detail.

> [card] [Subscriptions](https://docs.bachs.io/guides/subscriptions/overview.md)
>
> A subscription is one customer's ongoing relationship with a recurring product.

> [card] [Payouts](https://docs.bachs.io/guides/payouts/overview.md)
>
> Understand payouts and choose the dashboard or API flow.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.