Developers

Getnada API for Temporary Email Workflows

Integrate Getnada temporary email into your apps — create disposable inboxes, receive OTP and verification mail, poll or stream messages, and automate temp mail testing without hosting your own mail server.

  • 100% Free to start
  • No credit card
  • No hidden fees

Temp mail API for open, messages, stream, and automation workflows.

Build With Getnada Temporary Email

The Getnada API lets developers programmatically create temporary email addresses, open disposable inboxes, and read inbound messages in real time or on a poll interval. Use temp mail for signup flow testing, OTP automation, QA environments, and privacy-first workflows.

Guest integrations can call public endpoints immediately. Verified members unlock API keys for member-tier domains, private inbox management, and higher plan limits. Premium temporary email access is arranged manually via Contact.

What You Can Use the API For

Signup Flow Testing

Automate disposable inbox creation and read confirmation emails during CI or staging signups.

OTP and 2FA Testing

Capture OTP codes and verification links sent to temp mail addresses in automated test suites.

Automation Workflows

Wire Getnada temp mail into bots, scrapers, and backend jobs that need throwaway email inboxes.

Inbox Monitoring

Poll or stream incoming messages to detect delivery, latency, and content in disposable inboxes.

Domain-Based Testing

List enabled domains and test member-tier or premium temp mail domains with API keys.

API Access Levels

Guest Access

FREE

Call public endpoints and open guest-tier temporary email inboxes without signing in.

Member Access

FREE

Verify your email, create API keys, unlock member-tier temp mail domains, and manage private inboxes.

Basic API Workflow

  1. 1

    List domains

    Call GET /api/public/domains — guest tiers by default; append ?api_key= for member/personal domains.

  2. 2

    Open inbox

    POST /api/inbox/open with { email } returns a disposable address and inbox JWT token.

  3. 3

    Fetch messages

    Poll GET /api/inbox/messages or use SSE on /api/inbox/stream when Redis is available.

  4. 4

    Read & mark read

    GET /api/inbox/message?id= for full body; PATCH to toggle read state when needed.

  5. 5

    Session lifecycle

    Extend with POST /api/inbox/heartbeat; close with POST /api/inbox/close when finished.

Developer Best Practices

  • Use HTTPS for every API request in production integrations.
  • Store account API keys securely — the raw secret is shown only once at creation.
  • Prefer X-API-Key or Authorization headers over query strings when proxies log URLs.
  • Use the inbox JWT from open for messages, heartbeat, stream, and close — not your account API key.
  • Partner domains (partnerExternal: true) use string message ids and polling only — SSE is not available.
  • Respect rate limits on open, messages, and account key routes.
  • Close or archive inboxes you no longer need to stay within plan quotas.
  • Do not use temporary email for banking, medical, or other sensitive data.
  • Handle 403 PRIVATE_INBOX_ACCESS_DENIED when opening someone else's private inbox.

Quick API Example

Open a guest-tier temporary email inbox (pick a domain from GET /api/public/domains; add ?api_key= for member tiers):

curl -sS -X POST "https://getnada.net/api/inbox/open" \
  -H "Content-Type: application/json" \
  -d '{"email":"[email protected]"}'

200 OK

{ "inboxId": "123", "token": "eyJ…", "activeUntil": "2026-06-09T12:00:00.000Z", "sessionSeq": 1, "visibility": "public", "recipient": "[email protected]", "mailSource": "local" }

Need Higher Limits?

Upgrade to Premium Getnada temporary email for more domains, higher API ceilings, and manually arranged support.

API Reference

Integration Guide & Code Examples

Step-by-step temp mail API workflows with cURL, PHP, and Node.js examples. Replace YOUR_API_KEY and YOUR_INBOX_TOKEN with values from your account and from POST /api/inbox/open.

Prerequisites

Guests can call public endpoints and open guest-tier inboxes. To use ?api_key= on open, register, verify your email, then create a key on this page after sign-in.

Lost your password? Use Forgot password from the login page.

Step 0 — Health check (optional)

Confirms the app can reach the database (and optionally Redis). No API key or inbox token. Response shape: { "status": "ready", "database": "ok", "redis": "ok" } — or HTTP 503 with status: "not_ready" when MariaDB is down. Use GET /api/health for a lightweight liveness probe ({ "ok": true }, no dependency checks).

curl -sS "https://your-domain.example/api/ready"

Step 1 — List available domains

GET /api/public/domains returns { domains, items, planMax }. Each item includes domain, partnerExternal (partner mail vs local MX), and for authenticated callers also accessTier / scope (system or personal). Guests see guest-tier hostnames only.

Verified members: append ?api_key=YOUR_API_KEY (or send the key in headers) to include member/premium system domains and active personal domains in the same response.

Guest (default)

curl -sS "https://your-domain.example/api/public/domains"

Step 2 — Open (create) an inbox

POST /api/inbox/open with JSON body { "email": "local@domain" }. Append ?api_key=YOUR_API_KEY when you need member-tier domains (verified account). Omit the query param for guest-only domains. The JSON response includes visibility (public or private) and recipient.

Public vs private: New addresses opened through this route create a public inbox row unless the address already exists as a private inbox. If the row is private, the server returns HTTP 403 unless the request is authenticated as the owner: either your browser session (signed-in, verified user — same cookies as the site) or an account API key that belongs to that same user. Guests, pending accounts, and other users’ keys cannot open someone else’s private inbox. Public inbox behavior for anonymous open is unchanged when the row is public.

JSON body uses error: "PRIVATE_INBOX_ACCESS_DENIED" for that 403 — useful for scripts; the web UI shows a friendly message instead of the raw code.

curl -sS -X POST "https://your-domain.example/api/inbox/open?api_key=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"email":"[email protected]"}'

Response includes token (inbox JWT), inboxId, activeUntil, sessionSeq, recipient, and mailSource (local or partner). Use token in Step 3 — it is not the same as your account API key.

Step 3 — List messages

GET /api/inbox/messages requires the inbox token from Step 2. Either pass ?token=… or Authorization: Bearer … (same JWT). Response: { messages: [...], cursor }. Partner domains use string message id values — poll only (no SSE).

Option A — query string

curl -sS "https://your-domain.example/api/inbox/messages?token=YOUR_INBOX_TOKEN"

Option B — Authorization header

curl -sS -H "Authorization: Bearer YOUR_INBOX_TOKEN" \
  "https://your-domain.example/api/inbox/messages"

Step 4 — Keep-alive, polling, realtime

  • Heartbeat POST /api/inbox/heartbeat with JSON { "token": "…" } extends the session (browser UI does this on a timer).
  • Polling — repeat Step 3 on an interval if Redis/SSE is unavailable.
  • SSE GET /api/inbox/stream with the same inbox token (Bearer or ?token=) when Redis is configured; partner inboxes return 403 PARTNER_POLL_ONLY — use polling instead.

Heartbeat example

curl -sS -X POST "https://your-domain.example/api/inbox/heartbeat" \
  -H "Content-Type: application/json" \
  -d '{"token":"YOUR_INBOX_TOKEN"}'

Step 5 — Read one message

GET /api/inbox/message?id= returns full sanitized HTML body for a single message. Response: { message: { id, subject, from_addr, html_sanitized, text_plain, … } }. Local MX inboxes use numeric id from the messages list; partner inboxes use string uids.

curl -sS -H "Authorization: Bearer YOUR_INBOX_TOKEN" \
  "https://your-domain.example/api/inbox/message?id=MESSAGE_ID"

Step 6 — Mark read (optional)

PATCH /api/inbox/message with JSON { "id": "MESSAGE_ID", "read": true | false } and the inbox JWT. Returns { ok: true }. Partner inboxes accept the call but do not persist read state server-side.

curl -sS -X PATCH "https://your-domain.example/api/inbox/message" \
  -H "Authorization: Bearer YOUR_INBOX_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"id":"MESSAGE_ID","read":true}'

Step 7 — Close inbox (optional)

POST /api/inbox/close ends the inbox session when your automation finishes with the temporary email address.

curl -sS -X POST "https://your-domain.example/api/inbox/close" \
  -H "Content-Type: application/json" \
  -d '{"token":"YOUR_INBOX_TOKEN"}'

SSE stream example

When Redis is configured, subscribe to new-mail events instead of polling Step 3. Not available for partner (partnerExternal: true) domains.

curl -sS -N -H "Authorization: Bearer YOUR_INBOX_TOKEN" \
  "https://your-domain.example/api/inbox/stream"

Authentication cheat sheet

Account API key (verified members only) — used so open can resolve member-tier domain access. Preferred for scripts: append ?api_key=… to the /api/inbox/open URL. Also supported: X-API-Key or Authorization: Bearer … on that same request.

Query parameters may be logged by proxies and browsers. For production integrations in hostile networks, prefer sending the account key in headers instead of the query string.

Inbox token — short-lived JWT returned by open (or POST /api/account/inboxes / …/inboxes/<id>/open for private create/refresh). Use it for messages, message (GET/PATCH), heartbeat, stream, and close. Pass ?token=… or Authorization: Bearer ….

Endpoint reference

Complete Getnada temporary email API surface for temp mail automation, inbox monitoring, and member account management.

MethodPathAuthDescription
GET/api/healthNoneLiveness probe — process is up (no DB/Redis check).
GET/api/readyNoneReadiness — { status, database, redis }. 503 when DB is down; degraded when Redis is configured but unreachable.
GET/api/public/domainsNone; optional api_key or session expands tiersList domains for inbox creation. Guest tiers by default; verified session or ?api_key= adds member/premium system domains and active personal domains. Returns { domains, items, planMax }.
POST/api/inbox/openOptional api_key (member) or sessionCreate or reopen a temporary email inbox. Body: { email }. Returns inbox JWT plus inboxId, activeUntil, sessionSeq, visibility, recipient, mailSource.
GET/api/inbox/messagesInbox JWT (?token= or Bearer)List messages — { messages, cursor }. Fields: id, subject, from_addr, received_at, read_at, has_attachments, attachment_count. Partner inboxes use string ids.
GET/api/inbox/message?id=Inbox JWTFetch one message — { message: { …, html_sanitized, text_plain } }. Local MX: numeric id; partner: string uid.
PATCH/api/inbox/messageInbox JWTMark read/unread. JSON body: { id, read: boolean }. Partner inboxes accept the call but do not persist read state.
POST/api/inbox/heartbeatInbox JWT in JSON body { token }Extend inbox session lifetime — returns { activeUntil }.
GET/api/inbox/streamInbox JWT (Bearer or ?token=)Server-Sent Events for near-realtime new-mail when Redis is available. Partner inboxes return 403 PARTNER_POLL_ONLY — use polling.
POST/api/inbox/closeInbox JWT in JSON body { token }Close the inbox session — returns { ok: true }.
GET/api/account/api-keysSession cookie (verified member)List your API keys and quota (maxActiveApiKeys, activeKeyCount).
POST/api/account/api-keysSession cookie (verified member)Create an API key. Returns rawSecret once. Optional label in JSON body.
POST/api/account/api-keys/:id/revokeSession cookie (verified member)Revoke an API key immediately.
POST/api/account/inboxesSession cookie (verified member)Create a private temp mail inbox. Body: { domain, localPart? }.
GET/api/account/inboxesSession cookie (verified member)Paginated list of private inboxes. Query: page, scope=active|archived.
PATCH/api/account/inboxes/:idSession cookie (verified member)Archive or unarchive a private inbox. Body: { action: "archive" | "unarchive" }.
GET/api/account/inboxes/suggest?domain=Session cookie (verified member)Batch of human-style local-part suggestions for private inbox creation.
POST/api/account/inboxes/:id/openSession cookie (verified member)Refresh inbox JWT for an owned private inbox by numeric id.
GET/api/account/domainsSession cookie (verified member)List personal custom domains, DNS status, and inboxEligibleDomains (browser session only).

Common error codes

CodeHTTPMeaning
EMAIL_REQUIRED400Missing email in open request body.
EMAIL_NOT_ALLOWED400Email format or domain not permitted.
DOMAIN_REQUIRED400Missing domain query param on suggest route.
INVALID_JSON400Request body is not valid JSON.
INVALID_BODY400PATCH message body is not a JSON object.
INVALID_READ_FLAG400PATCH message requires read: boolean.
INVALID_MESSAGE_ID400Message id missing or wrong shape for inbox type.
INVALID_INBOX_ID400Account inbox route id is not numeric.
INVALID_ACTION400PATCH account inbox action must be archive or unarchive.
TOKEN_REQUIRED401Inbox JWT missing on message/stream routes.
UNAUTHORIZED401Session cookie missing on account routes.
INVALID_TOKEN401Inbox JWT expired or invalid.
DOMAIN_NOT_ALLOWED403Domain not enabled or above your plan tier on open.
PRIVATE_INBOX_ACCESS_DENIED403Cannot open another user's private inbox.
PRIVATE_INBOX_ARCHIVED403Private inbox is archived — unarchive first.
INBOX_UNAVAILABLE403Inbox session invalid, archived, or session mismatch.
GUEST_PARTNER_INBOX_LIMIT403Guest limit for partner-domain inboxes reached.
PERSONAL_DOMAIN_OWNER_REQUIRED403Personal domain requires owner session or API key.
PERSONAL_DOMAIN_NOT_ACTIVE403Personal domain DNS not active yet.
NOT_ACTIVE403Account not verified — API keys unavailable.
NOT_FOUND404Message or private inbox not found.
ALREADY_ARCHIVED409Private inbox is already archived.
NOT_ARCHIVED409Unarchive called on an active private inbox.
UNARCHIVE_BLOCKED_AT_LIMIT409Active private inbox quota full — archive another first.
LIMIT409Plan quota reached (API keys).
PRIVATE_INBOX_LIMIT409Active private inbox quota reached.
SUGGESTION_EXHAUSTED409Could not allocate a unique local part after retries.
SESSION_MISMATCH409Inbox JWT session no longer matches server state.
RATE_LIMITED429Too many requests — retry after backoff.
SERVICE_UNAVAILABLE503Database or dependency unreachable.
PARTNER_INBOX_NOT_CONFIGURED503Partner mail integration not configured.
PARTNER_INBOX_TIMEOUT504Partner inbox activation exceeded deadline.

Reference docs

Key storage, issuance, and HTTP errors: docs/PART_2_API_KEYS.md. Auth and activation: docs/PART_2_AUTH_PLAN.md.

Not built here: Swagger portal, org sharing, admin key console, usage analytics dashboards, or automated key rotation wizards.