# Errors & retries

Understand failures and retry requests without repeating a charge.

## Read the error envelope

Check the HTTP status and success flag before using data. Validation details identify fields that need correction. Keep X-Request-Id when contacting support; never include your secret API key.

```
{
  "success": false,
  "error": {
    "code": "VALIDATION_FAILED",
    "message": "The given data was invalid.",
    "details": { "amount": ["The amount must be a whole number."] }
  }
}
```

## Common errors

| Code / status | What to do |
| --- | --- |
| INVALID_API_KEY · 401 | Check the Bearer token and whether the key was revoked. |
| INSUFFICIENT_PERMISSION · 403 | Grant the required endpoint scope. |
| ENVIRONMENT_MISMATCH · 403 | Use the key for the resource’s environment. |
| PAYMENT_NOT_FOUND · 404 | Check the payment ID and environment. |
| DUPLICATE_REFERENCE · 409 | Look up the existing order/payment before trying again. |
| IDEMPOTENCY_KEY_REUSED · 409 | Use the original body for a retry; a new operation needs a new key. |
| VALIDATION_FAILED · 422 | Correct the fields in error.details. |
| PROVIDER_NOT_CONNECTED · 422 | Connect the provider in this environment. |
| RATE_LIMIT_EXCEEDED · 429 | Wait for Retry-After before retrying. |
| PROVIDER_UNAVAILABLE · 503 | Retry with backoff and the same persisted idempotency key. |

## Recover from timeouts

A timeout does not prove the provider did nothing. Inspect the stored payment when possible and retry the same operation with the same idempotency key and request body. Use bounded exponential backoff for transient errors and avoid retrying validation or authentication failures unchanged.
