Python & TypeScript SDKs
Official EmailVerify Pro clients for Python and TypeScript, plus examples for Go, PHP and Ruby. Zero-dependency Python package.
View as Markdown →Official clients for Python and TypeScript. Neither has a hand-written method per endpoint — both read a registry generated from the OpenAPI spec, so every endpoint is reachable the moment it ships.
Python
pip install emailverify
No runtime dependencies — standard library only. Python 3.10 or newer.
Get started
from emailverify import Client
client = Client.from_env() # EMAILVERIFY_API_KEY, or ~/.config/emailverify
result = client.verify("someone@example.com")
print(result["status"]) # "valid"
print(result["deliverability_score"]["can_send"]) # True
Configure explicitly
client = Client(
api_key="evp_your_key",
base_url="https://emailverifypro.com",
timeout=120, # seconds; raise for slow domains
max_retries=3, # 429 and 5xx are retried with exponential backoff
verbose=False, # log request lines to stderr
)
Built-in helpers
client.verify("a@example.com") # GET /validate
client.bulk(["a@example.com", "b@example.com"]) # POST /validate/bulk
client.score("a@example.com") # GET /score
client.usage() # GET /me/usage
Any endpoint by name
client.call("db:stats")
client.call("suppression:check", email="a@example.com")
client.call("domain-intel:domain", domain="stripe.com")
client.call("find-email", domain="example.com",
first_name="Jane", last_name="Doe")
Names are the CLI command names — emailverify list prints them all, and the endpoint reference shows each one.
Raw requests
client.request("GET", "/validate", query={"email": "a@example.com"})
client.request("POST", "/validate/bulk", body={"emails": ["a@example.com"]})
Errors
from emailverify import Client, AuthError, EmailVerifyError
try:
client.verify("someone@example.com")
except AuthError:
... # 401/403 — key missing, invalid or unauthorised
except EmailVerifyError as e:
print(e.status, e.body, e.url) # everything else, with the server's own detail
429 and 5xx are retried automatically. 401 and 403 are not — retrying a bad key never helps.
Introspection
from emailverify import endpoints, commands, api_version
print(api_version()) # "6.0.0"
print(len(endpoints())) # every endpoint, as dicts
print(commands()[:5]) # every command name
A complete example
import csv
from emailverify import Client, EmailVerifyError
client = Client.from_env(timeout=300)
with open("leads.csv") as fh:
emails = [r["email"] for r in csv.DictReader(fh) if r.get("email")]
safe = []
for i in range(0, len(emails), 100): # bulk caps at 100 per call
try:
for r in client.bulk(emails[i:i + 100])["results"]:
score = r.get("deliverability_score") or {}
if score.get("can_send"):
safe.append(r["email"])
except EmailVerifyError as e:
print(f"batch {i} failed: {e}")
print(f"{len(safe)} of {len(emails)} are safe to send")
TypeScript and JavaScript
npm install @emailverifypro/mcp
Node 18 or newer — it uses the built-in fetch. Ships its own type declarations.
Get started
import { Client } from "@emailverifypro/mcp";
const client = new Client(); // reads EMAILVERIFY_API_KEY
const result = await client.request("GET", "/validate", {
email: "someone@example.com",
});
console.log(result);
Configure explicitly
const client = new Client({
apiKey: "evp_your_key",
baseUrl: "https://emailverifypro.com",
timeoutMs: 120_000,
maxRetries: 3,
verbose: false,
});
Registry-driven calls
import { Client } from "@emailverifypro/mcp";
import { lookup, endpoints } from "@emailverifypro/mcp/registry";
const client = new Client();
const result = await client.callEndpoint(lookup("verify")!, {
email: "someone@example.com",
});
const bulk = await client.callEndpoint(lookup("bulk")!, {
emails: ["a@example.com", "b@example.com"],
deduplicate: true,
});
console.log(endpoints.length);
Errors
import { Client, AuthError, EmailVerifyError } from "@emailverifypro/mcp";
try {
await client.request("GET", "/me/usage");
} catch (e) {
if (e instanceof AuthError) {
// 401 / 403
} else if (e instanceof EmailVerifyError) {
console.log(e.status, e.body, e.url);
}
}
In an Express route
import express from "express";
import { Client } from "@emailverifypro/mcp";
const app = express();
const verifier = new Client();
app.post("/signup", express.json(), async (req, res) => {
const check = await verifier.request("GET", "/validate", {
email: req.body.email,
}) as any;
if (check.is_disposable) {
return res.status(400).json({ error: "Please use a permanent address." });
}
if (check.did_you_mean) {
return res.status(400).json({ error: `Did you mean ${check.did_you_mean}?` });
}
if (!check.deliverability_score?.can_send) {
return res.status(400).json({ error: "We couldn't verify that address." });
}
res.json({ ok: true });
});
Full verification can take seconds. On a request path, prefer GET /validate/quick and follow up properly in a background job.
Other languages
There is no official client for other languages, but the OpenAPI spec drives most generators:
npx @openapitools/openapi-generator-cli generate \
-i https://emailverifypro.com/openapi.json -g go -o ./emailverify-go
Substitute -g for java, php, ruby, rust, csharp and so on.
Or just call it — it is ordinary REST over HTTPS:
req, _ := http.NewRequest("GET",
"https://emailverifypro.com/validate?email=someone@example.com", nil)
req.Header.Set("X-API-Key", os.Getenv("EMAILVERIFY_API_KEY"))
resp, err := http.DefaultClient.Do(req)
$ch = curl_init("https://emailverifypro.com/validate?email=someone@example.com");
curl_setopt($ch, CURLOPT_HTTPHEADER, ["X-API-Key: " . getenv("EMAILVERIFY_API_KEY")]);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$result = json_decode(curl_exec($ch), true);
require "net/http"
uri = URI("https://emailverifypro.com/validate?email=someone@example.com")
req = Net::HTTP::Get.new(uri)
req["X-API-Key"] = ENV["EMAILVERIFY_API_KEY"]
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |h| h.request(req) }