API Documentation
All endpoints require an X-API-Key header with a valid API key. Keys are managed at /admin/api-keys.
/api/v1/validate/single
— Validate a single email address
Request
POST /api/v1/validate/single
X-API-Key: <your-key>
Content-Type: application/json
{
"email": "user@example.com",
"company_id": 1,
"force_revalidate": false
}
| Field | Required | Description |
|---|---|---|
email | Yes | The email address to validate |
company_id | No | Company to bill against. Defaults to the key's primary company. Required if the key is assigned to multiple companies. |
force_revalidate | No | true to skip the cache and always call the validator, even if a fresh result exists. Default: false |
Response
{
"email": "user@example.com",
"status": "Valid",
"raw_status": "ok",
"source": "elv",
"cached": true,
"date_last_validated": "2025-06-01T12:34:56"
}
| Field | Type | Description |
|---|---|---|
email | string | The email that was checked |
status | string | Valid, Invalid, or Greylist |
raw_status | string | The raw status code returned by the validator |
source | string | Validation provider used (elv, custom, …) |
cached | boolean | true if result was served from the local DB cache |
date_last_validated | string (ISO 8601) | When the email was last validated against the provider |
/api/v1/companies
— List companies accessible by this API key
Returns the companies your API key is authorized for. Use the id as company_id in other requests.
Request
GET /api/v1/companies X-API-Key: <your-key>
Response
[
{"id": 1, "name": "Acme Corp", "slug": "acme-corp"},
{"id": 3, "name": "Beta Ltd", "slug": "beta-ltd"}
]
/api/v1/validate/file
— Upload a CSV for bulk validation
Upload a CSV file with an email column (header must be exactly email).
The endpoint returns a job_id immediately; processing runs in the background.
Request — multipart/form-data
POST /api/v1/validate/file?company_id=1&force_revalidate=false X-API-Key: <your-key> Content-Type: multipart/form-data file=@emails.csv (field name must be "file")
| Query param | Required | Description |
|---|---|---|
company_id | No | Company to bill against. Defaults to the key's primary company. Required if the key is assigned to multiple companies. |
force_revalidate | No | true to skip cache for all emails in the file. Default: false |
Example CSV
email alice@example.com bob@example.com charlie@example.com
Response
{
"job_id": 42,
"status": "Processing",
"total": 3
}
/api/v1/jobs/{job_id}
— Poll job progress
Poll this endpoint until status is Done or Error.
Request
GET /api/v1/jobs/42 X-API-Key: <your-key>
Response — in progress
{
"job_id": 42,
"status": "Processing",
"progress": 65,
"total": 1000,
"processed": 650
}
Response — complete
{
"job_id": 42,
"status": "Done",
"progress": 100,
"total": 1000,
"processed": 1000
}
| Status value | Meaning |
|---|---|
Pending | Job queued, not started yet |
Processing | Currently being validated |
Done | Complete — download results with the endpoint below |
Error | Job failed — check error_message field |
/api/v1/reports/summary
— Summary counts for the report header
Query params
| Param | Type | Description |
|---|---|---|
company_id | int | Filter by company (omit = all) |
start_date | YYYY-MM-DD | Start of date range (filters date_last_validated) |
end_date | YYYY-MM-DD | End of date range (inclusive) |
Response
{
"total": 1500,
"valid": 900,
"greylist": 200,
"invalid": 400,
"last_called_count": 320
}
last_called_count = contacts whose last_called timestamp falls within the date range.
/api/v1/contacts
— Server-side paginated contacts list
Query params
| Param | Type | Default | Description |
|---|---|---|---|
company_id | int | N/A | Filter by company |
start_date | YYYY-MM-DD | N/A | Filter by last_called start |
end_date | YYYY-MM-DD | N/A | Filter by last_called end |
search | string | N/A | Free-text search on email, status, domain |
order_by | string | id | One of: id, email, status, domain, mx_records, date_last_validated, last_called |
order_dir | asc / desc | desc | Sort direction |
offset | int | 0 | Pagination offset |
limit | int | 50 | Page size (max 1000) |
draw | int | 1 | DataTables draw counter (passed through in response) |
Response
{
"draw": 1,
"recordsTotal": 1500,
"recordsFiltered": 320,
"data": [
{
"id": 1,
"email": "test@example.com",
"status": "Valid",
"domain": "example.com",
"mx_records": "mx1.example.com",
"date_last_validated": "2025-03-20 10:00:00",
"last_called": "2025-03-20 10:00:00"
}
]
}
/api/v1/jobs/{job_id}/download
— Download result CSV
Returns a CSV file once the job status is Done.
Request
GET /api/v1/jobs/42/download X-API-Key: <your-key>
Response — text/csv
email,status alice@example.com,Valid bob@example.com,Invalid charlie@example.com,Greylist
The status column contains Valid, Invalid, or Greylist.
cURL Examples
List companies
curl -s https://verify.sendability.com/api/v1/companies \ -H "X-API-Key: YOUR_KEY"
Single email
curl -s -X POST https://verify.sendability.com/api/v1/validate/single \
-H "X-API-Key: YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{"email": "test@example.com", "company_id": 1}'
Single email — force revalidate (skip cache)
curl -s -X POST https://verify.sendability.com/api/v1/validate/single \
-H "X-API-Key: YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{"email": "test@example.com", "company_id": 1, "force_revalidate": true}'
Bulk file upload
curl -s -X POST "https://verify.sendability.com/api/v1/validate/file?company_id=1" \ -H "X-API-Key: YOUR_KEY" \ -F "file=@emails.csv"
Poll until done & download
# Poll status curl -s https://verify.sendability.com/api/v1/jobs/42 \ -H "X-API-Key: YOUR_KEY" # Download results (once status=Done) curl -s https://verify.sendability.com/api/v1/jobs/42/download \ -H "X-API-Key: YOUR_KEY" -o results.csv