API Documentation
Authenticate with an nxv_ API key, verify single or bulk emails, poll jobs, export results, and receive signed completion webhooks. Integrate in about 10 minutes with the quickstart below.
https://api.nexiphorverifier.com/openapi/v1.jsonQuickstart
Create a sandbox key (nxv_test_) in Dashboard → API Keys, then run one of these — no credits charged, deterministic fake results:
# 1) Create a sandbox key in Dashboard → API Keys (prefix nxv_test_)
# 2) Verify one address (waits up to 15s for a result)
curl -X POST "https://api.nexiphorverifier.com/api/v1/verify/single?wait=true&waitTimeoutMs=15000" \
-H "Authorization: Bearer nxv_test_YOUR_SANDBOX_KEY" \
-H "Content-Type: application/json" \
-d '{"email":"user@example.com"}'Response (synchronous wait): 200 when the job finishes in time. Job status is Completed; the verdict lives on result.status (Valid / Invalid / Risky / Unknown). Use result.score, result.reasonCode, and result.verificationMethod (sandbox here; live SMTP uses values like smtp_positive). On live keys, Unknown / Failed are refunded.
{
"jobId": "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee",
"status": "Completed",
"email": "user@example.com",
"result": {
"email": "user@example.com",
"isValid": true,
"status": "Valid",
"score": 100,
"reason": "Mailbox exists",
"reasonCode": "mailbox_exists",
"verificationMethod": "sandbox",
"confidenceLevel": "VeryHigh"
}
}Swap to a live nxv_ key when you are ready for real SMTP probes. Prefer an official client? See SDKs below.
Authentication
Create a key in Dashboard → API Keys. Send it as a Bearer token (preferred) or X-Api-Key header. Keys use scopes verify:single, verify:bulk, finder:single, and finder:bulk. There is no rotate endpoint — revoke a key and create a new one (optionally with the same scopes and IP allowlist).
Authorization: Bearer nxv_your_key_here # or X-Api-Key: nxv_your_key_here
Sandbox keys
Create a sandbox key (prefix nxv_test_) to integrate without burning credits or hitting SMTP. Results are deterministic fakes (verificationMethod: "sandbox"). Bulk sandbox is capped at 100 emails. Sandbox does not run real syntax/IDN short-circuits — addresses are hashed into Valid / Invalid / Risky / Unknown buckets. Use a live key to exercise invalid_syntax and Unicode local-part rejection.
Authorization: Bearer nxv_test_...
Single verify
POST https://api.nexiphorverifier.com/api/v1/verify/single returns 202 Accepted with a job id by default. Poll until complete, or opt into a synchronous wait.
curl -X POST https://api.nexiphorverifier.com/api/v1/verify/single \
-H "Authorization: Bearer nxv_..." \
-H "Content-Type: application/json" \
-d '{"email":"user@example.com"}'
# Poll
curl https://api.nexiphorverifier.com/api/v1/verify/single/{jobId} \
-H "Authorization: Bearer nxv_..."Accepted response shape:
{
"jobId": "uuid",
"status": "Queued",
"email": "user@example.com",
"pollUrl": "/api/v1/verify/single/{jobId}",
"hubUrl": "/hubs/verification"
}Synchronous wait (optional): add ?wait=true or header X-Nexiphor-Wait: true. Optional waitTimeoutMs (5 000–30 000, default 20 000). Returns 200 with the completed job payload if finished in time; otherwise 202 and you must poll. Bulk jobs stay async only.
curl -X POST "https://api.nexiphorverifier.com/api/v1/verify/single?wait=true&waitTimeoutMs=15000" \
-H "Authorization: Bearer nxv_..." \
-H "Content-Type: application/json" \
-d '{"email":"user@example.com"}'Result fields
Completed single-job and bulk export rows share the same verification shape. status is one of Valid, Invalid, Risky, or Unknown. score is a confidence/deliverability score (higher is better for Valid / safe catch-all). Unknown and Failed verifications are refunded. The example below is a live SMTP outcome (verificationMethod: "smtp_positive"); sandbox keys return "sandbox" instead.
{
"email": "user@example.com",
"isValid": true,
"status": "Valid",
"score": 100,
"reason": "Mailbox exists",
"reasonCode": "mailbox_exists",
"suggestedEmail": null,
"typoDetected": false,
"provider": null,
"providerName": null,
"verificationMethod": "smtp_positive",
"confidenceLevel": "VeryHigh",
"checks": {
"syntaxValid": true,
"domainExists": true,
"mxFound": true,
"isDisposable": false,
"smtpAccepted": true,
"isCatchAll": false,
"isRoleAccount": false,
"isFreeEmail": true,
"isToxicDomain": false,
"isPossibleSpamTrap": false,
"catchAllProvider": null
},
"telemetry": {
"mxHost": "gmail-smtp-in.l.google.com",
"smtpCode": 250,
"smtpResponse": "2.1.5 OK",
"tlsUsed": true
}
}Common reasonCode values:
invalid_syntax/invalid_domain/disposable_domain→ Invalidmx_not_found/smtp_rejected/provider_account_not_found→ Invalidmailbox_exists→ Validcatch_all_detected/provider_non_authoritative_rcpt→ Riskysmtp_blocked/smtp_timeout/dns_timeout→ Unknown (refunded)toxic_domain/possible_spam_trap→ Risky (also exported asis_toxic_domain/is_possible_spam_trap)
Bulk CSV/TSV/XLSX/JSON exports include these columns plus is_toxic_domain and is_possible_spam_trap. Prefer the valid_and_safe_catchall export preset when you want Valid plus high-confidence catch-alls (score ≥ 70 by default — reputable managed hosts such as Google Workspace / Microsoft 365). Catch-all confidence is provider-graded (about 50–75) and may be reduced when a domain historically flip-flops.
Internationalized domains (IDN) and locale
Unicode domain labels are supported. Before DNS and SMTP, addresses are normalized with Punycode (ACE). For example, test@日本語.jp is converted to an ASCII domain and then verified like any other address. Malformed Punycode labels fail closed as invalid_syntax.
SMTPUTF8 / Unicode local parts are not supported on live keys. Addresses such as ユーザー@example.com return invalid_syntax even when the domain is valid. Probes use ASCII SMTP; this keeps bulk lists aligned with deliverability on mainstream MX hosts. Sandbox keys skip this check (see Sandbox keys above).
Bare IP hostnames and reserved domains are rejected as invalid_domain. Dashboard UI text is English; date and number formatting may follow the browser locale.
Bulk verify
JSON list (requires fileName plus emails), paste text via /verify/bulk/paste, or CSV upload. Optional callbackUrl receives a completion webhook.
Concurrent bulk jobs: each plan includes soft parallel bulk limits (Business 4, Agency 6, Enterprise custom). Starting another bulk job while at the limit queues or waits — contact sales@nexiphorverifier.com for Business+ concurrency packs.
# JSON emails (fileName is required)
curl -X POST https://api.nexiphorverifier.com/api/v1/verify/bulk \
-H "Authorization: Bearer nxv_..." \
-H "Content-Type: application/json" \
-d '{"fileName":"list.json","emails":["a@x.com","b@y.com"],"callbackUrl":"https://hooks.zapier.com/..."}'
# Paste text
curl -X POST https://api.nexiphorverifier.com/api/v1/verify/bulk/paste \
-H "Authorization: Bearer nxv_..." \
-H "Content-Type: application/json" \
-d '{"text":"a@x.com\nb@y.com"}'
# CSV upload
curl -X POST https://api.nexiphorverifier.com/api/v1/verify/bulk/upload \
-H "Authorization: Bearer nxv_..." \
-F "file=@list.csv" \
-F "callbackUrl=https://hooks.zapier.com/..."
# Poll summary
curl https://api.nexiphorverifier.com/api/v1/verify/bulk/{batchId}/summary \
-H "Authorization: Bearer nxv_..."Export
Authenticated download: GET https://api.nexiphorverifier.com/api/v1/verify/bulk/{batchId}/export
Webhooks include an absolute exportUrl and a short-lived exportToken. Send that token in the X-Export-Token header (query-string ?token= is rejected). Lifetime is up to 24h, or until zero-storage purge. No API key is required for that URL. The token is cleared when the batch is purged.
Webhooks
Prefer the Webhook Manager: register durable public http or https endpoints (ports 80/443 only; no localhost or private IPs) in Dashboard → Webhooks or use the Zapier / Make recipes for Catch Hook setup. Subscribe to batch.completed and verification.completed, inspect delivery history, and retry failures. Managed webhook create / rotate / test require a Pro plan (otherwise 403 with code: "plan_required"). Per-batch callbackUrl remains a one-shot override. Failed deliveries retry with backoff (1m, 5m, 15m, 1h; up to 4 attempts).
curl -X POST https://api.nexiphorverifier.com/api/v1/webhooks/endpoints \
-H "Authorization: Bearer nxv_..." \
-H "Content-Type: application/json" \
-d '{"name":"Zapier","url":"https://hooks.zapier.com/...","events":["batch.completed"]}'Generate a signing secret on the Webhooks page or in Settings → Privacy. Verify X-Nexiphor-Signature: sha256=... as HMAC-SHA256 of the raw body. Deduplicate with eventId / X-Nexiphor-Event-Id.
{
"eventId": "batch.completed:aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee",
"batchId": "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee",
"status": "Completed",
"totalCount": 1000,
"completedCount": 1000,
"results": { "valid": 820, "invalid": 100, "risky": 50, "unknown": 30 },
"exportUrl": "https://api.nexiphorverifier.com/api/v1/verify/bulk/.../export",
"exportToken": "<opaque>",
"exportTokenHeader": "X-Export-Token",
"exportExpiresAt": "2026-07-11T12:00:00Z",
"completedAt": "2026-07-10T12:00:00Z"
}Email Finder
Resolve a professional address from name + domain. Only SMTP-proven Valid results are returned — catch-all domains abort without a guess. Success costs 5 credits; misses cost 0. Requires API scopes finder:single / finder:bulk.
curl -X POST https://api.nexiphorverifier.com/api/v1/finder/single \
-H "Authorization: Bearer nxv_..." \
-H "Content-Type: application/json" \
-d '{"firstName":"Ada","lastName":"Lovelace","domain":"example.com"}'List recent single jobs: GET /api/v1/finder/single. Pro plan required. Webhook events include job.failed as an alias of verification.failed. After rotating a webhook signing secret,X-Nexiphor-Signature-Previous is sent for 24h.
Bulk CSV upload:
curl -X POST https://api.nexiphorverifier.com/api/v1/finder/bulk/upload \ -H "Authorization: Bearer nxv_..." \ -F "file=@people.csv"
Domain Intelligence
GET /api/v1/domains/lookup?domain=example.com (authenticated). Returns MX presence, provider hints, and a heuristic catch-all likelihood. This is not an SMTP RCPT probe of a specific mailbox — use single/bulk verify for mailbox-level truth.
curl "https://api.nexiphorverifier.com/api/v1/domains/lookup?domain=example.com" \ -H "Authorization: Bearer nxv_..."
Result cache
Teams can enable a result cache TTL (days) under Settings. Cache hits return verificationMethod: "result_cache" and may include fromCache: true on the enqueue response. Pass forceRefresh: true on single/bulk verify to bypass cache. Owners/Admins can purge with POST /api/v1/teams/result-cache/purge.
Verification profiles
Apply a named profile (export/unknown defaults) with POST /api/v1/teams/verification-profiles/apply body {"profileId":"cold_email"}. List profiles via GET /api/v1/teams/verification-profiles.
Rate limits
Verify and finder endpoints are rate limited per API key (default ~120 requests per minute). Each key has its own bucket; JWT dashboard sessions share a per-user bucket. Exceeding the limit returns 429 with Retry-After and X-RateLimit-* headers. Opt-in synchronous single-verify waits use a tighter limit (~30/min). Polling job status uses a separate, higher quota.
SDKs
Official thin clients for Node and Python wrap single verify, bulk, status, and export.
Node — @nexiphor/verifier on npm
npm i @nexiphor/verifier
import { createClient } from '@nexiphor/verifier';
const client = createClient({ apiKey: process.env.NXV_API_KEY });
const job = await client.verifyEmail('user@example.com', { wait: true });
console.log(job.status, job.result);Python — nexiphor-verifier on PyPI
pip install nexiphor-verifier
from nexiphor_verifier import create_client
client = create_client(api_key="nxv_test_...")
job = client.verify_email("user@example.com", wait=True)
print(job.status, job.result)For codegen against the full surface, download the OpenAPI spec.
Errors
JSON error bodies typically include a message / Message (and sometimes a machine code). Request validation uses 400 with a failures / Failures map — not HTTP 422.
400— request validation failed (empty email, missing bulkfileName, private webhook URL, etc.). Malformed addresses such asnot-an-emailare still accepted as jobs; on live keys they complete asInvalid/invalid_syntaxrather than failing at the HTTP layer401— missing/invalid session or API key; expired export token403— missing API key scope, or plan gate (requiredPlanfor webhooks / integrations)402— insufficient credits (live keys only)429— rate limited (~120/min per API key by default). CheckRetry-AfterandX-RateLimit-*headers.
Example validation error (empty email):
{
"Message": "One or more validation failures occurred.",
"Failures": {
"Email": ["Email is required."]
}
}401 — invalid or missing API key:
{
"message": "Invalid API key."
}402 — insufficient credits (live keys):
{
"code": "insufficient_credits",
"message": "Insufficient credits to start this verification."
}429 — rate limited (also set Retry-After):
{
"message": "Too many requests. Please try again later."
}Error handling
Check HTTP status before parsing the success body. Read message / Message, optional code, and validation Failures. On 429, sleep for Retry-After seconds (fallback 1s) and retry.
async function verifyOnce(email, apiKey) {
const res = await fetch(
"https://api.nexiphorverifier.com/api/v1/verify/single?wait=true",
{
method: "POST",
headers: {
Authorization: `Bearer ${apiKey}`,
"Content-Type": "application/json",
},
body: JSON.stringify({ email }),
}
);
const body = await res.json().catch(() => ({}));
if (res.status === 429) {
const retryAfter = Number(res.headers.get("Retry-After") || 1);
await new Promise((r) => setTimeout(r, retryAfter * 1000));
return verifyOnce(email, apiKey);
}
if (!res.ok) {
const msg = body.message ?? body.Message ?? res.statusText;
const code = body.code ? ` (${body.code})` : "";
throw new Error(`HTTP ${res.status}${code}: ${msg}`);
}
return body;
}Zero-storage
Enable in Settings or send X-Nexiphor-Zero-Storage: true. Results are kept only for your retention window (shortened after a successful webhook). Download before purgeAfterUtc.
Chrome extension
A browser extension is packaged in the Nexiphor frontend repo for one-click verify from CRM tabs. Chrome Web Store listing is pending founder submit — use API keys or the dashboard until the Store link is live. See also Dashboard → API Keys.
Base URL
Production: https://api.nexiphorverifier.com