JSON API reference
The Breachtide JSON API exposes the same scan state your dashboard renders, scoped to the monitored email addresses you own. It is read-only, JSON over HTTPS, and authenticated with a per-account Bearer token issued from your settings page.
Machine-readable spec: /openapi.json. Drop it into any OpenAPI 3.1 client to generate types or a SDK.
Base URL
https://breachtide.com/api/v1Authentication
Issue a token from /dashboard/settings. Send it on every request as a Bearer token in the Authorization header. The token is shown once at issue time; only its hash is stored. Rotate to invalidate the old token and issue a new one; revoke to disable API access entirely.
Authorization: Bearer bt_ak_<your-token>Requests with a missing or unrecognised token return 401 unauthorized.
Rate limit
60 requests per minute per API key, in a fixed one-minute window. Every response carries three headers so a client can pace itself without polling for limits:
Exceeding the limit returns 429 rate_limited. Wait until the reset and retry.
GET /me
Identity check. Returns the authenticated user, the email on file, and the active plan. Useful as a connectivity probe and for surfacing plan-gated features in your client.
{
"id": "u_01HW8N5XYZABCDEF",
"email": "[email protected]",
"plan": "pro"
}The plan field is one of free, personal, pro, or business. Users with no active subscription are reported as free.
GET /breaches
Returns the per-source scan state for one monitored email address you own. The address must already be added and verified on your account; unverified or unknown addresses are rejected before any data is returned.
{
"email": "[email protected]",
"sources": [
{
"source": "archive",
"breach_count": 3,
"source_dbs": [
"LinkedIn2016",
"Dropbox2012",
"MyFitnessPal2018"
],
"fields_exposed": [
"password",
"username"
],
"has_plaintext_password": true,
"last_scanned_at": "2026-05-08T11:42:18.000Z",
"last_changed_at": "2026-04-30T03:11:02.000Z"
},
{
"source": "enriched",
"breach_count": 1,
"source_dbs": [
"combolist.2026-04"
],
"fields_exposed": [
"password"
],
"has_plaintext_password": true,
"last_scanned_at": "2026-05-08T11:42:18.000Z",
"last_changed_at": "2026-05-02T17:08:44.000Z"
}
]
}Each entry in sources is the latest sweep result from one of the four feeds: archive (historical breach corpora), combolist (live credential combolists), index (continuously refreshed public breach index), and enriched (field-level breach detail on confirmed hits). Only sources that have been scanned at least once appear in the array.
Field reference
Errors
Examples
curl
curl -sS \
-H "Authorization: Bearer $BREACHTIDE_API_KEY" \
"https://breachtide.com/api/v1/[email protected]"Node.js
const token = process.env.BREACHTIDE_API_KEY;
const url = new URL('https://breachtide.com/api/v1/breaches');
url.searchParams.set('email', '[email protected]');
const res = await fetch(url, {
headers: { Authorization: `Bearer ${token}` },
});
if (res.status === 429) {
const reset = Number(res.headers.get('x-ratelimit-reset')) * 1_000;
await new Promise((r) => setTimeout(r, reset - Date.now()));
}
if (!res.ok) {
throw new Error(`breachtide ${res.status}: ${await res.text()}`);
}
const body = await res.json();
console.log(body.sources);Python
import os
import time
import httpx
token = os.environ["BREACHTIDE_API_KEY"]
client = httpx.Client(
base_url="https://breachtide.com/api/v1",
headers={"Authorization": f"Bearer {token}"},
)
resp = client.get("/breaches", params={"email": "[email protected]"})
if resp.status_code == 429:
reset = int(resp.headers["X-RateLimit-Reset"])
time.sleep(max(0, reset - int(time.time())))
resp = client.get("/breaches", params={"email": "[email protected]"})
resp.raise_for_status()
print(resp.json()["sources"])Operational notes
- The API surfaces only the metadata fields shown above. Decrypted values (passwords, DOBs, addresses, phones) are never returned over the API; they are visible only in the dashboard, gated by the Pro and Business plans, and audited per access.
- last_changed_at is the field to monitor in your own integration: a change here is the same signal that triggers a Breachtide alert.
- Tokens are tied to the issuing user. If you rotate, the old token stops working immediately; deploy the replacement before rotating.
- For push delivery instead of polling, see the webhook signing reference. Webhook delivery is gated to Pro and Business.