cherami.
API referenceSending and allowance

Forward a message

POST /v1/inboxes/{inbox_id}/forward

Read as Markdown ↗

POST /v1/inboxes/{inbox_id}/forward

Requires a Claim-issued API key: Authorization: Bearer YOUR_CREDENTIAL.

Creates an ordinary sent message with the send outcomes and recovery contract. HTTP success can report rejected or unknown; accepted means provider acceptance, not delivery.

message_id selects a ready received or accepted sent message in the sending inbox. Missing, deleted, other-inbox and other-account sources return 404; unready or unaccepted sources return 409 reply_not_ready. A forward does not require an RFC Message-ID.

Supply message_id and nonempty to. Optional fields are cc, bcc, plain-text note, boolean include_attachments (default true), labels, and idempotency_key. Recipient, label and size limits are the same as explicit send. Forward recipients are explicit and are not automatically deduplicated.

The subject receives Fwd: unless it already starts with Fw: or Fwd:. The note precedes a forwarded header block containing From, available Date, Subject, To and Cc, never Bcc. Original text and HTML are retained, including quoted history and earlier attribution. HTML-only originals get a non-rendered plain-text alternative. A forward has no reply parent or inherited reply headers and starts a new Cherami conversation.

Attachments are included by default with their original bytes; embedded images retain their Content-ID relationships. Unsafe or missing filenames get safe transport names. Unusable MIME types become application/octet-stream. Setting include_attachments: false excludes all original files, including embedded images, so images referenced by the HTML may be unavailable. No attachment is silently removed to fit a limit. Missing expected content returns 503 content_unavailable; oversized forwards return 413 message_too_large, or a provider rejection if generated MIME exceeds its limit. An unusable original inline Content-ID returns 400 invalid_message. Retrieve the original later for unavailable content; explicitly exclude attachments or use an explicit send for a deliberately reduced message.

Excluding Bcc from generated headers does not redact anything already written in the original body. Review the original content before authorizing disclosure.

Recover a helper send

Save the operation, sending inbox, exact helper payload, key and first request time. Helpers share the account's sending-key namespace: changing between reply, reply-all, forward or explicit send conflicts. Omitted include_attachments and true are equivalent; omitted and empty notes are equivalent. Derived recipients, bodies and the current sender name do not change retry intent.

Within the 24-hour protection window, a matching retry recovers the reserved attempt before reading the source, even if the source or its files have since been deleted. It never derives a replacement message or submits again. Deleting the resulting sent copy instead returns 409 idempotency_result_unavailable. Current permissions and sending-inbox ownership still apply. The ordinary uncertainty and expiry rules apply unchanged.

Parameters

ParameterLocationRequiredTypeMeaning
inbox_idpathYesstringOwned Cherami resource ID returned by the API.

Request body

JSON object. Total UTF-8 request body limit: 8388608 bytes.

Schema: ForwardInput

FieldRequiredTypeMeaning and constraints
message_idYesstringReceived or accepted sent resource ID in this inbox. The source must have usable reply headers. pattern: ^[a-f0-9-]{36}$
toYesarray of MailboxmaxItems: 50 minItems: 1
ccNoarray of MailboxmaxItems: 50
bccNoarray of MailboxmaxItems: 50
noteNostringOptional plain-text introduction.
include_attachmentsNobooleandefault: true
labelsNoarray of LabelTrimmed, deduplicated and case-sensitive. Order is not significant. maxItems: 32
idempotency_keyNostringRetain 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.

{
  "message_id": "22222222-2222-4222-8222-222222222222",
  "to": [
    {
      "address": "recipient@example.com"
    }
  ],
  "note": "For your review.",
  "idempotency_key": "RETAIN_A_UNIQUE_SEND_KEY"
}
curl --silent --show-error --include --request POST \
  "https://cherami.to/v1/inboxes/INBOX_ID/forward" \
  --header "Authorization: Bearer $CHERAMI_API_KEY" \
  --header 'Content-Type: application/json' \
  --data-binary @request.json

Responses

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

SendReceipt

Part 2

FieldRequiredTypeMeaning and constraints
replayedYestrue
idempotency_expires_atYesstringUTC 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$
{
  "limited": false,
  "message": {
    "id": "33333333-3333-4333-8333-333333333333",
    "inbox_id": "11111111-1111-4111-8111-111111111111",
    "created_at": "2026-10-01T00:00:00.000Z",
    "recipient_count": 1,
    "status": "unknown",
    "provider_message_id": null,
    "error_code": null,
    "thread_id": "44444444-4444-4444-8444-444444444444",
    "in_reply_to": null,
    "labels": []
  },
  "outcome_persisted": true,
  "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

SendReceipt

Part 2

FieldRequiredTypeMeaning and constraints
replayedNofalse

HTTP 400

invalid_json: Send a valid UTF-8 JSON object, not an array or scalar.

invalid_message: Correct the send fields, recipients, reply ID, or attachments using the message's guidance.

invalid_name: Correct the inbox, sender or recipient display name using the returned guidance.

invalid_labels: Correct label names, changes, filter groups, or discovery prefix.

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.

Error

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.

Error

HTTP 403

operation_not_allowed: This account cannot send mail, delete mail, or delete inboxes. Contact support if unexpected.

recipient_not_allowed: The inbox’s sending rules block one or more recipients. Nothing was submitted or charged. Use allowed recipients or ask the human to review Sending rules; do not bypass them through another inbox.

  • X-Request-ID: Support correlation ID, not an idempotency key.

Content type: application/json.

Error

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.

Error

HTTP 409

reply_not_ready: A received reply or forward source must be ready; a sent source must have confirmed provider acceptance.

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.

Error

HTTP 413

body_too_large: Reduce the JSON request to the endpoint's body limit.

message_too_large: Reduce message content and attachments. Passing local checks does not guarantee generated MIME fits the provider limit.

  • X-Request-ID: Support correlation ID, not an idempotency key.

Content type: application/json.

Error

HTTP 415

unsupported_media_type: Send Content-Type: application/json.

  • X-Request-ID: Support correlation ID, not an idempotency key.

Content type: application/json.

Error

HTTP 429

outbound_limit_reached: Read quota, reason and sufficient_capacity_at. Waiting cannot fix message_exceeds_allowance; see sending recovery.

  • X-Request-ID: Support correlation ID, not an idempotency key.
  • Retry-After: Delay in seconds when supplied. Quota uses sufficient_capacity_at; absent when waiting cannot make the message fit.

Content type: application/json.

QuotaError

HTTP 503

content_unavailable: Expected stored content is unavailable. Retry the read later.

outbound_unavailable: Outbound operation failed and a send's outcome may be unknown. Recover using the original key and unchanged payload within its window, or inspect sent messages.

  • X-Request-ID: Support correlation ID, not an idempotency key.

Content type: application/json.

Error

Schema: SendReceipt

Inspect message.status even on HTTP 201. accepted is provider acceptance, not delivery. Preserve a known outcome when outcome_persisted is false; later reads may lag. Keyed receipts add replayed and expiry. Draft-association recovery adds replayed without requiring an expiry.

FieldRequiredTypeMeaning and constraints
limitedYesfalse
messageYesSentMetadata
outcome_persistedYesboolean
replayedNoboolean
idempotency_expires_atNostringUTC 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: SentMetadata

FieldRequiredTypeMeaning and constraints
idYesstringCherami resource ID, distinct from the RFC Message-ID. Use the returned value.
inbox_idYesstringCherami resource ID, distinct from the RFC Message-ID. Use the returned value.
created_atYesstringUTC 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$
recipient_countYesintegerminimum: 0
statusYes"accepted" or "rejected" or "unknown"
provider_message_idYesstring or null
error_codeYesstring or null
thread_idYesstring or null
in_reply_toYesstring or null
labelsYesarray of string

Schema: Error

FieldRequiredTypeMeaning and constraints
errorYesobject

error fields

FieldRequiredTypeMeaning and constraints
codeYesstringProgrammatic error code. Handle unrecognized codes by status and operation-specific recovery.
messageYesstringHuman-readable context, not a stable string to match.

Schema: QuotaError

FieldRequiredTypeMeaning and constraints
errorYesobject
quotaYesQuota
requested_recipientsYesintegerminimum: 0
reasonYes"temporary_exhaustion" or "message_exceeds_allowance"
sufficient_capacity_atYesstring or null
guidanceYesstring

error fields

FieldRequiredTypeMeaning and constraints
codeYes"outbound_limit_reached"
messageYesstring

Schema: Quota

FieldRequiredTypeMeaning and constraints
allowanceYesintegerminimum: 0
usedYesintegerminimum: 0
remainingYesintegerminimum: 0
next_capacity_atYesstring or null
next_capacity_amountYesintegerminimum: 0
window_hoursYes24
unitYes"recipient_deliveries"
increase_requestYesstring
policy_urlYesstring

Schema: Mailbox

FieldRequiredTypeMeaning and constraints
addressYesstringBare ASCII address, at most 254 characters, local part at most 64. No display-name header syntax. maxLength: 254
nameNostringUnicode name, trimmed; blank means unnamed. No control characters. At most 256 UTF-8 bytes after trimming. x-max-utf8-bytes: 256

Unknown fields are rejected.

Schema: Label

1–128 UTF-8 bytes after trimming. Well-formed Unicode without control characters; case-sensitive.

string. x-max-utf8-bytes: 128

HTTP conventions, errors and pagination · Download OpenAPI 3.1

On this page