Sending

List outbound sent emails

Changed on

Returns a paginated list of OUTBOUND emails the caller's org has sent via /send-mail (and /emails/{id}/reply, which forwards through /send-mail). Includes every recorded attempt, including gate-denied attempts that the agent never called and rows still in queued state.

Under an address-bound agent connection credential, the list holds this agent's own sends plus delivered sends from other addresses in the org that name this agent in to, cc or bcc and have matching inbound delivery evidence at this agent. Pass from with the agent's own address to list only its own sends.

For inbound mail received at your verified domains, see /emails. There is no unified send/receive history endpoint; the two surfaces are intentionally separate because the underlying tables, statuses, and lifecycle differ.

Email bodies (body_text, body_html) are NOT included on list rows so a 50-row page can't balloon into a multi-MB response when sends are near the 5MB body cap. Use /sent-emails/{id} to fetch a single row with bodies, or cross-reference by client_idempotency_key if the caller already has the body locally.

get/sent-emails

Request

  • Base URL: https://api.primitive.dev/v1
  • URL: https://api.primitive.dev/v1/sent-emails
  • Auth: HTTP bearer

Query parameters

cursorstring

Pagination cursor from a previous response's meta.cursor field. Format: {ISO-datetime}|{id}

limitinteger

Number of results per page

status'queued' | 'submitted_to_agent' | 'agent_failed' | 'gate_denied' | 'unknown' | 'delivered' | 'bounced' | 'deferred' | 'wait_timeout' | 'scheduled' | 'canceled'

Lifecycle status of a sent_emails row. Possible values:

  • queued: pre-call INSERT; the outbound agent has not yet replied.
  • submitted_to_agent: agent accepted; queue_id is set.
  • agent_failed: agent rejected; error_code and error_message carry the reason.
  • gate_denied: a recipient-scope gate denied the send; the agent was never called. The gates array carries the denial detail. /send-mail returns 403 in this case so callers see the denial synchronously; /sent-emails additionally records the row for historical lookup, which is when this status appears in a listing.
  • unknown: terminal indeterminate; the on-box log poller couldn't classify the receiver's response.
  • delivered / bounced / deferred / wait_timeout: terminal delivery outcomes (see DeliveryStatus).
  • scheduled: created with a future scheduled_at and not yet executed; scheduled_at carries the pending execution time. Reschedulable via PATCH /sent-emails/{id} and cancelable via /sent-emails/{id}/cancel while in this status.
  • canceled: terminal; a scheduled send canceled before execution. canceled_at carries the cancellation time and nothing was dispatched.

Filter to rows in this status. Useful for polling queued rows that haven't transitioned, auditing gate-denied attempts, or listing only successful deliveries.

request_idstring uuid

Filter to the row matching a specific server-issued request_id. The /send-mail response surfaces request_id on every send; this lookup lets the caller find the historical row for a given live call without remembering its id.

idempotency_keystring

Filter to rows with the given client_idempotency_key. Multiple rows can share a key (a retry that hit the idempotent-replay path returns the same row, but a retry with a DIFFERENT canonical payload under the same key is rejected by /send-mail before the row is written, so duplicates are bounded).

date_fromstring date-time

Inclusive lower bound on created_at. 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.

date_tostring date-time

Inclusive upper bound on created_at. 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.

qstring

Literal case-insensitive substring filter over the subject, the retained plain-text body, the sender, and the To, CC and BCC recipients of each send. Matched verbatim: %, _ and \ are ordinary characters and do not act as wildcards, so a search for 10% finds the literal string 10% rather than everything beginning 10.

Leading and trailing whitespace is trimmed, and the result must be 3 to 500 UTF-16 code units. The three-character minimum is the search index's: a shorter pattern cannot be answered from the index and would scan the whole mailbox, so it is rejected rather than served as a request that times out.

Those bounds are deliberately NOT declared as minLength/maxLength. Both count Unicode code points on the value as sent, while the server trims first and counts UTF-16 code units, and the two disagree in both directions: two astral characters are 2 code points but 4 code units, so a declared minimum would reject a query the server accepts, and "<499 chars> " is 500 code points before trimming and 499 after, so a declared maximum would reject another. Declaring a bound the server does not enforce is worse than declaring none, because the client refuses locally and the caller never learns why. The server validates; a violation is a 400.

Recipients are matched one address at a time rather than against the serialized recipient list, so a query containing a quote, comma or bracket matches only where that character occurs inside an address. Bodies are searched only where the plain-text body was retained; HTML-only bodies are not searched.

Not served by every deployment. Where sent-mail search is not enabled the endpoint answers 503 with code sent_mail_search_unavailable, which callers should treat as a capability answer and fall back on rather than as an outage.

fromstring email

Exact case-insensitive sender mailbox filter. Returns only sends whose from address equals this value; it is not a substring match, so a partial mailbox matches nothing. Use q to search sender text loosely. Combines with every other filter, and unlike q it is served by every deployment.

Response

Page of sent-email summaries

successboolean required

Changes

    • info

      added the optional property /// to the response with the status

    • info

      removed the invalid_signup_code enum value from the / response property for the response status

    • info

      removed the invalid_signup_code enum value from the / response property for the response status

    • info

      removed the invalid_signup_code enum value from the / response property for the response status