Skip to main content

Anonymous Inboxes API

Create temporary email inboxes without an account, and read them with the viewer token returned on creation. Made for AI agents and scripts that need to read one signup or login email. See Inboxes without an account for a walkthrough.

RouteAuthResult
POST /api/v1/anon/inboxesNoneCreate an inbox
GET /api/v1/anon/inboxes/:idViewer tokenGet the inbox
GET /api/v1/anon/inboxes/:id/emailsViewer tokenList emails
GET /api/v1/anon/inboxes/:id/emails/waitViewer tokenWait for the next matching email
GET /api/v1/anon/inboxes/:id/emails/:email_idViewer tokenGet one email
GET /api/v1/anon/inboxes/:id/emails/:email_id/attachments/:indexViewer tokenDownload an attachment
POST /api/v1/anon/inboxes/:id/claimAPI key or sessionMove the inbox into your organization

Send the viewer token as Authorization: Bearer <viewer_token>.

Create an anonymous inbox​

POST /api/v1/anon/inboxes
curl -X POST https://app.hooklistener.com/api/v1/anon/inboxes \
-H "Content-Type: application/json" \
-d '{"ttl_seconds": 3600, "client": "claude-code"}'

No authentication required.

FieldTypeRequiredDescription
ttl_secondsintegerNoLifetime, from 60 to 86400. Default 3600 (1 hour)
clientstringNoThe agent or tool creating the inbox (claude-code, codex, cursor…). Only used for counting

Response: 201 Created

{
"id": "0d6f1c2a-9b8e-4c3d-a1f2-6e5d4c3b2a19",
"email_address": "[email protected]",
"expires_at": "2026-10-12T11:00:00Z",
"email_count": 0,
"max_emails": 50,
"emails_url": "https://app.hooklistener.com/api/v1/anon/inboxes/0d6f1c2a-9b8e-4c3d-a1f2-6e5d4c3b2a19/emails",
"wait_url": "https://app.hooklistener.com/api/v1/anon/inboxes/0d6f1c2a-9b8e-4c3d-a1f2-6e5d4c3b2a19/emails/wait",
"viewer_token": "Zk3qL0m9…",
"claim_token": "hkic_Q2x8…",
"claim_url": "https://app.hooklistener.com/claim/inbox/0d6f1c2a-9b8e-4c3d-a1f2-6e5d4c3b2a19?token=hkic_Q2x8…"
}

viewer_token and claim_token are returned only here. Keep them secret: the viewer token reads every email the address receives.

One IP can create 10 anonymous inboxes per hour and 30 per day. Above that the API answers 429 Too Many Requests with a Retry-After header.

Get an anonymous inbox​

GET /api/v1/anon/inboxes/:id
curl https://app.hooklistener.com/api/v1/anon/inboxes/INBOX_ID \
-H "Authorization: Bearer VIEWER_TOKEN"

Returns the create response without the tokens and claim_url: id, email_address, expires_at, email_count, max_emails, emails_url and wait_url.

List emails​

GET /api/v1/anon/inboxes/:id/emails

Same response, pagination (page, page_size) and filters (since, to, from, subject_contains) as List emails for inboxes in an account.

Wait for the next email​

GET /api/v1/anon/inboxes/:id/emails/wait
curl -s -G https://app.hooklistener.com/api/v1/anon/inboxes/INBOX_ID/emails/wait \
-H "Authorization: Bearer VIEWER_TOKEN" \
--data-urlencode "since=2026-10-12T10:05:00Z" -d timeout=60 \
| jq -r '.data.code'

Same as Wait for the next email: 200 with the full email as soon as one matches, the oldest match after since at once, or 204 No Content after timeout seconds (default 30, max 60). The wait also ends with 204 when the inbox expires.

Get an email​

GET /api/v1/anon/inboxes/:id/emails/:email_id

Returns {"data": email} with the same fields as Get an email: code, verification_link, codes, links, text, bodies, headers and attachments. Attachment download_urls point at the anonymous route below.

Download an attachment​

GET /api/v1/anon/inboxes/:id/emails/:email_id/attachments/:index

Returns the attachment's bytes as a download, like Download an attachment.

Claim an anonymous inbox​

POST /api/v1/anon/inboxes/:id/claim
curl -X POST https://app.hooklistener.com/api/v1/anon/inboxes/INBOX_ID/claim \
-H "Authorization: Bearer hklst_your_api_key" \
-H "Content-Type: application/json" \
-d '{"claim_token": "hkic_Q2x8…", "name": "Signup tests"}'

Authenticated with an API key or a user session; the inbox moves into that organization.

FieldTypeRequiredDescription
claim_tokenstringYesThe claim_token from the create response
namestringNoName for the inbox in the organization

Response: 201 Created with {"data": inbox} (the inbox object). The inbox keeps its ID, address and emails, stops expiring, and counts toward the organization's inbox limit. The viewer token stops working.

Users without an API key can claim in the browser by opening claim_url.

Errors​

StatusWhen
400A malformed since or timeout
401Missing or wrong viewer token
403Claim: invalid claim token, or the organization's plan has no room for another inbox (the body includes an upgrade object)
404Unknown inbox, email or attachment
410The inbox expired or was claimed
429Too many inboxes created from this IP

Most errors have the body {"error": "…"}. A 400 for a malformed filter has {"errors": {"detail": "…"}}, like the rest of the API.

Limitations​

  • Lifetime of 1 hour by default, 24 hours at most
  • Up to 50 emails over the inbox's lifetime; later mail is refused
  • No rename, delete, clear or webhook forwards until claimed
  • Anyone with the viewer token can read the inbox's mail