Create an inbox
POST /v1/inboxes
Read as Markdown ↗POST /v1/inboxes
Requires a Claim-issued API key: Authorization: Bearer YOUR_CREDENTIAL.
Both names accept Unicode text up to 256 UTF-8 bytes after trimming, without control characters. Omitted, null and blank names mean no name at creation. Existing inboxes without names return null for both fields. Names need not be unique. Unknown fields are rejected.
Addresses are globally unique. hello, test, reviewer_chatgpt and prefixes beginning reviewer_chatgpt_ are reserved; retired addresses cannot be reused. No custom domains or allocated-address renaming are supported. To replace an address while keeping the old inbox during transition, see Change your agent's email address.
New creation returns 201 with the inbox object and Location: /v1/inboxes/{id}. 400 means invalid input. 409 covers unavailable addresses, the inbox cap and key conflicts. A definitive address_unavailable permits choosing another prefix; do not create accounts to evade a cap.
An inbox-cap failure has error.code: "inbox_limit_reached" and error.details containing allowance (the same shape as inbox_allowance), increase_request and policy_url. Request additional slots for another workflow or an address transition rather than retiring an inbox you still need. See Free and custom allowances.
Recover creation
Creation keys are scoped to the authenticated account across HTTP and MCP, independently of sending keys. Protection lasts 24 hours from successful allocation, without renewal. Keyed results add replayed and idempotency_expires_at. Initial creation returns 201 with replayed: false; a matching retry returns 200 with replayed: true and the original inbox ID. Both supply Location.
A replay returns the inbox's current state, not a frozen creation response. Later name edits are preserved. Retry with the original creation inputs, not those edited names. JSON property order is irrelevant; address-prefix case and surrounding whitespace, trimmed name whitespace, and absent/null/blank names normalize equivalently. Different validated inputs return 409 idempotency_conflict.
Deleting the inbox does not free an active key. A matching retry returns 409 idempotency_result_unavailable, never allocates a replacement and never restores the deleted inbox. Concurrent matching requests allocate only one inbox and consume one slot.
If creation's outcome is uncertain, reuse the original key and unchanged payload within 24 hours of your first request. Do not replace the key or choose another address to resolve uncertainty. Validation and allocation failures that definitely precede creation do not consume a key; an infrastructure error may follow successful creation.
After expiry, the key no longer protects a request. List inboxes and reconcile the intended address instead of blindly creating again. An existing or retired address remains unavailable, but that is not a replay result. Unkeyed creation is supported: another request for the same address conflicts rather than returning the original resource. If its response was lost, list inboxes before deciding what to do.
Request body
JSON object. Total UTF-8 request body limit: 4096 bytes.
Schema: CreateInbox
| Field | Required | Type | Meaning and constraints |
|---|---|---|---|
local_part | Yes | string | Trimmed and lowercased, then 1–64 ASCII letters, digits, hyphens or underscores with alphanumeric ends. Reserved, existing and retired addresses are unavailable. |
name | No | string or null | |
sender_name | No | string or null | |
idempotency_key | No | string | Retain a unique key, exact payload and first request time for this intended operation. Account-scoped protection lasts 24 hours without renewal. pattern: ^[A-Za-z0-9_-]{1,128}$ |
Unknown fields are rejected.
curl example
Replace resource-ID placeholders with returned IDs. Supply CHERAMI_API_KEY through your private shell environment.
Save the intended payload as a private request.json file and replace illustrative values. For an uncertain response, follow the operation-specific recovery rules.
{
"local_part": "my-agent",
"name": "Research",
"idempotency_key": "RETAIN_A_UNIQUE_CREATION_KEY"
}curl --silent --show-error --include --request POST \
"https://cherami.to/v1/inboxes" \
--header "Authorization: Bearer $CHERAMI_API_KEY" \
--header 'Content-Type: application/json' \
--data-binary @request.jsonResponses
HTTP 200
Matching replay: current resource or saved attempt, without another allocation or provider submission.
X-Request-ID: Support correlation ID, not an idempotency key.Location: Relative URL of the resulting resource.
Content type: application/json.
All of these schemas apply.
Part 1
Part 2
| Field | Required | Type | Meaning and constraints |
|---|---|---|---|
replayed | Yes | true | |
idempotency_expires_at | Yes | string | UTC service instant with milliseconds and Z suffix. format: date-time pattern: ^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z$ |
{
"id": "11111111-1111-4111-8111-111111111111",
"local_part": "my-agent",
"address": "my-agent@cherami.to",
"name": null,
"sender_name": null,
"created_at": "2026-10-01T00:00:00.000Z",
"replayed": true,
"idempotency_expires_at": "2026-10-02T00:00:00.000Z"
}HTTP 201
Successful operation; inspect resource state and outcome fields.
X-Request-ID: Support correlation ID, not an idempotency key.Location: Relative URL of the resulting resource.
Content type: application/json.
All of these schemas apply.
Part 1
Part 2
| Field | Required | Type | Meaning and constraints |
|---|---|---|---|
replayed | No | false |
HTTP 400
invalid_json: Send a valid UTF-8 JSON object, not an array or scalar.
invalid_inbox: Use supported inbox fields; editing requires at least one name field.
invalid_local_part: Correct the requested address prefix.
invalid_name: Correct the inbox, sender or recipient display name using the returned guidance.
invalid_idempotency_key: Use 1–128 ASCII letters, digits, hyphens or underscores.
X-Request-ID: Support correlation ID, not an idempotency key.
Content type: application/json.
HTTP 401
unauthorized: Provide a valid bearer credential. Use human-approved recovery if access is lost.
X-Request-ID: Support correlation ID, not an idempotency key.WWW-Authenticate:"Bearer"
Content type: application/json.
HTTP 404
not_found: Resource is absent or inaccessible to this account. Reply targets must be in the sending inbox.
X-Request-ID: Support correlation ID, not an idempotency key.
Content type: application/json.
HTTP 409
address_unavailable: Choose another address prefix; this address cannot be allocated.
inbox_limit_reached: Read error.details.allowance for occupied and remaining slots; request an increase if needed.
idempotency_conflict: The key belongs to different input. Recover with the original inbox and payload, not a replacement key.
idempotency_result_unavailable: The key was used but its inbox, draft or sent copy is unavailable. No replacement was created or submitted; do not bypass protection with a new key.
X-Request-ID: Support correlation ID, not an idempotency key.
Content type: application/json.
HTTP 413
body_too_large: Reduce the JSON request to the endpoint's body limit.
X-Request-ID: Support correlation ID, not an idempotency key.
Content type: application/json.
HTTP 415
unsupported_media_type: Send Content-Type: application/json.
X-Request-ID: Support correlation ID, not an idempotency key.
Content type: application/json.
HTTP 500
internal_error: Operation failed; a write may already have happened. Follow the operation-specific recovery below.
X-Request-ID: Support correlation ID, not an idempotency key.
Content type: application/json.
Schema: CreatedInbox
Keyed creation adds both replay fields. Replay returns the inbox's current names, not the initial snapshot.
| Field | Required | Type | Meaning and constraints |
|---|---|---|---|
id | Yes | string | Cherami resource ID, distinct from the RFC Message-ID. Use the returned value. |
local_part | Yes | string | |
address | Yes | string | |
name | Yes | string or null | |
sender_name | Yes | string or null | |
created_at | Yes | string | UTC service instant with milliseconds and Z suffix. format: date-time pattern: ^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z$ |
replayed | No | boolean | |
idempotency_expires_at | No | string | UTC service instant with milliseconds and Z suffix. format: date-time pattern: ^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z$ |
Schema: Error
| Field | Required | Type | Meaning and constraints |
|---|---|---|---|
error | Yes | object |
error fields
| Field | Required | Type | Meaning and constraints |
|---|---|---|---|
code | Yes | string | Programmatic error code. Handle unrecognized codes by status and operation-specific recovery. |
message | Yes | string | Human-readable context, not a stable string to match. |
Schema: InboxError
| Field | Required | Type | Meaning and constraints |
|---|---|---|---|
error | Yes | object |
error fields
| Field | Required | Type | Meaning and constraints |
|---|---|---|---|
code | Yes | string | Programmatic error code. Handle unrecognized codes by status and operation-specific recovery. |
message | Yes | string | Human-readable context, not a stable string to match. |
details | No | object |
details fields
| Field | Required | Type | Meaning and constraints |
|---|---|---|---|
allowance | Yes | InboxAllowance | |
increase_request | Yes | string | |
policy_url | Yes | string |
Schema: InboxAllowance
| Field | Required | Type | Meaning and constraints |
|---|---|---|---|
allowance | Yes | integer | minimum: 0 |
used | Yes | integer | minimum: 0 |
remaining | Yes | integer | minimum: 0 |
unit | Yes | "inbox_slots" |
HTTP conventions, errors and pagination · Download OpenAPI 3.1