HTTP API
Plain HTTP under /api/v1. @mailwurf/e2e is optional.
Every mailbox call except health needs an API key of your organization:
Authorization: Bearer mw_live_…or header X-Api-Key: mw_live_…. Inboxes and messages of other organizations return 404. JSON errors look like {"error":"…"}. Create keys under API keys.
Call the API at your Mailwurf origin, for example https://api.mailwurf.io. /v1 is an alias of /api/v1. /health is an alias of /api/v1/health. /llm and /llms.txt return this contract as Markdown and do not require a key. Agents that speak MCP can connect by URL instead and need no key.
The same contract is published as OpenAPI: browse the API Reference or download openapi.yaml.
Endpoints
| Method | Path | Auth | Success | Notes |
|---|---|---|---|---|
| GET | /llm | no | 200 markdown | machine-readable guide |
| GET | /llms.txt | no | 200 markdown | same as /llm |
| GET | /api/v1/health | no | 200 | {"status":"ok"} |
| POST | /api/v1/inboxes | yes | 201 | empty body; custom address is rejected |
| GET | /api/v1/inboxes?address= | yes | 200 | lookup by address; address required |
| GET | /api/v1/inboxes/{id} | yes | 200 | 404 if the inbox is not yours |
| DELETE | /api/v1/inboxes/{id} | yes | 204 | temporary inboxes only |
| GET | /api/v1/inboxes/{id}/messages | yes | 200 | newest first; query subject, after |
| POST | /api/v1/inboxes/{id}/messages | yes | 202 | send from this inbox; to, subject, text |
| GET | /api/v1/inboxes/{id}/messages/wait | yes | 200 | server-side wait |
| GET | /api/v1/messages/{id} | yes | 200 | one message |
Status: 400 bad JSON / missing query / invalid after / bad send body, 401 missing or wrong API key, 403 permanent inbox cannot be deleted here, 404 unknown inbox, message, or local send recipient, 408 wait timeout, 429 too many concurrent waits or sends, 500 server error.
Wait
GET /api/v1/inboxes/{id}/messages/wait
Keep one request open. Do not poll from the client.
| Query | Meaning |
|---|---|
timeout | milliseconds. Default 15000. Max 120000. 0 = one lookup. Invalid → default |
subject | case-insensitive substring of Subject |
after | message id; only later messages |
Matching is oldest-first. If a match is already stored, it returns immediately. At most four waits may run at once per API key.
timeout=0 and no match → 404. Positive timeout and no match → 408. Too many concurrent waits → 429.
Examples
Create an inbox:
curl -s -X POST https://api.mailwurf.io/v1/inboxes \
-H "Authorization: Bearer $MAILWURF_API_KEY"Wait up to 15s for a subject containing Confirm:
curl -s "https://api.mailwurf.io/v1/inboxes/{id}/messages/wait?timeout=15000&subject=Confirm" \
-H "Authorization: Bearer $MAILWURF_API_KEY"Then pick the link you need from links, or read otp. See Messages.
Send from an inbox to another Mailwurf address (or the internet):
curl -s -X POST https://api.mailwurf.io/v1/inboxes/{id}/messages \
-H "Authorization: Bearer $MAILWURF_API_KEY" \
-H "Content-Type: application/json" \
-d '{"to":"other@mail.mailwurf.io","subject":"Hello","text":"ping"}'
Mailwurf