List inbound emails
Changed onReturns a paginated list of INBOUND emails received at your verified domains. Outbound messages sent via /send-mail are not included; this endpoint is the inbox view, not a unified send/receive history.
Supports filtering by domain, status, date range, and free-text search across subject, sender, and recipient fields.
For a compact text-table summary of the most recent N inbounds (no filters, no cursor pagination), the CLI ships primitive emails:latest as a one-line-per-email shortcut. It's TTY-aware so id columns are full UUIDs when piped, and a --json flag returns the same envelope this endpoint does. Use whichever fits the call site.
Request
- Base URLhttps://api.primitive.dev/v1
- URLhttps://api.primitive.dev/v1/emails
- AuthHTTP bearer
Query parameters
Pagination cursor from a previous response's meta.cursor field. Format: {ISO-datetime}|{id}
Number of results per page
Filter by domain ID
Lifecycle status of an INBOUND email (a row in the emails table). Distinct from SentEmailStatus, which describes the OUTBOUND lifecycle (the sent_emails table) and uses a different vocabulary because the lifecycles differ. Possible values:
- pending: the row was inserted at ingestion (mx_main) and has not yet completed the spam / filter / auth pipeline. Body and parsed fields are present; webhook delivery is not yet scheduled. Most rows transition out of pending within seconds.
- accepted: the inbound passed the policy gates and is queued for webhook delivery. The webhook_status field tracks the separate webhook-delivery lifecycle from this point.
- completed: terminal success. Webhook delivery attempted and acknowledged by every active endpoint, OR no endpoints are configured, so the row is durably archived.
- rejected: terminal failure at ingestion (spam, blocked sender, filter rule, malformed). The body and metadata are stored for auditing but no webhook fires and the row is not repliable.
See also webhook_status (separate enum tracking the webhook-delivery state machine) and SentEmailStatus (the outbound vocabulary).
Filter inbound rows by lifecycle status. See EmailStatus for what each value means. Note that the webhook delivery state is a SEPARATE lifecycle on the same row; filter by webhook_status semantics is not currently supported on this endpoint.
Search subject, sender, and recipient (case-insensitive)
Filter emails created on or after this timestamp. An ISO 8601 timestamp with Z or a numeric UTC offset (2026-10-02T00:00:00Z, 2026-10-02T00:00:00-04:00). An offset is read as the instant it names. A time with no zone, or a bare date, is rejected.
Filter emails created on or before this timestamp. An ISO 8601 timestamp with Z or a numeric UTC offset (2026-10-02T00:00:00Z, 2026-10-02T00:00:00-04:00). An offset is read as the instant it names. A time with no zone, or a bare date, is rejected.
Forward-tail cursor. Returns rows that became visible AFTER this cursor, oldest-first, so a caller can stream new inbound mail by re-passing the cursor from each response. Mutually exclusive with cursor (which pages history newest-first). Pass the meta.cursor from the previous since response; an empty page means caught up.
Long-poll: hold the request up to this many seconds waiting for new mail past since, returning as soon as any arrives (or an empty page when the wait elapses). Requires since. Omitted means no wait (returns immediately); the server treats an absent value as 0. NOT given an OpenAPI default on purpose: a default makes some generators (e.g. openapi-python-client) send wait=0 on every call, which then fails the wait requires since check for plain history listings.
Only return emails whose awaiting has this value. awaiting=you lists mail waiting on your reply. Combines with every other filter and with both cursor and since. The filter (either value, here, on search and as the awaiting: search term) matches delivered mail only: emails whose status is rejected are never returned by it. A rejected email (for example one refused because the organization is over its storage limit) was never delivered, so nobody can answer it and it is awaiting no one; its own awaiting field still reports the stored value, usually you. Whose turn it is in this email's conversation. A send counts as a reply unless its status is gate_denied, agent_failed, canceled (queued and scheduled replies count: they are committed to go). For an email with a thread_id: them when the thread's latest counted outbound send (by send created_at, including any counted reply to this email itself) is at or after the thread's latest inbound message (by received_at); otherwise you. For an email with no thread_id: them when it has at least one counted reply (reply_count > 0 for an API key), otherwise you. It is a thread-level fact: every email in a thread carries the same value, and it reflects sends made by any credential in the organization, including other agent connections. It changes without a new inbound message, for example when a reply is sent, a queued reply fails, a scheduled reply is canceled, or a message is deleted, and is always current when read.
Only return emails whose automated has this value. awaiting=you&automated=false lists mail from people that is waiting on your reply. Combines with every other filter and with both cursor and since. An inbound email is automated when any of these holds, decided once when it arrives: null_envelope_sender (an empty MAIL FROM, a bounce); no_identifiable_sender (no address in the envelope or From); own_address (a sender address is exactly one of the addresses the mail was delivered to; sharing a domain with the recipient is not enough, so a colleague or another agent in the organization is not automated); mailer_daemon (mailer-daemon@ or postmaster@ on any domain); auto_submitted (Auto-Submitted with any keyword but no, an empty one included); precedence (Precedence bulk, list, junk or auto_reply); list_unsubscribe (List-Unsubscribe present); list_id (List-Id present); auto_response_suppress (X-Auto-Response-Suppress asks for no automatic reply: All, OOF or AutoReply); failed_recipients (X-Failed-Recipients present, a bounce); report (a delivery, feedback or disposition report). Mail Primitive's own automatic responders decline to answer is always automated. The header rules only see headers captured at ingest, so older mail may lack them. This is loop and noise protection, not sender authentication.
Exact case-insensitive delivered recipient mailbox, applied before pagination. Combines with existing filters and cursors; does not search message text.
With true, leave out emails whose fyi is true. Combines with every other filter and with both cursor and since.
Only return emails whose from_verified (the From domain was authenticated on arrival; see the field) has this value. Combines with every other filter and with both cursor and since.
Extra parts on every row, comma-separated: body_text, body_html, headers, attachments. Reads a page of messages in one request instead of one detail read per row. Parts are withheld where the detail read withholds them. Each body field is cut to 64 KiB per row and a response carries at most 2048 KiB of body text, in page order; a cut or omitted body is named in truncated_fields. Unknown values are a validation_error.
Only return emails in this thread (the thread_id on an email or sent email). Combines with every other filter and with both cursor and since. Returns the same emails the list would return without it, narrowed to the thread, so an agent connection key still sees only mail delivered to its address.
With true, leave out emails whose muted is true. Combines with every other filter and with both cursor and since.
With true, search is a POSIX regular expression matched against the subject, sender and recipient (case-insensitive unless search_case_sensitive is true). At most 100 characters; nested quantifiers, groups of five or more alternatives and repeated range quantifiers are refused with 400. Needs a non-empty search; not with wait.
With true, search matches case exactly. Needs a non-empty search; not with wait.
With true, keep only emails whose subject, sender and recipient all fail to match search (an empty field counts as not matching). Needs a non-empty search; not with wait.
Only received messages of this kind: regular mail, a delivery status notification (dsn), a complaint, an auto_reply, or a tls_report, dmarc_report or dmarc_failure report.
With true, only emails whose content was discarded after delivery; with false, only emails that still have it.
Receiver presence mail: the presence probes sent to a connected agent and its answers. Left out by default for a connected-agent credential and listed by default for any other credential. true lists it, false leaves it out. Presence mail that inbound processing verified as presence on arrival expects no answer and does not count toward awaiting. Presence mail stored before that verification existed keeps the awaiting value it was stored with, so it can still count toward awaiting; include_presence=true, or any credential other than a connected agent's, still lists it. Combines with every other filter and with both cursor and since.
Response
Paginated list of emails
Changes
- warning
added the new
access_mode_unavailableenum value to the/response property for the response status - warning
added the new
access_mode_unavailableenum value to the/response property for the response status - warning
added the new
builtin_roleenum value to the/response property for the response status - warning
added the new
builtin_roleenum value to the/response property for the response status - warning
added the new
cleanup_incompleteenum value to the/response property for the response status - warning
added the new
cleanup_incompleteenum value to the/response property for the response status - warning
added the new
cli_access_refusedenum value to the/response property for the response status - warning
added the new
cli_access_refusedenum value to the/response property for the response status - warning
added the new
confirmation_requiredenum value to the/response property for the response status - warning
added the new
confirmation_requiredenum value to the/response property for the response status - warning
added the new
connection_owner_address_requiredenum value to the/response property for the response status - warning
added the new
connection_owner_address_requiredenum value to the/response property for the response status - warning
added the new
email_rule_author_onlyenum value to the/response property for the response status - warning
added the new
email_rule_author_onlyenum value to the/response property for the response status - warning
added the new
email_rule_compiler_unavailableenum value to the/response property for the response status - warning
added the new
email_rule_compiler_unavailableenum value to the/response property for the response status - warning
added the new
email_rule_conflictenum value to the/response property for the response status - warning
added the new
email_rule_conflictenum value to the/response property for the response status - warning
added the new
email_rule_not_compiledenum value to the/response property for the response status - warning
added the new
email_rule_not_compiledenum value to the/response property for the response status - warning
added the new
grant_forbiddenenum value to the/response property for the response status - warning
added the new
grant_forbiddenenum value to the/response property for the response status - warning
added the new
keep_refusedenum value to the/response property for the response status - warning
added the new
keep_refusedenum value to the/response property for the response status - warning
added the new
last_ownerenum value to the/response property for the response status - warning
added the new
last_ownerenum value to the/response property for the response status - warning
added the new
mailbox_not_claimableenum value to the/response property for the response status - warning
added the new
mailbox_not_claimableenum value to the/response property for the response status - warning
added the new
mailbox_shared_with_othersenum value to the/response property for the response status - warning
added the new
mailbox_shared_with_othersenum value to the/response property for the response status - warning
added the new
member_address_reservedenum value to the/response property for the response status - warning
added the new
member_address_reservedenum value to the/response property for the response status - warning
added the new
plan_requiredenum value to the/response property for the response status - warning
added the new
plan_requiredenum value to the/response property for the response status - warning
added the new
redeploy_failedenum value to the/response property for the response status - warning
added the new
redeploy_failedenum value to the/response property for the response status - warning
added the new
removal_failedenum value to the/response property for the response status - warning
added the new
removal_failedenum value to the/response property for the response status - warning
added the new
removal_timeoutenum value to the/response property for the response status - warning
added the new
removal_timeoutenum value to the/response property for the response status - warning
added the new
role_assignedenum value to the/response property for the response status - warning
added the new
role_assignedenum value to the/response property for the response status - warning
added the new
role_assignment_unavailableenum value to the/response property for the response status - warning
added the new
role_assignment_unavailableenum value to the/response property for the response status - warning
added the new
role_key_takenenum value to the/response property for the response status - warning
added the new
role_key_takenenum value to the/response property for the response status - warning
added the new
rotation_in_progressenum value to the/response property for the response status - warning
added the new
rotation_in_progressenum value to the/response property for the response status - warning
added the new
rotation_incompleteenum value to the/response property for the response status - warning
added the new
rotation_incompleteenum value to the/response property for the response status - warning
added the new
step_up_invalidenum value to the/response property for the response status - warning
added the new
step_up_invalidenum value to the/response property for the response status - warning
added the new
step_up_not_acceptedenum value to the/response property for the response status - warning
added the new
step_up_not_acceptedenum value to the/response property for the response status - warning
added the new
step_up_refusedenum value to the/response property for the response status - warning
added the new
step_up_refusedenum value to the/response property for the response status - warning
added the new
step_up_requiredenum value to the/response property for the response status - warning
added the new
step_up_requiredenum value to the/response property for the response status - warning
added the new
template_roleenum value to the/response property for the response status - warning
added the new
template_roleenum value to the/response property for the response status - warning
added the new
upstream_unavailableenum value to the/response property for the response status - warning
added the new
upstream_unavailableenum value to the/response property for the response status
This list may be incomplete.
- warning
- warning
added the new
agent_changedenum value to the/response property for the response status - warning
added the new
agent_changedenum value to the/response property for the response status - warning
added the new
agent_limitenum value to the/response property for the response status - warning
added the new
agent_limitenum value to the/response property for the response status - warning
added the new
already_memberenum value to the/response property for the response status - warning
added the new
already_memberenum value to the/response property for the response status - warning
added the new
directory_limitenum value to the/response property for the response status - warning
added the new
directory_limitenum value to the/response property for the response status - warning
added the new
invitation_acceptedenum value to the/response property for the response status - warning
added the new
invitation_acceptedenum value to the/response property for the response status - warning
added the new
invitation_changedenum value to the/response property for the response status - warning
added the new
invitation_changedenum value to the/response property for the response status - warning
added the new
invitation_pendingenum value to the/response property for the response status - warning
added the new
invitation_pendingenum value to the/response property for the response status - warning
added the new
invitation_sendingenum value to the/response property for the response status - warning
added the new
invitation_sendingenum value to the/response property for the response status - warning
added the new
invitation_unconfirmedenum value to the/response property for the response status - warning
added the new
invitation_unconfirmedenum value to the/response property for the response status - warning
added the new
invitations_pendingenum value to the/response property for the response status - warning
added the new
invitations_pendingenum value to the/response property for the response status - warning
added the new
member_changedenum value to the/response property for the response status - warning
added the new
member_changedenum value to the/response property for the response status - warning
added the new
project_changedenum value to the/response property for the response status - warning
added the new
project_changedenum value to the/response property for the response status - warning
added the new
recipient_changedenum value to the/response property for the response status - warning
added the new
recipient_changedenum value to the/response property for the response status
- warning