Email — entry 012 of 19
mail.tm
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.
GreatAPIs Score
Auth quickstart
- 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 /accountswith a JSON body{"address":..., "password":...}on a domain from/domainsreturned a genuine201 Createdaccount record. Second,POST /tokenwith the same address/password returned a bearer token as a plain JSON body ({"token":...,"id":...}). Third,GET /messagessent withAuthorization: Bearer <token>returned a genuine200 {"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.
Your key is stored only in this browser (localStorage) and sent directly to the API — never to greatapis.
Endpoints
Account4
POST/accountsCreates a Account resource.
application/ld+json — Account.jsonld-account.write (required)
| Status | Description | Schema |
|---|---|---|
201 | Account resource created | Account.jsonld-account.read |
400 | Invalid input | — |
422 | Unprocessable entity | — |
GET/accounts/{id}Retrieves a Account resource.
| Name | In | Required | Type |
|---|---|---|---|
id | path | yes | string |
| Status | Description | Schema |
|---|---|---|
200 | Account resource | Account.jsonld-account.read |
404 | Resource not found | — |
DELETE/accounts/{id}Removes the Account resource.
| Name | In | Required | Type |
|---|---|---|---|
id | path | yes | string |
| Status | Description | Schema |
|---|---|---|
204 | Account resource deleted | — |
404 | Resource not found | — |
GET/meRetrieves a Account resource.
| Status | Description | Schema |
|---|---|---|
200 | Account resource | Account.jsonld-account.read |
404 | Resource not found | — |
Domain2
GET/domainsRetrieves the collection of Domain resources.
| Name | In | Required | Type |
|---|---|---|---|
page | query | no | integer |
| Status | Description | Schema |
|---|---|---|
200 | Domain collection | — |
GET/domains/{id}Retrieves a Domain resource.
| Name | In | Required | Type |
|---|---|---|---|
id | path | yes | string |
| Status | Description | Schema |
|---|---|---|
200 | Domain resource | Domain.jsonld |
404 | Resource not found | — |
Login Check1
POST/tokenCreates a user token.
application/json (required)
| Status | Description | Schema |
|---|---|---|
200 | User token created | — |
Message6
GET/messagesRetrieves the collection of Message resources.
| Name | In | Required | Type |
|---|---|---|---|
page | query | no | integer |
| Status | Description | Schema |
|---|---|---|
200 | Message collection | — |
GET/messages/{id}Retrieves a Message resource.
| Name | In | Required | Type |
|---|---|---|---|
id | path | yes | string |
| Status | Description | Schema |
|---|---|---|
200 | Message resource | Message.jsonld-message.read |
404 | Resource not found | — |
PATCH/messages/{id}Updates the Message resource.
| Name | In | Required | Type |
|---|---|---|---|
id | path | yes | string |
application/merge-patch+json — Message-message.write (required)
| Status | Description | Schema |
|---|---|---|
200 | Message resource updated | Message.jsonld-message.write |
400 | Invalid input | — |
404 | Resource not found | — |
422 | Unprocessable entity | — |
DELETE/messages/{id}Removes the Message resource.
| Name | In | Required | Type |
|---|---|---|---|
id | path | yes | string |
| Status | Description | Schema |
|---|---|---|
204 | Message resource deleted | — |
404 | Resource not found | — |
GET/messages/{id}/attachment/{attachmentId}Retrieves a Message resource.
| Name | In | Required | Type |
|---|---|---|---|
id | path | yes | string |
attachmentId | path | yes | string |
| Status | Description | Schema |
|---|---|---|
200 | Message resource | Message.jsonld-messages.read |
404 | Resource not found | — |
GET/messages/{id}/downloadDownload a Message resource.
| Name | In | Required | Type |
|---|---|---|---|
id | path | yes | string |
| Status | Description | Schema |
|---|---|---|
200 | Download the message | — |
404 | Message not found | — |
Source1
GET/sources/{id}Retrieves a Source resource.
| Name | In | Required | Type |
|---|---|---|---|
id | path | yes | string |
| Status | Description | Schema |
|---|---|---|
200 | Source resource | Source.jsonld-source.read |
404 | Resource not found | — |
Try it
Developer reference
https://api.mail.tm8 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)
- 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 expectingresponse.bodyto be a plain array directly will getundefinedwhere it expects.length. GET /messageswith no bearer token is a real HTTP 401 — a live call this run returned{"code":401,"message":"JWT Token not found"}with aWWW-Authenticate: Bearerheader. The entry's storedauth: Nonedescribes 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-policyresponse header:POST /accountscarriedratelimit-policy: 1; w=60(one account per 60 seconds), whileGET /domainsand the authenticatedGET /messagesboth carriedratelimit-policy: 30; w=60. POST /tokenreturns plainapplication/json(a flat{"token":...,"@id":...,"id":...}object), not theapplication/ld+jsonHydra envelope every other route in this run returned — confirmed live. Don't assume every response needs Hydra unwrapping.