VaultMail
REST · SSE · v1

API reference

Free during MVP — no API keys, no rate limits, no auth. The Developer tier (with API keys, webhook delivery, custom domains, and higher rate limits) is in roadmap. Base URL:

https://vaultmail.viktorarsov.com
POST/api/v1/inboxes/generateGenerate an inbox
Request body
{
  "domain": "misterrium.bg",
  "local_part": "myalias"   // optional; random if omitted
}
Response
{
  "id": "0416d8e4-...",
  "address": "myalias@misterrium.bg",
  "message_count": 0,
  "unread_count": 0,
  "inbox_expires_at": "2026-05-08T11:30:00Z"
}
GET/api/v1/domains/List domains
Response
{
  "domains": [
    { "name": "misterrium.bg",  "is_public": true, "tier_required": 0 },
    { "name": "tincar.bg",      "is_public": true, "tier_required": 0 },
    { "name": "barberscrew.bg", "is_public": true, "tier_required": 0 }
  ]
}
GET/api/v1/inboxes/{address}Get inbox + stats
Response
{ "id": "...", "address": "...", "message_count": 4, "unread_count": 1, ... }
Use /api/v1/inboxes/{address}/stats for aggregate counters (unread, OTPs, total bytes, attachments).
GET/api/v1/inboxes/{address}/messages?limit=50List messages
Response
[
  {
    "id": "ecbfa70e-...",
    "from_address": "noreply@spotify.com",
    "subject": "Confirm your account (code 482193)",
    "received_at": "...",
    "is_read": false,
    "has_otp": true,
    "raw_size": 533,
    "link_count": 1,
    "attachment_count": 0
  }
]
GET/api/v1/messages/{id}Read a message
Response
{
  "id": "...",
  "from_address": "noreply@spotify.com",
  "subject": "...",
  "body_text": "...",
  "body_html": "...",
  "links": [{ "index": 0, "url": "https://..." }],
  "attachments": [{ "filename": "...", "size": ... }],
  "otp_detected": "482193",
  "headers": { "From": "...", "DKIM-Signature": "..." }
}
Hitting this endpoint marks the message read.
GET/api/v1/messages/{id}/rawDownload raw .eml
Response
(application/rfc822 bytes; Content-Disposition: attachment)
GET/api/v1/sse/inbox/{address}Real-time stream (SSE)
Response
event: connected
data: {"address":"..."}

event: message
data: {"type":"new_message","id":"...","from":"...","subject":"...","has_otp":true}
Long-lived connection. Server emits 'connected' on subscribe, 'message' on every delivered email, and periodic 'ping' keepalives. Use EventSource on the browser, or a streaming HTTP client elsewhere.
POST/api/v1/inboxes/{address}/mark-all-readMark all as read
Response
204 No Content
POST/api/v1/inboxes/{address}/clearClear inbox
Response
204 No Content
Deletes every message. Address remains active.
DELETE/api/v1/messages/{id}Delete a message
Response
204 No Content

End-to-end example

# 1. Generate an inbox
ADDR=$(curl -s -X POST https://vaultmail.viktorarsov.com/api/v1/inboxes/generate \
  -H 'Content-Type: application/json' -d '{}' | jq -r .address)
echo "Inbox: $ADDR"

# 2. Watch for messages in another terminal
curl -N https://vaultmail.viktorarsov.com/api/v1/sse/inbox/$ADDR

# 3. Send a test email to that address (from any provider)

# 4. List messages
curl https://vaultmail.viktorarsov.com/api/v1/inboxes/$ADDR/messages

# 5. Read OTP
curl https://vaultmail.viktorarsov.com/api/v1/messages/<id> | jq .otp_detected