# Errors, idempotency and recovery

The API returns normal HTTP errors. Read the response's `message` or `error` when available. Authentication failures, ownership checks and purchase business rules remain enforced by the underlying API when used through MCP.

| Status | Handling |
| --- | --- |
| 400 | Check required fields, milliseconds, decimal price and idempotency key. Do not retry unchanged invalid input. |
| 401 / 403 | Check the key, revocation and matching store. Do not retry with account selectors. |
| 404 | Resource absent or unavailable to the caller. Check the order/service/attempt ID. |
| 409 | Conflict: for example an idempotency key reused with different input or an ineligible state transition. Read the current state before acting. |
| 429 | Back off and honor `Retry-After` if present. |
| 5xx / network timeout | Outcome may be uncertain, particularly for purchases and cancellations. Reconcile before retrying. |

These are handling categories; a particular business failure's actual status and message are authoritative. An MCP tool error includes the upstream status when available and marks uncertain mutation outcomes explicitly. It never automatically repeats a purchase or cancellation.

## One key per intended purchase

`POST /verifications` and `POST /rentals` require `Idempotency-Key`: **8–128 letters, digits, underscores or hyphens**. Save the key and exact body before sending. A new key means a new purchase, not a retry. The required `maxPrice` is the maximum total customer charge in USD; use a decimal string with no more than two decimal places, such as `"1.50"`.

When a response is lost, call:

```http
GET /api/v1/developer/purchase-attempts/example_purchase_0001
```

The response contains `key`, `status`, `activationId`, `recoveryState`, `error` and `createdAt`. If an activation is available, read the corresponding order. A pending or ambiguous supplier result must be reconciled without issuing another purchase. A 404 does not justify creating a new key immediately: the first request may still be in flight. If retrying, use the same key and identical body.

For cancellations, read the order after an uncertain response. A missing or delayed response is not proof of a refund. Do not create your own wallet credits or retry supplier operations directly.

Read requests can be retried with bounded backoff. Fetch message pages using `totalPages`. Prefer customer webhooks for message delivery, with read requests for reconciliation.

[Documentation index](https://sms.red/docs/ai/index.md)
