docs
v1 Pricing Dashboard
API reference / v1

API reference

The complete /v1 surface — every endpoint, parameter, and status code, stated as the server actually behaves. For the semantics behind them (TTLs, long-polling, extraction), each section links its concept page.

Conventions & auth

Base URL: https://api.mailfixture.com/v1 — the canonical API origin (requests to mailfixture.com/v1 answer 308 to it). Every request carries your key as a bearer token; create keys in Dashboard → API keys. Requests and responses are JSON; timestamps are RFC 3339 UTC; ids are UUIDs.

every request
Authorization: Bearer mfx_your-key

Errors

Failures are RFC 7807 application/problem+jsonstatus repeats the HTTP code, detail says what to fix:

403 example
{
  "type": "about:blank",
  "title": "forbidden",
  "status": 403,
  "detail": "custom domains require a paid plan"
}

Rate limits

Per key: 2 requests/second sustained, bursting to 60. Inbox creation has its own stricter bucket (bursts of 10, refilling 10/minute). Over either limit you get 429 with a Retry-After header — the SDKs absorb these automatically inside wait helpers.

Inboxes

Concepts: Inboxes & TTLs.

POST/v1/inboxes

Create an inbox. Body optional — empty gets a random address on the shared domain. Returns 201 with the inbox, including email_address.

local_partoptional — 1–64 chars of a-z0-9._-, no leading/trailing dot, lowercased. Omit for a random 10-char one. 409 if taken on the domain.
domainoptional — a verified custom domain on your account; defaults to the shared domain. 404 if not yours.
ttl_secondsoptional — 60 to 2,592,000 (30 days). Expired inboxes stop receiving immediately and are swept hourly. Omit = lives until deleted.

Also: 403 when frozen or at the plan's active-inbox cap, 429 from the creation bucket.

GET/v1/inboxes

List active inboxes: {"inboxes": [...]} with id, local_part, fqdn, ttl_expires_at, created_at, message_count.

DELETE/v1/inboxes/{id}

Delete the inbox and all its messages. 204 on success, 404 if it isn't yours.

POST/v1/inboxes/{id}/clear

Drop the messages, keep the address. 204.

GET/v1/inboxes/{id}/messages

List messages, newest last, as summaries (id, received_at, from_addr, to_addrs, subject, tls). This is the long-poll endpoint — see Messages.

waitoptional — seconds to hold the request until a matching message arrives. Clamped to 60; chain requests for longer waits (the SDKs do).
sinceoptional — RFC 3339 timestamp; only messages received strictly after it. Use the last summary's received_at as a cursor.
matchoptional — subject:, from:, or to: prefix + case-insensitive substring; a bare term matches the subject.

Messages

Concepts: Messages, Extraction, Attachments.

GET/v1/messages/{id}

Full detail: summary fields plus inbox_id, text_body, html_body, headers, extracted, attachments (metadata array), raw_size, expires_at. extracted includes auth — SPF/DKIM/DMARC verdicts for the delivering session (absent on messages received before verification shipped; see Extraction).

GET/v1/messages/{id}/otp

{"best": "482913", "candidates": [...]}best is null when no candidate clears the confidence threshold.

GET/v1/messages/{id}/links

{"links": [...]} — each with url, text (anchor), class (verify | reset | unsubscribe | other).

POST/v1/messages/{id}/links/follow

Follow one of the message's extracted links server-side: we GET it (up to 5 redirects, https-only, public hosts only) and return {"requested_url", "final_url", "status", "redirects", "ok"}status is the target's final answer (a remote 500 is a 200 from us with "status": 500), and the target's body is never returned. Only URLs present in the message's links can be followed.

classoptional — follow the first link of this class. Default when the body is empty: verify. 404 (listing the classes that exist) when there's no such link.
indexoptional — 0-based index into the links array.
urloptional — exact URL as it appears in links. At most one of class/index/url; 400 if more.

Guard failures on the link itself are 400 (http:// target, private/internal host); an unreachable target, a redirect somewhere we refuse to go, or more than 5 redirects is 502.

GET/v1/messages/{id}/attachments/{index}

Decoded bytes of one attachment; index is 0-based into the detail's attachments array. Always application/octet-stream with a forced-download disposition. 404 for an index past the array.

Phone numbers & SMS

Paid plans, US numbers, receive-only — the fine print lives in the SMS quickstart.

POST/v1/phone-numbers

Provision a dedicated number. No body. 201 with id, phone_number (E.164), status (pending flips to active within about a minute), created_at, release_after (null). 403 on free plans or at the plan's number cap; 503 if the provider is unavailable.

GET/v1/phone-numbers

List the account's numbers. release_after is non-null when a plan downgrade left the account over its number cap and the number is scheduled for automatic release — upgrade or release other numbers before that date to keep it.

DELETE/v1/phone-numbers/{id}

Release the number (it goes back to the carrier pool — you won't get the same one again) and delete its messages. 204; 409 while the order is still pending.

GET/v1/phone-numbers/{id}/messages

Long-poll for texts — same wait/since as email. Summaries include the full text (the body is the message). match takes from:, to:, body:; a bare term matches the body — SMS has no subject.

GET/v1/sms/{id}

Detail: id, phone_number_id, received_at, from_number, to_number, text, extracted, expires_at.

GET/v1/sms/{id}/otp · GET/v1/sms/{id}/links · POST/v1/sms/{id}/links/follow

Byte-identical shapes and semantics to their email counterparts (including the follow endpoint's selectors and status codes).

Domains

Concepts: Custom domains. Paid plans only.

POST/v1/domains

Register a custom domain: body {"fqdn": "testmail.acme.com"}. 201 with the domain plus setup — the TXT and MX records to publish (setup.txt.name/value, setup.mx.name/value/priority). 403 on the free plan; 409 if the domain is already registered.

GET/v1/domains

{"domains": [...]} — your custom domains (with verified_at, mx_ok_at, and pending ones carrying setup) plus the shared domains.

POST/v1/domains/{id}/verify

Run the TXT + MX checks now. Returns txt_ok, mx_ok, verified_at, mx_ok_at, and setup. A background task also re-checks every 60s for the domain's first 7 days.

DELETE/v1/domains/{id}

Remove the domain and every inbox and message on it. 204.

API keys

POST/v1/keys

Mint a key: body {"label": "ci"} (label optional). 201 with id, prefix, and key — the full mfx_ key appears in this response only; we store an argon2id hash.

GET/v1/keys

{"keys": [...]} — metadata only (id, prefix, label, created_at), never key material.

DELETE/v1/keys/{id}

Revoke the key immediately. 204.

Webhooks

Concepts: Webhooks — events, signatures, and the retry ladder. Paid plans only.

POST/v1/webhooks

Create an endpoint: {"url": "https://...", "description": "..."} (description optional; URL must be HTTPS on a public address). 201 with the endpoint and its whsec_ secret — shown in this response only. 403 on free plans or past the plan's endpoint cap; 409 for a duplicate URL.

GET/v1/webhooks

{"webhooks": [...]} — with secret_hint (masked), consecutive_failures, disabled_at/disabled_reason.

GET/v1/webhooks/{id}/deliveries

Delivery history, most recent first: {"deliveries": [...]} with event_type, status, attempts, next_attempt_at, last_status_code, last_error, delivered_at. limit query param defaults to 50 (max 200); history is kept 7 days.

POST/v1/webhooks/{id}/test

Fire a signed endpoint.test event. 202 with {"delivery_id": "..."} — follow it in the delivery history. 409 if the endpoint is disabled.

POST/v1/webhooks/{id}/enable

Re-enable an auto-disabled endpoint after fixing the receiver. 204.

DELETE/v1/webhooks/{id}

Delete the endpoint; queued deliveries stop. 204.

Next

Quickstart: Playwright
The SDKs wrap all of this.
Concepts: Messages
Long-polling semantics in depth.
Quickstart: MCP agents
The same surface as agent tools.
Was this page useful? yes no Quickstart: Playwright →
ON THIS PAGE
edit this page ↗
report an issue ↗