Skip to main content
Every account Sente holds is backed by an identity, and every identity owns a real mailbox on sente.run. It receives what the third-party app sends — verification codes, security notices, invoices, replies from humans — and it can send as that address. This page covers the mailbox itself; for “block until the code arrives”, see Receive verification codes.

The address

An identity’s address is <local-part>@sente.run, and mail is live from the moment the identity exists.
  • Auto-provisioned (you called connect/register without an identityId): the local part is derived from the app’s hostname — https://github.com/logingithub@sente.run, with a short random suffix if that address is taken (github-x7k2@sente.run).
  • Chosen: POST /v1/identities with localPart. A taken address returns 409 unless you pass onConflict: "suffix".
Role addresses (support, admin, security, abuse, postmaster, and the rest of the RFC-2142 set) are reserved for Sente’s own mail and can’t be allocated — 409 LOCAL_PART_RESERVED. Only the exact word is reserved: support-bot is fine. Mail to an address with no matching identity, or to an identity you’ve deleted, is dropped.

List messages

Newest first, archived hidden, 50 by default.
The org-wide feed is REST-only: both SDKs and the CLI take an identity as a required argument. For a dashboard or an audit sweep, call GET /v1/messages directly and group by the identityId each message carries.

Read one message

A list row is already the full object, but you’ll usually fetch by id after a message.received webhook — that payload carries only the envelope, never the body.
Bodies live under parsed: text and html for inbound mail, plus messageId (the sender’s own Message-ID header, used for threading). Outbound rows carry { text, html, inReplyTo }.
Attachments are not exposed. Only the text and HTML parts are parsed out; there is no attachment download endpoint. And email bodies are untrusted input — never hand a raw body to an agent that holds tools or credentials.

Send

text, html, or both — at least one is required. One recipient per call; there is no cc, bcc, or attachment support.
Mail leaves as the identity’s own address, DKIM-signed on sente.run, and is persisted as an outbound message.

Reply in-thread

Pass the Sente message id of the inbound message you’re answering. Sente looks up that email’s original Message-ID and sets In-Reply-To and References, so the reply threads properly in the recipient’s client.
The inReplyTo id must belong to the same identity. If it doesn’t — or the original email carried no Message-ID — the mail still sends, just unthreaded. The recipient address is not derived from it either: set to yourself.

Delivery status

Outbound messages start at sent and are updated from the provider’s delivery events. Poll the message by id, or list with direction=outbound. Inbound messages have deliveryStatus: null.

Archive

Archiving is a dismissal, not a delete: the message stays fetchable by id, drops out of listings unless you pass includeArchived=true, and is never matched by messages/wait. Both calls are idempotent and return the updated message.
Archive/unarchive are REST-only — neither SDK nor the CLI wraps them yet. Archiving a message that a wait loop is expecting will make that wait time out; archive after you’ve handled it, not before.

React to new mail

Failure paths

Every identity sends from the same shared domain. Deliverability is a shared resource: one tenant sending unsolicited bulk mail gets the domain flagged, and a flagged domain means verification emails stop landing for everyone. Sending is for the account’s own correspondence — see the Acceptable use policy.

Next steps

Verification codes

Wait for an OTP or magic link and get just the value.

Webhooks

Push message.received to your service instead of polling.

Messages API

Every parameter, response, and error shape.