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

# Errors

> Common CHIP Collect error codes and how to handle them.

CHIP Collect returns errors in two places:

* **HTTP responses** to your API requests. Errors come back as 4xx
  (client errors) or 5xx (server errors) with a JSON body containing a
  `code` and a human-readable `message`.
* **Webhook events** for things that happen after the initial request,
  such as `purchase.payment_failure` with an `error_code` field in the
  payload.

This page lists the most common codes and the recommended next step.
Always log the full response so you can debug from the raw error.

## HTTP error responses

| Status | `code`                    | Meaning                                                      | Recommended action                                                                                                      |
| ------ | ------------------------- | ------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------- |
| 400    | `invalid_request`         | One or more required fields are missing or malformed.        | Inspect the `message` field for the offending field. Validate inputs client-side before sending.                        |
| 400    | `invalid_recurring_token` | The recurring token is unknown, revoked, or expired.         | Re-prompt the buyer for a new card. Do not retry the charge.                                                            |
| 401    | `unauthorized`            | API key is missing, malformed, or invalid.                   | Verify the `Authorization` header is `Bearer <secret_key>` and the key is from the right brand.                         |
| 403    | `forbidden`               | The API key does not have access to this resource.           | Confirm the key has the required scopes in the merchant portal.                                                         |
| 404    | `not_found`               | The purchase, client, or webhook does not exist.             | Double-check the ID. Records in CHIP Collect are not deleted by default.                                                |
| 409    | `conflict`                | The operation is not valid for the resource's current state. | Inspect the resource's `status` field. For example, you cannot capture an already-captured purchase.                    |
| 422    | `unprocessable_entity`    | The request is well-formed but semantically invalid.         | Read the `message` field. Common cause: amount exceeds the remaining capturable balance.                                |
| 429    | `rate_limited`            | Too many requests in a short window.                         | Back off and retry with jitter. Honor any `Retry-After` header if present.                                              |
| 500    | `internal_error`          | Something went wrong on CHIP's side.                         | Safe to retry with idempotency. If it persists, contact [support@chip-in.asia](mailto:support@chip-in.asia).            |
| 502    | `bad_gateway`             | Upstream provider (bank, card network) returned an error.    | Do not retry immediately. Wait for the corresponding webhook before acting.                                             |
| 503    | `service_unavailable`     | Planned maintenance or temporary outage.                     | Retry with exponential backoff. Status page: [https://status.chip-in.asia](https://status.chip-in.asia) (if available). |

## Webhook `error_code` values

These appear on `purchase.payment_failure` and `purchase.cancelled` events.

| `error_code`              | Meaning                                                                   | Recommended action                                                                                  |
| ------------------------- | ------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------- |
| `insufficient_funds`      | The buyer's account did not have enough funds at the time of payment.     | Ask the buyer to use a different payment method. Do not auto-retry.                                 |
| `payment_declined`        | The buyer's bank or card issuer declined the transaction.                 | Ask the buyer to contact their bank or use a different method.                                      |
| `payment_cancelled`       | The buyer explicitly cancelled the payment on the bank or card page.      | Treat as a soft decline. Allow the buyer to retry.                                                  |
| `payment_expired`         | The buyer did not complete payment within the expiry window.              | Issue a new purchase if the buyer still wants to pay.                                               |
| `invalid_signature`       | (Only when re-validating locally) The webhook signature could not verify. | Check that you are reading the **raw** request body and using the public key for the right webhook. |
| `invalid_recurring_token` | The recurring token has been deleted or revoked.                          | Re-prompt the buyer to enrol a new card.                                                            |

## Idempotency

For write operations (create, charge, capture, refund, etc.), the same
request body sent twice with the same `Idempotency-Key` header will
return the same result without performing the action twice. Always
generate an `Idempotency-Key` server-side for non-idempotent operations
so a network retry does not create duplicates.

## When to contact support

Open a ticket to [support@chip-in.asia](mailto:support@chip-in.asia) if:

* The same error code is returned for more than 1% of your traffic.
* You receive an HTTP 5xx response that retries do not clear.
* A webhook `event_id` is not delivered within 5 minutes of the
  corresponding `purchase.paid` event.

Always include the `purchase_id`, the request timestamp, and the full
response body.
