Skip to main content

Sending

Sending onto an existing thread

Pass thread_id and the message joins that conversation — no inbound message required. This is how an agent chases something it promised last week:
This is the capability most email-for-agents setups lack. An agent limited to replying inside an inbound webhook can only ever react; one that can open its own turn on a thread can actually follow up.

Replying

Recipients are derived from the parent message, so to is optional. By default the reply goes to the parent’s Reply-To (falling back to its From). Pass reply_all: true to include everyone on the original to and cc, minus the inbox itself. There is no cap on replies per conversation.

Forwarding

The original message is quoted beneath your note.

Reading messages

/raw returns the original MIME source, byte for byte, when it was retained.

The message object

Give your model extracted_text, not text. text is the body exactly as it arrived, which on a mature thread is mostly the conversation quoted back at you — it burns context and tempts the model into answering a message from two weeks ago.

Labels

PATCH /v0/inboxes/{inbox_id}/messages/{message_id} sets labels. The service applies a few itself: The auto-reply label is the one to check before your agent answers. Replying to an out-of-office generates another out-of-office, and two automated systems will happily do that to each other for as long as you let them.

Threads

Fetching a single thread includes its messages array in order, which is what you want when assembling context for a model.
participants has sub-address tags stripped, so [email protected] appears as [email protected] and a thread does not look like it has a new participant every time someone replies.

Searching

Full-text search across the messages in one inbox. q is required; omitting it returns 422.

How threading works

Getting a reply onto the right conversation is the hard part of agent email, and it drives the design. Two obvious signals are both unreliable. Message-ID is assigned by the sending provider, and some providers — Cloudflare included — refuse to let you set it and do not report the one they chose, so a sent message cannot always contribute its own id to the chain. Subject and References get rewritten, stripped or dropped by real mail clients. So resolution runs in layers, strongest signal first:
1

Reply-To thread token

Outbound mail carries Reply-To: [email protected]. The +tag routes to the same inbox, so it costs no extra DNS or configuration, and it survives any subject edit. The tag is HMAC-signed, so a guessed or tampered token is rejected rather than filing mail onto someone else’s thread.
2

In-Reply-To and References

Matched against stored message ids, for clients that preserve them.
3

Normalized subject plus participant overlap

Within a time window. Re: Fwd: RE: Invoice normalizes to invoice.
4

New thread

If nothing matches, a new thread is created rather than guessing.
The message.received event carries a matched_by field naming which layer resolved it (token, references, subject or new), so a threading problem is diagnosable from your event log rather than being a mystery. It travels on the event, not on the stored message.
Setting reply_to yourself replaces the thread token, and drops resolution to the weaker layers. Only override it when you have a specific reason, and expect threading to get less reliable when you do.