- authentication
- Secret API key as a bearer token
- billing
- Free.
Every email lookup the account ran through any channel — the API, the dashboard, the form widget, batch and bulk runs, monitors, the MCP server — newest first, 100 per page, for the retention window (meta.retention_days, 30 days by default). Each row records the verdict, the reason, the risk score, whether the mailbox handshake answered, what the lookup cost, whether it was a 7-day repeat, and the channel that ran it as via.
Rows are written after billing, so a refused lookup never appears here, and test addresses are never logged. Filters combine. An unknown verdict or an unparseable date answers 422.
Parameters
| name | in | type | description |
|---|---|---|---|
| page | query | integer | The page to return. Default: 1. |
| verdict | query | string | Only lookups with this verdict. One of: deliverable, risky, undeliverable. |
| query | string | Only lookups of this exact address, compared case-insensitively against the address as it was checked. At most 254 characters. | |
| since | query | string | Only lookups on or after this date or timestamp (ISO 8601). |
| until | query | string | Only lookups on or before this timestamp; a bare date covers the whole day. |
| via | query | string | Only lookups from this channel, matched exactly: `api · {key name}`, `dashboard`, `widget · {key name}`, `bulk run #{id}`, `monitor · {name}`, or `mcp · {key name}`. At most 120 characters. |
Example request
curl https://spaw.co/api/v1/email/history \ -H "Authorization: Bearer sk_live_…"
Responses
200One page of history rows.
{
"success": true,
"data": {
"lookups": [
{
"id": 9310,
"email": "[email protected]",
"deliverable": "deliverable",
"reason": null,
"risk_score": 0,
"mx_provider": "google",
"smtp_checked": true,
"credits_used": 1,
"cache_hit": false,
"via": "api · Production key",
"created_at": "2026-09-03T10:12:44+00:00"
},
{
"id": 9309,
"email": "[email protected]",
"deliverable": "risky",
"reason": "role",
"risk_score": 30,
"mx_provider": "other",
"smtp_checked": true,
"credits_used": 0,
"cache_hit": true,
"via": "dashboard",
"created_at": "2026-09-03T09:58:02+00:00"
}
]
},
"meta": {
"page": 1,
"per_page": 100,
"total": 2,
"retention_days": 30
}
}401The key is missing, malformed, or revoked.
{
"success": false,
"error": {
"code": "UNAUTHENTICATED",
"message": "Provide a valid API key as a bearer token.",
"request_id": "req_01m1kgdm4xngzmbmff68g94w0c"
}
}422The request body could not be validated; `error.errors` lists the fields.
{
"success": false,
"error": {
"code": "VALIDATION_FAILED",
"message": "The email field is required.",
"errors": {
"email": [
"The email field is required."
]
},
"request_id": "req_01m1kgdm4xngzmbmff68g94w0c"
}
}429Over 5 requests per second for the key. Retry after the limit resets.
{
"success": false,
"error": {
"code": "RATE_LIMITED",
"message": "Too many requests. Retry after the limit resets.",
"request_id": "req_01m1kgdm4xngzmbmff68g94w0c"
}
}Error codes
Failures answer { success: false, error: { code, message, request_id } }. Each code has its own page.