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

# Error handling

> Understand error responses and how to handle them

All Crycket API errors return a consistent envelope. Use the HTTP status code as the primary signal and the `code` field for machine-readable error identification.

## Error format

```json theme={null}
{
  "error": {
    "code": "intent.already_fulfilled",
    "message": "This payment intent has already been fulfilled.",
    "param": null,
    "details": {
      "intent_id": "pi_abc123",
      "current_state": "confirmed"
    }
  }
}
```

| Field     | Description                                                       |
| --------- | ----------------------------------------------------------------- |
| `code`    | Machine-readable error code in `resource.error_type` dot notation |
| `message` | Human-readable error message                                      |
| `param`   | Field name if this is a validation error                          |
| `details` | Additional context about the error                                |

## HTTP status codes

| Status | Meaning                                                       |
| ------ | ------------------------------------------------------------- |
| 400    | Malformed request or validation error                         |
| 401    | Invalid or missing API key                                    |
| 402    | Feature requires a higher plan tier                           |
| 404    | Resource not found                                            |
| 409    | Conflict — wrong state for this operation                     |
| 422    | Semantically invalid (e.g. token not available on this chain) |
| 503    | RPC upstream unavailable — includes `retry_after`             |

## Common error scenarios

### State conflicts (409)

Returned when you try an operation that isn't valid for the intent's current state:

* Cancelling an intent that isn't in `created` state
* Building a transaction for an already-confirmed intent
* Submitting to an expired intent

Always check the intent's current state before performing operations.

### Stale updates (409)

`PATCH /v1/intents/:id` requires the current `updatedAt` timestamp for optimistic concurrency. If another update happened between your read and write, you get a 409. Re-fetch the intent and retry with the fresh `updatedAt`.

### RPC unavailable (503)

Returned when the upstream RPC provider is unreachable during transaction submission. The response includes a `retry_after` value. Implement retry with exponential backoff.

### Sanctions screening (422)

Every `POST /v1/intents` and `POST /v1/intents/:id/submit` screens wallet addresses against the OFAC SDN list. If the screening API is unavailable, the request is rejected with `503` (fail closed). A match returns `422` with `error.code: "address.sanctions_match"`.
