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

# Errors rate limits idempotency

# Errors, Rate Limits, And Idempotency

Use structured errors and idempotency keys to make your integration safe under retries, network failures, and duplicate requests.

## Error shape

PayChain errors use a structured response:

```json theme={null}
{
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "Invalid request data",
    "details": [],
    "requestId": "req_..."
  }
}
```

Always log the `requestId` without logging secrets.

## Common error categories

| Category                        | Typical HTTP status | Retry?                                                |
| ------------------------------- | ------------------: | ----------------------------------------------------- |
| Validation error                |               `400` | No. Fix the request.                                  |
| Authentication error            |               `401` | No. Check API key and environment.                    |
| Permission error                |               `403` | No. Check key type and policy.                        |
| Not found                       |               `404` | No, unless the resource may be created later.         |
| Conflict / idempotency conflict |               `409` | Usually no. Inspect the existing request or resource. |
| Rate limited                    |               `429` | Yes, after backoff.                                   |
| Server or network error         |               `5xx` | Yes, with backoff and idempotency.                    |

## Error code catalog

Use the machine-readable `code` field for integration logic and the `message` for human-readable context. Codes can expand over time, so integrations should handle unknown codes gracefully.

| Code                                          | Meaning                                                                         | Typical action                                                                                                |
| --------------------------------------------- | ------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------- |
| `VALIDATION_ERROR`                            | Request body, query parameter, or field value is invalid.                       | Fix the request before retrying.                                                                              |
| `UNAUTHORIZED`                                | API key or session is missing or invalid.                                       | Check environment and key storage.                                                                            |
| `FORBIDDEN`                                   | The key or user does not have permission for the action.                        | Check key type, payout policy, or dashboard permission.                                                       |
| `NOT_FOUND`                                   | Resource does not exist or does not belong to the business.                     | Check IDs and environment.                                                                                    |
| `CONFLICT`                                    | Request conflicts with current resource state.                                  | Fetch the resource and resolve state before retrying.                                                         |
| `DUPLICATE_REQUEST`                           | A duplicate create request was detected.                                        | Reuse idempotency keys and inspect the existing resource.                                                     |
| `IDEMPOTENCY_REQUEST_IN_PROGRESS`             | Another request with the same key is still processing.                          | Wait, then fetch the resource or retry safely.                                                                |
| `IDEMPOTENCY_KEY_MISMATCH`                    | Same idempotency key was reused with a different payload.                       | Use stable keys per unique business action.                                                                   |
| `RATE_LIMIT_EXCEEDED`                         | Too many requests in a window.                                                  | Back off and reduce polling.                                                                                  |
| `INSUFFICIENT_BALANCE`                        | Available business balance is not enough for the action.                        | Reconcile balance or reduce the amount.                                                                       |
| `WITHDRAWAL_AMOUNT_EXCEEDS_AVAILABLE_BALANCE` | Requested withdrawal exceeds current withdrawable capacity after policy checks. | Use a smaller amount, wait for `pending_funds` to clear where applicable, or resolve recovery-required funds. |
| `SPONSORED_GAS_CREDIT_INSUFFICIENT`           | Sponsored outbound operation needs more gas credit.                             | Top up gas credits or wait for the next included allowance.                                                   |
| `WEBHOOK_EVENT_IN_FLIGHT`                     | Webhook delivery is already being processed.                                    | Wait for terminal delivery state.                                                                             |
| `WEBHOOK_EVENT_ALREADY_SCHEDULED`             | Retry or replay is already scheduled.                                           | Do not schedule another duplicate attempt.                                                                    |
| `WEBHOOK_EVENT_ALREADY_DELIVERED`             | Webhook already reached a delivered state.                                      | Treat as successful or replay only when supported.                                                            |
| `WEBHOOK_EVENT_NOT_FOUND`                     | Webhook event ID was not found.                                                 | Check environment and event ID.                                                                               |
| `WEBHOOK_RETRY_COOLDOWN`                      | Retry is temporarily blocked by cooldown.                                       | Retry later.                                                                                                  |
| `WEBHOOK_REPLAY_NOT_SUPPORTED`                | The event cannot be replayed.                                                   | Use normal retry or fetch the resource directly.                                                              |
| `WEBHOOK_REPLAY_REQUIRES_TERMINAL_STATE`      | Event must reach terminal state before replay.                                  | Wait for delivery to finish.                                                                                  |
| `WEBHOOK_REPLAY_COOLDOWN`                     | Replay is temporarily blocked by cooldown.                                      | Retry later.                                                                                                  |
| `BILLING_INVOICE_NOT_FOUND`                   | Billing invoice was not found.                                                  | Check invoice ID and environment.                                                                             |
| `BILLING_UNDERPAYMENT`                        | Billing payment was lower than required.                                        | Pay the required invoice amount.                                                                              |
| `BILLING_INVOICE_NOT_PAYABLE`                 | Billing invoice is cancelled, expired, or not payable.                          | Start a new billing or upgrade flow.                                                                          |
| `BILLING_PAYMENT_REPLAY_CONFLICT`             | Billing payment conflicts with a prior payment record.                          | Contact support with request ID.                                                                              |
| `REDIS_COORDINATION_UNAVAILABLE`              | Temporary coordination dependency is unavailable.                               | Retry later with idempotency.                                                                                 |
| `SERVICE_UNAVAILABLE`                         | PayChain dependency or service is temporarily unavailable.                      | Retry later with backoff.                                                                                     |
| `INTERNAL_SERVER_ERROR`                       | Unexpected PayChain error.                                                      | Retry if safe, then contact support with request ID.                                                          |

<Info>
  **Support note:** When contacting support, include the request ID, resource ID, environment, and timestamp. Do not send API keys, webhook secrets, or raw credential headers.
</Info>

## Idempotency keys

Send `Idempotency-Key` on mutating requests:

```http theme={null}
Idempotency-Key: order_123_invoice
```

Use stable keys based on your own business object:

* `order_123_invoice`
* `payout_456`
* `customer_789_invoice_001`

Recommended formats:

| Action                           | Example key                        |
| -------------------------------- | ---------------------------------- |
| Create invoice for an order      | `order_123_invoice`                |
| Create invoice with payout route | `order_123_route_invoice`          |
| Create dynamic-recipient invoice | `order_123_dynamic_payout_invoice` |
| Quote withdrawal                 | `payout_456_quote`                 |
| Create withdrawal                | `payout_456_create`                |
| Execute approved contract action | `order_123_contract_action`        |

<Warning>
  **Retry note:** Do not automatically retry non-idempotent `POST` requests unless you sent an idempotency key.
</Warning>

## Rate limits

Rate limits protect PayChain and merchants from accidental request bursts.

Recommended behavior:

* Back off on `429`.
* Respect retry headers if present.
* Avoid tight polling loops.
* Prefer webhooks for lifecycle changes.
* Use list pagination for reconciliation jobs.

## Safe retry policy

Retry:

* Network timeouts.
* `408`.
* `429`.
* `5xx`.

Do not blindly retry:

* Invalid request data.
* Wrong API key type.
* Rejected payout policy.
* Insufficient balance.
* Recovery-required balance that is not withdrawable.
* Expired or cancelled invoices.
* Webhook events already delivered.

If a valid withdrawal returns or emits `pending_funds`, do not create a replacement withdrawal. Keep the same idempotency key and wait for the existing withdrawal to continue after sweepable funds become available.

## Operational logging

Log:

* `requestId`.
* PayChain resource ID.
* Your order/customer reference.
* HTTP status.
* Error code.

Do not log:

* API keys.
* Webhook secrets.
* Request headers containing credentials.
* Raw payout destination secrets.
* Full raw webhook payloads in shared logs.
