API reference.
disposable inboxes with built-in OTP & magic-link extraction - one REST call, no inbox scraping. plus a long-poll wait, SSE, webhooks, and a hosted MCP server.
https://api.voidash.comintroduction
voidash is a disposable-email API with built-in OTP and magic-link extraction. create an inbox, point a signup at it, and pull the verification code straight from the API - no parsing, no IMAP, no inbox scraping.
everything an agent or a CI job needs is one REST call away, plus a long-poll wait endpoint, server-sent events, outbound webhooks, and a hosted MCP server for AI agents.
base URL & versioning
all endpoints live under https://api.voidash.com. the REST API is versioned under /api/v1. the MCP server is at /mcp. responses are JSON unless noted (raw .eml and attachments return their original content type).
authentication
most endpoints require a Bearer token in the Authorization header. creating your first inbox without a token mints a new anonymous session and returns its session_key once - store it. you can also mint scoped API keys (vd_sk_...) from the account panel or the keys API; all token formats authenticate identically.
curl https://api.voidash.com/api/v1/me \
-H "Authorization: Bearer $VOIDASH_KEY"plans & limits
two plans, free and pulsar, scale the same limits: inbox count, visible messages per inbox, retention, request rate, the long-poll wait budget, webhook count, and MCP concurrency. your live entitlements are always readable from GET /api/v1/me - don't hard-code them. rate-limit headers (X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset) are returned on every call; a 429 includes Retry-After.
errors
errors use standard HTTP status codes with a JSON body { "error": "message" }. common codes: 400 bad request, 401 missing or invalid token, 403 not available on your plan, 404 not found, 429 rate limited, 5xx server error.
{
"error": "webhooks are not available on your plan"
}create an inbox
/api/v1/inboxesallocate a fresh disposable address. with a Bearer token the inbox joins that account; without one, a new anonymous session is created and its session_key is returned once. optionally request a specific issuing domain (must be one of GET /domains).
body parameters
domainstringoptional. issuing domain; defaults to the service default.
session_key is present only when a brand-new session was created.
request
curl -X POST https://api.voidash.com/api/v1/inboxes \
-H "Authorization: Bearer $VOIDASH_KEY" \
-H "Content-Type: application/json" \
-d '{}'response
{
"id": "9db42d9d-3a25-4c52-a92d-7f634282a527",
"address": "nova.packet-orbit7qk@voidash.cyou",
"domain": "voidash.cyou",
"created_at": "2026-06-26T12:00:00Z",
"expires_at": "2026-07-26T12:00:00Z",
"last_activity": "2026-06-26T12:00:00Z",
"session_key": "vd_sess_…"
}list inboxes
/api/v1/inboxesreturn the live inboxes owned by the current account.
request
curl https://api.voidash.com/api/v1/inboxes \
-H "Authorization: Bearer $VOIDASH_KEY"response
{
"inboxes": [
{
"id": "9db42d9d-…",
"address": "nova.packet-orbit7qk@voidash.cyou",
"domain": "voidash.cyou",
"created_at": "2026-06-26T12:00:00Z"
}
]
}retrieve an inbox
/api/v1/inboxes/{id}fetch one inbox owned by the account.
path parameters
idstringthe inbox id.
request
curl https://api.voidash.com/api/v1/inboxes/{id} \
-H "Authorization: Bearer $VOIDASH_KEY"response
{
"id": "9db42d9d-…",
"address": "nova.packet-orbit7qk@voidash.cyou",
"domain": "voidash.cyou",
"created_at": "2026-06-26T12:00:00Z"
}delete an inbox
/api/v1/inboxes/{id}delete an inbox. an empty, never-used address goes to quarantine and may be reissued later; an address that received mail is burned and never reissued. returns 204.
path parameters
idstringthe inbox id.
request
curl -X DELETE https://api.voidash.com/api/v1/inboxes/{id} \
-H "Authorization: Bearer $VOIDASH_KEY"response
204 No Contentlist messages in an inbox
/api/v1/inboxes/{id}/messageslist received messages for one inbox, newest first. each message carries any extracted OTP code and/or magic link with a confidence score.
path parameters
idstringthe inbox id.
query parameters
limitintegerpage size (default 50, max 200).
offsetintegeroffset for paging.
unreadbooleanonly unread when true.
has_signalbooleanonly messages with an extracted code/link.
request
curl https://api.voidash.com/api/v1/inboxes/{id}/messages \
-H "Authorization: Bearer $VOIDASH_KEY"response
{
"messages": [
{
"id": "a1b2c3d4-…",
"inbox_id": "9db42d9d-…",
"from_addr": "noreply@github.com",
"subject": "Your GitHub launch code",
"preview_text": "Continue signing in…",
"otp_code": "778899",
"otp_confidence": 96,
"otp_source": "subject",
"otp_format": "numeric",
"magic_link": null,
"has_attachments": false,
"received_at": "2026-06-26T12:01:10Z",
"is_read": false
}
],
"total": 1,
"limit": 50,
"offset": 0
}list all messages
/api/v1/messageslist messages across all of the account’s inboxes (same filters as above, plus inbox_id and a free-text q search).
query parameters
limitintegerpage size (default 50, max 200).
offsetintegeroffset for paging.
inbox_idstringfilter to one inbox.
unreadbooleanonly unread when true.
has_signalbooleanonly messages with a code/link.
qstringfree-text search over sender/subject.
request
curl https://api.voidash.com/api/v1/messages?has_signal=true \
-H "Authorization: Bearer $VOIDASH_KEY"response
{ "messages": [ … ], "total": 12, "limit": 50, "offset": 0 }retrieve a message
/api/v1/messages/{id}fetch one message with its sanitized text + html bodies (inline), its attachment list, and all extracted signals. fetching also marks it read.
path parameters
idstringthe message id.
request
curl https://api.voidash.com/api/v1/messages/{id} \
-H "Authorization: Bearer $VOIDASH_KEY"response
{
"id": "a1b2c3d4-…",
"inbox_id": "9db42d9d-…",
"from_addr": "noreply@github.com",
"subject": "Your GitHub launch code",
"text": "Your verification code is 778899.",
"html": "<p>Your verification code is <b>778899</b>.</p>",
"otp_code": "778899",
"otp_confidence": 96,
"magic_link": null,
"received_at": "2026-06-26T12:01:10Z",
"is_read": true,
"attachments": []
}download raw .eml
/api/v1/messages/{id}/rawreturn the original RFC822 message (message/rfc822). raw retention is plan-dependent.
path parameters
idstringthe message id.
request
curl https://api.voidash.com/api/v1/messages/{id}/raw \
-H "Authorization: Bearer $VOIDASH_KEY"response
From: noreply@github.com
To: nova.packet-orbit7qk@voidash.cyou
Subject: Your GitHub launch code
…download an attachment
/api/v1/messages/{id}/attachments/{aid}stream one attachment in its original content type. availability is plan-dependent.
path parameters
idstringthe message id.
aidstringthe attachment id.
request
curl https://api.voidash.com/api/v1/messages/{id}/attachments/{aid} \
-H "Authorization: Bearer $VOIDASH_KEY"response
200 OK (original content type)mark all read
/api/v1/messages/readmark every message in the account read, or scope to one inbox with an optional {"inbox_id":"…"} body. returns the number updated.
body parameters
inbox_idstringoptional. scope to one inbox; omit for all.
request
curl -X POST https://api.voidash.com/api/v1/messages/read \
-H "Authorization: Bearer $VOIDASH_KEY"response
{ "updated": 12 }report an extraction
/api/v1/messages/{id}/feedbacktell us a code/link was wrong, missed, or low-confidence. used to improve the extractor; reason-only.
path parameters
idstringthe message id.
body parameters
reasonstringone of wrong, missed, low_confidence, other.
request
curl -X POST https://api.voidash.com/api/v1/messages/{id}/feedback \
-H "Authorization: Bearer $VOIDASH_KEY" \
-H "Content-Type: application/json" \
-d '{"reason":"missed"}'response
{
"message_id": "a1b2c3d4-…",
"reason": "missed",
"created_at": "2026-06-26T12:02:00Z",
"updated_at": "2026-06-26T12:02:00Z"
}set read state
/api/v1/messages/{id}explicitly mark one message read or unread with {"seen": true|false}. (fetching a message via GET /messages/{id} auto-marks it read; this is the manual control.) returns the updated message metadata.
path parameters
idstringthe message id.
body parameters
seenbooleanrequired. true = read, false = unread.
request
curl -X PATCH https://api.voidash.com/api/v1/messages/{id} \
-H "Authorization: Bearer $VOIDASH_KEY" \
-H "Content-Type: application/json" \
-d '{"seen":false}'response
{ "id": "a1b2c3d4-…", "is_read": false, "received_at": "2026-06-26T12:01:10Z", … }delete a message
/api/v1/messages/{id}permanently delete a message and its stored blobs (raw .eml, bodies, attachments). returns 204.
path parameters
idstringthe message id.
request
curl -X DELETE https://api.voidash.com/api/v1/messages/{id} \
-H "Authorization: Bearer $VOIDASH_KEY"response
204 No Contentwait for an OTP or magic link
/api/v1/inboxes/{id}/auththe core endpoint for agents and CI. returns the latest auth signal (code and/or magic link) for an inbox, optionally blocking until one arrives - no polling. pass wait (seconds, capped by your plan) and after (only match mail newer than this timestamp). the REST wait is paid: free gets 403 (use the MCP server's limited 15s wait instead); pulsar blocks up to 90s.
path parameters
idstringthe inbox id.
query parameters
waitintegerseconds to long-poll for a signal (plan-capped). omit for an instant check.
afterstringRFC3339; only match mail received after this time.
preferstringwhich signal becomes primary: otp (default), magic_link, or a link kind (login/verify/confirm/reset/invite), or any.
detailstringcompact (default) or full to add from_addr/subject/service.
returns 404 no auth signal yet if nothing arrives within the wait window - call again to keep waiting.
request
curl "https://api.voidash.com/api/v1/inboxes/{id}/auth?wait=60&detail=full" \
-H "Authorization: Bearer $VOIDASH_KEY"response
{
"status": "found",
"message_id": "a1b2c3d4-…",
"received_at": "2026-06-26T12:01:10Z",
"primary": {
"kind": "otp",
"value": "778899",
"confidence": 96,
"source": "subject",
"format": "numeric"
},
"signals": [ { "kind": "otp", "value": "778899", "confidence": 96 } ],
"warnings": [],
"from_addr": "noreply@github.com",
"subject": "Your GitHub launch code"
}wait for an OTP (legacy)
/api/v1/inboxes/{id}/otplegacy long-poll kept stable for older integrations. /auth is the canonical endpoint.
path parameters
idstringthe inbox id.
query parameters
waitintegerseconds to long-poll (plan-capped).
afterstringRFC3339 lower bound.
request
curl https://api.voidash.com/api/v1/inboxes/{id}/otp?wait=60 \
-H "Authorization: Bearer $VOIDASH_KEY"response
{ "code": "778899", "confidence": 96, "magic_link": null, "message_id": "a1b2c3d4-…" }stream all events
/api/v1/eventsserver-sent events for every inbox in the account. each message.new event carries the same payload as a message list item.
request
curl https://api.voidash.com/api/v1/events \
-H "Authorization: Bearer $VOIDASH_KEY"response
event: message.new
data: { "id": "a1b2c3d4-…", "inbox_id": "9db42d9d-…", "otp_code": "778899", … }stream one inbox
/api/v1/inboxes/{id}/eventsserver-sent events scoped to a single inbox.
path parameters
idstringthe inbox id.
request
curl https://api.voidash.com/api/v1/inboxes/{id}/events \
-H "Authorization: Bearer $VOIDASH_KEY"response
event: message.new
data: { … }get account & entitlements
/api/v1/mereturn the account summary: current plan, live entitlements (limits + feature flags), inbox count, linked logins, and API-key count.
request
curl https://api.voidash.com/api/v1/me \
-H "Authorization: Bearer $VOIDASH_KEY"response
{
"account_id": "9db42d9d-…",
"plan": {
"id": "dev",
"name": "Pulsar",
"price": "$9.99 -> $4.99",
"price_monthly_cents": 999,
"intro_price_monthly_cents": 499
},
"inbox_count": 3,
"max_inboxes": 10000,
"is_supporter": false,
"keys_count": 1,
"logins": [],
"limits": {
"msg_cap_per_inbox": 100,
"size_cap_per_inbox_bytes": 2147483648,
"message_ttl_seconds": 1209600,
"raw_ttl_seconds": 1209600
},
"entitlements": {
"plan_id": "dev",
"rate_limit_per_minute": 6000,
"wait_max_seconds": 90,
"webhook_limit": 1,
"mcp_enabled": true,
"allow_raw_eml": true,
"allow_attachments": true
}
}list API keys
/api/v1/keyslist the account’s API keys (metadata only; secrets are never returned). scopes: [] means full access; expires_at: null means the key never expires.
request
curl https://api.voidash.com/api/v1/keys \
-H "Authorization: Bearer $VOIDASH_KEY"response
{
"keys": [
{
"id": "k_…",
"name": "ci-reader",
"last4": "9f2a",
"kind": "api",
"scopes": ["mail:read"],
"expires_at": "2026-07-26T12:00:00Z",
"last_used_at": "2026-06-26T12:30:00Z",
"created_at": "2026-06-26T12:00:00Z"
}
]
}create an API key
/api/v1/keysmint a new API key (vd_sk_...). the secret is returned exactly once. optionally scope the key to least privilege and give it an expiry - omit both for a full-access, non-expiring key.
body parameters
namestringoptional label (max 64 chars).
scopesstring[]optional least-privilege grants. any of mail:read (read inboxes & messages), mail:write (create/delete inboxes, mark read, edit messages), account (manage keys, billing, webhooks, logins). omit or send [] for full access; account implies the mail scopes.
expires_in_daysnumberoptional. key expires this many days after creation; omit or 0 to never expire.
request
curl -X POST https://api.voidash.com/api/v1/keys \
-H "Authorization: Bearer $VOIDASH_KEY" \
-H "Content-Type: application/json" \
-d '{"name":"ci-reader","scopes":["mail:read"],"expires_in_days":30}'response
{
"id": "k_…",
"name": "ci-reader",
"last4": "9f2a",
"kind": "api",
"scopes": ["mail:read"],
"expires_at": "2026-07-26T12:00:00Z",
"created_at": "2026-06-26T12:00:00Z",
"secret": "vd_sk_…"
}rotate an API key
/api/v1/keys/{id}/rotateissue a new secret for a key and invalidate the old one. the new secret is returned once.
path parameters
idstringthe key id.
request
curl -X POST https://api.voidash.com/api/v1/keys/{id}/rotate \
-H "Authorization: Bearer $VOIDASH_KEY"response
{ "id": "k_…", "key": "vd_sk_…", "last4": "1c7d" }revoke an API key
/api/v1/keys/{id}permanently revoke an API key.
path parameters
idstringthe key id.
request
curl -X DELETE https://api.voidash.com/api/v1/keys/{id} \
-H "Authorization: Bearer $VOIDASH_KEY"response
{ "status": "revoked" }redeem a promo code
/api/v1/promo/redeemredeem a promo code to grant a plan trial. codes are single-use per account.
body parameters
codestringthe promo code.
request
curl -X POST https://api.voidash.com/api/v1/promo/redeem \
-H "Authorization: Bearer $VOIDASH_KEY" \
-H "Content-Type: application/json" \
-d '{"code":"VOID-EXAMPLE1"}'response
{ "status": "redeemed", "plan": { "plan_id": "dev" }, "grant_expires_at": "2026-07-03T12:00:00Z" }list webhooks
/api/v1/webhookslist the account’s webhooks and your plan’s webhook limit. webhooks are a paid feature - free returns 403; pulsar allows 1.
request
curl https://api.voidash.com/api/v1/webhooks \
-H "Authorization: Bearer $VOIDASH_KEY"response
{ "webhooks": [ { "id": "wh_…", "url": "https://example.com/hook", "events": ["message.new"], "active": true } ], "limit": 1 }create a webhook
/api/v1/webhooksregister an HTTPS endpoint that receives delivered mail events, signed with HMAC. the signing secret is returned once. optionally scope to one inbox_id.
body parameters
urlstringHTTPS endpoint to deliver to.
eventsstring[]defaults to ["message.new"].
inbox_idstringoptional. scope to one inbox; omit for all.
each delivery is signed: X-Voidash-Signature: sha256=HMAC_SHA256(secret, body). return any 2xx to acknowledge; failures retry with backoff.
request
curl -X POST https://api.voidash.com/api/v1/webhooks \
-H "Authorization: Bearer $VOIDASH_KEY" \
-H "Content-Type: application/json" \
-d '{"url":"https://example.com/hook","events":["message.new"]}'response
{
"id": "wh_…",
"url": "https://example.com/hook",
"events": ["message.new"],
"secret": "whsec_…"
}delete a webhook
/api/v1/webhooks/{id}delete a webhook and its pending deliveries.
path parameters
idstringthe webhook id.
request
curl -X DELETE https://api.voidash.com/api/v1/webhooks/{id} \
-H "Authorization: Bearer $VOIDASH_KEY"response
{ "status": "deleted" }hosted MCP server
/mcpa Model Context Protocol server (JSON-RPC 2.0 over Streamable HTTP) so agents like Claude or Cursor can create inboxes and wait for codes natively. auth is the same Bearer token. tools: create_inbox, list_inboxes, wait_for_otp, list_messages, get_message. MCP is available on every plan, but the wait_for_otp budget scales: free is capped at a 15s wait and 1 concurrent call; pulsar unlocks 90s waits and 20 concurrent.
request
// client config
{
"mcpServers": {
"voidash": {
"url": "https://api.voidash.com/mcp",
"headers": { "Authorization": "Bearer vd_sk_…" }
}
}
}response
// tools/call → wait_for_otp
{
"content": [
{ "type": "text", "text": "{\"code\":\"778899\",\"confidence\":96}" }
]
}list domains
/api/v1/domainslist the domains addresses can be issued on. tier runs 1 (premium .com) to 3 (free pool); the first entry is the default. premium domains need a paid plan (plan_required: "paid") - pass one as domain to POST /inboxes.
request
curl https://api.voidash.com/api/v1/domainsresponse
{
"domains": [
{ "domain": "voidash.cyou", "tier": 2, "default": true },
{ "domain": "voidash.com", "tier": 1, "premium": true, "plan_required": "paid" }
]
}OpenAPI spec
/api/v1/openapi.yamlthe machine-readable OpenAPI description of the REST API.
request
curl https://api.voidash.com/api/v1/openapi.yamlresponse
openapi: 3.0.0
info:
title: Voidash API
…