API quickstart
-
Create a key. In the app, open Profile → API and create a key. Copy it — it’s shown only once. (No API tab? API access starts with any purchase.)
-
Check it works.
Terminal window export EMAILSHIELD_API_KEY="evf_your_api_key"curl https://app.emailshield.co/api/v1/account/credits \-H "X-API-Key: $EMAILSHIELD_API_KEY"{"credits": 49000, "credits_used_today": 1000, "credits_used_this_month": 12000, "plan_limit": null, "renewal_date": "2026-11-08T10:00:00Z"} -
Verify one address. The answer comes back in the same response, usually within a few seconds (at most 30).
Terminal window curl -X POST https://app.emailshield.co/api/v1/verify/single \-H "X-API-Key: $EMAILSHIELD_API_KEY" \-H "Content-Type: application/json" \-d '{"email": "jane.doe@example.com"}'{"email": "jane.doe@example.com","status": "valid","valid": true,"score": 0.95,"reason": "Mailbox confirmed","details": {"primary_label": "valid", "tags": [], "label_reasons": ["Mailbox confirmed"]},"credits_used": 1,"credits_remaining": 48999,"processed_at": "2026-10-09T12:00:03Z"} -
Submit a list. Up to 50,000 addresses per call. You get a
job_idstraight away.Terminal window curl -X POST https://app.emailshield.co/api/v1/verify/bulk \-H "X-API-Key: $EMAILSHIELD_API_KEY" \-H "Content-Type: application/json" \-d '{"name": "October campaign", "emails": ["jane.doe@example.com", "info@example.org"]}'{"job_id": "3f1c…", "status": "queued", "total_emails": 2, "credits_used": 2, "credits_remaining": 48997, "created_at": "2026-10-09T12:01:00Z"} -
Wait for it to finish. Poll the job until
terminalistrue(or use a webhook).Terminal window curl https://app.emailshield.co/api/v1/jobs/3f1c… -H "X-API-Key: $EMAILSHIELD_API_KEY" -
Read the results, 100 per page by default (up to 1,000), until
has_moreisfalse.Terminal window curl "https://app.emailshield.co/api/v1/jobs/3f1c…/results?page=1&per_page=1000" \-H "X-API-Key: $EMAILSHIELD_API_KEY"
The same in Python
Section titled “The same in Python”import os, time, requests
BASE = "https://app.emailshield.co/api"session = requests.Session()session.headers["X-API-Key"] = os.environ["EMAILSHIELD_API_KEY"]
emails = ["jane.doe@example.com", "info@example.org"]job = session.post(f"{BASE}/v1/verify/bulk", json={"name": "October campaign", "emails": emails}).json()
while True: status = session.get(f"{BASE}/v1/jobs/{job['job_id']}").json() if status["terminal"]: break time.sleep(15)
page, rows = 1, []while True: data = session.get(f"{BASE}/v1/jobs/{job['job_id']}/results", params={"page": page, "per_page": 1000}).json() rows += data["results"] if not data["has_more"]: break page += 1
for row in rows: print(row["email"], row["details"].get("primary_label"))Before you go live
Section titled “Before you go live”- Remove obviously broken addresses before sending: one address that isn’t valid email syntax makes the whole bulk call fail with
422. - Handle
402(out of credits),429(over your API allowance) and503(new jobs paused, retry after theRetry-Afterheader). Limits and errors →