anonym.es

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.

LinksTemp MailErrors

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.

FieldTypeWhat it does
idintegerNumeric id of the link, used by the other calls.
shortstringThe short address to share.
urlstring | nullThe destination; null for a note-only link.
statusstringactive | expired | exhausted (visit cap reached) | flagged (destination on a safety list) | banned.
passwordbooleanVisitors must enter a password.
created_atstringISO 8601, UTC.
expires_atstring | nullWhen the link expires; null = no expiry.
max_hitsinteger | nullVisit cap; null = no cap.
self_destructbooleanThe link deletes itself, for good, when the cap or the lifetime is reached.
delayinteger | nullSeconds on the forwarding page; null = the plan default, 0 = instant.
no_countdownbooleanThe forwarding page shows no countdown and waits for a click on the address.
adultbooleanVisitors confirm being 18 or older before the forwarding page.
notestring | nullThe note shown on the forwarding page.
tagsstring[]Tags, lowercase.
clicksintegerVisits for the whole life of the link.
uniquesintegerUnique 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
TokenWhere to get itWhat it is for
Account tokenIn the dashboardAll links of the account, with the rights of the plan
Link tokenReturned when a link is createdOne 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.

MethodPathTokenCostWhat it does
GET/api/v1optional1About this API: version, documentation and schema addresses.
POST/api/v1/linksoptional5 + 1/urlCreate 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/checkoptional2Is this custom name available? Suggestions when it is taken.
GET/api/v1/linksaccount2The account's links, newest first.
GET/api/v1/links/lookuplink or account1Find one of your links by its short address.
GET/api/v1/links/{id}link or account1One 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 account3Change 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 account2Delete the link; the name becomes free again.
GET/api/v1/links/{id}/qrlink or account3The QR code of the short address as an image (PNG or SVG); needs a token, so it suits server-side use.
GET/api/v1/qroptional3The 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/meaccount1The account: plan, limits, quota left, alias domains, what the plan allows.
GET/api/v1/openapi.jsonoptional1This API as an OpenAPI 3.1 document.

Temp Mail

MethodPathTokenCostWhat it does
GET/api/v1/mail/domainsaccount1Temp Mail: the domains the plan may create addresses on, and which of them take a pinned address (pinnable).
GET/api/v1/mail/limitsaccount1Temp Mail: how many addresses the plan allows at once and in an hour, and what is left.
GET/api/v1/mail/addressesaccount2Temp Mail: the account's live addresses with their remaining time.
POST/api/v1/mail/addressesaccount5Temp 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}account1Temp Mail: one address with its remaining time, extensions and today's send quota.
POST/api/v1/mail/addresses/{id}/keyaccount3Temp 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}/pinaccount3Temp 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}/unpinaccount3Temp Mail: make a pinned or reserved address temporary. The clock of the plan starts at once.
POST/api/v1/mail/addresses/{id}/extendaccount3Temp Mail: reset the address clock to the plan's full lifetime (counts as an extension).
DELETE/api/v1/mail/addresses/{id}account2Temp Mail: delete the address and everything in it.
GET/api/v1/mail/addresses/{id}/messagesaccount2Temp 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}account1Temp 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}account3Temp Mail: mark a message read or unread.
DELETE/api/v1/mail/addresses/{id}/messages/{mid}account2Temp Mail: delete a message.
GET/api/v1/mail/addresses/{id}/messages/{mid}/attachments/{n}account1Temp Mail: one attachment as a file download. Needs X-Mail-Key.
POST/api/v1/mail/addresses/{id}/messages/{mid}/replyaccount5Temp 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}/sendaccount5Temp Mail: send a message to any address (the plan's free sends).
GET/api/v1/mail/addresses/{id}/sentaccount2Temp 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:

FieldTypeWhat it does
linkobjectThe created link.
tokenstringThe link token (32 characters): manages this link.
leftinteger | nullLinks still available in the current quota period; null when the plan has no limit.
qrobjectThe QR code, present when qr=true was sent.
batchbooleantrue when several addresses were sent.
resultsarrayOne 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:

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:

FieldTypeWhat it does
availablebooleantrue when the name can be used.
namestringThe name that was checked.
errorstringWhy the name is not available: taken, reserved, too_short and the other name errors.
messagestringThe reason in words.
fieldstringAlways name.
suggestarrayFree 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.

FieldTypeWhat it does
urlstring, requiredThe destination. Or urls: several addresses, one per line or as a JSON array (up to 50); each gets its own link.
namestringCustom name for a single link (checked against the rules and the name filter).
domainstringOne 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.
subbooleanMake it name.alias instead of alias/name. Max plan, alias domains only.
expires_daysintegerLifetime in days. Paid plans.
max_hitsintegerVisit cap. Paid plans.
self_destructbooleanDelete the link for good when the visit cap or the lifetime is reached (needs max_hits or expires_days).
passwordstringPassword visitors must enter. Paid plans.
notestringText shown on the forwarding page. Paid plans; length by plan.
note_onlybooleanThe link opens the note itself, no destination. Pro+ and up.
delayintegerSeconds on the forwarding page, 0 = instant. Paid plans.
no_countdownbooleanNo countdown on the forwarding page: no timer, no automatic forward, the visitor clicks the address. Paid plans.
adultbooleanAdult content (18+): visitors confirm their age on a page of its own before anything else is shown. Every plan.
tagsstringComma-separated tags (up to 5, 24 characters each). Account tokens on paid plans.
qrbooleanInclude the QR code of the short address (base64) in the response.
qr_sizeintegerSide of the QR image in pixels, 100-1000 (default 300; PNG rounds down to whole modules).
qr_formatstringpng (default) or svg.
qr_logobooleanfalse = 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"
FieldTypeWhat it does
pageintegerPage number (default 1).
perintegerLinks per page, 1-100 (default 50).
qstringSearch in the short name, domain and destination (one flat list, up to 50).
tagstringOnly 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:

FieldTypeWhat it does
pageintegerCurrent page.
perintegerLinks per page.
totalintegerNumber of links matched.
pagesintegerNumber of pages.
linksarrayLink 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"
ValueReport period
dayLast 30 days, by day
weekLast 26 weeks, by ISO week
monthLast 24 months, by month

Fields of the response: stats

FieldTypeWhat it does
modestringday, week or month.
fromstringFirst day of the report, YYYY-MM-DD.
tostringLast day of the report.
seriesarrayOne entry per bucket, oldest first: [from, to, visits, uniques].
summaryobjectcur (the current bucket), prev (the previous one), avg (the average of the buckets before the current one), each with hits and uniq.
dimsobjectBreakdown 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.

FieldTypeWhat it does
urlstringNew destination. Pro+ and up.
namestringNew name (same rules as a custom name).
expires_daysintegerNew lifetime in days; empty = no expiry.
max_hitsintegerNew visit cap; empty = no cap.
self_destructbooleanDelete for good when the cap or the lifetime is reached; false turns it off.
passwordstringNew password; an empty string removes the password.
notestringNew note; empty removes it (a note-only link keeps needing one).
delayintegerSeconds on the forwarding page; empty = the plan default.
no_countdownbooleantrue = no countdown on the forwarding page; false turns the countdown back on.
adultbooleantrue = age confirmation (18+) before the forwarding page; false removes it.
tagsstringNew comma-separated tag list; empty removes all tags.

Clearing a value

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:

FieldTypeWhat it does
deletedintegerThe 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:

FieldTypeWhat it does
shortstring, requiredThe short address, for example https://anonym.es/abc12.
qr_sizeintegerSide of the QR image in pixels, 100-1000 (default 300; PNG rounds down to whole modules).
qr_formatstringpng (default) or svg.
qr_logobooleanfalse = plain code without the logo; paid plans only, otherwise ignored.

The qr member in JSON responses:

FieldTypeWhat it does
formatstringpng or svg.
mimestringimage/png or image/svg+xml.
sizeintegerRequested side length in pixels.
logobooleanWhether the logo is drawn in the center.
base64stringThe 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"
FieldTypeWhat it does
loginstringThe account login.
planstringPlan key: free, pro, pro_plus, max or enterprise.
plan_labelstringThe plan name as shown on the site.
untilstring | nullWhen the paid plan ends, ISO 8601; null on Free or without an end date.
limitsobjectlinks (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).
leftinteger | nullLinks still available in the current quota period; null without a limit.
aliasesarrayThe alias domains the plan may use.
canobjectOne 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"}'
FieldTypeWhat it does
namestringLocal part, 3-30 letters, digits, dots or hyphens. Empty = a random name.
domainstringOne of the plan's domains (see /mail/domains). The first one by default.

Fields of the response: address

FieldTypeWhat it does
idintegerNumeric id of the address, used by the other calls.
addressstringThe full address.
domainstringIts domain.
created_atstringISO 8601, UTC.
expires_atstring | nullWhen the address dies, null for a pinned address.
seconds_leftinteger | nullSeconds until it dies, null = never.
extendsintegerExtensions used so far.
extends_leftinteger | nullExtensions left, null = unlimited.
pinnedbooleantrue when the address is pinned: no clock, it lives while the plan does.
reservedbooleantrue 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_leftinteger | nullSeconds until a reserved address is deleted with its mail, null when it is not reserved.
mailsintegerMessages in the inbox of the address. Only in the list of GET /mail/addresses.
unreadintegerUnread messages among them. Only in the list of GET /mail/addresses.
quotaobjectToday's send quota: replies, replies_left, sends, sends_left (UTC day).
encryptedbooleantrue when the mail of the address is stored encrypted.
keystringThe 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

FieldTypeWhat it does
addresses.limitinteger | nullAddresses the plan allows at once, null = unlimited.
addresses.usedintegerLive addresses of the account.
new_per_hour.limitinteger | nullNew addresses the plan allows in an hour, null = unlimited.
new_per_hour.leftinteger | nullNew addresses left in the current hour, null = unlimited.
new_per_hour.wait_minintegerMinutes until a new address can be made, 0 = right now.
pinned.limitinteger | nullAddresses the plan may pin, null = unlimited, 0 = none.
pinned.usedintegerPinned addresses of the account, the reserved ones too.
pinned.reservedintegerHow 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[]

FieldTypeWhat it does
idintegerNumeric id of the message.
fromstringSender address.
from_namestringSender display name.
subjectstringSubject.
previewstringFirst 140 characters of the text.
received_atstringISO 8601, UTC.
readbooleantrue once the message was opened (or marked read).
verifiedbooleantrue 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_domainstring | nullThe authenticated domain, or null.
attachmentsintegerNumber of attachments.
encryptedbooleanPresent 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:

FieldTypeWhat it does
textstringPlain-text body.
htmlstringHTML body, if any (render it sandboxed).
attachmentsarrayAttachments with n, name, type, size and url. The url is the download address and needs the same token.
authobjectCloudflare'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."}'
FieldTypeWhat it does
tostring, requiredRecipient address.
subjectstring, requiredSubject line.
textstring, requiredMessage 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"
FieldTypeWhat it does
idintegerNumeric id of the sent item.
kindstringreply or free.
tostringRecipient.
subjectstringSubject.
textstringThe text that was sent.
created_atstringISO 8601, UTC.
reply_tointeger | nullId of the message this was a reply to; null for a free send.

Temp Mail by plan

PlanAddresses at onceNew addresses an hourLifetimeExtensionsReplies / dayFree sends / dayDomains
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.

HTTPMeaning
400Error in the request parameters
401Token missing or invalid
403The plan or the token type does not allow this call
404The link does not exist or belongs to someone else
405Method not allowed for this path
409The custom name is taken
429Rate limit or quota exhausted. See Retry-After
501PNG is not available on this server. Request svg
All error codes
CodeHTTPFieldWhat it does
bad_request400Malformed request.
bad_url400urlThe address is missing or is not a valid http(s) URL.
blocked400urlThis destination cannot be linked.
bad_name400nameThis name is not allowed.
dirty400nameThis name is not allowed.
brand400nameThis name looks like a brand name and cannot be used.
reserved400nameThis name is reserved.
too_short400nameThe name is too short for your plan.
sub_format400nameA subdomain name is 3 to 32 letters, digits or hyphens.
sub_main400domainSubdomain links exist on the alias domains only.
name_batch400nameA custom name works for a single address, not for a batch.
taken409nameThis name is already taken.
note_long400noteThe note is longer than your plan allows.
note_required400noteA note-only link needs a note.
bad_tag400tagsTags: up to 5 of them, each up to 24 characters.
pro_only403This option needs a paid plan.
max_only403Subdomain links need the Max plan.
account_only403This call needs an account token.
limit429The link quota for this period is used up.
domain_limit429urlToday's limit for links to this site without an account is used up.
ai_limit429nameToo many custom names this hour; try again later.
rate_limited429Too many requests; slow down.
busy429Too many links being created at once; retry in a moment.
auth401Missing or invalid token.
not_found404No such link.
no_route404No such endpoint.
method405Method not allowed.
fetch500Could not create the link; try again.
qr_unavailable501qr_formatPNG QR codes are not available on this server; request svg.
no_address404No such address.
no_message404No such message.
bad_domain400domainThis domain is not in your plan.
addr_limit429The plan's address limit is reached. Delete one first.
new_rate429The plan's hourly limit of new addresses is reached. Try again later.
extend_limit429No extensions left for this address.
no_expiry400This address never expires.
address_reserved409The address is in the reserve: the plan no longer covers it. Renew the plan or make the address temporary.
pin_plan403Pinned addresses come with a paid plan.
pin_limit429The plan pins no more addresses.
pin_domain400Addresses on this domain cannot be pinned.
temp_no_room429The plan has no free place for this address. Delete an address first.
unverified403The sender of this message failed authentication, so a reply to it is not allowed.
reply_limit429No replies left today for this address.
send_limit429No free sends left today for this address.
send_off403Sending is not part of this plan.
bad_to400toEnter a valid recipient address.
bad_subject400subjectA subject is required.
empty400textThe message text is empty.
send_unavailable503Sending is not switched on for this address yet.
send_rejected422toThe mail service refused this message. Check the recipient address, or try again later.
send_failed502The message could not be sent. Try again in a minute.
key_required403The mail of this address is encrypted. Send the address key in the X-Mail-Key header.
bad_key403The X-Mail-Key header does not hold the key of this address.
site_address403This address was created on the site. Its key lives in the browser and the API cannot replace it.
worker502The 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:

HeaderValue
X-RateLimit-LimitBudget of units per minute
X-RateLimit-RemainingUnits left in the current minute
X-RateLimit-ResetSeconds until the budget renews
Retry-AfterOn 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.

PlanLinksCustom names per hourShortest nameNote lengthUnits a minuteOptions
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.