API reference
The reference is rendered from the same OpenAPI document the API is built from and served next to it, so it can never be a version behind. Twelve operations on nine paths, every request and response schema, and the error bodies – plus a request console that takes your fep_ key and fires real calls from the page.
The page is open – no key needed to read it: https://api.fake-email.pro/docs. Download the OpenAPI document from it and point a client generator at it to get a typed SDK in your language – that is the route we recommend while no official SDKs are published.
Conventions
- Time. RFC 3339 in UTC, always with milliseconds: 2026-10-22T18:01:02.123Z (.000Z when the fraction is zero). Headers such as Retry-After and X-RateLimit-Reset stay in seconds.
- Shape. Field names are camelCase; a field whose value is null is present, an empty list is []; enums are UPPERCASE (bodyState: "STORED"), error codes lowercase (not_found).
- Lists. page (from 0) and size (1–50, 20 by default); out of range is a 400, never clamped. The answer is { content, page, size, totalPages, totalElements }, newest first.
- Errors. Every error is JSON { "error": "<code>", "message": "<phrase>" }. Switch on error; message is a fixed English phrase for the developer reading the log.
A time you are shown is not a cursor: the server keeps microseconds, the JSON shows milliseconds, so two messages can share a createdAt. To go on after a message, use its id.
Waiting for an email
GET /v1/mailboxes/{address}/messages/wait is a long poll: it holds the request open until a matching email is in and answers with it, instead of a loop over the list of messages. It spends nothing of the monthly quota and one request of the per-minute rate limit, however long it waits (Limits).
timeout– Whole seconds to hold the request open, 1–60; 30 when left out.after– Where to start: the id of a message of this mailbox, or an RFC 3339 time by the server's clock. Only a message strictly after it counts; without it, every message of the mailbox does – one that came before the call included.from– A substring of the sender address, case-insensitive.subject– A substring of the subject, case-insensitive.
200– The earliest matching message, in the same short form the list of messages uses – id, from, subject, bodyState, code and confirmLink. Sent at once if it is already there, the moment it arrives otherwise. Bodies, attachments and every code and link: GET /v1/mailboxes/{address}/messages/{id}.204– No matching message within timeout. No body; ask again.400 bad_request– timeout outside 1–60 or not a number, or an after that is neither a message id nor an RFC 3339 time.404 not_found– No such active mailbox of yours (it may have expired or been deleted while the request waited), or an after id this mailbox does not hold.429 too_many_waits– Too many waits of yours held open at once, with Retry-After: 1. The cap is concurrentWaits in GET /v1/limits; any wait that ends frees its slot.
To take a mailbox's emails one by one, pass the id of the last one you got as after: each wait then answers with the next email, and none is skipped – not even one that arrived between two requests or in the same millisecond. To wait only for mail sent from some moment on, pass a time from the server's clock – the Date header of the response that created the mailbox, say – not the createdAt of a message you already have. A + in an offset goes into the URL as %2B.
Downloads
Two operations answer with a file instead of JSON. Both are reads: they cost nothing against the monthly quota, only against the per-minute rate limit, and a 404 still comes back as the usual JSON error, not_found.
GET /v1/mailboxes/{address}/messages/{id}/rawThe message exactly as received, as an .eml file (message/rfc822) – headers, every part, every attachment. It is the only way to read a message whose bodyState is UNPARSED; an OVERFLOW message kept no source and answers 404.GET /v1/mailboxes/{address}/messages/{id}/attachments/{attachmentId}The decoded bytes of one attachment, with the Content-Type the sender declared and the real file name in Content-Disposition. Take the id from attachments of the message; an UNPARSED or OVERFLOW message has none.