Skip to content

API reference/status

Health, latency and data freshness

GET/api/v1/status/data

authentication
No authentication
billing
Free.

The facts behind the public status page, without authentication: the state of each component behind an answer (the database, IP geolocation, the mailbox handshake, the live carrier check, and the server-side renderer behind the website), the sync date, freshness and range counts of every dataset behind the lookups, measured API latency per endpoint group over the last hour and the last 24 hours, and ninety days of measured availability rolled up a day at a time.

ok is false when any component is degraded; a component that was never switched on for this deployment reads not_configured and does not make it false. A degraded component that is holding off says when it will be retried in retry_in_seconds. Percentiles are computed over the requests that succeeded — a refusal that never reached a provider is not evidence the API is fast — and success_rate reports the share that succeeded, over sample requests of which answered were answered. error_rate is the share that failed on this side — a 402, 429 or 422 is an answer about the request, not a fault here, so only error_rate is a reason to worry. A window with fewer than 20 requests is not published at all, and the percentiles are withheld unless at least 20 of them were answered. The weekly quality measurements published on the status page — the delivery outcomes customers reported back against the email verdicts we gave, and the business-register round trip — are page copy and are deliberately not in this payload: they are measured once a week and dated on the page, and a monitor polling for one would be polling for last Sunday. Point a monitor at it, or read it before a big run to know how fresh the feeds are. Throttled at 60 requests per minute per IP.

Example request

curl https://spaw.co/api/v1/status/data
const response = await fetch('https://spaw.co/api/v1/status/data', {
  method: 'GET',
});
const result = await response.json();
import requests

response = requests.get(
    'https://spaw.co/api/v1/status/data',
)
result = response.json()
$ch = curl_init('https://spaw.co/api/v1/status/data');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
]);
$result = json_decode(curl_exec($ch), true);
from spaw import Client

client = Client('sk_live_…')
result = client.data_status()
import Spaw from 'spaw';

const spaw = new Spaw({ apiKey: 'sk_live_…' });
const result = await spaw.dataStatus();
use Spaw\Client;

$spaw = new Client('sk_live_…');
$result = $spaw->dataStatus();

This endpoint has no console on its page. It is free and needs no key, but it takes no input either — there is nothing to type. /status publishes the same table with the dates spelled out.

Responses

200The current status.

{
    "success": true,
    "data": {
        "ok": false,
        "checked_at": "2026-09-04T18:00:00+00:00",
        "components": [
            {
                "component": "database",
                "name": "Database",
                "state": "operational",
                "detail": "Queries are answering.",
                "retry_in_seconds": null
            },
            {
                "component": "ip-geolocation",
                "name": "IP geolocation",
                "state": "operational",
                "detail": "The geolocation database is installed.",
                "retry_in_seconds": null
            },
            {
                "component": "mailbox-handshake",
                "name": "Mailbox handshake",
                "state": "degraded",
                "detail": "Probes are paused after repeated upstream failures, so addresses answer unverified instead of waiting out a timeout. The next attempt is in 240 seconds.",
                "retry_in_seconds": 240
            },
            {
                "component": "live-carrier-check",
                "name": "Live carrier check",
                "state": "not_configured",
                "detail": "Not switched on for this deployment: phone verdicts come from the numbering data alone.",
                "retry_in_seconds": null
            },
            {
                "component": "ssr",
                "name": "Server-side rendering",
                "state": "operational",
                "detail": "Pages are rendered on the server before they are sent.",
                "retry_in_seconds": null
            }
        ],
        "datasets": [
            {
                "dataset": "dbip-city-lite",
                "version": "2026-08-01",
                "installed": true,
                "feeds": null,
                "freshness": "current",
                "age_days": 34
            },
            {
                "dataset": "datacenter-ranges",
                "version": "2026-09-04",
                "installed": true,
                "feeds": 12,
                "freshness": "current",
                "age_days": 0
            },
            {
                "dataset": "libphonenumber",
                "version": "9.0.37",
                "installed": true,
                "feeds": null,
                "freshness": "not_dated",
                "age_days": null
            }
        ],
        "latency": [
            {
                "group": "ip",
                "window": "1h",
                "p50_ms": 2,
                "p95_ms": 6,
                "success_rate": 100,
                "error_rate": 0,
                "sample": 812,
                "answered": 812
            },
            {
                "group": "email",
                "window": "1h",
                "p50_ms": 410,
                "p95_ms": 2100,
                "success_rate": 98.42,
                "error_rate": 0.08,
                "sample": 1204,
                "answered": 1185
            }
        ],
        "availability": {
            "days": 90,
            "since": "2026-06-13",
            "until": "2026-09-10",
            "measured_days": 62,
            "days_without_requests": 28,
            "requests": 184320,
            "answered": 184102,
            "failed": 218,
            "availability": 99.88,
            "history": [
                {
                    "date": "2026-09-09",
                    "requests": 3140,
                    "answered": 3138,
                    "failed": 2,
                    "availability": 99.94,
                    "state": "operational",
                    "complete": true
                },
                {
                    "date": "2026-09-10",
                    "requests": 812,
                    "answered": 812,
                    "failed": 0,
                    "availability": 100,
                    "state": "operational",
                    "complete": false
                },
                {
                    "date": "2026-06-13",
                    "requests": 0,
                    "answered": 0,
                    "failed": 0,
                    "availability": null,
                    "state": "no_requests",
                    "complete": true
                }
            ]
        }
    }
}

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.

markdown version·openapi.json