HTTP API
The same operations the CLI and MCP server use. Every request carries a bearer token.
Authentication
Tokens come from GitHub sign-in. The simplest way to get one is the CLI: after npx @smails/cli login, the access token is in ~/.config/smails/credentials.json (it lasts an hour; the CLI refreshes it). Apps can also run the OAuth 2.1 flow themselves — the authorization server metadata is at /.well-known/oauth-authorization-server.
TOKEN=$(jq -r '.servers["https://smails.dev"].access_token' ~/.config/smails/credentials.json)
curl -s -X POST https://smails.dev/api/mailboxes -H "Authorization: Bearer $TOKEN"Endpoints
- GET/api/meAccount, plan and today's quota
- POST/api/mailboxesCreate a mailbox → { address, created_at, expires_at }
- GET/api/mailboxesYour active mailboxes
- DELETE/api/mailboxes/{address}Expire a mailbox now
- GET/api/mailboxes/{address}/messagesMessages: id, from, subject, received_at
- GET/api/mailboxes/{address}/waitWait for new mail (?since, ?timeout ≤ 50, ?from, ?subject)
- GET/api/messages/{id}One message with text and html
- DELETE/api/messages/{id}Delete a message
Waiting for mail
Instead of polling, make one request that returns as soon as a matching message arrives (or after timeout seconds with { message: null }). Pass since (ms since epoch) to include mail that arrived before the request.
curl -s "https://smails.dev/api/mailboxes/$ADDRESS/wait?subject=code&timeout=50" \
-H "Authorization: Bearer $TOKEN" | jq -r .message.textErrors and limits
Errors are JSON: { "error": "quota_exceeded", "message": "…" }. 401 means sign in again; 404 means the mailbox or message does not exist or is not yours; 429 means today's quota is used up (the Retry-After header says when it resets). The anonymous API of earlier versions answers 410.
Prefer tools over raw HTTP? Use the MCP server or the CLI.