Migrate from Emailable
This guide shows how to replace Emailable's verification calls with Mailbeam.
Most migrations take 30–60 minutes: the work is swapping one request and mapping
Emailable's state string onto Mailbeam's boolean plus score.
Why developers switch
- EU data residency: Emailable processes on US infrastructure, so EU companies need Standard Contractual Clauses; Mailbeam processes in Frankfurt with a DPA on every plan
- Built for forms: Emailable's single-address latency is around 250ms, slow for validating inline while someone is still typing
- Graded catch-all: Emailable returns accept-all domains as
riskyorunknownwith nothing to threshold on; Mailbeam adds a 0–100 score and areason - Pricing you can isolate: credit bundles plus separately priced deliverability add-ons make the cost of verification itself hard to read
- Sandbox mode: a deterministic test mode for CI, rather than calling production
One thing genuinely favours Emailable: it offers seed and inbox-placement testing and ongoing deliverability monitoring, which Mailbeam deliberately does not. Teams that need those often keep Emailable for deliverability and move only verification.
Endpoint mapping
| Emailable | Mailbeam | Notes |
|---|---|---|
GET /v1/verify?email=&api_key= | POST /v1/verify | Single verification |
POST /v1/batch | POST /v1/verify/batch | Up to 500,000 addresses per job |
GET /v1/batch?id= | GET /v1/jobs/{id} | Batch status |
Authentication
Emailable passes the API key as a URL query parameter, which means it ends up in access logs, browser history and proxy traces. Mailbeam takes a Bearer token in the header, so the credential stays out of the URL.
Emailable (old):
curl "https://api.emailable.com/v1/verify?email=user@example.com&api_key=YOUR_KEY"Mailbeam (new):
curl -X POST https://api.mailbeam.dev/v1/verify \
-H "Authorization: Bearer $MAILBEAM_KEY" \
-H "Content-Type: application/json" \
-d '{"email": "user@example.com"}'Response mapping
Emailable reports a single state string. Mailbeam splits the same information
into a boolean you can branch on and a score you can threshold.
| Emailable field | Mailbeam equivalent |
|---|---|
state: "deliverable" | valid: true, score >= 70 |
state: "undeliverable" | valid: false |
state: "risky" | valid: true, score 30–69 |
state: "unknown" | status: "unknown" |
reason | reason (machine-readable code) |
disposable | disposable |
role | role |
accept_all | catchAll plus a graded score |
Migrating the call
Emailable (old):
const res = await fetch(
`https://api.emailable.com/v1/verify?email=${email}&api_key=${apiKey}`
);
const { state } = await res.json();
if (state !== "deliverable") return 422;Mailbeam (new):
// No SDK to install — see /docs/quickstart for this 12-line wrapper.
import { verifyEmail } from "./lib/mailbeam.js";
const { valid, score, reason } = await verifyEmail(email);
if (!valid || score < 60) return 422;Note what the old branch was doing: state !== "deliverable" rejects risky
and unknown along with genuine failures. If your signup funnel was quietly
dropping accept-all corporate addresses, this is where it was happening.
What to check first: risky and unknown
Emailable collapses two different situations into strings you have to interpret.
An accept-all domain and a server that refused to answer both arrive as
something other than deliverable, and most integrations reject both. Mailbeam
separates them, so you can decide once and for each case:
const { valid, status, catchAll, score, reason } = await verifyEmail(email);
if (status === "unknown") {
// The server would not answer — greylisting, timeout, temporary refusal.
// This is not evidence the mailbox is bad. Accept and re-verify later.
return acceptPendingReverification();
}
if (catchAll) {
return score >= 70 ? accept() : challenge({ reason });
}
return valid ? accept() : reject({ reason });