The AI-regulation dataset, as a clean JSON API
Read-only, versioned access to every AI law and bill we track — US state & federal, the EU, and globally — with a changelog you can poll and HMAC-signed webhooks for changes. Get a free key in seconds.
https://ai-law-tracker.com/api/v1Quick start
Every endpoint works anonymously at a low rate. Add your key to raise the limit and identify your app.
# List the 5 most recently updated records
curl "https://ai-law-tracker.com/api/v1/laws?limit=5&sort=updated_at&order=desc" \
-H "X-API-Key: alt_free_9f3c…"const res = await fetch(
"https://ai-law-tracker.com/api/v1/laws?scope=state&jurisdiction=colorado",
{ headers: { "X-API-Key": process.env.ALT_API_KEY } }
);
const { data, meta } = await res.json();Authentication
Pass your key on every request in either header:
X-API-Key: alt_free_9f3c…
# or
Authorization: Bearer alt_free_9f3c…A missing key is fine — you're served as anonymous at the per-IP cap. An invalid or revoked key returns 401/403. Keep keys server-side.
Get a free key
Rate limits
Every response carries X-RateLimit-Limit, X-RateLimit-Remaining and X-RateLimit-Reset. Over the limit returns 429 with Retry-After.
| Tier | Per minute | Per day |
|---|---|---|
| Anonymous (no key) | 20 | 500 |
| Free | 60 | 2,000 |
| Developer | 120 | 5,000 |
| Pro | 300 | 50,000 |
| Business | 1,000 | 500,000 |
Need more? See paid tiers →
Endpoints
/v1/healthcurl "https://ai-law-tracker.com/api/v1/health" \
-H "X-API-Key: alt_free_9f3c…"{
"api_version": "v1",
"status": "ok",
"backend": "supabase",
"records": 697
}/v1/laws| Param | In | Type | Description |
|---|---|---|---|
| scope | query | state | federal | eu | global | Filter by scope. |
| jurisdiction | query | string | Exact jurisdiction slug (e.g. colorado, eu, us-federal, canada). |
| status | query | string | Case-insensitive substring match on status. |
| in_force | query | boolean | Filter by the in_force flag. |
| updated_since | query | string | Only records updated at/after this ISO timestamp. |
| q | query | string | Substring search over title + summary. |
| sort | query | updated_at | record_date | title | |
| order | query | asc | desc | |
| limit | query | integer | |
| offset | query | integer |
curl "https://ai-law-tracker.com/api/v1/laws?scope=state&jurisdiction=value" \
-H "X-API-Key: alt_free_9f3c…"{
"api_version": "v1",
"data": [
{
"id": "5f9c2b0a-1e34-4d21-9a77-0c1b2d3e4f56",
"scope": "state",
"jurisdiction": { "slug": "colorado", "name": "Colorado", "abbr": "CO" },
"identifier": "SB 24-205",
"title": "Consumer Protections for Artificial Intelligence",
"record_type": "bill",
"status": "Signed — effective 2026-02-01",
"in_force": null,
"record_date": "2024-05-17T00:00:00Z",
"summary": "Requires developers and deployers of high-risk AI systems to use reasonable care to avoid algorithmic discrimination…",
"source": "leg.colorado.gov",
"official_url": "https://leg.colorado.gov/bills/sb24-205",
"updated_at": "2026-07-05T14:02:11Z",
"attribution": "Data by AI Law Tracker (CC BY 4.0) — https://ai-law-tracker.com"
}
],
"meta": { "total": 564, "count": 1, "limit": 20, "offset": 0 }
}/v1/laws/{id}| Param | In | Type | Description |
|---|---|---|---|
| id * | path | string |
curl "https://ai-law-tracker.com/api/v1/laws/5f9c2b0a-…" \
-H "X-API-Key: alt_free_9f3c…"{
"api_version": "v1",
"data": {
"id": "5f9c2b0a-1e34-4d21-9a77-0c1b2d3e4f56",
"scope": "state",
"jurisdiction": { "slug": "colorado", "name": "Colorado", "abbr": "CO" },
"identifier": "SB 24-205",
"title": "Consumer Protections for Artificial Intelligence",
"status": "Signed — effective 2026-02-01",
"official_url": "https://leg.colorado.gov/bills/sb24-205",
"updated_at": "2026-07-05T14:02:11Z",
"attribution": "Data by AI Law Tracker (CC BY 4.0) — https://ai-law-tracker.com"
}
}/v1/laws/{id}/historyEvery snapshot of the record (ascending observed_at), each with change_kind, changed_fields and the record values as of that snapshot.
| Param | In | Type | Description |
|---|---|---|---|
| id * | path | string |
curl "https://ai-law-tracker.com/api/v1/laws/5f9c2b0a-…/history" \
-H "X-API-Key: alt_free_9f3c…"/v1/changesTime-ordered feed of every observed insert/update across the dataset, unioned from the append-only history of legal records and jurisdiction summaries. Poll with ?since=<meta.cursor>. Free-beta clamps the lookback window per tier (see meta.window).
| Param | In | Type | Description |
|---|---|---|---|
| since | query | string | Only changes observed after this ISO timestamp (pass the previous response meta.cursor to poll). |
| scope | query | state | federal | eu | global | Filter by scope. |
| jurisdiction | query | string | Exact jurisdiction slug. |
| entity | query | law_record | jurisdiction | Restrict to one dataset (default: both). |
| significant | query | boolean | Drop internal metadata-only updates (keeps inserts + real field changes). |
| order | query | asc | desc | Order by observed_at. |
| limit | query | integer | |
| offset | query | integer |
curl "https://ai-law-tracker.com/api/v1/changes?since=value&scope=state" \
-H "X-API-Key: alt_free_9f3c…"{
"api_version": "v1",
"data": [
{
"event_id": "a1b2c3d4-0000-4444-8888-abcdef012345",
"entity": "law_record",
"record_id": "5f9c2b0a-1e34-4d21-9a77-0c1b2d3e4f56",
"scope": "state",
"jurisdiction": { "slug": "washington", "name": "Washington", "abbr": "WA" },
"identifier": "HB 1170",
"change_kind": "update",
"changed_fields": ["status"],
"field_changes": [{ "field": "status", "from": "In committee", "to": "Passed House" }],
"observed_at": "2026-07-07T09:15:44.512Z",
"attribution": "Data by AI Law Tracker (CC BY 4.0) — https://ai-law-tracker.com"
}
],
"meta": {
"count": 1, "limit": 50, "offset": 0, "order": "desc",
"cursor": "2026-07-07T09:15:44.512Z",
"window": { "tier": "free", "lookback_days": 90, "clamped": false }
}
}/v1/feedConvenience view over /changes with significant=true and no value diffs — the newest meaningful changes, human-scannable.
| Param | In | Type | Description |
|---|---|---|---|
| since | query | string | Only changes observed after this ISO timestamp (pass the previous response meta.cursor to poll). |
| scope | query | state | federal | eu | global | Filter by scope. |
| jurisdiction | query | string | Exact jurisdiction slug. |
| entity | query | law_record | jurisdiction | Restrict to one dataset (default: both). |
| limit | query | integer |
curl "https://ai-law-tracker.com/api/v1/feed?since=value&scope=state" \
-H "X-API-Key: alt_free_9f3c…"/v1/jurisdictions| Param | In | Type | Description |
|---|---|---|---|
| scope | query | state | federal | eu | global |
curl "https://ai-law-tracker.com/api/v1/jurisdictions?scope=state" \
-H "X-API-Key: alt_free_9f3c…"{
"api_version": "v1",
"data": [
{ "slug": "california", "name": "California", "abbr": "CA", "scope": "state", "count": 55 },
{ "slug": "eu", "name": "European Union", "abbr": "EU", "scope": "eu", "count": 12 }
],
"meta": { "count": 74 }
}/v1/search| Param | In | Type | Description |
|---|---|---|---|
| q * | query | string | |
| scope | query | state | federal | eu | global | Filter by scope. |
| jurisdiction | query | string | Exact jurisdiction slug (e.g. colorado, eu, us-federal, canada). |
| status | query | string | Case-insensitive substring match on status. |
| in_force | query | boolean | Filter by the in_force flag. |
| updated_since | query | string | Only records updated at/after this ISO timestamp. |
| sort | query | updated_at | record_date | title | |
| order | query | asc | desc | |
| limit | query | integer | |
| offset | query | integer |
curl "https://ai-law-tracker.com/api/v1/search?q=value&scope=state" \
-H "X-API-Key: alt_free_9f3c…"/v1/countriescurl "https://ai-law-tracker.com/api/v1/countries" \
-H "X-API-Key: alt_free_9f3c…"/v1/statescurl "https://ai-law-tracker.com/api/v1/states" \
-H "X-API-Key: alt_free_9f3c…"/v1/categoriescurl "https://ai-law-tracker.com/api/v1/categories" \
-H "X-API-Key: alt_free_9f3c…"/v1/keysSubmit an email to mint a free-tier key. The plaintext key is emailed to that address AND returned once in this response — it is never stored and cannot be recovered. One active free key per email; abusive request rates are throttled per IP.
curl "https://ai-law-tracker.com/api/v1/keys" \
-X POST -H "Content-Type: application/json" \
-d '{"email":"you@company.com"}'{
"api_version": "v1",
"key": "alt_free_9f3c… (shown once — store it now)",
"key_prefix": "alt_free_9f3c",
"id": "7c0d…",
"tier": "free",
"email": "you@company.com",
"email_delivery": { "delivered": true },
"note": "This key is shown only once and cannot be recovered."
}/v1/webhooksCreate a webhook. When a matching legal record change is observed, an HMAC-SHA256-signed POST is delivered to target_url. The signing_secret is returned ONCE in this response. Verify each delivery (see x-webhooks).
curl "https://ai-law-tracker.com/api/v1/webhooks" \
-X POST \
-H "X-API-Key: alt_pro_…" \
-H "Content-Type: application/json" \
-d '{"target_url":"https://your-app.com/hooks/alt"}'{
"api_version": "v1",
"data": {
"id": "b3c4…",
"target_url": "https://your-app.com/hooks/alt",
"events": ["law.created", "law.updated"],
"active": true,
"signing_secret": "whsec_… (shown once)",
"created_at": "2026-07-08T12:00:00Z"
}
}/v1/webhookscurl "https://ai-law-tracker.com/api/v1/webhooks" \
-H "X-API-Key: alt_free_9f3c…"{
"api_version": "v1",
"data": {
"id": "b3c4…",
"target_url": "https://your-app.com/hooks/alt",
"events": ["law.created", "law.updated"],
"active": true,
"signing_secret": "whsec_… (shown once)",
"created_at": "2026-07-08T12:00:00Z"
}
}/v1/webhooks/{id}| Param | In | Type | Description |
|---|---|---|---|
| id * | path | string |
curl "https://ai-law-tracker.com/api/v1/webhooks/5f9c2b0a-…" \
-H "X-API-Key: alt_free_9f3c…"/v1/webhooks/{id}| Param | In | Type | Description |
|---|---|---|---|
| id * | path | string |
curl "https://ai-law-tracker.com/api/v1/webhooks/5f9c2b0a-…" \
-X DELETE \
-H "X-API-Key: alt_free_9f3c…"Webhooks & signature verification
Subscribe with POST /v1/webhooks. Each change is delivered as an HMAC-SHA256-signed POST to your target_url. The signing_secret is returned once when you create the webhook.
| Header | Meaning |
|---|---|
| X-ALT-Signature | sha256=<hex HMAC-SHA256 of `${timestamp}.${rawBody}` under your signing_secret> |
| X-ALT-Timestamp | Unix seconds; folded into the signed content (reject if skew is large). |
| X-ALT-Event | law.created | law.updated |
| X-ALT-Delivery | Delivery uuid — use as an idempotency key. |
| X-ALT-Webhook-Id | The subscription uuid. |
Verify each delivery before trusting it — recompute the signature over `${timestamp}.${rawBody}`:
const crypto = require('crypto');
function verify(req, secret) {
const ts = req.headers['x-alt-timestamp'];
const sig = (req.headers['x-alt-signature'] || '').replace(/^sha256=/, '');
const expected = crypto.createHmac('sha256', secret).update(`${ts}.${req.rawBody}`).digest('hex');
const a = Buffer.from(sig), b = Buffer.from(expected);
return a.length === b.length && crypto.timingSafeEqual(a, b);
}Errors
Every error uses one uniform shape:
{
"api_version": "v1",
"error": {
"code": "rate_limited",
"message": "Rate limit exceeded for the minute window. Retry in 42s.",
"docs": "https://ai-law-tracker.com/developers",
"retry_after": 42
}
}Common codes: invalid_key (401), revoked_key (403), not_found (404), rate_limited (429), backend_unavailable (503).
Data is licensed CC BY 4.0 — free to use commercially with attribution. Attribution is mandatory on the free tier (a dofollow link to ai-law-tracker.com) and optional on paid tiers. Informational only — not legal advice. Verify against each record's official_url before relying on it.