> ## 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.

# Statuses

> Understand payment charge statuses, what each one means, and how substatuses add detail.

A charge tracks the outcome of a customer's payment. Its `status` tells you where the charge stands. Some statuses also have a `substatus` that explains what is happening or why the charge ended.

Use [Get Charge Status](/guides/payments/get-charge-status) to retrieve a charge, or use [webhooks](/guides/webhooks/overview) to receive payment updates as they happen.

## Charge statuses

| Status | Meaning |
| - | - |
| `open` | The charge can still be paid. A payment method may be waiting for the customer, or the customer may be able to try again. |
| `incomplete` | The checkout ended without a successful payment. See `substatus` for more detail. |
| `succeeded` | The payment was successfully collected. |
| `accepted` | An underpayment or overpayment was accepted as the final payment outcome. |
| `underpaid` | The customer paid less than the amount due. |
| `overpaid` | The customer paid more than the amount due. |
| `failed` | The charge ended after a payment attempt failed and no further attempt is available. |
| `refunded` | The payment was fully refunded. |
| `partially_refunded` | Part of the payment was refunded. Check `refunded_amount` for the amount returned. |
| `auto_refunded` | The payment was fully refunded automatically. |

## How statuses and substatuses relate

`status` describes the charge's overall state. `substatus` adds detail to certain statuses. It does not replace `status`, and it does not by itself confirm that money was collected.

For an `open` charge, `substatus` describes the current payment attempt:

| Status | Substatus | Meaning |
| - | - | - |
| `open` | `awaiting_payment` | A payment attempt is active and waiting for payment. |
| `open` | `awaiting_approval` | The customer needs to approve the payment, for example with a PIN, OTP, 3DS check, or phone prompt. |
| `open` | `last_attempt_failed` | The latest attempt failed, but the charge is still open and another attempt may be made. |
| `open` | `null` | No payment method has been selected, or there is no current attempt detail to show. |

For a charge that has ended without payment, `substatus` explains why:

| Status | Substatus | Meaning |
| - | - | - |
| `incomplete` | `abandoned` | The checkout ended without payment. |
| `incomplete` | `expired` | The charge timed out, another payment method completed the payment, or the merchant cancelled it. |
| `failed` | `insufficient_funds` | The account or wallet did not have enough funds. |
| `failed` | `declined` | The payment was declined. |
| `failed` | `authentication_failed` | The payment was not approved. |
| `failed` | `expired_card` | The card has expired. |
| `failed` | `invalid_details` | Payment details were invalid. |
| `failed` | `timed_out` | The payment attempt took too long. |
| `failed` | `provider_error` | The payment provider could not process the attempt. |

The `open` substatus reflects the current attempts and can change as they progress. For example, an `open` charge with `last_attempt_failed` is still payable. A failed attempt does not mean the whole charge has failed.

A completed charge keeps its ending `substatus`. For compatibility, webhooks can report the reason as a status such as `cancelled` or `expired`, while the Payments API reports `incomplete` with a substatus. Check the status and substatus together when handling these records.

## Decide what to do

* Keep the order pending while the charge is `open`.
* Fulfill when the payment reaches `succeeded`, `accepted`, or `overpaid`, applying your own rules for the amount received.
* Do not fulfill an `incomplete` or `failed` charge.
* When a charge is refunded, use its refund status and `refunded_amount` to update your records.
* For an asynchronous payment, use webhooks for updates and retrieve the charge when you need its current state.

For refund processing and refund-specific statuses, see the [Refunds guide](/guides/refunds).
