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

# Limits, pagination, and retries

> Handle REST quotas, subscription states, durable idempotency, pagination, and uncertain provider outcomes.

## Rate limits and request IDs

Default limits are **300 requests/minute per API key** and **50,000 requests/day per workspace**. Inspect `/v1/me` and returned headers for the limits applying to your credential.

* `X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`: rate-limit window information.
* `Retry-After`: wait guidance when a limit is reached.
* `X-Request-Id`: request correlation when supplied; include it in support reports.
* `X-LinkedIn-Messages-Remaining`, `X-LinkedIn-Connections-Remaining`, `X-LinkedIn-Quota-Reset-At`: sender capacity on applicable outreach responses.

Early authentication/authorization refusals may not contain every header. Sender quotas are independent of API request limits. [Get sender quotas](/api-reference/endpoint/get-sender-quotas) before planning a batch; resets follow each sender's configured timezone.

## Pagination

| REST resource | Parameters | Defaults and bounds |
| - | - | - |
| Campaigns | `page`, `limit` | Page 1; limit 20; both 1–100 |
| Campaign leads | Required `campaignId`, plus `page`, `limit` | Page 1; limit 50; both 1–100 |
| Conversations | `continuationToken`, `limit` | Limit 20; max 100 |
| Conversation messages | Required `accountId`, plus `continuationToken`, `limit` | Limit 50; max 100 |
| Search/extraction results | `offset`, `limit` | Offset 0–10,000; default limit 100, max 500 |

Pass continuation tokens unchanged. These are REST bounds; MCP wraps pagination in opaque cursors and has its own smaller tool page-size limits. Never substitute an MCP cursor for a REST page/offset/token.

## Idempotent writes

Send `Idempotency-Key` on POST/PATCH requests. A UUID or another **1–255 visible ASCII character** value works. Reuse the same key for retries of the same method, path, body and API-key/workspace context.

```bash theme={null}
curl -X PATCH https://api.sendpilot.ai/v1/campaigns/CAMPAIGN_ID \
  -H "X-API-Key: $SENDPILOT_API_KEY" \
  -H 'Content-Type: application/json' \
  -H 'Idempotency-Key: pause-campaign-001' \
  -d '{"action":"pause"}'
```

* The replay window is **24 hours**. Stored results are returned with `Idempotent-Replayed: true`.
* Reusing a key with a different request returns **422 `IDEMPOTENCY_KEY_REUSED`**.
* An attempt still in progress returns **409 `IDEMPOTENCY_IN_PROGRESS`**.
* An uncertain or unavailable stored outcome can return **409 `IDEMPOTENCY_REPLAY_UNAVAILABLE`**. Check the operation's state rather than changing the key to force another attempt.
* Once execution is claimed, errors as well as successes can be retained. A crash or storage failure after a provider call does not make another execution safe.
* Requests refused before execution is claimed, such as authentication or rate-limit refusals, can be retried with the same key after resolving the cause.

Without the header, REST does not promise request deduplication. MCP's `idempotency_key` argument and automatic identical-call suppression are a separate interface.

## Subscription and workspace access

MCP and direct REST have separate entitlement checks. REST enforces workspace activity, effective scopes and the configured public-API entitlement policy.

When entitlement enforcement is active, an inactive workspace returns **403 `WORKSPACE_INACTIVE`**. A lapsed subscription permits reads but refuses ordinary writes with **402 `SUBSCRIPTION_INACTIVE`**. Pausing a campaign and setting a lead to `DONE`, `UNSUBSCRIBED`, or `IRRELEVANT` remain available to reduce outreach. These exceptions do not bypass authentication or scope requirements.

## Errors and uncertain outcomes

Inspect `statusCode`, `message`, and the machine-readable `code` when present. Validation messages may be arrays; some legacy errors do not include a code.

| HTTP status | Typical handling |
| - | - |
| 400 | Fix payload, URL, identifier or pagination validation |
| 401 | Check the key, expiry, revocation and creator membership |
| 402 | Check subscription/MCP entitlement for the interface being used |
| 403 | Check scopes, workspace permissions, eligibility or credits |
| 404 | Verify that the resource belongs to this workspace |
| 409 | Read the error code; resolve in-progress/conflicting/uncertain state |
| 422 | Do not reuse an idempotency key for a different request |
| 429 | Respect limit/reset guidance; sender and API limits differ |
| 500/503 | Use the request ID; retry only when the operation's outcome is known |

`DELIVERY_UNCONFIRMED` and `UPSTREAM_TIMEOUT` can mean a provider accepted an action without returning a conclusive result. Check the conversation before sending again. For sourcing, retain the returned job ID and poll its status/results; do not start another paid job merely because results are not ready.
