VanishInbox
Developer API

Disposable email,
in your code.

Generate temporary inboxes and get the full email pushed to your app the instant it arrives. Real-time webhooks, free. Pay only for the requests you make.

Free real-time webhooks

The full email lands at your endpoint the instant it arrives: sender, subject, HTML and text body. No credit cost, no polling.

Simple auth

One Bearer token. Generate as many keys as you need on the dashboard.

Pay-as-you-go

Credits never expire. No subscriptions. Top up only when you run out.

Built for testing

Long-poll endpoint, custom usernames, 5 domains, instant inbox generation.

Simple credit packs

One credit = one billable request. Generating inboxes is free.

Starter

$5
10,000 credits
$0.0005/credit · never expires
Sign up to buy

Developer

Best value
$20
50,000 credits
$0.0004/credit · never expires
Sign up to buy

Scale

$50
150,000 credits
$0.00033/credit · never expires
Sign up to buy

Every account gets 10 free credits to try the API. No card required.

API reference

Everything you need to integrate the API. Copy-paste ready.

Base URL & authentication

All endpoints live under:

https://vanishinbox.com/api/v1

Authenticate every request with a Bearer token from your API keys page:

Authorization: Bearer vib_live_YOUR_KEY

Code samples, issue tracking, and anything we ship for the API (like the upcoming n8n node) live on GitHub.

Pricing & metering

One credit equals one billable API request. Generating addresses, listing domains, account info, and clearing inboxes are free. Fetching email contents costs one credit per call.

Every response includes the current balance in headers:

X-Credits-Remaining: 9842
X-Credits-Used: 1

If you run out of credits, requests return 402 Payment Required. Top up on the billing page. Credits never expire.

Rate limits

Each API key is limited to 120 requests per minute across all endpoints. The limit is per key, so if you need higher throughput you can create additional keys on the keys page.

Every response includes your current limit state:

X-RateLimit-Limit: 120
X-RateLimit-Remaining: 117
X-RateLimit-Reset: 1748419260

When you exceed the limit, requests return 429 Too Many Requests with a Retry-After header telling you how many seconds to wait. Tight polling loops should use the /wait endpoint instead. It's the same cost, but counts once against the limit.

Endpoints

GET/meFree

Returns the authenticated account's credit balance and key metadata. Use this to verify your key works.

Request
curl https://vanishinbox.com/api/v1/me \
  -H "Authorization: Bearer vib_live_YOUR_KEY"
Response
{
  "credits": 9842,
  "key": {
    "id": "2cfdd221-0515-472e-8ed1-9e83d9a4e1ac",
    "name": "Production",
    "prefix": "vib_live_Jo4"
  }
}
POST/inbox/generateFree

Generates a fresh disposable inbox address. The address is reserved as soon as the first email arrives and lives for 10 minutes from then. All body fields are optional.

Request body
{
  "domain":   "fommie.com" | "random",  // optional, default 'random'
  "username": "my-test-flow"            // optional, auto-generated if omitted
}
Request
curl -X POST https://vanishinbox.com/api/v1/inbox/generate \
  -H "Authorization: Bearer vib_live_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{"domain": "random"}'
Response
{
  "address": "[email protected]",
  "username": "leanmink654",
  "domain": "fommie.com",
  "expires_in_seconds": 600,
  "webhook_eligible": true
}
GET/domainsFree

Lists all domains available through the API. Use this to avoid hardcoding the domain list; we may add or rotate domains over time.

Request
curl https://vanishinbox.com/api/v1/domains \
  -H "Authorization: Bearer vib_live_YOUR_KEY"
Response
{
  "domains": [
    { "name": "fommie.com" },
    { "name": "whoopza.org" },
    { "name": "fommie.online" },
    { "name": "fommie.store" },
    { "name": "whoopza.store" }
  ]
}
GET/inbox/{address}1 credit

Fetches all emails received at the address. Returns an empty array if nothing has arrived yet. The 10-minute expiry timer starts when the first email arrives.

Request
curl https://vanishinbox.com/api/v1/inbox/[email protected] \
  -H "Authorization: Bearer vib_live_YOUR_KEY"
Response
{
  "address": "[email protected]",
  "emails": [
    {
      "id": "...",
      "from": "[email protected]",
      "subject": "Verify your email",
      "html": "<p>Click here...</p>",
      "text": "Click here...",
      "receivedAt": "2026-05-21T08:15:00.000Z"
    }
  ],
  "expires_in_seconds": 580
}
GET/inbox/{address}/wait1 credit

Long-polls for new emails. Returns immediately if emails already exist, otherwise blocks up to 30 seconds waiting for one. Use this instead of tight polling: same cost, far less traffic.

Query params
timeout=30  // optional, max 60
Request
curl "https://vanishinbox.com/api/v1/inbox/[email protected]/wait?timeout=30" \
  -H "Authorization: Bearer vib_live_YOUR_KEY"
Response
{
  "address": "[email protected]",
  "emails": [...],
  "timed_out": false,
  "expires_in_seconds": 580
}
DELETE/inbox/{address}Free

Clears the inbox and expires the address.

Request
curl -X DELETE https://vanishinbox.com/api/v1/inbox/[email protected] \
  -H "Authorization: Bearer vib_live_YOUR_KEY"
Response
{
  "address": "[email protected]",
  "cleared": true
}

Webhooks

How webhooks work

Register a webhook and we POST to your URL the moment an email arrives, usually within a second of delivery. No polling required.

Eligibility: only addresses generated without a custom username are webhook-eligible. Check the webhook_eligible field on the generate response. Custom usernames are free and guessable, so allowing webhooks on them would let anyone pre-claim an address before a real person types the same string into the free web tool. Auto-generated addresses don't have that problem, so they're always eligible.

One webhook per address. Registering a new one replaces any existing subscription. Subscriptions expire with the address, 10 minutes, same as the inbox itself.

Deliveries carry the full email: sender, subject, HTML and plain-text body, timestamp. You won't need a follow-up call to GET /inbox/{address} to read what arrived. The body goes to whatever URL you register, so point target_url only at an endpoint you trust.

Verifying deliveries

Every delivery includes a signature header. Verify it before trusting the payload:

X-Webhook-Signature: t=1748419260000,v1=<hmac_sha256_hex>
const crypto = require('crypto')

function verify(secret, timestamp, rawBody, signatureHeader) {
  const [, v1] = signatureHeader.split(',')
  const expected = crypto
    .createHmac('sha256', secret)
    .update(`${timestamp}.${rawBody}`)
    .digest('hex')
  return expected === v1.split('=')[1]
}

secret comes back once, at registration. Store it yourself; we can't show it again. If you lose it, register a new webhook for a fresh one.

POST/inbox/{address}/webhooksFree

Registers a webhook for the address. Requires the address to be webhook_eligible (auto-generated, owned by this key). Replaces any existing webhook on the same address.

Request body
{
  "target_url": "https://your-app.example.com/hooks/vanishinbox"  // required, https only
}
Request
curl -X POST https://vanishinbox.com/api/v1/inbox/[email protected]/webhooks \
  -H "Authorization: Bearer vib_live_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{"target_url": "https://your-app.example.com/hooks/vanishinbox"}'
Response
{
  "id": "9e2b1a3c-...",
  "address": "[email protected]",
  "target_url": "https://your-app.example.com/hooks/vanishinbox",
  "secret": "whsec_9f2c...",
  "created_at": "2026-05-21T08:10:00.000Z"
}
GET/inbox/{address}/webhooksFree

Fetches metadata for the registered webhook. The secret is never returned again after creation.

Request
curl https://vanishinbox.com/api/v1/inbox/[email protected]/webhooks \
  -H "Authorization: Bearer vib_live_YOUR_KEY"
Response
{
  "id": "9e2b1a3c-...",
  "address": "[email protected]",
  "target_url": "https://your-app.example.com/hooks/vanishinbox",
  "created_at": "2026-05-21T08:10:00.000Z"
}
DELETE/inbox/{address}/webhooksFree

Removes the webhook subscription for the address.

Request
curl -X DELETE https://vanishinbox.com/api/v1/inbox/[email protected]/webhooks \
  -H "Authorization: Bearer vib_live_YOUR_KEY"
Response
{
  "address": "[email protected]",
  "deleted": true
}

Custom usernames

Pass username in the generate request to pick your own local part. Useful when you want a predictable address for test fixtures.

curl -X POST https://vanishinbox.com/api/v1/inbox/generate \
  -H "Authorization: Bearer vib_live_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{"username": "signup-test-42", "domain": "fommie.com"}'

# → [email protected]

Rules:

  • 3 to 64 characters
  • Lowercase letters, digits, dot, hyphen, underscore
  • Must start and end with a letter or digit
  • No consecutive dots

Usernames aren't reserved. If two people generate the same address, they share the inbox. For test isolation, include a unique component (timestamp, UUID fragment) in your username.

Addresses with a custom username aren't webhook-eligible; see the Webhooks section above for why. If you need both a predictable address and a webhook, that combination isn't supported yet.

Errors

Errors come back as JSON with a type and message:

{
  "error": {
    "type": "insufficient_credits",
    "message": "You have no credits remaining. Top up your balance to continue.",
    "topup_url": "https://vanishinbox.com/dashboard/billing"
  }
}
400invalid_requestmalformed input
401unauthorizedmissing or invalid API key
402insufficient_creditsout of credits
403not_eligibleaddress isn't webhook-eligible or isn't yours
404not_foundno webhook registered for this address
429rate_limit_exceededtoo many requests; honour Retry-After
500internal_errorserver failure; credit is refunded automatically

End-to-end example

A complete signup-verification flow in Node.js:

const API_KEY = process.env.VANISHINBOX_KEY
const BASE = 'https://vanishinbox.com/api/v1'
const headers = { Authorization: `Bearer ${API_KEY}` }

// 1. Generate a fresh inbox
const { address } = await fetch(`${BASE}/inbox/generate`, {
  method: 'POST',
  headers,
}).then(r => r.json())

// 2. Use it to sign up wherever
await signupOnSomeService({ email: address })

// 3. Wait for the verification email
const { emails } = await fetch(
  `${BASE}/inbox/${address}/wait?timeout=30`,
  { headers }
).then(r => r.json())

// 4. Extract the verification link
const verifyLink = emails[0].html.match(/href="([^"]+verify[^"]*)"/)[1]
console.log('Click here:', verifyLink)

Ready to start?

Sign up with just an email. No credit card. 10 free credits on the house.

Get my API key