API Documentation

Validate email addresses over a simple REST API. All endpoints live under https://skipbounce.com/api/v1 and return JSON.

API access requires a Pro or Scale plan. Create keys in Dashboard → API keys.

Authentication

Pass your API key as a Bearer token in the Authorization header. Keys look like sb_live_… and can be revoked at any time.

curl
curl https://skipbounce.com/api/v1/validate?email=name@company.com \
  -H "Authorization: Bearer sb_live_YOUR_KEY"

Validate one email

GET/api/v1/validate?email=...

Runs the full pipeline in real time — syntax, DNS, blacklists, and a live SMTP mailbox check. Typical response time is 1–5 seconds depending on the receiving server. Each call consumes one validation.

curl
curl "https://skipbounce.com/api/v1/validate?email=petter@moenco.no" \
  -H "Authorization: Bearer sb_live_YOUR_KEY"
JavaScript
const res = await fetch(
  "https://skipbounce.com/api/v1/validate?email=" + encodeURIComponent(email),
  { headers: { Authorization: `Bearer ${process.env.SKIPBOUNCE_KEY}` } }
);
const result = await res.json();
if (result.status !== "deliverable") {
  // ask the user to double-check their address
}
Response 200
{
  "email": "petter@moenco.no",
  "status": "deliverable",
  "score": 97,
  "checks": {
    "valid_syntax": true,
    "valid_domain": true,
    "mx_found": true,
    "smtp_deliverable": true,
    "catch_all": false,
    "disposable": false,
    "free_provider": false,
    "role_account": false,
    "blacklisted": false
  },
  "did_you_mean": null,
  "mx_record": "aspmx.l.google.com",
  "smtp_response": "250 2.1.5 OK",
  "duration_ms": 1240
}

Batch validation

POST/api/v1/validate-batch

Submit up to 10,000 emails per request. The call returns immediately with a job id; validation runs asynchronously. Duplicates are removed before counting against your quota.

curl
curl -X POST https://skipbounce.com/api/v1/validate-batch \
  -H "Authorization: Bearer sb_live_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{"emails": ["a@example.com", "b@example.com"]}'
Response 202
{
  "job_id": "6f6f3d1e-...",
  "status": "pending",
  "total": 2,
  "poll": "https://skipbounce.com/api/v1/jobs/6f6f3d1e-..."
}

Job status & results

GET/api/v1/jobs/:id

Poll until status is completed. Pass ?include=results to embed the per-email results. Jobs and their results are deleted 48 hours after completion.

Response 200
{
  "job_id": "6f6f3d1e-...",
  "status": "completed",
  "total": 2,
  "processed": 2,
  "counts": {
    "deliverable": 1,
    "undeliverable": 1,
    "risky": 0,
    "unknown": 0
  },
  "expires_at": "2026-08-16T14:00:00Z",
  "results": [ /* with ?include=results */ ]
}

Result statuses

Deliverable

The mail server explicitly accepted the mailbox. Safe to send.

Undeliverable

Hard failure: bad syntax, dead domain, or the server rejected the mailbox. Sending will bounce.

Risky

Will probably accept mail, but: catch-all domain, role account (info@, post@), or disposable inbox.

Unknown

The server gave no definitive answer (greylisting, timeouts). We never guess — treat with care.

Errors & rate limits

Errors always use the same shape and meaningful HTTP status codes:

Error shape
{
  "error": {
    "code": "quota_exceeded",
    "message": "Validation quota exhausted. Upgrade your plan or wait for the next billing period."
  }
}
StatusCodeMeaning
400bad_requestMalformed input
401unauthorizedMissing or invalid API key
402quota_exceededMonthly validation quota used up
403forbiddenYour plan does not include API access
404not_foundUnknown job id
429rate_limitedToo many requests — max 60/min per key
503validation_unavailableEngine temporarily unreachable; retry with backoff

Rate limit: 60 requests/minute per key for real-time validation. Batch jobs are queued and don't count toward the per-minute limit.

API Documentation · SkipBounce