POST /v1/intake/email (signed by a mail provider, or with an API key). Ignored and refused emails are
tracked too, so your CRM can account for every message that came in, not only the ones that became jobs.
The email id
Each email gets an id likeem_3f1c0e9a6b2d4c8e1a7f5b90. It is stable: a redelivery of the same message (an
Email Worker retry, a provider pushing it again, a mailbox resync) is the same email, never a second one. The id
comes back:
- in the
X-Email-IDheader of everyPOST /v1/intake/emailanswer, and asemail_idin an ignored email’s body; - as
email_idin each row ofGET /v1/mailboxes/{id}/messages; - in a job’s
intake.email.email_id: the email that started the job (also in every job event); - in the
email.receivedwebhook.
The record
GET /v1/emails/{email_id} (jobs:read):
The body is never part of the record or of any event.
GET /v1/emails lists emails newest first, filtered by
mailbox_id, thread_id, tag, outcome (job, merged, ignored for any reason, one ignored:<reason>,
refused), sender, since and job_id, paged with cursor.
The raw .eml
GET /v1/emails/{email_id}/raw returns the message exactly as it was received, byte for byte, as
message/rfc822 with Content-Disposition: attachment. It is stored as job files are, encrypted with your
tenant’s own key.
store_raw_email is a mailbox setting, on by default:
PATCH replaces the mailbox’s whole settings: send the others you set too. An email posted with an API key
(no mailbox) keeps its raw message. Messages are capped at 64 MB on every path.
Threads
A deal arrives as a thread: the submission, internal forwards, questions back, replies that add a statement.GET /v1/emails/threads/{thread_id} lists every tracked email of the thread in the order they arrived, each
with its outcome and job:
job-2 with every document of the thread (job-1’s
superseded_by names it), and the forward brought nothing new. From a job, intake.email.thread_id is its
thread, and GET /v1/emails?job_id= lists the emails that point at it.
GET /v1/emails/threads/{thread_id}/raw downloads the thread’s kept messages as one mbox file (mboxrd), in
order. A thread id contains /; put it in the path as it is.
Tags
Tag emails with your own labels, e.g.client:lifetime or stage:funded. A tag is trimmed and lowercased, then
must be 1 to 64 of a-z 0-9 _ : -; an email has at most 20. Writing tags needs mailboxes:manage, reading them
jobs:read.
A mailbox’s
default_tags setting tags every email it receives, as it arrives:
email.tags, with the tags the email ended with). An invalid tag, or one
past 20, is refused with 422.
Erasure and retention
DELETE /v1/emails/{email_id}erases one email: its record, its raw.emland itsemail.receivedevents.DELETE /v1/emails/threads/{thread_id}erases every email of a thread the same way.DELETE /v1/jobs/{job_id}(andDELETE /v1/jobs?end_user_id=) erases, with the job, the emails that fed it: the emails whose job it is (the one that started it, those merged into it, those that arrived while it was the thread’s job), and the thread’s earlier emails carrying a document it holds (a reply’s job gathers the thread’s earlier attachments). So in the thread above, erasingjob-2erases all three emails, while erasing only the supersededjob-1erases the submission alone and leaves the reply and the forward withjob-2.- A tenant’s
retention_dayserases emails older than it, with their raw messages, as it erases old jobs.
jobs:delete and are in the audit log (email.delete, email.delete_thread, job.delete). Another tenant’s
email or thread answers 404.