> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.getsinbad.com/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.getsinbad.com/_mcp/server.

# Limits and limitations

> Rate limits, size limits, timings and idempotency rules, plus the known limitations to plan for before you go live.

This page is the single reference for numeric limits. Other pages link here instead of repeating them.

## Rate limits

| Call                                                                          | Limit                   | Scope                               |
| ----------------------------------------------------------------------------- | ----------------------- | ----------------------------------- |
| `POST /v1/sessions`                                                           | 60 per minute (default) | Your partner                        |
| `POST /v1/sessions`                                                           | 5 per minute (default)  | Each customer                       |
| `POST /v1/offers/best` and `POST /v1/trade-breakdowns`                        | 60 per minute           | Each customer, shared by both calls |
| Webhook create, update, delete, test, rotate and replay                       | 60 per minute           | Your partner                        |
| `POST /v1/webhooks/{webhookId}/test` and `.../deliveries/{deliveryId}/replay` | 5 per minute            | Each endpoint                       |
| `POST /v1/webhooks/{webhookId}/rotate-secret`                                 | 1 per minute            | Each endpoint                       |

When a limit is exceeded, the response is `429 RATE_LIMITED` with `details.retryAfter` and a `Retry-After` header, both in seconds. Wait that long. Do not retry in a tight loop.

**Sessions.** Session creation uses per-partner and per-customer quotas. The defaults are 60 and 5 per minute. Sinbad can configure different values for your partner, so confirm them during onboarding. Only a session that is actually created consumes quota. Requests with invalid credentials do not. Cache each customer's session token until shortly before it expires.

**Offers and breakdowns.** Offer searches and breakdown creation share one limit for each customer. Three details affect how you count:

* A repeated call with the same `Idempotency-Key` still counts toward the limit.
* Sinbad checks the request body first and the limit second.
* Sinbad checks the `Idempotency-Key` header after the limit, so a request with a missing or malformed key still counts toward the limit.

**Webhooks.** Only successful calls count. A failed rotation does not count toward the rotation limit, and a replay of an earlier request with the same `Idempotency-Key` does not count either.

## Size limits

| Item                                       | Limit                                                                                        |
| ------------------------------------------ | -------------------------------------------------------------------------------------------- |
| Most JSON request bodies                   | 16 KiB (16,384 bytes)                                                                        |
| Proof of payment uploads and chat messages | 5 MiB of JSON                                                                                |
| Image (PNG or JPEG)                        | 3 MiB decoded, sent as base64 text of at most 4,194,304 characters, without a `data:` prefix |
| Chat text                                  | 2,000 characters                                                                             |
| Webhook endpoints per partner              | 5                                                                                            |
| Webhook payload                            | 64 KiB (65,536 bytes)                                                                        |
| Webhook delivery timeout                   | 10 seconds                                                                                   |

A larger request body returns `400 VALIDATION_ERROR`. Registering a sixth webhook endpoint returns `409 CONFLICT` with `details.kind: "ENDPOINT_LIMIT"`. See [Payment proof](/payment-proof) and [Chat and images](/trade-chat).

## Timings

| Item                                              | Duration                                                                                       |
| ------------------------------------------------- | ---------------------------------------------------------------------------------------------- |
| Customer session                                  | 86,400 seconds (24 hours). It cannot be refreshed. Create a new session for the same customer. |
| Breakdown signing window                          | 300 seconds (5 minutes) from creation. `expiresAt` shows the deadline.                         |
| Transaction finality                              | A fixed number of confirmations, shown in `transaction.requiredConfirmations`.                 |
| Idempotency keys for webhook calls and breakdowns | Kept for 24 hours.                                                                             |
| Webhook retries                                   | Up to 12 attempts or 24 hours, whichever comes first.                                          |

Trade updates and webhooks can arrive later than the chain confirmation. Sinbad does not guarantee a delivery latency. See [Sign and track transactions](/transactions).

## Idempotency

An `Idempotency-Key` must match `^[A-Za-z0-9_-]{8,128}$`.

| Required on                                                                                                                       | Not used on                                                                                                                                               |
| --------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `POST /v1/trade-breakdowns`, `POST /v1/trade-breakdowns/{breakdownId}/approval`, `POST /v1/transactions` and every webhook change | Session creation (every call creates a new session), trade actions, chat messages, proof uploads, saved payment methods, and fee or configuration changes |

* Sending the same key with the same body returns the first result.
* Sending the same key with a different body returns `409 CONFLICT`. Use a new key when you change the request.
* A chat message sent twice appears twice.
* An identical proof upload returns the existing matching receipt. After an uncertain result, read the current proof before you change it.

See [Errors and recovery](/errors) for how to retry each status.

## Webhook checks on your side

Sinbad signs each webhook delivery with a timestamp. Sinbad does not enforce the following two rules for you, so build them into your receiver:

* Reject a timestamp more than 5 minutes away from your own clock.
* Keep the IDs of the events you have processed for at least 30 days, and ignore repeats. Delivery is at least once.

See [Webhooks](/webhooks).

## Trade statuses you will not see yet

The API lists `PENDING`, `FUNDING_FAILED` and `FUNDING_EXPIRED` as trade statuses, but they are reserved and Sinbad does not produce them today. A trade first appears as `CREATED`, once the escrow is funded and confirmed. Before that, follow the breakdown, which shows `AWAITING_FUNDING` and then `CONFIRMED` or `EXPIRED`.

The `includePending` query parameter on the trade list is accepted for future use. Today it only changes the sort order. Build your status handling to accept the reserved values anyway. See [Trade lifecycle](/trades).

## One open trade per side

A customer can have one open BUY and one open SELL at a time. The rules for creating, replacing and releasing them are in [Offers and breakdowns](/offers-quotes#one-open-trade-per-side).

## Known limitations

* **Delayed status.** Trade updates and webhooks can lag the chain confirmation and arrive out of order. Track existing transactions, deduplicate events, and reconcile current state by reading the trade.
* **Receiving details on a SELL.** A funded trade in `CREATED`, `PAID` or `DISPUTED` returns the customer's selected receiving-account snapshot when you read it. Lists and webhooks include only its display label.
* **Deleting a customer is permanent.** After `DELETE /v1/partner-users/{partnerUserId}`, that `partnerUserId` can never get a session again. Trade history is kept. The customer's wallet, email address and phone number can be used by a new customer.
* **Webhook availability.** Confirm webhook delivery for your environment. Register and verify an endpoint subscribed to each event type you need. A queued test alone does not prove delivery works.
* **One wallet per customer.** The wallet is fixed at the first session. A session request with a different wallet or chain returns `409 CONFLICT`.
* **Merchant actions are outside this API.** On a SELL, the merchant marks the trade paid. On a BUY, the merchant releases. Both happen in Sinbad's merchant tools, and you see them as status changes. Sinbad does not guarantee how quickly merchants act.
* **Webhooks leave out private data.** Payloads do not include payment account details, proof files or contact data. Read them through the API. Chat message text is included.
* **No replay of earlier events.** Endpoint creation, verification and subscription changes determine which events you receive. Do not expect events from before your subscription. Reconcile current trades through the API.
* **Hash-only reports skip the balance check.** If you report a transaction by hash instead of sending signed bytes, Sinbad does not run its gas balance check. Sending the signed bytes is the recommended path.
* **Fee draft precision.** `upperUsd` and `FLAT_USD` amounts allow at most six decimal places. More returns `400 VALIDATION_ERROR`.
* **Fee publication needs your manager wallet.** `POST /v1/partner/fees/publish` only prepares a transaction. You send it from your registered manager wallet and pay its gas. The new schedule applies after it confirms.
* **Screening and verification are yours.** Location screening is off in the current phase, so blocked-country settings do not stop a customer from trading. Sinbad does not verify your customers' identity. You are responsible for both.