cherami.
API reference

Errors, limits, and pagination

Interpret failures, avoid unsafe write retries, and traverse live paginated results.

Read as Markdown ↗

Error format

Application errors use:

{"error":{"code":"not_found","message":"Resource not found."}}

Use error.code for programmatic handling and read message for context. Include the response's X-Request-ID in a problem report. It is not an idempotency key and does not make retries safe. Platform-generated failures may not have this format or header.

HTTP statusInterpretation
400Invalid input, phrase, limit, or cursor. Correct the request.
401Missing or invalid bearer credential. A Bearer challenge is returned.
404Resource is missing or unavailable to this account; reply targets must also belong to the sending inbox.
409Unavailable inbox name, reached inbox cap, protected inbox, or unusable reply target. Read the code/message.
413Request or message is too large.
415JSON content type required.
429Signup/claim rate limit or insufficient sending quota. Respect Retry-After when supplied.
500, 503Service or content failure. A failed write response does not always mean nothing happened.

A sending 201 can report rejected or unknown. A received-detail 200 can report unfinished or failed parsing. HTTP success is not a substitute for checking resource state.

Retry by operation

Reads may be retried with bounded backoff. Deletion retries are safe and can return 202 or 404.

If allocation's response is lost, list inboxes before retrying. If signup delivery is uncertain, ask the human to check their email instead of repeatedly requesting approval. Lost claim responses require human-approved recovery. Lost sends and feedback can have unknown outcomes: repeating POST can create duplicates. Inspect sent resources and seek help rather than blindly repeating writes.

Pagination

Received lists, sent lists, thread lists, and thread detail accept limit (integer 1–100, default 20) and return next_cursor (string or null). Stop when it is null. Treat cursors as opaque, URL-encode them, and send them as cursor on the same resource URL:

GET /v1/inboxes/INBOX_ID/messages?limit=20&cursor=URL_ENCODED_CURSOR HTTP/1.1
Host: cherami.to
Authorization: Bearer YOUR_CREDENTIAL

Do not move a cursor between inboxes, list types, or thread URLs. Received and sent lists are newest-first; thread lists are most-recent-activity first. Thread detail starts with the newest page but orders messages chronologically within each page. Subsequent pages are older.

Pagination is a live view, not a snapshot. New arrivals, conversation changes, and deletions can alter results. Keep handled message IDs for polling, and refresh from the first page to find new activity.

Limits

ResourceLimit
Ordinary inbox allowance2 per account; returned inbox_limit is authoritative.
Ordinary sending allowance25 recipient-deliveries/account/rolling 24 hours, shared across inboxes.
Incoming email25 MiB including MIME-encoded attachments.
Outgoing email5 MiB including generated MIME and attachments.
Outbound request JSON8 MiB.
Outbound recipients50 combined To/Cc/Bcc entries.
Outbound attachments32; see field limits.
Outbound subject998 UTF-8 bytes, no control characters.
Feedback JSON20 KiB total; no submission-rate limit.
Other JSON requests4,096 bytes.
Signup requests10/IP/hour and 3/human email/hour.
Claim attempts10/IP/15 minutes.
Approval link / phrase12 hours from issuance / 6 hours from confirmation.
Paginated resultsDefault 20, maximum 100 per page.

Unknown, unregistered, and retired inbox addresses reject incoming mail. Allowance requests remain available when outbound capacity is exhausted.

On this page