API reference
Every Postfleet endpoint lives under /api/v1/ and authenticates with a bearer
pf_ API key:
Authorization: Bearer pf_...
A machine-readable OpenAPI 3.1 description of this surface is served at
/openapi.json. It documents shipped behavior only — every
path, method, status code, request field, and error code is transcribed from
the route handlers and kept honest by a drift test. Point your OpenAPI client,
code generator, or agent at that file.
The narrative guides — sending & idempotency, drafts & HITL, send lists, authentication, and webhooks — explain the semantics behind these endpoints.
Endpoints
Send
POST /api/v1/send— send an email. Optionalclient_idfor idempotent duplicate protection. On arequire_approvalmailbox the send is queued as a forced draft (202).
Messages
GET /api/v1/messages?mailbox_id=— list recent messages in a mailbox (can_read).GET /api/v1/messages/{id}— get one message with body, comprehension, and attachments (can_read).
Drafts
POST /api/v1/drafts— create a voluntary draft (can_send).GET /api/v1/drafts?mailbox_id=— list open drafts in a mailbox (can_read).GET /api/v1/drafts/{id}— get a draft (can_read).PATCH /api/v1/drafts/{id}— edit a draft's envelope (can_send).DELETE /api/v1/drafts/{id}— discard a draft (can_send).POST /api/v1/drafts/{id}/send— send a draft. Delivers (201) or, on arequire_approvalmailbox, promotes to the human queue (202).
Mailboxes
POST /api/v1/mailboxes— provision a mailbox. Account-plane: rejected for a mailbox-bound key.
Domains
POST /api/v1/domains— add a custom sending domain (paid plan).GET /api/v1/domains— list custom domains.POST /api/v1/domains/{id}/verify— re-check a domain's verification.
Error shapes
Errors are JSON. Client-facing failures with a stable machine-readable code:
403key_scope— the key cannot perform this action, or is scoped to a different mailbox, or is a mailbox-bound key on an account-plane route.403send_blocked_by_list— the recipient is blocked by a send list; carriesreason(block_match/no_allow_match),scope(account/mailbox), andlist_entry_idon a block match.409idempotency_conflict— theclient_idwas reused with a different payload.409idempotency_in_progress— a send with thisclient_idis still running; retry shortly.409approval_conflict— the draft is no longer editable / deletable / sendable (a concurrent transition moved it).502delivery_outcome_unknown— an ambiguous provider outcome; the send may or may not have gone out and is left for reconciliation.
Other statuses: 400 validation, 401 bad bearer, 402 quota exhausted, 404
not found (also returned for cross-account and cross-mailbox ids as
anti-enumeration), 422 suppressed recipient. Cross-account and cross-mailbox
object ids return 404 rather than 403 so a caller cannot enumerate ids it
does not own.