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

# Errors, retries and pagination

> Diagnose requests without duplicating sends or exposing secrets.

All JSON responses include `message`. When present, `data` is an object. Collections use `data.items`; paginated collections add `page`, `pageSize`, `totalItems`, `totalPages`, `hasNextPage` and `hasPreviousPage` directly within `data`.

```json theme={null}
{
  "message": "Records retrieved successfully.",
  "data": {
    "items": [], "page": 1, "pageSize": 20,
    "totalItems": 0, "totalPages": 0,
    "hasNextPage": false, "hasPreviousPage": false
  }
}
```

Pages start at one, default to 20 items and allow at most 100. Requests and routes use camelCase JSON and lowercase route paths. Uppercase routes are rejected. Dates use ISO 8601 with an offset; billing periods use UTC.

| HTTP | Meaning | Action |
| - | - | - |
| 200 | Read/action succeeded | Inspect `data` |
| 201 | Resource created | Save returned ID |
| 202 | Durable asynchronous acceptance | Save ID and track status; not proof of delivery |
| 400 | Malformed input, validation or missing idempotency key | Fix input; optional `errors` maps fields to messages |
| 401 | Missing, expired, revoked or invalid credential | Check server configuration |
| 403 | Missing scope or denied organization/action | Request the proper grant |
| 404 | Missing resource or resource outside granted scope | Check project/environment/sender IDs |
| 409 | State conflict, stale version, insufficient funds/budget or changed idempotent payload | Resolve the stated conflict |
| 422 | Semantically invalid request | Correct content or dimensions |
| 429 | Rate limited | Honor `Retry-After`, then back off |
| 5xx | Provider/configuration or unexpected failure | Check service availability; retry cautiously |

Global limits currently allow 600 requests per minute per authenticated credential per API instance, plus stricter Verify limits enforced in PostgreSQL. Instance-local limits are not a distributed quota guarantee. 429 responses include `Retry-After: 60`; a daily Verify limit may require waiting longer. Avoid polling repeatedly when the limit window has not reset.

### Safe idempotent sends

For each logical message or verification send, generate and persist a unique `Idempotency-Key` before the first request. It must contain 1–128 printable non-space ASCII characters. Resend the **identical payload and same key** after an unknown transport result. The key is scoped to organization/project/environment and, for shared sends, service. Reusing it for different content returns 409.

Do not automatically retry creation/submission/rotation operations unless their own contract makes the operation safe. Template submission and uncertain provider outcomes require reconciliation. A successful but lost verification check response may already have consumed the code; bind and reconcile the login flow on your server rather than interpreting another check as a new success.

### Request diagnostics

Responses include a server-generated `X-Request-Id`. Record it with your internal operation ID, never the API secret or OTP. Use `GET /request-logs` with project/environment and optional `requestId`, `apiKeyId` or `statusCode` filters.

Seven-day request logs store route templates, method, status, duration, API-key identity and timestamp. They omit bodies, query strings, raw resource IDs in paths, authorization headers, OTPs and credentials. Invalid unauthenticated keys cannot be safely attributed to an organization and do not appear in this tenant log. Logging is best-effort; an observability write failure never reverses a durably accepted charge.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.