Skip to main content
Erdo sends email for you all the time: an agent mails a weekly summary, an event pipeline alerts your sales desk the moment a lead lands, an automation sends a digest. Each of those is recorded as it happens, and the sent email log is how you read that record back. This matters most when something is automated. An alert that fires at 2am is invisible unless you can go and look at it afterwards — and “did it actually go out, and what did it say?” is the first question anyone asks when a notification seems to have gone missing. The log answers it directly, scoped to your own organization, so you can show it in your own product rather than sending people to a mail provider’s dashboard.

What a record holds

Every audited send stores the recipient and display name, the subject, both the plain-text and HTML bodies exactly as they were sent, the delivery outcome, and the timestamps. The status walks the whole delivery story, not just our side of it. pending, sent, and failed are recorded at the moment of sending — sent means the mail provider accepted the message, which says nothing about arrival. The rest comes back from the provider as it happens: delivered (the receiving server took it), delayed (it is being deferred — a greylist, a full mailbox), bounced (it can never arrive), and complained (the recipient marked it as spam). A bounce or a failure also records why — “the recipient’s mailbox does not exist” is the difference between a status you can act on and a label — and a bounced or complained address is one your automations should stop mailing. That includes suppression: after a hard bounce or complaint the mail provider refuses further sends to that address on its own, and such a send records failed with the suppression as its reason rather than pretending it went out. Mail sent before delivery tracking existed stays at sent, so sent must never be read as “not delivered”. It also stores the address the message went out from, and the reply address that went with it. That is worth recording rather than assuming, because the sender is no longer fixed: an organization that has verified an email sending domain has its agent outreach sent from its own address, while Erdo’s product mail keeps coming from Erdo. Reading the from address back off the record is how you tell, for any given message, which one it was — and how you can see a domain take effect without waiting for someone to forward you a copy. It also stores context — a small set of key/value tags describing what the message was about. This is the part that makes the log genuinely queryable, and it exists because the recipient is very often not the subject. A new-lead alert is addressed to your sales desk, so filtering by recipient tells you nothing about which lead it concerned. Tag the send instead:
and “every email we’ve sent about Ana” becomes a real query rather than a substring search over subject lines that breaks the moment someone rewords a template. Context is never shown to the recipient.
Context values are flat text. Nested objects and arrays are dropped rather than stored, because the lookup that reads them back matches on flat key/value pairs — keeping them would advertise a query that could never work.

Reading the log

GET /v1/emails lists your organization’s mail, newest first, filtered by recipient (to), by time (since, an RFC 3339 timestamp), or by subject text (search). Bodies are omitted from the listing so a page of results doesn’t drag a page of HTML documents with it.
To filter by context, use POST /v1/emails-query — a query string can’t carry a key/value map, so the structured probe travels in a JSON body. The probe is a containment match: name only the keys you care about and rows carrying those plus others still match.
GET /v1/emails/{emailID} returns one message in full, including both bodies as they were sent. Listings report a total alongside the page, so you can page without having to discover the end by requesting an empty result. Agents in the product read the same log with the list_sent_emails tool, so “did the follow-up to that lead go out?” is a question you can ask in chat — the agent checks the record rather than its own memory, which also covers sends made by automations and other conversations.

Tagging what you send

The send_email action takes an optional context object, wherever you invoke it — from an agent, from a script.run step on an event pipeline, or from a scripted job:
It costs nothing to set and it is the difference between a log you can search and one you can only scroll. Set it whenever the recipient isn’t the subject of the message. Mail sent before context existed, and mail from senders that don’t set it, simply carries an empty context — treat it as optional on read, never as a guarantee.

Access

The log is scoped to the organization of the caller, enforced in the query itself. Requesting a message id belonging to another organization returns not found — identical to an id that doesn’t exist, so the endpoint can’t be used to probe for someone else’s mail.

Inboxes

The other direction — an address Erdo can receive at.

Event pipelines

Where lead-arrival alerts are usually sent from.

Email sending domains

Send outreach from your own domain instead of Erdo’s.