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

# Conventions

> Envelopes, pagination, rate limits, and error shapes — consistent across every endpoint.

## Response envelope

Successful responses wrap the payload in `data`, with `meta` present when there's pagination:

```json theme={null}
{ "data": [ … ], "meta": { "pagination": { "limit": 50, "offset": 0, "nextOffset": 50 } } }
```

Errors are flat:

```json theme={null}
{ "error": "validation_failed", "reason": "from must be an ISO date (YYYY-MM-DD)" }
```

## Pagination

List endpoints take `limit` (default 50, max 200) and `offset`. When a page comes back full, `meta.pagination.nextOffset` tells you where to continue; when it's `null`, you've reached the end.

## Amount sign convention

Bank transaction amounts use the banking convention throughout: **positive = money out (expense), negative = money in (income)**. Financial statements use normal accounting presentation.

## Dates

All dates are ISO `YYYY-MM-DD`. Transaction queries default to the last 30 days when no range is given.

## Rate limits

Limits apply per API key, in three buckets:

| Bucket  | Applies to                                        | Burst | Sustained  |
| ------- | ------------------------------------------------- | ----- | ---------- |
| Reads   | List and detail `GET`s                            | 120   | 3,600/hour |
| Reports | Trial balance, statements, health score           | 20    | 240/hour   |
| Writes  | Pushing accounts and transactions, recategorizing | 60    | 240/hour   |

A `429` includes `retryAfterSeconds` in the body and a `Retry-After` header.

## Idempotency

Pushed transactions are idempotent: supply your own `id` per transaction, or omit it and Cherry derives a stable identity from date, amount, and description. Re-sending the same batch never creates duplicates.
