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}/burnnoneDeletes every message but keeps the address alive
DELETE /api/inboxes/{addr}noneReleases 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/latestnoneNewest message, or { email: null } when the inbox is empty
POST /api/inboxes/{addr}/emails/{id}/readnoneMarks one message read
DELETE /api/inboxes/{addr}/emails/{id}noneDeletes one message
GET /api/inboxes/{addr}/emails/{id}/attachments/{aid}noneThe attached file itself. On an encrypted inbox it returns the envelope instead, because 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 allowedNo inbox …@… for this API key…
404That message or attachment is not in that inboxMessage 42 not found in inbox …
422A field is missing, mistyped, or not a field at allInvalid request: 'email' is required
429Too many sign-in / sign-up attemptsToo many requests, please slow down
Rate limit: only the anonymous auth endpoints are throttled, per IP. Sign-up and password reset 5/hour, login 10/minute, OTP verification 5/minute. Everything you do with a session token or an API key is bounded by your plan quota, not by a request ceiling, so polling for a message is fine.
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.