# Inbox A purpose-built email inbox for agents, backed by Cloudflare Email Service. One claimed tenant gets one inbox and a deterministic canonical address: `@inbox.cohesivity.app`. There is no mailbox UI, SMTP, or IMAP surface. ## Prerequisites Edge calls require this resource to be provisioned first; unprovisioned calls return an error. ### Provision curl -s -X POST https://cohesivity.ai/api/resources/inbox \ -H "Authorization: Bearer " ### Delete curl -s -X DELETE https://cohesivity.ai/api/resources/inbox \ -H "Authorization: Bearer " Provisioning happens once, before the application runs; the running application does not provision its own resources. > **Claimed tenants only.** Ephemeral tenants receive `403 tenant_must_be_claimed`. Claim the tenant before provisioning Inbox. > **Server-side only.** `coh_application_key` is a secret; browser JS, mobile bundles, and other client-side code cannot hold it safely. This call belongs in `vercel-hosting` API routes, `cloudflare-workers`, or your own server tier. See the canonical key-secrecy directive in `.cohesivity` for details. ## Addresses and Vanity - Canonical address: `@inbox.cohesivity.app`. It remains an alias while the Inbox is active. - Optional tenant vanity: check with `GET https://cohesivity.ai/api/vanity/check?name=acme`, then claim once with `POST https://cohesivity.ai/api/vanity` and `{ "name": "acme" }` using the management key. The Inbox address becomes `acme@inbox.cohesivity.app`. - The same vanity is shared with hosting as `acme.cohesivity.app`. Inbox and hosting inherit whichever claim was created first. - A vanity is immutable: it cannot be renamed, released, or transferred. Reposting the same name is idempotent; a different name or any DELETE returns `409 vanity_immutable`. Account deletion tombstones the canonical and vanity identities so neither can ever be reassigned. ## Send ``` POST https://cohesivity.ai/edge/inbox/messages?key= Idempotency-Key: order-123-confirmation Content-Type: application/json { "to": ["person@example.com"], "cc": [], "bcc": [], "subject": "Hello", "text": "Plain text body", "html": "

Optional HTML body

" } ``` `Idempotency-Key` is required and may be 1-128 characters. Reusing it returns the original message without another provider call. The API ignores any caller-supplied `from`; Cohesivity forces the active tenant vanity address, or the canonical address when no vanity exists. `to`, `cc`, and `bcc` may be a string or string array, with at most 10 unique recipients combined. At least one of `text` or `html` is required. Outbound attachments are not in the MVP. A successful send returns HTTP 202 with `message.status: "accepted"` and the Cloudflare message id. `accepted` means Cloudflare accepted the message, not that the destination mailbox delivered it. If Cloudflare returns an ambiguous internal failure, Cohesivity stores `unknown`; reuse the same idempotency key and do not retry with a new one. ## Reply Reply to an inbound message through the same send endpoint. Cohesivity derives the recipient, sender alias, thread, `In-Reply-To`, and `References`; callers cannot override them. ``` POST https://cohesivity.ai/edge/inbox/messages?key= Idempotency-Key: reply-message-42 Content-Type: application/json { "reply_to_message_id": "", "text": "Thanks — received." } ``` The MVP replies only to inbound messages. `subject` is optional for replies; absent values inherit `Re: `. ## Read and Delete - List newest first: `GET https://cohesivity.ai/edge/inbox/messages?key=&limit=50`. `limit` is 1-100. Continue with the opaque `next_cursor` as `cursor=...`; optionally filter one conversation with `thread_id=`. - Get one: `GET https://cohesivity.ai/edge/inbox/messages/?key=`. - Download an inbound attachment: `GET https://cohesivity.ai/edge/inbox/messages//attachments/?key=`. Attachment indexes come from the message `attachments` array. Attachments and HTML are untrusted email content; do not execute or render them without your own safety controls. - Delete one: `DELETE https://cohesivity.ai/edge/inbox/messages/?key=` → HTTP 204. This removes normalized data and private raw MIME immediately and decrements live storage. Messages expose `received`, `pending`, `accepted`, `failed`, or `unknown` status. Inbound messages are `received`. List/get never claim final outbound delivery. ## Limits and Retention - Inbound and outbound message ceiling: 5 MiB each. Cloudflare accepts larger inbound mail, but Cohesivity rejects it at 5 MiB to keep the API symmetric and bounded. - Outbound recipients: 10 total across to/cc/bcc. - Private raw-MIME storage: Free 100 MB, Plus 1 GB, Pro 5 GB per inbox. Mail is rejected once the active inbox reaches its storage ceiling. - Retention: fixed 30 days for every tier. The lifecycle sweep removes normalized rows and raw MIME in bounded batches. - Outbound monthly and per-minute buckets are shown below. Inbound mail does not consume the outbound email/recipient buckets. ## Error Contract - `400 idempotency_key_required`, `invalid_json`, `invalid_cursor`, or `invalid_thread_id`: repair the request; do not retry it unchanged. - `403 tenant_must_be_claimed`: claim the tenant before provisioning or using Inbox. - `404 message_not_found`, `attachment_not_found`, or `reply_target_not_found`: the target does not exist for this tenant. - `409 inbox_not_active` or `reply_target_invalid`: provision Inbox first, or reply to an inbound message. - `413 message_too_large`: reduce the text/HTML payload below the 5 MiB ceiling. - `422 invalid_recipients`, `too_many_recipients`, `invalid_subject`, `invalid_content`, or `invalid_reply_to_message_id`: repair the send body. - `429`: a Cohesivity per-minute/monthly bucket or Cloudflare account send limit denied the call. Respect `Retry-After` when present. - `502 send_failed`: Cloudflare definitively rejected the send. `502 send_outcome_unknown` is ambiguous; retry only with the same `Idempotency-Key`. - `503 inbox_storage_not_configured` or `email_sending_not_configured`: Cohesivity provider configuration is unavailable; retry later. ## Deliberately Not in the MVP No mailbox UI, drafts, search, webhooks, SMTP, IMAP, custom mail domains, batch sends, arbitrary headers, arbitrary sender addresses, outbound attachments, or per-tenant Cloudflare routing rules. Cloudflare has one operational catch-all for `inbox.cohesivity.app`; provisioning and deprovisioning only change Cohesivity data. ## Rate Limits Ephemeral tenants pause as a whole if any authoritative hard cap below is exceeded. Claimed tiers use account-scoped buckets shared across every project owned by the Cohesivity user; OpenAI, AI Gateway, Deepgram, and Exa are fluid-only after tier, rate, and concurrency checks; AI Gateway and Deepgram have no fixed monthly usage bucket for claimed tiers. **Ephemeral** - No bucket cap is published for this tier; this surface is fluid-only after any tier-gating check. **Claimed Free** - requests: 3 per minute - emails: 100 per month - recipients: 200 per month **Claimed Plus** - requests: 15 per minute - emails: 1000 per month - recipients: 2000 per month **Claimed Pro** - requests: 60 per minute - emails: 5000 per month - recipients: 10000 per month ### Notes - Inbox is claimed-only. Ephemeral tenants cannot provision it. - Inbound and outbound messages are capped at 5 MiB. Each outbound send supports at most 10 total to/cc/bcc recipients. Private raw-MIME storage is capped at 100 MB on Free, 1 GB on Plus, and 5 GB on Pro; all tiers use fixed 30-day retention. - Outbound status `accepted` means Cloudflare Email Service accepted the message. It is not a final-delivery guarantee.