Email — entry 012 of 19

mail.tm

Verified Oct 2026

mail.tm issues disposable inboxes on shared domains and exposes a Hydra/JSON-LD REST API to create accounts, fetch a bearer token, and read incoming messages, all without any signup fee. It's the fully free, actively maintained sibling of mail.gw.

mail.tm issues disposable inboxes on rotating shared domains and exposes a Hydra/JSON-LD REST API to create an account, fetch a bearer token, and read incoming mail — all with no signup fee. A live GET this run against /domains returned exactly 1 active domain, web-library.net ("hydra:totalItems":1); the pool rotates over time, so don't hard-code that hostname.

temporary-emaildisposable-emailfreeinbox
AuthenticationNone requiredCall it straight away — no key, no signup.
HTTPSSupportedTraffic is encrypted in transit.
CORSEnabledCallable directly from browser JavaScript.
PricingFreeNo paid tier — free for the documented use case.
FormatsJSONResponses can be requested as JSON.

GreatAPIs Score

Score94out of 100
Authentication25/25No authentication required
Pricing20/20Free to use
Docs20/20Machine-readable spec file bundled
Formats9/15Single response format
Freshness20/20Verified within 6 months

Embed this badge

Scored 94 on greatapis.com
<a href="https://greatapis.com/api/mail-tm/"><img src="https://greatapis.com/badge/mail-tm.svg" alt="Scored 94 on greatapis.com"></a>

Auth quickstart

  1. No API key or payment is required, but reading mail is not fully keyless end to end — confirmed live this run in three steps. First, POST /accounts with a JSON body {"address":..., "password":...} on a domain from /domains returned a genuine 201 Created account record. Second, POST /token with the same address/password returned a bearer token as a plain JSON body ({"token":...,"id":...}). Third, GET /messages sent with Authorization: Bearer <token> returned a genuine 200 {"hydra:totalItems":0,"hydra:member":[]} for the brand-new, empty inbox — confirming the full create-account-to-read-mail flow works with no payment, only a throwaway account of your own making.
Stored keyNo key stored

Your key is stored only in this browser (localStorage) and sent directly to the API — never to greatapis.

Endpoints

Servers
/
Auth
JWT
Account4
POST/accountsCreates a Account resource.
Request body

application/ld+json — Account.jsonld-account.write (required)

Responses
StatusDescriptionSchema
201Account resource createdAccount.jsonld-account.read
400Invalid input—
422Unprocessable entity—
GET/accounts/{id}Retrieves a Account resource.
Parameters
NameInRequiredType
idpathyesstring
Responses
StatusDescriptionSchema
200Account resourceAccount.jsonld-account.read
404Resource not found—
DELETE/accounts/{id}Removes the Account resource.
Parameters
NameInRequiredType
idpathyesstring
Responses
StatusDescriptionSchema
204Account resource deleted—
404Resource not found—
GET/meRetrieves a Account resource.
Responses
StatusDescriptionSchema
200Account resourceAccount.jsonld-account.read
404Resource not found—
Domain2
GET/domainsRetrieves the collection of Domain resources.
Parameters
NameInRequiredType
pagequerynointeger
Responses
StatusDescriptionSchema
200Domain collection—
GET/domains/{id}Retrieves a Domain resource.
Parameters
NameInRequiredType
idpathyesstring
Responses
StatusDescriptionSchema
200Domain resourceDomain.jsonld
404Resource not found—
Login Check1
POST/tokenCreates a user token.
Request body

application/json (required)

Responses
StatusDescriptionSchema
200User token created—
Message6
GET/messagesRetrieves the collection of Message resources.
Parameters
NameInRequiredType
pagequerynointeger
Responses
StatusDescriptionSchema
200Message collection—
GET/messages/{id}Retrieves a Message resource.
Parameters
NameInRequiredType
idpathyesstring
Responses
StatusDescriptionSchema
200Message resourceMessage.jsonld-message.read
404Resource not found—
PATCH/messages/{id}Updates the Message resource.
Parameters
NameInRequiredType
idpathyesstring
Request body

application/merge-patch+json — Message-message.write (required)

Responses
StatusDescriptionSchema
200Message resource updatedMessage.jsonld-message.write
400Invalid input—
404Resource not found—
422Unprocessable entity—
DELETE/messages/{id}Removes the Message resource.
Parameters
NameInRequiredType
idpathyesstring
Responses
StatusDescriptionSchema
204Message resource deleted—
404Resource not found—
GET/messages/{id}/attachment/{attachmentId}Retrieves a Message resource.
Parameters
NameInRequiredType
idpathyesstring
attachmentIdpathyesstring
Responses
StatusDescriptionSchema
200Message resourceMessage.jsonld-messages.read
404Resource not found—
GET/messages/{id}/downloadDownload a Message resource.
Parameters
NameInRequiredType
idpathyesstring
Responses
StatusDescriptionSchema
200Download the message—
404Message not found—
Source1
GET/sources/{id}Retrieves a Source resource.
Parameters
NameInRequiredType
idpathyesstring
Responses
StatusDescriptionSchema
200Source resourceSource.jsonld-source.read
404Resource not found—

Try it

Developer reference

Base URLhttps://api.mail.tm
Rate limit

8 queries/second (QPS) per IP address; exceeding it returns HTTP 429 'Too many requests', per docs.mail.tm (sibling service to mail.gw, same documented limit)

Key endpoints
  • GET/domains
  • POST/accounts
  • POST/token
  • GET/messages

Gotchas & limits

  • Every response is a JSON-LD/Hydra envelope (@context, @id, @type, hydra:totalItems, hydra:member), not a bare array or plain object — confirmed live this run on /domains. Code expecting response.body to be a plain array directly will get undefined where it expects .length.
  • GET /messages with no bearer token is a real HTTP 401 — a live call this run returned {"code":401,"message":"JWT Token not found"} with a WWW-Authenticate: Bearer header. The entry's stored auth: None describes signup being free, not every route being open with no credentials at all.
  • Account creation is rate-limited far tighter than reads — confirmed live this run via the ratelimit-policy response header: POST /accounts carried ratelimit-policy: 1; w=60 (one account per 60 seconds), while GET /domains and the authenticated GET /messages both carried ratelimit-policy: 30; w=60.
  • POST /token returns plain application/json (a flat {"token":...,"@id":...,"id":...} object), not the application/ld+json Hydra envelope every other route in this run returned — confirmed live. Don't assume every response needs Hydra unwrapping.