Link and Temp Mail API
The API creates anonymous short links, returns their click statistics, changes their settings and deletes them. Requests and responses use JSON. CORS is enabled, so calls work from browser code as well. On Pro and up it also runs temporary inboxes: create an address, poll it for mail and reply to incoming messages.
Base address:
https://anonym.es/api/v1
Quick start
To create a short link, send the destination address:
curl -X POST https://anonym.es/api/v1/links \
-H "Content-Type: application/json" \
-d '{"url":"https://example.com/article"}'
No token is required for this call. Without one, the link is created as a guest link within the Free quota of your IP address.
With an account token the same call puts the link into your dashboard and counts it against your plan:
curl -X POST https://anonym.es/api/v1/links \
-H "Authorization: Bearer anon_YOUR_ACCOUNT_TOKEN" \
-H "Content-Type: application/json" \
-d '{"url":"https://example.com/article"}'
The response contains the short address, the link id and the token that manages this link. Keep the token: it is needed to read or delete the link later.
{
"ok": true,
"link": {
"id": 4821,
"short": "https://anonym.es/k7m2q",
"url": "https://example.com/article",
"status": "active",
"password": false,
"created_at": "2026-09-05T14:02:11Z",
"expires_at": null,
"max_hits": null,
"self_destruct": false,
"delay": null,
"no_countdown": false,
"adult": false,
"note": null,
"tags": [],
"clicks": 0,
"uniques": 0
},
"token": "3f9c1b7e2d4a4c0e9b8f7a6d5c4b3a21",
"left": 4
}
Fields of the link object
All endpoints that return a link use this structure. Timestamps are ISO 8601 in UTC. The clicks and uniques counters cover the entire lifetime of the link.
| Field | Type | What it does |
|---|---|---|
id | integer | Numeric id of the link, used by the other calls. |
short | string | The short address to share. |
url | string | null | The destination; null for a note-only link. |
status | string | active | expired | exhausted (visit cap reached) | flagged (destination on a safety list) | banned. |
password | boolean | Visitors must enter a password. |
created_at | string | ISO 8601, UTC. |
expires_at | string | null | When the link expires; null = no expiry. |
max_hits | integer | null | Visit cap; null = no cap. |
self_destruct | boolean | The link deletes itself, for good, when the cap or the lifetime is reached. |
delay | integer | null | Seconds on the forwarding page; null = the plan default, 0 = instant. |
no_countdown | boolean | The forwarding page shows no countdown and waits for a click on the address. |
adult | boolean | Visitors confirm being 18 or older before the forwarding page. |
note | string | null | The note shown on the forwarding page. |
tags | string[] | Tags, lowercase. |
clicks | integer | Visits for the whole life of the link. |
uniques | integer | Unique visitors (one per address per day) for the whole life of the link. |
Authorization
Authorized requests carry the token in the Authorization header. The X-API-Key header is accepted as an alternative. Tokens are never passed in the query string.
Authorization: Bearer YOUR_TOKEN
| Token | Where to get it | What it is for |
|---|---|---|
| Account token | In the dashboard | All links of the account, with the rights of the plan |
| Link token | Returned when a link is created | One specific link, with the rights of the Free plan |
An account token starts with anon_. A link token consists of 32 characters. Generating a new account token invalidates the previous one.
Example:
curl https://anonym.es/api/v1/me \ -H "Authorization: Bearer anon_YOUR_ACCOUNT_TOKEN"
Generate an account token in the dashboard
Endpoints
Request bodies may be sent as application/json or as application/x-www-form-urlencoded. Parameter names and error codes are identical across all endpoints.
| Method | Path | Token | Cost | What it does |
|---|---|---|---|---|
GET | /api/v1 | optional | 1 | About this API: version, documentation and schema addresses. |
POST | /api/v1/links | optional | 5 + 1/url | Create a link, or up to 50 at once. Without a token: as a guest, on the Free quota. Returns the link with its token. |
GET | /api/v1/names/check | optional | 2 | Is this custom name available? Suggestions when it is taken. |
GET | /api/v1/links | account | 2 | The account's links, newest first. |
GET | /api/v1/links/lookup | link or account | 1 | Find one of your links by its short address. |
GET | /api/v1/links/{id} | link or account | 1 | One link: settings, status, clicks and unique visitors for its whole life. Account tokens may add a statistics report. |
PATCH | /api/v1/links/{id} | link or account | 3 | Change settings. Only the fields sent change. Paid plans (a link token has Free rights, so it cannot edit). |
DELETE | /api/v1/links/{id} | link or account | 2 | Delete the link; the name becomes free again. |
GET | /api/v1/links/{id}/qr | link or account | 3 | The QR code of the short address as an image (PNG or SVG); needs a token, so it suits server-side use. |
GET | /api/v1/qr | optional | 3 | The QR code of a short address as an image, without a token: the address itself is the key. Made for <img> tags. |
GET | /api/v1/me | account | 1 | The account: plan, limits, quota left, alias domains, what the plan allows. |
GET | /api/v1/openapi.json | optional | 1 | This API as an OpenAPI 3.1 document. |
Temp Mail
| Method | Path | Token | Cost | What it does |
|---|---|---|---|---|
GET | /api/v1/mail/domains | account | 1 | Temp Mail: the domains the plan may create addresses on, and which of them take a pinned address (pinnable). |
GET | /api/v1/mail/limits | account | 1 | Temp Mail: how many addresses the plan allows at once and in an hour, and what is left. |
GET | /api/v1/mail/addresses | account | 2 | Temp Mail: the account's live addresses with their remaining time. |
POST | /api/v1/mail/addresses | account | 5 | Temp Mail: create a disposable address on one of the plan's domains. The answer carries key, the secret key of the address, shown once. Mail is stored encrypted and only this key opens it. Send it as X-Mail-Key. |
GET | /api/v1/mail/addresses/{id} | account | 1 | Temp Mail: one address with its remaining time, extensions and today's send quota. |
POST | /api/v1/mail/addresses/{id}/key | account | 3 | Temp Mail: issue a new key for an address made through the API when its key is lost. Mail sealed with the old key stays closed and keeps coming back with encrypted = true. |
POST | /api/v1/mail/addresses/{id}/pin | account | 3 | Temp Mail: pin the address. A pinned address has no clock, it lives for the time of the active plan or while the domain is available. |
POST | /api/v1/mail/addresses/{id}/unpin | account | 3 | Temp Mail: make a pinned or reserved address temporary. The clock of the plan starts at once. |
POST | /api/v1/mail/addresses/{id}/extend | account | 3 | Temp Mail: reset the address clock to the plan's full lifetime (counts as an extension). |
DELETE | /api/v1/mail/addresses/{id} | account | 2 | Temp Mail: delete the address and everything in it. |
GET | /api/v1/mail/addresses/{id}/messages | account | 2 | Temp Mail: the messages of an address, newest first, with read flags and the sender verdict. Needs X-Mail-Key. Without it the rows come back with encrypted = true and no content. |
GET | /api/v1/mail/addresses/{id}/messages/{mid} | account | 1 | Temp Mail: one message in full, with text, HTML, attachments and authentication results. Marks it read. Needs X-Mail-Key. |
PATCH | /api/v1/mail/addresses/{id}/messages/{mid} | account | 3 | Temp Mail: mark a message read or unread. |
DELETE | /api/v1/mail/addresses/{id}/messages/{mid} | account | 2 | Temp Mail: delete a message. |
GET | /api/v1/mail/addresses/{id}/messages/{mid}/attachments/{n} | account | 1 | Temp Mail: one attachment as a file download. Needs X-Mail-Key. |
POST | /api/v1/mail/addresses/{id}/messages/{mid}/reply | account | 5 | Temp Mail: reply to a message. Allowed only when its sender passed authentication, and only to that sender. Needs X-Mail-Key. |
POST | /api/v1/mail/addresses/{id}/send | account | 5 | Temp Mail: send a message to any address (the plan's free sends). |
GET | /api/v1/mail/addresses/{id}/sent | account | 2 | Temp Mail: messages sent from this address. Needs X-Mail-Key to show recipient, subject and text. |
The cost is given in rate-limit units, see Rate limits.
Creating a link
POST /api/v1/links
The minimal request contains only the url field:
curl -X POST https://anonym.es/api/v1/links \
-H "Content-Type: application/json" \
-d '{"url":"https://example.com/article"}'
With an account token the link belongs to the account and counts against its plan. Without a token it is a guest link on the IP quota:
curl -X POST https://anonym.es/api/v1/links \
-H "Authorization: Bearer anon_YOUR_ACCOUNT_TOKEN" \
-H "Content-Type: application/json" \
-d '{"url":"https://example.com/article"}'
A successful request returns status 201 together with the link, its token and the number of links left in the current quota period.
Fields of the response:
| Field | Type | What it does |
|---|---|---|
link | object | The created link. |
token | string | The link token (32 characters): manages this link. |
left | integer | null | Links still available in the current quota period; null when the plan has no limit. |
qr | object | The QR code, present when qr=true was sent. |
batch | boolean | true when several addresses were sent. |
results | array | One entry per address, in the order sent: {ok: true, link, token, qr} or {ok: false, url, error, message, field}. |
Link with a custom name
The short address gets the name my-article if it is free and meets the rules below.
curl -X POST https://anonym.es/api/v1/links \
-H "Content-Type: application/json" \
-d '{"url":"https://example.com/article","name":"my-article"}'
Name rules:
- Latin letters, digits, hyphen and underscore. From 5 characters on the Free plan and from 3 on paid plans, up to 32. Case does not matter: Promo and promo are the same link.
- Page names, language codes and service words are reserved.
- Brand names and offensive words are refused. Names pass a word list and an automated review. The number of custom names per hour is limited by plan.
- A taken name returns status 409 with free alternatives in suggest.
- A subdomain name (sub: true, Max plan) is one DNS label: letters, digits and hyphens, no hyphen at either end, no underscore. Names such as www, mail or ns1 are reserved.
A name can be checked before the link is created:
curl "https://anonym.es/api/v1/names/check?name=my-article"
Fields of the check response:
| Field | Type | What it does |
|---|---|---|
available | boolean | true when the name can be used. |
name | string | The name that was checked. |
error | string | Why the name is not available: taken, reserved, too_short and the other name errors. |
message | string | The reason in words. |
field | string | Always name. |
suggest | array | Free alternatives when the name is taken. |
Several links at once
The urls field accepts up to 50 addresses, as a JSON array or as text with one address per line. Each address becomes its own link with its own token, and the other fields apply to all of them. A custom name is not available in a batch.
curl -X POST https://anonym.es/api/v1/links \
-H "Content-Type: application/json" \
-d '{"urls":["https://example.com/a","https://example.com/b","https://example.com/c"]}'
The response contains batch: true and a results array with one entry per address, in the order sent. A faulty address produces an entry with ok: false and the error code without stopping the rest.
Additional settings
curl -X POST https://anonym.es/api/v1/links \
-H "Authorization: Bearer anon_YOUR_ACCOUNT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"url": "https://example.com/article",
"name": "my-article",
"expires_days": 30,
"max_hits": 1000,
"self_destruct": true,
"password": "secret",
"note": "Available until the end of the month",
"delay": 5,
"tags": "blog,promo",
"qr": true,
"qr_size": 300,
"qr_format": "png"
}'
Options marked as paid are ignored for guests and on the Free plan. The response reflects the settings the link actually received.
| Field | Type | What it does |
|---|---|---|
url | string, required | The destination. Or urls: several addresses, one per line or as a JSON array (up to 50); each gets its own link. |
name | string | Custom name for a single link (checked against the rules and the name filter). |
domain | string | One of the alias domains, random, or random-alias (random among the alias domains only). Paid plans; default is random: links never sit on the main domain. Free and guests: anonymes.click. |
sub | boolean | Make it name.alias instead of alias/name. Max plan, alias domains only. |
expires_days | integer | Lifetime in days. Paid plans. |
max_hits | integer | Visit cap. Paid plans. |
self_destruct | boolean | Delete the link for good when the visit cap or the lifetime is reached (needs max_hits or expires_days). |
password | string | Password visitors must enter. Paid plans. |
note | string | Text shown on the forwarding page. Paid plans; length by plan. |
note_only | boolean | The link opens the note itself, no destination. Pro+ and up. |
delay | integer | Seconds on the forwarding page, 0 = instant. Paid plans. |
no_countdown | boolean | No countdown on the forwarding page: no timer, no automatic forward, the visitor clicks the address. Paid plans. |
adult | boolean | Adult content (18+): visitors confirm their age on a page of its own before anything else is shown. Every plan. |
tags | string | Comma-separated tags (up to 5, 24 characters each). Account tokens on paid plans. |
qr | boolean | Include the QR code of the short address (base64) in the response. |
qr_size | integer | Side of the QR image in pixels, 100-1000 (default 300; PNG rounds down to whole modules). |
qr_format | string | png (default) or svg. |
qr_logo | boolean | false = plain code without the logo; paid plans only, otherwise ignored. |
Listing links
GET /api/v1/links
Requires an account token.
Requires an account token. Links are returned newest first.
curl "https://anonym.es/api/v1/links?page=1&per=50" \ -H "Authorization: Bearer anon_YOUR_ACCOUNT_TOKEN"
| Field | Type | What it does |
|---|---|---|
page | integer | Page number (default 1). |
per | integer | Links per page, 1-100 (default 50). |
q | string | Search in the short name, domain and destination (one flat list, up to 50). |
tag | string | Only links with this tag. |
Search and the tag filter can be combined:
curl "https://anonym.es/api/v1/links?q=example&tag=promo" \ -H "Authorization: Bearer anon_YOUR_ACCOUNT_TOKEN"
Fields of the response:
| Field | Type | What it does |
|---|---|---|
page | integer | Current page. |
per | integer | Links per page. |
total | integer | Number of links matched. |
pages | integer | Number of pages. |
links | array | Link objects, newest first. |
Finding a link by its short address
A link is addressed by its numeric id (the id field, for example 4821), not by the name in the short address. When only the short address is known, the id can be looked up with any token that manages the link:
curl --get https://anonym.es/api/v1/links/lookup \ -H "Authorization: Bearer YOUR_TOKEN" \ --data-urlencode "short=https://anonym.es/k7m2q"
Link details and statistics
GET /api/v1/links/{id}
Returns the settings of the link, its status, the number of visits and the number of unique visitors for its whole life:
curl https://anonym.es/api/v1/links/4821 \ -H "Authorization: Bearer YOUR_TOKEN"
With an account token, a visits report can be added with the stats parameter:
curl "https://anonym.es/api/v1/links/4821?stats=day" \ -H "Authorization: Bearer anon_YOUR_ACCOUNT_TOKEN"
| Value | Report period |
|---|---|
day | Last 30 days, by day |
week | Last 26 weeks, by ISO week |
month | Last 24 months, by month |
Fields of the response: stats
| Field | Type | What it does |
|---|---|---|
mode | string | day, week or month. |
from | string | First day of the report, YYYY-MM-DD. |
to | string | Last day of the report. |
series | array | One entry per bucket, oldest first: [from, to, visits, uniques]. |
summary | object | cur (the current bucket), prev (the previous one), avg (the average of the buckets before the current one), each with hits and uniq. |
dims | object | Breakdown for the range: ref, country, device, os, browser, hour, each a list of [value, visits]. |
Editing a link
PATCH /api/v1/links/{id}
Only the fields sent change:
curl -X PATCH https://anonym.es/api/v1/links/4821 \
-H "Authorization: Bearer anon_YOUR_ACCOUNT_TOKEN" \
-H "Content-Type: application/json" \
-d '{"max_hits": 2000, "delay": 3, "tags": "blog,updated"}'
Editing requires a paid plan. A link token has the rights of the Free plan and cannot change settings.
| Field | Type | What it does |
|---|---|---|
url | string | New destination. Pro+ and up. |
name | string | New name (same rules as a custom name). |
expires_days | integer | New lifetime in days; empty = no expiry. |
max_hits | integer | New visit cap; empty = no cap. |
self_destruct | boolean | Delete for good when the cap or the lifetime is reached; false turns it off. |
password | string | New password; an empty string removes the password. |
note | string | New note; empty removes it (a note-only link keeps needing one). |
delay | integer | Seconds on the forwarding page; empty = the plan default. |
no_countdown | boolean | true = no countdown on the forwarding page; false turns the countdown back on. |
adult | boolean | true = age confirmation (18+) before the forwarding page; false removes it. |
tags | string | New comma-separated tag list; empty removes all tags. |
Clearing a value
- password, note and tags: an empty string removes the value.
- expires_days and max_hits: null, an empty string or 0 removes the limit. self_destruct turns off when neither a cap nor a lifetime is left.
- delay: null or an empty string restores the plan default. 0 means an instant redirect.
- url cannot be emptied, and a note-only link keeps needing a note.
curl -X PATCH https://anonym.es/api/v1/links/4821 \
-H "Authorization: Bearer anon_YOUR_ACCOUNT_TOKEN" \
-H "Content-Type: application/json" \
-d '{"password": "", "note": "", "expires_days": null, "max_hits": null, "delay": 0}'
Deleting a link
DELETE /api/v1/links/{id}
curl -X DELETE https://anonym.es/api/v1/links/4821 \ -H "Authorization: Bearer YOUR_TOKEN"
After deletion the custom name becomes free again. The statistics are deleted together with the link.
Fields of the response:
| Field | Type | What it does |
|---|---|---|
deleted | integer | The id of the deleted link. |
QR code
For an HTML img tag, request the code by the short address. This endpoint needs no token: the short address itself is the key, and anyone who has it can generate the same code.
<img src="https://anonym.es/api/v1/qr?short=https%3A%2F%2Fanonym.es%2Fk7m2q&qr_size=400" alt="QR code" >
Server-side code can also request the image by id with a token, or receive it base64-encoded in JSON by adding qr=true to the create or details call:
curl "https://anonym.es/api/v1/links/4821/qr?qr_size=400&qr_format=svg" \ -H "Authorization: Bearer YOUR_TOKEN" -o qr.svg
Parameters of both image endpoints:
| Field | Type | What it does |
|---|---|---|
short | string, required | The short address, for example https://anonym.es/abc12. |
qr_size | integer | Side of the QR image in pixels, 100-1000 (default 300; PNG rounds down to whole modules). |
qr_format | string | png (default) or svg. |
qr_logo | boolean | false = plain code without the logo; paid plans only, otherwise ignored. |
The qr member in JSON responses:
| Field | Type | What it does |
|---|---|---|
format | string | png or svg. |
mime | string | image/png or image/svg+xml. |
size | integer | Requested side length in pixels. |
logo | boolean | Whether the logo is drawn in the center. |
base64 | string | The image, base64-encoded. |
Account details
GET /api/v1/me
Requires an account token. Returns the plan, its limits and the remaining quota:
curl https://anonym.es/api/v1/me \ -H "Authorization: Bearer anon_YOUR_ACCOUNT_TOKEN"
| Field | Type | What it does |
|---|---|---|
login | string | The account login. |
plan | string | Plan key: free, pro, pro_plus, max or enterprise. |
plan_label | string | The plan name as shown on the site. |
until | string | null | When the paid plan ends, ISO 8601; null on Free or without an end date. |
limits | object | links (per period), per (day or month), ai_hourly (custom names per hour), name_min (shortest custom name), note_max (note length), api_units (API budget per minute). |
left | integer | null | Links still available in the current quota period; null without a limit. |
aliases | array | The alias domains the plan may use. |
can | object | One boolean per option: password, ttl, edit, edit_url, tags, note, note_only, alias, sub, instant, qr_no_logo. |
Temp Mail API
Create an address on one of the plan's domains, poll it for mail, read messages with their authentication results, reply to incoming messages and delete the address when done. You need an account token on Pro or higher. The plan's limits apply.
An address lives as long as the plan allows. The table below has the numbers. Calling extend resets that clock. Replies and free sends are counted per address per UTC day.
Mail of an address is stored encrypted. The key comes once, in the key field of the answer that creates the address. The server does not keep it, so store it yourself. Send it in the X-Mail-Key header when you list messages, read one, download an attachment, list sent items or reply. The server opens the mail in memory and only for that one answer. Without the header the rows come back with encrypted = true and no content.
Create an address
curl -X POST https://anonym.es/api/v1/mail/addresses \
-H "Authorization: Bearer anon_YOUR_ACCOUNT_TOKEN" \
-H "Content-Type: application/json" \
-d '{"name":"quiet-heron-41","domain":"anon.skin"}'
| Field | Type | What it does |
|---|---|---|
name | string | Local part, 3-30 letters, digits, dots or hyphens. Empty = a random name. |
domain | string | One of the plan's domains (see /mail/domains). The first one by default. |
Fields of the response: address
| Field | Type | What it does |
|---|---|---|
id | integer | Numeric id of the address, used by the other calls. |
address | string | The full address. |
domain | string | Its domain. |
created_at | string | ISO 8601, UTC. |
expires_at | string | null | When the address dies, null for a pinned address. |
seconds_left | integer | null | Seconds until it dies, null = never. |
extends | integer | Extensions used so far. |
extends_left | integer | null | Extensions left, null = unlimited. |
pinned | boolean | true when the address is pinned: no clock, it lives while the plan does. |
reserved | boolean | true when the plan no longer covers this pinned address. It keeps its name and takes mail, every call that reads or sends answers address_reserved. |
reserved_left | integer | null | Seconds until a reserved address is deleted with its mail, null when it is not reserved. |
mails | integer | Messages in the inbox of the address. Only in the list of GET /mail/addresses. |
unread | integer | Unread messages among them. Only in the list of GET /mail/addresses. |
quota | object | Today's send quota: replies, replies_left, sends, sends_left (UTC day). |
encrypted | boolean | true when the mail of the address is stored encrypted. |
key | string | The secret key of the address, base64. It comes only in the answer to POST /mail/addresses and POST /mail/addresses/{id}/key. It is shown once and not kept on the server. Send it as the X-Mail-Key header to read mail, attachments and sent items and to reply. Pasted into the key box of the address on the site, it opens the mail there too. A lost key cannot be recovered. |
The domains your plan can create addresses on:
curl https://anonym.es/api/v1/mail/domains \ -H "Authorization: Bearer anon_YOUR_ACCOUNT_TOKEN"
How many addresses the plan gives at once and in an hour, and what is left:
curl https://anonym.es/api/v1/mail/limits \ -H "Authorization: Bearer anon_YOUR_ACCOUNT_TOKEN"
Fields of the response: limits
| Field | Type | What it does |
|---|---|---|
addresses.limit | integer | null | Addresses the plan allows at once, null = unlimited. |
addresses.used | integer | Live addresses of the account. |
new_per_hour.limit | integer | null | New addresses the plan allows in an hour, null = unlimited. |
new_per_hour.left | integer | null | New addresses left in the current hour, null = unlimited. |
new_per_hour.wait_min | integer | Minutes until a new address can be made, 0 = right now. |
pinned.limit | integer | null | Addresses the plan may pin, null = unlimited, 0 = none. |
pinned.used | integer | Pinned addresses of the account, the reserved ones too. |
pinned.reserved | integer | How many of them wait in the reserve. |
Lost the key? The call below issues a new one. Mail sealed with the old key stays closed.
curl -X POST https://anonym.es/api/v1/mail/addresses/17/key \ -H "Authorization: Bearer anon_YOUR_ACCOUNT_TOKEN"
Poll the inbox
curl https://anonym.es/api/v1/mail/addresses/17/messages \ -H "Authorization: Bearer anon_YOUR_ACCOUNT_TOKEN" \ -H "X-Mail-Key: ADDRESS_KEY"
Fields of the response: messages[]
| Field | Type | What it does |
|---|---|---|
id | integer | Numeric id of the message. |
from | string | Sender address. |
from_name | string | Sender display name. |
subject | string | Subject. |
preview | string | First 140 characters of the text. |
received_at | string | ISO 8601, UTC. |
read | boolean | true once the message was opened (or marked read). |
verified | boolean | true when the sender's domain passed authentication (DMARC pass, or DKIM / SPF pass aligned with the From domain); only then a reply is allowed. |
verified_domain | string | null | The authenticated domain, or null. |
attachments | integer | Number of attachments. |
encrypted | boolean | Present and true when the request carried no X-Mail-Key. The row then comes without its content. With the key of the address the server opens the message in memory for this one answer and keeps neither the key nor the text. |
read stays false until the message is fetched in full or marked read. To peek without marking, add keep_unread=true to the full fetch.
Read a message
curl https://anonym.es/api/v1/mail/addresses/17/messages/2 \ -H "Authorization: Bearer anon_YOUR_ACCOUNT_TOKEN" \ -H "X-Mail-Key: ADDRESS_KEY"
The full message adds these fields to the list fields:
| Field | Type | What it does |
|---|---|---|
text | string | Plain-text body. |
html | string | HTML body, if any (render it sandboxed). |
attachments | array | Attachments with n, name, type, size and url. The url is the download address and needs the same token. |
auth | object | Cloudflare's authentication results: spf, dkim, dkim_domain, dmarc. |
Replies are allowed only when verified is true.
Mark a message read or unread:
curl -X PATCH https://anonym.es/api/v1/mail/addresses/17/messages/2 \
-H "Authorization: Bearer anon_YOUR_ACCOUNT_TOKEN" \
-H "Content-Type: application/json" \
-d '{"read": false}'
Reply
curl -X POST https://anonym.es/api/v1/mail/addresses/17/messages/2/reply \
-H "Authorization: Bearer anon_YOUR_ACCOUNT_TOKEN" \
-H "X-Mail-Key: ADDRESS_KEY" \
-H "Content-Type: application/json" \
-d '{"text":"Confirmed, thanks."}'
The reply goes to the From address of the message, threaded with In-Reply-To and References, and counts against the plan's replies per day.
Send a message
curl -X POST https://anonym.es/api/v1/mail/addresses/17/send \
-H "Authorization: Bearer anon_YOUR_ACCOUNT_TOKEN" \
-H "Content-Type: application/json" \
-d '{"to":"[email protected]","subject":"Hello","text":"Sent from a temporary address."}'
| Field | Type | What it does |
|---|---|---|
to | string, required | Recipient address. |
subject | string, required | Subject line. |
text | string, required | Message text (plain text, up to 4000 characters). |
Sent items
curl https://anonym.es/api/v1/mail/addresses/17/sent \ -H "Authorization: Bearer anon_YOUR_ACCOUNT_TOKEN" \ -H "X-Mail-Key: ADDRESS_KEY"
| Field | Type | What it does |
|---|---|---|
id | integer | Numeric id of the sent item. |
kind | string | reply or free. |
to | string | Recipient. |
subject | string | Subject. |
text | string | The text that was sent. |
created_at | string | ISO 8601, UTC. |
reply_to | integer | null | Id of the message this was a reply to; null for a free send. |
Temp Mail by plan
| Plan | Addresses at once | New addresses an hour | Lifetime | Extensions | Replies / day | Free sends / day | Domains |
|---|---|---|---|---|---|---|---|
| Free | 1 | 10 | 2 h | 2 | 0 | 0 | 4 |
| Pro | 3 | 30 | 12 h | 6 | 1 | 0 | 9 |
| Pro+ | 10 | 60 | 2 d | 6 | 3 | 1 | 14 |
| Max | 30 | 150 | 7 d | 7 | 10 | 2 | 23 |
| Enterprise | unlimited | unlimited | 30 d | unlimited | unlimited | unlimited | 23 |
Errors
Errors are returned in a single JSON format:
{
"ok": false,
"error": "taken",
"message": "This name is already taken.",
"field": "name",
"suggest": ["my-article-26", "my-my-article", "my-article-link"]
}
field contains the name of the faulty parameter, or null when the error does not concern a specific field. A taken name adds suggest, a paid option adds upgrade, quotas and rate limits add the Retry-After header.
| HTTP | Meaning |
|---|---|
400 | Error in the request parameters |
401 | Token missing or invalid |
403 | The plan or the token type does not allow this call |
404 | The link does not exist or belongs to someone else |
405 | Method not allowed for this path |
409 | The custom name is taken |
429 | Rate limit or quota exhausted. See Retry-After |
501 | PNG is not available on this server. Request svg |
All error codes
| Code | HTTP | Field | What it does |
|---|---|---|---|
bad_request | 400 | Malformed request. | |
bad_url | 400 | url | The address is missing or is not a valid http(s) URL. |
blocked | 400 | url | This destination cannot be linked. |
bad_name | 400 | name | This name is not allowed. |
dirty | 400 | name | This name is not allowed. |
brand | 400 | name | This name looks like a brand name and cannot be used. |
reserved | 400 | name | This name is reserved. |
too_short | 400 | name | The name is too short for your plan. |
sub_format | 400 | name | A subdomain name is 3 to 32 letters, digits or hyphens. |
sub_main | 400 | domain | Subdomain links exist on the alias domains only. |
name_batch | 400 | name | A custom name works for a single address, not for a batch. |
taken | 409 | name | This name is already taken. |
note_long | 400 | note | The note is longer than your plan allows. |
note_required | 400 | note | A note-only link needs a note. |
bad_tag | 400 | tags | Tags: up to 5 of them, each up to 24 characters. |
pro_only | 403 | This option needs a paid plan. | |
max_only | 403 | Subdomain links need the Max plan. | |
account_only | 403 | This call needs an account token. | |
limit | 429 | The link quota for this period is used up. | |
domain_limit | 429 | url | Today's limit for links to this site without an account is used up. |
ai_limit | 429 | name | Too many custom names this hour; try again later. |
rate_limited | 429 | Too many requests; slow down. | |
busy | 429 | Too many links being created at once; retry in a moment. | |
auth | 401 | Missing or invalid token. | |
not_found | 404 | No such link. | |
no_route | 404 | No such endpoint. | |
method | 405 | Method not allowed. | |
fetch | 500 | Could not create the link; try again. | |
qr_unavailable | 501 | qr_format | PNG QR codes are not available on this server; request svg. |
no_address | 404 | No such address. | |
no_message | 404 | No such message. | |
bad_domain | 400 | domain | This domain is not in your plan. |
addr_limit | 429 | The plan's address limit is reached. Delete one first. | |
new_rate | 429 | The plan's hourly limit of new addresses is reached. Try again later. | |
extend_limit | 429 | No extensions left for this address. | |
no_expiry | 400 | This address never expires. | |
address_reserved | 409 | The address is in the reserve: the plan no longer covers it. Renew the plan or make the address temporary. | |
pin_plan | 403 | Pinned addresses come with a paid plan. | |
pin_limit | 429 | The plan pins no more addresses. | |
pin_domain | 400 | Addresses on this domain cannot be pinned. | |
temp_no_room | 429 | The plan has no free place for this address. Delete an address first. | |
unverified | 403 | The sender of this message failed authentication, so a reply to it is not allowed. | |
reply_limit | 429 | No replies left today for this address. | |
send_limit | 429 | No free sends left today for this address. | |
send_off | 403 | Sending is not part of this plan. | |
bad_to | 400 | to | Enter a valid recipient address. |
bad_subject | 400 | subject | A subject is required. |
empty | 400 | text | The message text is empty. |
send_unavailable | 503 | Sending is not switched on for this address yet. | |
send_rejected | 422 | to | The mail service refused this message. Check the recipient address, or try again later. |
send_failed | 502 | The message could not be sent. Try again in a minute. | |
key_required | 403 | The mail of this address is encrypted. Send the address key in the X-Mail-Key header. | |
bad_key | 403 | The X-Mail-Key header does not hold the key of this address. | |
site_address | 403 | This address was created on the site. Its key lives in the browser and the API cannot replace it. | |
worker | 502 | The mail service did not answer. Try again in a moment. |
Rate limits
Each call costs units, and each plan has a budget of units per minute (see Plans and limits). A read costs 1 unit, a list page 2, a QR code 3, an edit 3, a deletion 2, a creation 5 plus 1 per address. Every response carries these headers:
| Header | Value |
|---|---|
X-RateLimit-Limit | Budget of units per minute |
X-RateLimit-Remaining | Units left in the current minute |
X-RateLimit-Reset | Seconds until the budget renews |
Retry-After | On 429: seconds to wait before retrying |
Within any 10-second window at most a quarter of the minute budget can be spent, with a minimum of 20 units. When the budget is exhausted, the API responds with status 429.
Plans and limits
The exact limits of each plan. Links are counted per day and IP address on Free, per month and account on paid plans. The last column lists the settings a plan can use.
| Plan | Links | Custom names per hour | Shortest name | Note length | Units a minute | Options |
|---|---|---|---|---|---|---|
| Free | 5 per day, per IP address | 5 | 5 | 0 | 60 | none |
| Pro | 500 per month | 10 | 3 | 300 | 150 | password, expires_days, max_hits, edit, tags, note, domain, delay, qr_logo |
| Pro+ | 2,000 per month | 50 | 3 | 2,000 | 400 | password, expires_days, max_hits, edit, edit url, tags, note, note_only, domain, delay, qr_logo |
| Max | 50,000 per month | 200 | 3 | 5,000 | 1,000 | password, expires_days, max_hits, edit, edit url, tags, note, note_only, domain, sub, delay, qr_logo |
| Enterprise | unlimited | unlimited | 3 | 5,000 | 2,500 | password, expires_days, max_hits, edit, edit url, tags, note, note_only, domain, sub, delay, qr_logo |
Without an account token, creation counts against the Free quota of the IP address: 5 links per day. Links to a destination domain registered less than a year ago share one guest cap of 5 a day, whoever makes them. At most 2 links per caller can be in creation at the same time.
OpenAPI specification
The complete technical description as an OpenAPI 3.1 document: https://anonym.es/api/v1/openapi.json
It contains schemas and examples of every request and response, the plan limits, the name rules and the error codes. It suits Swagger UI, Postman, Insomnia and client generators.