Supermail
API reference

Fetching content

Raw message and attachment bytes flow only through the authorized content lane of client-owned mail replication.

Events are thin change notifications: they identify messages and their mailbox occurrences but carry no metadata, content, or content handles (see Data model). Raw message and attachment bytes are served only through the content lane of client-owned mail replication (RFC 18), to a DUCS Consumer with an authorized, currently active mail-replication stream.

Gateway has exactly two content HTTP routes:

RoutePurpose
POST /gateway/content/v1Download: the bounded, framed content lane described below
POST /gateway/contentUpload: staged RFC 5322 bytes for drafts and submissions

Why not JSON-RPC

Content is the one place the API moves opaque bytes rather than a typed message. Putting a possibly multi-megabyte body into a JSON-RPC result would mean base64 (≈33% larger, buffered whole) inside the envelope. The content lane instead streams bounded binary frames, so neither Gateway nor the client needs to hold a complete body in memory. Supermail stores none of the bytes; Sync reads them from the provider for each request.

The content lane

POST /gateway/content/v1
Authorization: Bearer <access_token>
traummail-content-request-nonce: <32 bytes, hex>
traummail-content-request-digest: <32 bytes, hex>

<binary ContentRequestV1>

The request body is one binary ContentRequestV1 of at most 4 KiB. It names:

  • the protocol revision (1) and a fresh 32-byte request nonce;
  • the mail-replication stream id;
  • the Mail/1 message id and, for a single MIME part, an optional attachment id;
  • the message's content locator: the opaque content reference and content_revision exactly as replicated in the Mail/1 relation.

The two headers must repeat the request's nonce and digest. The bearer must authorize the exact current active stream named in the request. Gateway checks that before it opens any provider read and keeps rechecking the authority while bytes flow; losing it ends the response without a result frame.

Use @traummail/gateway-client rather than building requests by hand: its content facade opens the carrier, and @traummail/replication-sdk verifies the frames. The V1 content lane is currently implemented for Gmail only.

Response

The response has Content-Type: application/vnd.traummail.content-v1, Cache-Control: no-store, no-cache, private, and a traummail-content-open header carrying the base64url-encoded open result:

StatusOpen result
200 OKAccepted. The body is a sequence of data frames followed by one result frame.
400 Bad RequestMissing correlation headers, or refused as an invalid request (including a nonce or digest that does not match the body).
403 ForbiddenRefused: the stream is not currently authorized for this bearer.
429 Too Many RequestsRefused: capacity, with an optional retry-after in milliseconds.

Each data frame carries at most 256 KiB, a response carries at most 8,192 data frames and 2 GiB in total, and one request may run for at most 30 minutes. The final result frame reports success or a failure reason (content changed, content unavailable, provider failure, object too large, or deadline exceeded) together with the data-frame count, total length, and body digest the client verifies. A response that ends without a result frame is incomplete and must be discarded.

Transport

The V1 lane carries provider plaintext and relies on TLS. It does not use DUCS payload encryption. Public traffic must arrive through a trusted secure edge; only direct loopback requests without forwarding headers may use cleartext. Anything else is refused with 421 Misdirected Request.

On this page