MailFlatDocs
Documentation/API References/Web / Session API

Web & Session API

The endpoints the web interface itself uses. Authenticate with a session token, or with a single inbox's own key.

Two ways to authenticate

HeaderScopeWhere it comes from
Authorization: Bearer <token>The whole accountReturned by login/verify, what the browser uses
X-API-Key: mf_…One inbox onlyThe 🔑 button in that inbox's header
Account keys do not work here
mf_live_… keys belong to the /api/v1 agent API. On these paths use a session token or the per-inbox key. Mixing them is what produces a confusing 401 on an otherwise valid key.

Endpoints

Authregister · verify · login
Method & pathBodyReturns
POST /api/auth/register{ email, password, username?, full_name? }Sends a 6-digit code to the address
POST /api/auth/verify{ email, otp }{ token, user }
POST /api/auth/login{ identifier, password }A second-factor code, then { token, user } on verify
identifier accepts either the username or the email address.
Inboxescreate · list · burn · delete
Method & pathBody / queryNotes
POST /api/inboxes{ prefix, name?, group_name?, retention_hours?, subdomain?, domain_id? }prefix is required here (1–50 chars). Encrypted automatically when the account has E2E on.
GET /api/inboxes?agent=1 | ?agent=01 = agent pool only, 0 = human pool only, omitted = both
POST /api/inboxes/{addr}/burnDeletes every message but keeps the address alive
DELETE /api/inboxes/{addr}Releases the address itself, permanently
Mailread · latest · tag filter · mark read · delete · send
Method & pathBody / queryNotes
GET /api/inboxes/{addr}/emails?tag=promoEach item carries id, from, subject, body, otp_code, is_read, direction, plus links, headers, attachments (metadata only — the bytes come from the attachment endpoint below) and spam (SpamAssassin score, threshold and the rules that fired; null means not scanned, which is not the same as clean)
GET /api/inboxes/{addr}/emails/latestNewest message, or { email: null } when the inbox is empty
POST /api/inboxes/{addr}/emails/{id}/readMarks one message read
DELETE /api/inboxes/{addr}/emails/{id}Deletes one message
GET /api/inboxes/{addr}/emails/{id}/attachments/{aid}The attached file itself. On an encrypted inbox it returns the envelope instead — the server cannot open it.
POST /api/inboxes/{addr}/send{ to, subject?, body?, html? }Sends from this address, DKIM-signed. Counts against your monthly allowance.

Working examples

# every message in an inbox
curl https://mailflat.net/api/inboxes/you@a7f2c.mailflat.net/emails \
-H "Authorization: Bearer <token>"
# → { "emails": [ { id, from, subject, body, otp_code, is_read }, … ] }
# newest message only, the OTP polling call
curl https://mailflat.net/api/inboxes/you@a7f2c.mailflat.net/emails/latest \
-H "Authorization: Bearer <token>"
# filter by tag (plus-addressing: you+promo@…)
curl "https://mailflat.net/api/inboxes/you@a7f2c.mailflat.net/emails?tag=promo" \
-H "Authorization: Bearer <token>"
# the same call with that inbox's own key
curl https://mailflat.net/api/inboxes/you@a7f2c.mailflat.net/emails/latest \
-H "X-API-Key: mf_9d2f8a…"
# mark read · delete · send
curl -X POST .../emails/123/read -H "Authorization: Bearer <token>"
curl -X DELETE .../emails/123 -H "Authorization: Bearer <token>"
curl -X POST .../send -H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{"to":"a@gmail.com","subject":"Hi","body":"Hello"}'
Line by linewhat each step of this curl example does
/emails
Everything in the inbox, newest first.
/emails/latest
One message, cheaper to poll than the full list.
?tag=promo
Only mail sent to you+promo@…, so you can see who shared your address.
X-API-Key: mf_…
Same routes, scoped to this one inbox. Safe to give to a third party.
OTP loop: call /emails/latest every 2–3s until otp_code is non-null, then stop. That is exactly what wait_for_otp does under the hood.

Status codes, rate limits & quota

Errors return { "detail": "…" } with the status below.
StatusMeaningExample detail
200OKrequest succeeded
400Business rule rejected itMonthly email quota reached
401Missing / invalid credentialsA valid session token is required
403Authenticated but not allowedInbox not found for this key
404Resource not foundNot found
422Malformed body, schema validation failedfield required
429Rate limit exceededToo many requests, please slow down
Rate limit: 500 requests/hour per IP. Space OTP polling to ~1 call every 2–3s.
Monthly quota: each plan has an allowance covering received and sent mail (see /api/plans); once spent, both directions are rejected with 400 Monthly email quota reached until the next month.
Retention: messages auto-purge after the inbox's window; the address itself is permanent.