Skip to main content
POST
cURL

Authorizations

Authorization
string
header
required

JWT Bearer token obtained from authentication. Pass as: Authorization: Bearer

Body

application/json

Request body for sending an email with threading support

agentId
string
required

ID of the agent sending the email

Pattern: ^[cC][^\s-]{8,}$
to
string<email>[]
required

List of recipient email addresses (at least one required)

Minimum array length: 1
subject
string
required

Email subject line (max 998 characters per RFC 2822)

Required string length: 1 - 998
body
string
required

Plain-text body of the email

Minimum string length: 1
fromIdentityId
string

Optional EmailIdentity ID to send from. An agent has exactly one email identity, so the only valid value is that one — supply it to assert which address you expect to send as, or omit it and the agent's identity is used. Discover the ID via GET /agents/{agentId}/email-identities.

Pattern: ^[cC][^\s-]{8,}$
cc
string<email>[]

List of CC recipient email addresses

bcc
string<email>[]

List of BCC recipient email addresses

bodyHtml
string

Optional HTML body of the email

attachments
object[]

Optional file attachments. Max 25MB total across all attachments (after base64 decode for inline, after fetch for URL-source); max 20 attachments per email. Each entry provides either inline base64 content or a public url for server-fetch.

Maximum array length: 20
headers
object

Custom email headers as key-value pairs

metadata
object

Arbitrary key-value metadata to attach to the message

inReplyTo
string

The message this email replies to: either an RFC 5322 Message-ID (with or without angle brackets, e.g. from an inbound email's externalId) or an Anima message id (cuid). The reply joins that message's thread and emits In-Reply-To/References so external clients thread it too.

references
string[]

Explicit References chain (RFC 5322 Message-IDs, oldest first) emitted on the wire. If omitted on a reply, the chain is derived from the replied-to message automatically.

Response

200 - application/json

OK

Full message resource representation

id
string
required

Unique identifier of the message

Pattern: ^[cC][^\s-]{8,}$
agentId
string
required

ID of the agent that sent or received the message

Pattern: ^[cC][^\s-]{8,}$
inboxId
string | null
required

ID of the inbox this message belongs to — the inbox it was delivered to (inbound) or sent from (outbound). Null when no inbox backs the address: SMS/MMS/voice messages, and email sent from an email identity that has no inbox (such as a custom-domain identity added to an agent). Pass it to GET /messages?inboxId= to list one inbox's mail.

Pattern: ^[cC][^\s-]{8,}$
channel
enum<string>
required

Communication channel used

Available options:
EMAIL,
SMS,
MMS,
VOICE
direction
enum<string>
required

Whether the message was inbound or outbound

Available options:
INBOUND,
OUTBOUND
status
enum<string>
required

Current delivery status

Available options:
QUEUED,
SENT,
DELIVERED,
FAILED,
BOUNCED,
BLOCKED,
PENDING_APPROVAL
fromAddress
string
required

Sender address (email or phone number)

toAddress
string
required

Recipient address (email or phone number)

subject
string | null
required

Message subject line, or null for channels that do not support subjects

body
string
required

Plain-text content of the message

bodyHtml
string | null
required

HTML content of the message, or null if not available

extractedText
string | null
required

Plain-text body with the quoted reply chain and signature stripped — just what this sender actually wrote. Read this instead of body to avoid re-reading (and paying for) the whole thread on every message. Null when nothing was extracted: non-email channels, messages your agent sent, and mail received before this field existed — so extractedText ?? body is always correct. Best-effort and heuristic; body remains the verbatim source of truth. Known weak cases: forwards and bottom-posted replies have no separable 'new' part, so this returns the full body rather than nothing.

extractedHtml
string | null
required

HTML body with quoted reply chains removed. Same semantics as extractedText; bodyHtml stays verbatim. Quoting styles that mark the chain with a sibling element rather than wrapping it (Outlook) are not stripped here — extractedText still is.

headers
object | null
required

Raw message headers as key-value pairs, or null

metadata
object | null
required

Arbitrary metadata attached to the message, or null

threadId
string | null
required

Thread identifier for conversation grouping, or null

labels
string[]
required

Workflow labels on this message. Always contains exactly one of the system labels unread or read; may also contain archived, spam (the inbound spam verdict — see includeSpam on list/search), and any labels you add yourself. Stored lowercase, deduped, and sorted. Change them with PATCH /messages/{id}/labels.

inReplyTo
string | null
required

Message ID this message is replying to, or null

externalId
string | null
required

External identifier, or null. For email: the RFC 5322 Message-ID (bare, no angle brackets) — pass it as inReplyTo to reply in-thread. For SMS: the provider-assigned message id.

deletedAt
string<date-time> | null
required

When this message was moved to Trash, or null if it is live. Deleted messages are hidden from listings unless deleted is set to include or only, and can be brought back with POST /messages/{id}/restore. Nothing purges them.

sentAt
string<date-time> | null
required

Timestamp when the message was sent, or null if not yet sent

receivedAt
string<date-time> | null
required

Timestamp when the message was received, or null for outbound messages

attachments
object[]
required

File attachments associated with this message

createdAt
string<date-time>
required

Timestamp when the message record was created

updatedAt
string<date-time>
required

Timestamp when the message record was last updated