Everything, in detail
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/v1Ask a general-purpose chatbot which AI laws apply to you and it will produce a fluent, confident, unciteable answer — and sometimes a statute that does not exist. This API answers the same question from a curated corpus of primary sources, with no language model anywhere in the path. Every obligation, deadline and penalty we return is retrieved verbatim from a real record and carries the government URL it came from. Same input, same output, every time.
Why teams pay — what paid unlocks
The free tier is not a crippled dataset — it is the full record quality at low volume. What you buy is the interpreted layer above the raw law, the change stream beneath it, and the headroom to run both in production.
Turns "here is the statute" into "here is what you must do, by when, or you owe what."
Raw law records tell you a bill exists. /v1/obligations, /v1/assess and /v1/penalties answer the question a compliance team actually has: given this jurisdiction, sector and AI use, which duties attach, what is the deadline, who enforces it, and what is the penalty. The derivation runs through the same deterministic engine as our paid compliance report — no LLM in the path — so it cannot invent a statute, a deadline or a fine. Each item ships with its citation, the enforcing body, a primary-source URL and a source_tier you can audit.
GET /v1/obligationsPOST /v1/assessGET /v1/penaltiesGET /v1/sectorsA signed webhook the moment a record changes — instead of re-crawling the dataset on a timer.
Every observed insert and update lands in an append-only history, exposed as /v1/changes and the human-scannable /v1/feed with field-level diffs (status: "In committee" → "Passed House"). Poll it with a cursor, or stop polling entirely: subscribe a webhook and each change is delivered as an HMAC-SHA256-signed POST, retried with backoff and dead-lettered if your endpoint stays down. This is what a static PDF tracker structurally cannot give you.
GET /v1/changesGET /v1/feedGET /v1/laws/{id}/historyPOST /v1/webhooksSee the full data quality for free. Pay when you put it in front of your users.
A free key returns the complete record — full fields, full filters — so you can evaluate the data properly before spending anything. What paid tiers add is production capacity: higher rate limits and durable daily quotas, deep pagination, bulk export at Business, and commercial use without the attribution backlink the free tier requires.
GET /v1/meGET /v1/lawsGET /v1/searchA live record from the deterministic engine — not a mock-up. This page renders it by calling the same code /v1/obligations runs, so it always matches what the endpoint would answer today.
{
"law": "NYC Local Law 144 (Automated Employment Decision Tools)",
"jurisdiction": "New York",
"layer": "landscape",
"lifecycle": "in_force",
"in_force": true,
"not_yet_effective": false,
"effective_date": "2023-07-05",
"applies_because": "Notable New York AI law, included for the national landscape. It binds businesses in New York — it may not apply to you unless you operate there.",
"obligation": "Employers using automated employment decision tools to screen candidates or employees for NYC positions must conduct an annual independent bias audit, publish a summary on the employer website, notify candidates at least 10 business days in advance, and offer an alternative selection process on request.",
"deadline": null,
"penalty": "$500 for first violation; $500 to $1,500 for each subsequent violation, per day per candidate; DCWP enforcement",
"status": null,
"citation": "NYC Admin. Code Section 20-870 et seq.; 6 RCNY Sections 5-300 to 5-304 (effective July 5, 2023)",
"government_body": "NYC Department of Consumer and Worker Protection",
"may_not_apply": true,
"source_url": "https://www.nyc.gov/site/dca/about/automated-employment-decision-tools.page",
"source_tier": "primary"
}Note source_url and source_tier: every obligation is traceable to the government page it came from, and you can tell a primary source from a secondary one. Informational only — not legal advice.
What each tier unlocks
Every cell below is read straight from the capability matrix the API enforces at request time — this table cannot promise something the gate would refuse. Prices and billing live on the pricing page.
| Capability | Free | Starter | Pro | Business |
|---|---|---|---|---|
| Interpreted obligation layer | ||||
| Obligations — GET /v1/obligations Opens at Pro | Preview (1 item) | Preview (1 item) | Full | Full |
| Risk assessment — POST /v1/assess Opens at Pro | Preview (1 item) | Preview (1 item) | Full | Full |
| Penalties & enforcement — GET /v1/penalties Opens at Starter | Preview (1 item) | Full | Full | Full |
| Change intelligence | ||||
| Change feed — /v1/changes, /v1/feed Developer+ | — | 30-day window | 90-day window | Full history |
| Per-record history — /v1/laws/{id}/history Developer+ | — | 30-day window | 365-day window | Full history |
| HMAC-signed change webhooks Pro+ | — | — | 3 endpoints | 25 endpoints |
| Volume & access | ||||
| Records per request | 25 | 100 | 100 | 100 |
| Pagination depth (max offset) | 200 | 100,000 | 500,000 | 5,000,000 |
| Rate limit | 60/min · 300/day | 150/min · 5,000/day | 300/min · 10,000/day | 1,000/min · 15,000/day |
| Bulk export | — | — | — | Included |
Enterprise is quoted per contract: unlimited API requests (no monthly quota, no overage) with 2,000 req/min guaranteed, full history, unlimited webhooks, bulk export, and OEM/resale terms — subject to Fair Use (we reach out before we throttle; bulk redistribution needs a licence). See /terms#fair-use.
Quick 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();Use it in Claude & ChatGPT
The same data is exposed as an MCP (Model Context Protocol) server, so you can ask Claude or ChatGPT about AI regulation and it will query this dataset live — laws, jurisdictions, news, the change feed, and the interpreted obligations / penalties / risk layer. No key works at the anonymous tier; paste your key to unlock full tiers.
https://ai-law-tracker.com/api/mcp (Streamable HTTP)- Claude.ai → Settings → Connectors → Add custom connector.
- URL:
https://ai-law-tracker.com/api/mcp - Under Request headers, add
x-api-key= your AI Law Tracker key (optional — skip it to try the anonymous tier). - Save, then ask e.g. “What AI hiring laws apply in California?”
- Create a GPT → Configure → Actions → Import from URL.
- Schema URL:
https://ai-law-tracker.com/api/v1/openapi.json - Authentication → API Key, custom header name
X-API-Key, paste your key. - In ChatGPT developer mode you can instead add the MCP endpoint above as an app.
Full setup notes (including the Connectors Directory / GPT Store path) live in docs/MCP-CONNECTOR.md. The connector is read-only and returns informational data — not legal advice.
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 | 100 |
| Free | 60 | 300 |
| Starter | 150 | 5,000 |
| Pro | 300 | 10,000 |
| Business | 1,000 | 15,000 |
| OEM / White-label | 1,500 | 20,000 |
| Enterprise | 2,000 | 2,000,000 |
Need more? See paid tiers →
US Law Platform — /v1/us-law
A separate product from the AI-law endpoints above: the general US-law corpus (~31,800 records across 52 jurisdictions), classified into 33 branches and 227 subcategories. A key is licensed for one product line or both — check yours with GET /v1/me, which reports product, your record allowance and your export entitlement. On a surface outside your licence you are served at the public (keyless) level, and the X-ALT-Product-Scope response header says so.
Metered on records served, not just requests. A request cap stops a fast client; a record cap stops a patient one. Every response carries meta.record_budget with what is left in the day and 30-day windows.
| Endpoint | What it does | Access |
|---|---|---|
GET /v1/us-law | List + filter the corpus (jurisdiction, instrument_type, branch, domain, in_force) | Everyone, metered |
GET /v1/us-law/search | Full-text + citation + EO-number search | Everyone, metered |
GET /v1/us-law/records/{uid} | One record in full | Everyone, metered |
GET /v1/us-law/jurisdictions | Per-jurisdiction coverage rollup | Open — no key, not metered |
GET /v1/us-law/taxonomy | The classification tree + corpus health | Open — no key, not metered |
GET /v1/us-law/export | Bulk export manifest — signed part links | US Law Business+ (licence) |
GET /v1/us-law/export/download | Stream one part (NDJSON | CSV | JSON) | Signed token only |
GET /v1/us-law/opinions | US case law — 988,554 published opinions (2015+): court, date range, case name, citation | Everyone, metered |
GET /v1/us-law/opinions/{cluster_id} | One opinion record in full | Everyone, metered |
GET /v1/us-law/courts | Per-court opinion coverage + the court lookup | Open — no key, not metered |
US case law
988,554 published opinions filed 2015 onward, from federal appellate courts and state supreme/appellate courts. Each record identifies a decision — case name, court, filing date, docket number, reporter citation, and how many later opinions cite it — and links to the decision itself. There is no opinion text and no holding in this corpus. It is metered on the same record budget as /v1/us-law, not a second one, so nothing about your existing allowance changes.
# every opinion a court filed in a date window, newest first curl "https://ai-law-tracker.com/api/v1/us-law/opinions?court=scotus&filed_from=2024-01-01&limit=25" -H "X-API-Key: $ALT_KEY" # by reporter citation (exact, case-sensitive) — or widen with citation_prefix curl "https://ai-law-tracker.com/api/v1/us-law/opinions?citation=2022%20OK%2038" -H "X-API-Key: $ALT_KEY" # by case name: websearch syntax, quoted phrases and -exclusion curl "https://ai-law-tracker.com/api/v1/us-law/opinions?q=%22Trump%20v.%20Cook%22" -H "X-API-Key: $ALT_KEY" # which courts we cover, and how deeply — no key needed curl "https://ai-law-tracker.com/api/v1/us-law/courts?jurisdiction_level=federal"
Two things behave differently here because the table is a million rows, and they apply at every tier including Enterprise. meta.total is the query planner's estimate above 1,000 rows — always read meta.total_is_estimate, and pass count=exact (needs any key, takes seconds) when you need the real number. And sort=citation_count / cited_min have no index behind them, so they are refused with a 400 unless your query already carries a narrowing filter. Coverage is uneven and /v1/us-law/courts publishes it: 147 of the 293 registered courts hold zero opinions, and a zero there is a gap in our coverage, not a fact about the court.
Bulk export in two calls
Ask for any slice the list endpoint can filter. You get back the exact row count, what it will cost against your record allowance, and one signed, 15-minute link per 10,000-row part. The links carry no API key, so you can hand one to a loader without handing over your credential — and every download is still metered against the key that created it.
# 1. plan it — nothing is charged here
curl "https://ai-law-tracker.com/api/v1/us-law/export?format=csv&instrument_type=executive_order" \
-H "X-API-Key: $ALT_KEY"
# -> { "export": { "records": 277, "parts": 1, "record_cost": 277, ... },
# "parts": [ { "part": 1, "records": 277, "url": "...?token=...", "expires_at": "..." } ] }
# 2. pull each part (order matters; for CSV keep only the first header row)
curl -L -o part01.csv "<parts[0].url>"Bulk export is not sold self-serve: taking the whole corpus as a file is arranged with us under licence, from the US Law — Business tier up. Exported records are metered against your allowance exactly as paged ones are. Every self-serve plan keeps full API access to the same data. See the ladder →
Enforcement layer — /v1/enforcement
AI enforcement actions and litigation at matter level — one row per dispute, not per press release. An agency action with a complaint, a settlement and a final order is three rows on /v1/enforcement (the news feed) and one matter here, with a timeline, parties, the relief imposed and the statutes invoked attached.
| Endpoint | What it does | Access |
|---|---|---|
GET /v1/enforcement/matters | List, filter and search matters (agency, jurisdiction, type, status, AI role, dates, q) | Everyone |
GET /v1/enforcement/matters/{uid} | One matter + its chain: events, parties, relief, statutes, source docs | Everyone; chain sampled below Pro |
GET /v1/enforcement/sources | The 254 monitored sources, with freshness and fault state | Open — no key, not metered |
GET /v1/enforcement/categories | The 13 controlled vocabularies every filter accepts | Open — no key, not metered |
GET /v1/enforcement/coverage | How many matters are held, publishable and withheld | Open — no key, not metered |
GET /v1/enforcement | The enforcement + litigation NEWS feed (a separate dataset) | Enterprise |
What the tier meters is depth, not count. The registry is a few dozen matters, so a record budget would limit nothing. Listing and searching are open at every tier; the assembled dossier — parties, relief amounts, the event timeline, the cited statutes — is a 2-row sample below Pro, and chain_totals always reports the real size of every chain so you can see what a sample is a sample of.
# every FTC matter we hold curl "https://ai-law-tracker.com/api/v1/enforcement/matters?agency=FTC&limit=25" \ -H "X-API-Key: $ALT_KEY" # one matter with its chain curl "https://ai-law-tracker.com/api/v1/enforcement/matters/us-ftc-2026-cleo-ai-inc" -H "X-API-Key: $ALT_KEY" # what we watch, and how much of it is answering right now — no key needed curl "https://ai-law-tracker.com/api/v1/enforcement/sources?is_stale=true" # how big the registry really is, including what is withheld — no key needed curl "https://ai-law-tracker.com/api/v1/enforcement/coverage"
Two things to read before you quote a number from this dataset
1. Every matter is single_source. Each one is recorded from one official source and published with the URL it came from. verification is never withheld at any tier — read it, and follow source_url, before relying on any claim.
2. An empty result is a statement about us, not about the agency. Roughly half of the 254 registered sources are currently stale or disabled, and part of the registry is withheld pending review. /v1/enforcement/sources and /v1/enforcement/coverage both publish those numbers — including the withheld count — so coverage can be checked rather than assumed.
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/lawsTIER-GATING: filters and sorting (scope, jurisdiction, status, in_force, updated_since, sort, order) are honoured at EVERY tier including anonymous — they are documented query semantics, so they are never silently dropped. What Free/anonymous callers get instead is low volume and shallow pagination: anon 5 rows per page with a trimmed field envelope, free-key 25 rows with the full field set. Developer+ raises the page size and unlocks deep pagination, the change feed and per-record history. When a request is capped, the response echoes meta.gated + an upgrade hint (it is never a hard error).
| 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. TIER-GATING: Developer+ only — anonymous/Free callers get 403 tier_upgrade_required. Lookback window climbs by tier: Developer 30 days, Pro 365 days, Business/Enterprise full history.
| 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>. TIER-GATING: Developer+ only — anonymous/Free callers get 403 tier_upgrade_required (the change feed is the paid differentiator). The lookback window is clamped per tier (Developer 30-day, Pro 90-day, Business/Enterprise full) — 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. TIER-GATING: same as /changes — Developer+ only (403 tier_upgrade_required for anonymous/Free).
| 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/newsThe audited AI-regulation news feed (headline + short excerpt + publisher + source URL — never full article text). Free/anon get a TASTE: fewer results, shallow pagination, only the newest headlines (a recency window) and the excerpt withheld. Developer+ gets the full archive, high volume and the excerpt. meta.window shows the tier recency floor; meta.gated + meta.upgrade show what was limited.
| Param | In | Type | Description |
|---|---|---|---|
| scope | query | state | federal | eu | global | Filter by scope. |
| jurisdiction | query | string | Exact jurisdiction slug (e.g. california, federal, eu, global). |
| q | query | string | Keyword substring search over the headline + excerpt. |
| from | query | string | Only headlines published on/after this date (YYYY-MM-DD). Free/anon are clamped to their recency window (see meta.window). |
| since | query | string | Alias for `from` — poll for headlines since a date. |
| to | query | string | Only headlines published on/before this date (YYYY-MM-DD). |
| limit | query | integer | Free/anon are capped lower (a taste). |
| offset | query | integer |
curl "https://ai-law-tracker.com/api/v1/news?scope=state&jurisdiction=value" \
-H "X-API-Key: alt_free_9f3c…"/v1/sectorscurl "https://ai-law-tracker.com/api/v1/sectors" \
-H "X-API-Key: alt_free_9f3c…"/v1/obligationsThe interpreted "what must I do" layer — who must do what, by when, or owe what penalty — for the given context. Every obligation is grounded in a real law record + its primary source (no LLM). Provide at least a jurisdiction or a sector. NOT legal advice. Paid feature (Pro+); lower tiers receive a one-item preview (meta.preview=true) with an upgrade hint.
| Param | In | Type | Description |
|---|---|---|---|
| jurisdiction | query | string | A US state slug (e.g. california) OR a covered country slug (e.g. canada, eu-germany). See /jurisdictions. |
| sector | query | string | A sector slug (see /sectors), e.g. healthcare, finance, hr-recruiting. |
| use | query | string | Comma-separated AI uses: hiring, customer, content, analytics, product, other. |
| decision_impact | query | hiring_firing | credit_insurance | healthcare | housing | internal_only | not_sure | What the AI decides about people (escalates applicability). |
curl "https://ai-law-tracker.com/api/v1/obligations?jurisdiction=value§or=value" \
-H "X-API-Key: alt_free_9f3c…"/v1/penaltiesPer applicable law: the monetary/other penalty, enforcing body, citation, and primary source, plus a sector-level penalty-structure summary (full result only). Provide at least a jurisdiction or a sector. Paid feature (Developer+); lower tiers receive a one-item preview.
| Param | In | Type | Description |
|---|---|---|---|
| jurisdiction | query | string | A US state slug (e.g. california) OR a covered country slug (e.g. canada, eu-germany). See /jurisdictions. |
| sector | query | string | A sector slug (see /sectors), e.g. healthcare, finance, hr-recruiting. |
curl "https://ai-law-tracker.com/api/v1/penalties?jurisdiction=value§or=value" \
-H "X-API-Key: alt_free_9f3c…"/v1/assessThe compliance-report engine (deterministic, no LLM — cannot hallucinate) as an API. POST a business profile; get the applicable AI-law obligations plus a reproducible 1–10 risk score with a named factor breakdown. state + sector are required. Paid feature (Pro+); lower tiers receive a preview (risk band + counts + one sample obligation; factor breakdown withheld).
curl "https://ai-law-tracker.com/api/v1/assess" \
-X POST \
-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 (your durable copy — find it again there anytime) AND returned once in this response. We never store the plaintext server-side. 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 on screen; also emailed to you)",
"key_prefix": "alt_free_9f3c",
"id": "7c0d…",
"tier": "free",
"email": "you@company.com",
"email_delivery": { "delivered": true },
"note": "Copy your key now — shown once on this screen. We also emailed it to you, so you can always find it again in that email."
}/v1/meReturns the presenting key's own account — tier, effective rate/quota limits, live durable usage (requests used today + this month, from the api_usage counter), remaining, reset times, and the capabilities the tier unlocks. The key IS the credential; no separate login. Powers the self-serve dashboard at /developers/dashboard. This call itself counts as one request.
curl "https://ai-law-tracker.com/api/v1/me" \
-H "X-API-Key: alt_free_9f3c…"{
"api_version": "v1",
"data": {
"key_prefix": "alt_free_9f3c",
"tier": "free",
"owner": "y••••@company.com",
"revoked": false,
"created_at": "2026-07-08T12:00:00Z",
"last_used_at": "2026-07-09T14:22:07Z",
"limits": { "per_min": 60, "per_day": 2000, "per_month": 60000 },
"usage": {
"tracking": true,
"day": { "used": 137, "limit": 2000, "remaining": 1863, "resets_in_seconds": 35080 },
"month": { "used": 4210, "limit": 60000, "remaining": 55790, "resets_in_seconds": 2110480 }
},
"capabilities": {
"list_max": 25, "full_fields": true, "advanced_filters": true,
"changes_window_days": null, "history_window_days": null,
"webhooks": 0, "bulk_export": false
}
}
}/v1/meSelf-service revoke of the presenting key. Irreversible — the key can no longer authenticate afterwards. Create a new key to keep using the API.
curl "https://ai-law-tracker.com/api/v1/me" \
-X DELETE \
-H "X-API-Key: alt_free_9f3c…"{
"api_version": "v1",
"data": {
"key_prefix": "alt_free_9f3c",
"tier": "free",
"owner": "y••••@company.com",
"revoked": false,
"created_at": "2026-07-08T12:00:00Z",
"last_used_at": "2026-07-09T14:22:07Z",
"limits": { "per_min": 60, "per_day": 2000, "per_month": 60000 },
"usage": {
"tracking": true,
"day": { "used": 137, "limit": 2000, "remaining": 1863, "resets_in_seconds": 35080 },
"month": { "used": 4210, "limit": 60000, "remaining": 55790, "resets_in_seconds": 2110480 }
},
"capabilities": {
"list_max": 25, "full_fields": true, "advanced_filters": true,
"changes_window_days": null, "history_window_days": null,
"webhooks": 0, "bulk_export": false
}
}
}/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). TIER-GATING: Pro+ only (Free/Developer allowance = 0 → 403 tier_upgrade_required). Per-key subscription cap: Pro 3, Business 25, Enterprise unlimited.
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…"/v1/accuracyThe machine-readable form of the public /accuracy page. Returns the latest source-liveness sweep summary (how many cited sources were checked, verified live, confirmed broken, or unverified), the count of confirmed-broken sources in the review queue, and the total append-only change-observations on record. Free/public: no tier gate, rate-limited like any endpoint. Every figure is a live count over real rows.
curl "https://ai-law-tracker.com/api/v1/accuracy" \
-H "X-API-Key: alt_free_9f3c…"/v1/enforcementAI-related regulatory enforcement (FTC/DOJ/SEC/state AG actions, etc.) and civil litigation (federal court dockets), over the same six AET fields — agency, respondent, allegation, outcome, penalty, statutory basis — plus forum for litigation rows. `change_type` tells the two lanes apart. ONLY status approved/published rows are ever returned: every draft the automated watch crons write starts pending and is invisible here until reviewed, so an empty data[] with meta.total: 0 is the expected response while a batch awaits approval — not an error. TIER-GATING: Enterprise-only. Anonymous, Free, and every self-serve paid tier (Developer $29 / Pro $99 / Business $299) get a hard 403 tier_upgrade_required — there is no teaser and no partial access below Enterprise. Same hard-gate pattern as /v1/changes, /v1/feed, and /v1/webhooks.
| Param | In | Type | Description |
|---|---|---|---|
| scope | query | state | federal | eu | global | Filter by scope. |
| jurisdiction | query | string | Exact jurisdiction slug. |
| q | query | string | Keyword substring search over title + summary. |
| agency | query | string | Substring match on the acting agency/regulator (e.g. FTC, DOJ, California Attorney General). |
| change_type | query | enforcement | litigation | Restrict to one lane: enforcement (agency actions) or litigation (civil dockets). Default: both. |
| date_from | query | string | Only items recorded on/after this date (YYYY-MM-DD). |
| date_to | query | string | Only items recorded on/before this date (YYYY-MM-DD). |
| limit | query | integer | |
| offset | query | integer |
curl "https://ai-law-tracker.com/api/v1/enforcement?scope=state&jurisdiction=value" \
-H "X-API-Key: alt_free_9f3c…"/v1/sectors/{sector}The free awareness OVERVIEW of a sector (name, risk, enforcement bodies, federal penalty structure) plus the DERIVED per-law obligations & penalties. The overview is open to every tier; the derived obligations/penalties are the interpreted layer — full for Pro+, a one-item preview (meta.preview=true) + upsell below. NOT legal advice.
| Param | In | Type | Description |
|---|---|---|---|
| sector * | path | string | A sector slug (see /sectors). |
curl "https://ai-law-tracker.com/api/v1/sectors/{sector}" \
-H "X-API-Key: alt_free_9f3c…"/v1/deadlinesA forward-looking compliance calendar derived deterministically from the curated corpus — each entry carries the VERBATIM source deadline text + primary-source URL (no fabricated dates; a jurisdiction whose deadline text has no explicit date is only counted in meta.undated). Free for every tier. Pass ?format=ical (alias ics) for an RFC 5545 .ics you can subscribe to (webcal). The interpreted "what must I do about each deadline" layer is on /obligations + /assess.
| Param | In | Type | Description |
|---|---|---|---|
| scope | query | state | federal | eu | global | Filter by scope. |
| jurisdiction | query | string | Exact jurisdiction slug (e.g. california, eu-germany). |
| upcoming | query | boolean | Only future dates (default). Set false (or all=true) to include past effective dates. |
| format | query | json | ical | ics | ical/ics returns a text/calendar .ics feed. |
curl "https://ai-law-tracker.com/api/v1/deadlines?scope=state&jurisdiction=value" \
-H "X-API-Key: alt_free_9f3c…"/v1/billsThe named, name-searchable AI laws (valid slugs for /bills/{slug}), from the primary-sourced landmark registry. Free.
curl "https://ai-law-tracker.com/api/v1/bills" \
-H "X-API-Key: alt_free_9f3c…"/v1/bills/{slug}One curated bill — core fields, tiered source URLs, citations (identifier + audited alternate names), and cross-links. Where a matching legal_records row exists, the response binds the live change timeline (links.history → /laws/{id}/history). Primary-sourced; the DB binding is best-effort (a miss omits the link, never fabricates it).
| Param | In | Type | Description |
|---|---|---|---|
| slug * | path | string | A bill slug (see /bills). |
curl "https://ai-law-tracker.com/api/v1/bills/{slug}" \
-H "X-API-Key: alt_free_9f3c…"/v1/laws/{id}/sourcesA record's own official/.gov link plus the curated jurisdiction sources, each tiered primary/secondary. Basic tiers (anon/Free) get primary sources only; Developer+ get the full set incl. secondary/analysis links. Only real held URLs — never fabricated.
| Param | In | Type | Description |
|---|---|---|---|
| id * | path | string |
curl "https://ai-law-tracker.com/api/v1/laws/5f9c2b0a-…/sources" \
-H "X-API-Key: alt_free_9f3c…"/v1/laws/{id}/citationsA record's identifier, title, audited alternate names, and a formatting-convenience suggested citation over public metadata (labelled — never an official cite). Free at every tier.
| Param | In | Type | Description |
|---|---|---|---|
| id * | path | string |
curl "https://ai-law-tracker.com/api/v1/laws/5f9c2b0a-…/citations" \
-H "X-API-Key: alt_free_9f3c…"/v1/auth/tokenA conventional token endpoint over the same key store as POST /keys. Submit an email; get a free-tier token, emailed once (durable copy) and returned once here. Only ever mints a FREE token (no privilege escalation); the owner/HMAC secret is never exposed. Paid tiers are granted via Polar checkout (POST /checkout). Throttled per IP; one active token per email.
curl "https://ai-law-tracker.com/api/v1/auth/token" \
-X POST \
-H "X-API-Key: alt_free_9f3c…"/v1/reportGenerate the personalized, source-grounded AI-law compliance report for a business profile — the SAME deterministic engine behind the $79 /compliance-report product (no LLM in the grounded path — it cannot invent a statute, deadline, or penalty). POST state + sector (+ optional AI-use profile). Default response is JSON: the risk assessment (1–10 score + obligations) plus a signed `report.download_url` for the rendered PDF. Pass `format:"pdf"` (or send `Accept: application/pdf`) to stream the PDF binary inline instead. Paid feature (Pro+) with a monthly report quota per tier (Pro 5/mo, Business 25/mo); when the quota is exhausted the endpoint returns 402 with an upgrade / single-report hint. Lower tiers receive a preview (risk band + counts + one sample obligation) with the PDF/download withheld behind an upgrade hint. Informational only — NOT legal advice.
curl "https://ai-law-tracker.com/api/v1/report" \
-X POST \
-H "X-API-Key: alt_free_9f3c…"/v1/us-lawStatutes, regulations and federal executive instruments at title/chapter/part level, each with its official citation, status, effective date, the official government source URL, and a many-to-many classification into 33 branches and 227 subcategories. Records LINK to the official text; they do not reproduce it. METERED ON RECORDS SERVED, not just on requests. A request cap stops a fast client; a record cap stops a patient one, and only the second is priced against the size of the corpus. Every response carries `meta.record_budget` with what is left in the day and 30-day windows; exhausting it returns 429 `record_budget_exceeded` (distinct from 429 `rate_limited`). PRODUCT SCOPE: this endpoint belongs to the US Law Platform. A key licensed only for AI Law Tracker (`product: ai_law`) is NOT refused here — it is served at the PUBLIC (keyless) capability level, the same few records any anonymous caller gets. The response headers say so explicitly: `X-ALT-Product` (what your key holds), `X-ALT-Product-Surface` (`us_law`) and `X-ALT-Product-Scope` (`in_product` | `out_of_product`). Your request rate and daily/monthly quota are NEVER degraded — those are metered per key wherever you call. What degrades is capability: page size, pagination depth, field envelope and the record budget.
| Param | In | Type | Description |
|---|---|---|---|
| branch | query | string | PRIMARY branch id from /us-law/taxonomy. Matches only records whose primary classification is this branch - narrower than branch_any, and usually not what you want for a coverage question. |
| branch_any | query | string | Branch id matched against ANY assignment, primary or secondary. Records are genuinely multi-branch (HIPAA is health law AND privacy law), so this is the complete answer: branch=health_law matches 1,942 records, branch_any=health_law matches 2,852. |
| domain | query | string | Subcategory id matched against ANY assignment, primary or secondary. |
| domain_primary | query | string | Subcategory id, primary classification only. |
| jurisdiction | query | string | Jurisdiction slug, e.g. california. Comma-separated for several: california,new-york. |
| jurisdiction_level | query | string | federal and/or state, comma-separated. |
| instrument_type | query | string | Document KIND: statute, regulation, executive_order, proclamation, agency_guidance, constitution, presidential_memorandum... Comma-separated for several. SCARCE types (executive orders, proclamations, agency guidance and other presidential instruments - about 3% of the corpus) are content-gated below the top tiers: the response is a small real SAMPLE, reported as meta.sampled with meta.sampled_reason "scarce_instrument_type", never a silent truncation. Listing a scarce type alongside a common one still arms that gate. |
| status | query | string | in_force, superseded, repealed, enacted, unknown. Comma-separated for several. |
| in_force | query | boolean | Operative law only (or only non-operative). |
| is_binding | query | boolean | Whether the instrument carries the force of law. false selects the guidance-type corpus. |
| effective_from | query | string | Effective on or after this date (YYYY-MM-DD). |
| effective_to | query | string | |
| enacted_from | query | string | |
| enacted_to | query | string | |
| repealed_from | query | string | |
| repealed_to | query | string | |
| retrieved_since | query | string | Records WE re-fetched on or after this time. This is our freshness stamp, NOT a claim that the law changed then - for that see /us-law/records/{record_uid}/history. |
| verified_since | query | string | Records WE re-verified on or after this time. Same caveat as retrieved_since. |
| citation | query | string | Exact citation match, case-insensitive - e.g. 45 CFR Part 164. Use citation_prefix to widen. |
| citation_prefix | query | string | Citation starts-with, e.g. 45 CFR for everything under that part. |
| identifier | query | string | Exact identifier match, e.g. Pub. L. 117-58. |
| record_uid | query | string | Fetch specific records by uid; comma-separated, up to 100. The batch form of /us-law/records/{record_uid}. |
| q | query | string | Substring match on title / short title / citation. For ranked full text over the summary as well, use /us-law/search. |
| sort | query | effective_date | enacted_date | repealed_date | retrieved_at | last_verified_at | title | citation | |
| order | query | asc | desc | |
| limit | query | integer | Clamped to your tier cap; the clamp is reported in `meta.gated`. |
| offset | query | integer | Clamped to your tier pagination depth. |
curl "https://ai-law-tracker.com/api/v1/us-law?branch=value&branch_any=value" \
-H "X-API-Key: alt_free_9f3c…"/v1/us-law/searchWebsearch-syntax full text ("quoted phrases", -exclusion) with a citation-substring fallback; the strategy that answered is reported in `meta.strategy`. A query that is a presidential document number ("EO 14110", "Proclamation 10925") is resolved against the INDEXED number column only — a miss returns nothing with an explanatory `meta.notice`, never a guessed match, because misidentifying a presidential document is worse than returning nothing. METERED ON RECORDS SERVED, not just on requests. A request cap stops a fast client; a record cap stops a patient one, and only the second is priced against the size of the corpus. Every response carries `meta.record_budget` with what is left in the day and 30-day windows; exhausting it returns 429 `record_budget_exceeded` (distinct from 429 `rate_limited`). PRODUCT SCOPE: this endpoint belongs to the US Law Platform. A key licensed only for AI Law Tracker (`product: ai_law`) is NOT refused here — it is served at the PUBLIC (keyless) capability level, the same few records any anonymous caller gets. The response headers say so explicitly: `X-ALT-Product` (what your key holds), `X-ALT-Product-Surface` (`us_law`) and `X-ALT-Product-Scope` (`in_product` | `out_of_product`). Your request rate and daily/monthly quota are NEVER degraded — those are metered per key wherever you call. What degrades is capability: page size, pagination depth, field envelope and the record budget.
| Param | In | Type | Description |
|---|---|---|---|
| q * | query | string | |
| branch | query | string | PRIMARY branch id from /us-law/taxonomy. Matches only records whose primary classification is this branch - narrower than branch_any, and usually not what you want for a coverage question. |
| branch_any | query | string | Branch id matched against ANY assignment, primary or secondary. Records are genuinely multi-branch (HIPAA is health law AND privacy law), so this is the complete answer: branch=health_law matches 1,942 records, branch_any=health_law matches 2,852. |
| domain | query | string | Subcategory id matched against ANY assignment, primary or secondary. |
| domain_primary | query | string | Subcategory id, primary classification only. |
| jurisdiction | query | string | Jurisdiction slug, e.g. california. Comma-separated for several: california,new-york. |
| jurisdiction_level | query | string | federal and/or state, comma-separated. |
| instrument_type | query | string | Document KIND: statute, regulation, executive_order, proclamation, agency_guidance, constitution, presidential_memorandum... Comma-separated for several. SCARCE types (executive orders, proclamations, agency guidance and other presidential instruments - about 3% of the corpus) are content-gated below the top tiers: the response is a small real SAMPLE, reported as meta.sampled with meta.sampled_reason "scarce_instrument_type", never a silent truncation. Listing a scarce type alongside a common one still arms that gate. |
| status | query | string | in_force, superseded, repealed, enacted, unknown. Comma-separated for several. |
| in_force | query | boolean | Operative law only (or only non-operative). |
| is_binding | query | boolean | Whether the instrument carries the force of law. false selects the guidance-type corpus. |
| effective_from | query | string | Effective on or after this date (YYYY-MM-DD). |
| effective_to | query | string | |
| enacted_from | query | string | |
| enacted_to | query | string | |
| repealed_from | query | string | |
| repealed_to | query | string | |
| retrieved_since | query | string | Records WE re-fetched on or after this time. This is our freshness stamp, NOT a claim that the law changed then - for that see /us-law/records/{record_uid}/history. |
| verified_since | query | string | Records WE re-verified on or after this time. Same caveat as retrieved_since. |
| citation | query | string | Exact citation match, case-insensitive - e.g. 45 CFR Part 164. Use citation_prefix to widen. |
| citation_prefix | query | string | Citation starts-with, e.g. 45 CFR for everything under that part. |
| identifier | query | string | Exact identifier match, e.g. Pub. L. 117-58. |
| record_uid | query | string | Fetch specific records by uid; comma-separated, up to 100. The batch form of /us-law/records/{record_uid}. |
| sort | query | relevance | effective_date | enacted_date | title | |
| order | query | asc | desc | Ignored when sort=relevance. |
| limit | query | integer | |
| offset | query | integer |
curl "https://ai-law-tracker.com/api/v1/us-law/search?q=value&branch=value" \
-H "X-API-Key: alt_free_9f3c…"/v1/us-law/taxonomyThe 33 branches and 227 subcategories the corpus is classified into, with descriptions, so a consumer can build ?branch= / ?domain= filters without guessing. Deliberately OPEN to everyone and NOT metered: it DESCRIBES the corpus, it is not the corpus, and a classification a customer cannot inspect is a black box. Also returns `meta.health` — `records_total`, `records_placeholder` (records still in the `other_unclassified` bucket) and `avg_domains_per_record`. That placeholder count is published rather than hidden: it is the honest measure of how far the classification actually reaches, and it is the number every public coverage claim on the site is checked against.
curl "https://ai-law-tracker.com/api/v1/us-law/taxonomy" \
-H "X-API-Key: alt_free_9f3c…"/v1/us-law/jurisdictionsOne row per jurisdiction: record counts by instrument type, the code edition held, and the verification stamps. Aggregated in the database — this endpoint must never be answered by paging the corpus, since inviting a caller to walk 31,800 records just to count them is exactly the bulk copy the record budget exists to prevent. Open for the same reason as /us-law/taxonomy: coverage is how you evaluate the dataset before paying for it.
| Param | In | Type | Description |
|---|---|---|---|
| jurisdiction_level | query | federal | state |
curl "https://ai-law-tracker.com/api/v1/us-law/jurisdictions?jurisdiction_level=federal" \
-H "X-API-Key: alt_free_9f3c…"/v1/us-law/opinionsPublished opinions filed 2015-01-01 onward from federal appellate courts and state supreme/appellate courts. Each record IDENTIFIES a decision — case name, court, filing date, docket number, reporter citation, and how many later opinions cite it — and links to the full decision at `absolute_url`. THERE IS NO OPINION TEXT AND NO HOLDING IN THIS CORPUS. `q` is a websearch full-text match over the CASE NAME only (quoted phrases and -exclusion work: `"Trump v. Cook"`, `monsanto -durnell`), and every response that ran one says so in `meta.search_field`. Do not describe this endpoint as searching the text of decisions. METERED ON RECORDS SERVED, on the SAME budget as /v1/us-law rather than a second one. That is deliberate: a separate allowance would have widened every existing key the day this dataset shipped. Every response carries `meta.record_budget`; exhausting it returns 429 `record_budget_exceeded`. TWO LIMITS COME FROM THE SIZE OF THE TABLE, NOT FROM YOUR TIER, and they apply identically at every tier including Enterprise. (1) `meta.total` is the PLANNER’S ESTIMATE above 1,000 rows — it measured 53% low on one full-text query — so it is always accompanied by `meta.total_is_estimate`; pass `count=exact` for the true number, at up to ~3.3 s. (2) `sort=citation_count` and `cited_min` have no index behind them and are refused with 400 unless the query already carries a narrowing filter; unfiltered, they are cancelled by the database statement timeout. PRODUCT SCOPE: this endpoint belongs to the US Law Platform. A key licensed only for AI Law Tracker is served here at the public (keyless) level, reported in `X-ALT-Product-Scope` — not refused.
| Param | In | Type | Description |
|---|---|---|---|
| court | query | string | Court slug, comma-separated for several (max 25), e.g. scotus,ca9. The valid values are published by /us-law/courts, which needs no key. |
| court_level | query | string | federal_appellate, state_supreme and/or state_appellate, comma-separated. |
| jurisdiction_level | query | string | federal and/or state, comma-separated. `state` covers both state_supreme and state_appellate. Combined with court_level it means the INTERSECTION; a contradictory pair returns an empty page rather than a silently dropped filter. |
| cluster_id | query | string | Fetch specific opinions by cluster id; comma-separated, up to 100. The batch form of /us-law/opinions/{cluster_id}. |
| filed_from | query | string | Filed on or after this date (YYYY-MM-DD). |
| filed_to | query | string | Filed on or before this date (YYYY-MM-DD). |
| q | query | string | Websearch full-text over the CASE NAME. Quoted phrases and -exclusion supported. It does NOT search opinion text — this corpus holds none. |
| citation | query | string | Exact reporter citation, e.g. 2022 OK 38. CASE-SENSITIVE against the canonical citation: the index that makes this a 212 ms lookup instead of a 6.3 s scan cannot answer a case-insensitive match. |
| citation_prefix | query | string | Citation starts-with, e.g. "2022 OK" for that year and reporter. The deliberate widening of `citation`, asked for by name so you know which you got. |
| cited_min | query | integer | Only opinions cited by at least this many later opinions. Requires at least one narrowing filter (see the endpoint description). |
| sort | query | date_filed | citation_count | citation_count requires at least one narrowing filter. case_name sorting is not offered — no index, and nobody pages a million captions alphabetically. |
| order | query | asc | desc | |
| count | query | estimated | exact | exact costs up to ~3.3 s and needs a key (any key, including a free one) — an unauthenticated request that can pin a database core for 3 s is a self-inflicted denial-of-service. A keyless caller silently gets `estimated` and sees `count` in meta.gated. |
| limit | query | integer | Clamped to your tier cap; the clamp is reported in meta.gated. |
| offset | query | integer | Clamped to your tier pagination depth. |
curl "https://ai-law-tracker.com/api/v1/us-law/opinions?court=value&court_level=value" \
-H "X-API-Key: alt_free_9f3c…"/v1/us-law/opinions/{cluster_id}The complete record for one CourtListener cluster id — the `cluster_id` field of any list result. Provenance (absolute_url, source_authority, bulk_edition, retrieved_at) is never withheld at any tier: the link to the decision is how you check our work, and withholding it to build an upsell would mean selling an unverifiable claim. The record identifies the decision; it does not contain it. `meta.corpus.full_text_at` points at the opinion itself. To fetch many at once use /us-law/opinions?cluster_id=1,2,3 (up to 100).
| Param | In | Type | Description |
|---|---|---|---|
| cluster_id * | path | integer | CourtListener cluster id. |
curl "https://ai-law-tracker.com/api/v1/us-law/opinions/{cluster_id}" \
-H "X-API-Key: alt_free_9f3c…"/v1/us-law/courtsOne row per REGISTERED court: how many opinions we hold, how many carry a reporter citation, and the earliest and latest filing dates. It is both the coverage table and the lookup the `court=` filter needs — a filter whose valid values are undiscoverable is not a filter, which is why this is open. 293 courts are registered and 146 hold opinions, so 147 rows come back with `opinions: 0`. They are not hidden: omitting them would overstate coverage. Read the date spans too — scotus shows 37,792 rows because CourtListener publishes orders and summary dispositions as clusters, and those thin out sharply after 2020. THE COUNTS ARE MATERIALISED AND THE RESPONSE SAYS WHEN. Computed live the aggregate takes 2.8 s against 988,554 rows, which on a keyless endpoint would be a self-inflicted denial-of-service. So every response carries `meta.counts_refreshed_at`, and `meta.counts_stale` goes true once the rollup is more than 48 hours old (the refresh runs daily). The numbers are never presented as current — they are presented with the timestamp that says how current they are.
| Param | In | Type | Description |
|---|---|---|---|
| court_level | query | federal_appellate | state_supreme | state_appellate | |
| jurisdiction_level | query | federal | state | |
| with_opinions | query | boolean | true = only courts we hold opinions for; false = only the registered courts we hold nothing for. |
curl "https://ai-law-tracker.com/api/v1/us-law/courts?court_level=federal_appellate&jurisdiction_level=federal" \
-H "X-API-Key: alt_free_9f3c…"/v1/us-law/exportPlans a bulk export of any slice /us-law can filter and returns a MANIFEST: the exact row count, what it will cost against your record allowance, and one SIGNED, short-lived download URL per part (NDJSON | CSV | JSON). The bytes come from the signed part URLs; this call serves no records and charges nothing. NOT SOLD SELF-SERVE AT ANY PRICE. Taking the whole corpus as a file is a licensing conversation, not a checkout — every self-serve plan keeps full API access to the same data and pages it instead. A below-tier caller gets 403 `tier_upgrade_required` naming the tier it opens at. Part URLs carry a signed token rather than your API key, so a link can be handed to a loader without handing over your credential; every download is still metered against the key that created it. PRODUCT SCOPE: this endpoint belongs to the US Law Platform. A key licensed only for AI Law Tracker (`product: ai_law`) is NOT refused here — it is served at the PUBLIC (keyless) capability level, the same few records any anonymous caller gets. The response headers say so explicitly: `X-ALT-Product` (what your key holds), `X-ALT-Product-Surface` (`us_law`) and `X-ALT-Product-Scope` (`in_product` | `out_of_product`). Your request rate and daily/monthly quota are NEVER degraded — those are metered per key wherever you call. What degrades is capability: page size, pagination depth, field envelope and the record budget.
| Param | In | Type | Description |
|---|---|---|---|
| format | query | ndjson | csv | json | |
| fields | query | full | basic | A tier restricted to the trimmed envelope cannot obtain the full one by asking; `basic` can only be chosen downward. |
| jurisdiction | query | string | |
| instrument_type | query | string | |
| branch | query | string | |
| domain | query | string | |
| in_force | query | boolean |
curl "https://ai-law-tracker.com/api/v1/us-law/export?format=ndjson&fields=full" \
-H "X-API-Key: alt_free_9f3c…"/v1/us-law/records/{record_uid}The complete record for one record_uid, including provenance (official_url, source_authority, full_text_url, full_text_sha256, retrieved_at, last_verified_at). Provenance is never withheld at any tier: on a legal surface the citation and the link to the government source are how you check our work, and withholding them to create an upsell would mean selling an unverifiable claim. To fetch many at once use /us-law?record_uid=uid1,uid2 (up to 100).
| Param | In | Type | Description |
|---|---|---|---|
| record_uid * | path | string |
curl "https://ai-law-tracker.com/api/v1/us-law/records/{record_uid}" \
-H "X-API-Key: alt_free_9f3c…"/v1/us-law/records/{record_uid}/historyThe recorded change log for one record: one entry per changed FIELD, newest first, across status, dates, citation, identifier, title, instrument type, classification, source URLs and summary. READ meta.capture_started_at BEFORE READING data. Nothing recorded a record-level diff on this corpus before 2026-08-20, and there is deliberately NO BACKFILL, because a backfill would have to invent what the record used to say. An empty result therefore means "we did not observe a change since capture began" and says so in meta.notice — it is NEVER a claim that the law has not changed. TIER: sampled below Pro (the most recent few entries, with the true total stated), full at Pro and above on either product ladder.
| Param | In | Type | Description |
|---|---|---|---|
| record_uid * | path | string |
curl "https://ai-law-tracker.com/api/v1/us-law/records/{record_uid}/history" \
-H "X-API-Key: alt_free_9f3c…"/v1/us-law/compareOne row per jurisdiction holding law in a branch or subcategory, with record counts, how many are in force, the split by instrument type, the latest effective date and when we last verified it. This is the answer you would otherwise have to page the entire 31,867-record corpus to assemble. COUNTING. `records` counts EVERY domain assignment, primary or secondary; `records_primary` counts only records whose PRIMARY classification is this branch. Both are reported because they differ a lot (health_law: 2,852 vs 1,942) and a comparison built on primary assignments alone would report that a state has no privacy law when its privacy statutes happen to be filed under consumer protection first. TIER. Ordinary single-field filtering on /us-law is open at every tier including keyless — discovery is never the thing that is metered. This is the assembled answer, so below Pro it returns a real 5-jurisdiction SAMPLE with the true totals stated in meta, and the full table at Pro and above on either product ladder.
| Param | In | Type | Description |
|---|---|---|---|
| branch | query | string | Branch id from /us-law/taxonomy. Either branch or domain is required. |
| domain | query | string | Subcategory id, for a narrower comparison. Mutually exclusive with branch. |
| jurisdiction_level | query | federal | state | |
| in_force_only | query | boolean | Only jurisdictions holding at least one operative record. |
curl "https://ai-law-tracker.com/api/v1/us-law/compare?branch=value&domain=value" \
-H "X-API-Key: alt_free_9f3c…"/v1/us-law/export/downloadStreams a single part of an export planned by GET /us-law/export. Authenticated by the SIGNED TOKEN in the manifest, not by an API key — so a part URL can be handed to a loader without handing over your credential. Tokens are short-lived and each download is still metered against the key that created the manifest. Any API key sent alongside is ignored: authority here comes from the token.
| Param | In | Type | Description |
|---|---|---|---|
| token * | query | string | The signed token from a manifest part URL. |
curl "https://ai-law-tracker.com/api/v1/us-law/export/download?token=value" \
-H "X-API-Key: alt_free_9f3c…"/v1/disclosuresAI-related risk-factor disclosures extracted from SEC EDGAR filings. ENTERPRISE-ONLY: there is no teaser and no partial access on any self-serve tier — a below-tier caller gets 403 tier_upgrade_required, never a trimmed response. Documented here so the capability is discoverable; the gate is in the route, not in this spec.
| Param | In | Type | Description |
|---|---|---|---|
| q | query | string | |
| company | query | string | |
| cik | query | string | Numeric CIK. |
| form | query | string | Filing form type, e.g. 10-K. |
| date_from | query | string | |
| date_to | query | string | |
| limit | query | integer | |
| offset | query | integer |
curl "https://ai-law-tracker.com/api/v1/disclosures?q=value&company=value" \
-H "X-API-Key: alt_free_9f3c…"/v1/enforcement/mattersRegulatory enforcement actions and private litigation involving AI, at MATTER level: forum, agency, parties, status, relief and the statutes invoked. One row per dispute, not per press release — an agency action with a complaint, a settlement and a final order is three rows on /v1/enforcement and ONE matter here. OPEN AT EVERY TIER since 2026-08-22. It used to answer a hard 403 below Enterprise, which made the dataset invisible and therefore unsellable. What is metered instead is DEPTH: the assembled chain on /enforcement/matters/{matter_uid} — parties, relief amounts, the event timeline and the cited statutes — is sampled below the paid step. A record budget would have been theatre on a 91-row registry. A SECOND GATE THAT IS NOT ABOUT MONEY: 30 of 91 matters are duplicates of another row or still carry an untranslated CAPTION, and are withheld from every caller not licensed for the raw registry — `meta.registry.withheld_not_publish_ready` reports how many THIS query hid. A further 6 ARE published with one descriptive field nulled and named in `unavailable_fields`; withholding a $1.4bn settlement because its forum_name has an untranslated clause would have been a worse answer. See /enforcement/coverage for the full breakdown. READ `verification` BEFORE QUOTING ANYTHING. Every matter currently held is `single_source`. An empty data[] means no matter matched — never that an agency has taken no action. /enforcement/sources says which of the 254 monitored sources are actually answering.
| Param | In | Type | Description |
|---|---|---|---|
| jurisdiction | query | string | Jurisdiction slug, comma-separated for several. |
| jurisdiction_level | query | string | federal, state and/or multistate, comma-separated. |
| forum_type | query | string | Comma-separated. Values from /enforcement/categories. |
| matter_type | query | string | enforcement_action, civil_litigation, guidance_document, investigation, inquiry_6b. Comma-separated. |
| matter_status | query | string | Comma-separated. Values from /enforcement/categories. |
| agency | query | string | Agency code, e.g. FTC, DOJ, SEC, Texas AG. Comma-separated for several; a single value may contain spaces, parentheses and accents. NOTE: an agency_code that itself contains a COMMA cannot be matched here, because the comma is the multi-value delimiter — three live values are in that state. Use q= for those; it searches agency_code as a substring. |
| ai_role | query | string | Comma-separated. Several roles mean the matter carries ALL of them. |
| domain | query | string | Primary subject domain id, comma-separated. |
| verification | query | string | Corroboration level. Currently every held matter is single_source. |
| date_from | query | string | Bounds filed_date, which is null on 71 of 91 matters — a date filter therefore EXCLUDES the undated majority. |
| date_to | query | string | |
| q | query | string | Substring over caption, summary and agency. |
| sort | query | filed_date | first_seen_at | last_verified_at | closed_date | |
| order | query | asc | desc | |
| limit | query | integer | Clamped to your tier cap; the clamp is reported in meta.gated. |
| offset | query | integer |
curl "https://ai-law-tracker.com/api/v1/enforcement/matters?jurisdiction=value&jurisdiction_level=value" \
-H "X-API-Key: alt_free_9f3c…"/v1/enforcement/matters/{matter_uid}The matter plus its EVENTS (timeline), PARTIES, RELIEF, statutory CITATIONS and the SOURCE DOCUMENTS each claim traces to. This is the dossier the product is sold on. THE CHAIN IS WHAT IS METERED. Below the paid step each chain is a 2-row sample and `data.chain_totals` reports the true size of every one of them — never an empty wall, and never a sample you cannot tell is a sample. Listing and searching matters stays fully open. FIELDS THAT LOOK LIKE HEDGES AND ARE THE PRODUCT: `events[].is_date_estimated` (the source gave a year, not a day), `verification`, `laws[].link_status` (`unlinked` = we hold the citation verbatim but have not resolved it — a confidently wrong citation is worse), and `duplicate_of`. PARTIES ARE REDACTED BY POLICY, in the database, not here: 97 of 235 party rows publish and the rest are withheld — named private individuals and minors by default. See the pii_class and redaction_policy vocabularies on /enforcement/categories. A 404 is returned both for a matter that does not exist AND for one withheld pending review, on purpose: distinguishable codes would turn the readiness gate into an enumeration oracle.
| Param | In | Type | Description |
|---|---|---|---|
| matter_uid * | path | string | An opaque stable key, not a description — read caption for the matter name. |
curl "https://ai-law-tracker.com/api/v1/enforcement/matters/{matter_uid}" \
-H "X-API-Key: alt_free_9f3c…"/v1/enforcement/sourcesThe 254 official sources behind the enforcement layer — agency newsrooms, AG press feeds, court dockets — with the last successful read, the fault state and whether each is stale against its own silence budget. IT PUBLISHES THE BAD NEWS. 132 of 254 are enabled and 123 are stale (measured 2026-08-22). Those go out as they are, on the same argument /v1/us-law/jurisdictions publishes its OLDEST verification stamp: an enforcement product whose coverage table only showed the healthy sources would be advertising, not data. FAULTS ARE CLASSIFIED, NOT QUOTED. `last_fault_reason_code` is a closed vocabulary (blocked, unauthorized, not_found, timeout, adapter_missing, egress_unavailable, other) with a one-line label; the raw internal fault text never leaves the server. Read this before concluding anything from an empty /enforcement/matters result: a stale source is a gap in OUR monitoring, never a statement that an authority has taken no action.
| Param | In | Type | Description |
|---|---|---|---|
| jurisdiction_level | query | federal | state | multistate | territory | local | international | |
| is_enabled | query | boolean | |
| is_stale | query | boolean | true = sources not read inside their own max_silence_hours. |
curl "https://ai-law-tracker.com/api/v1/enforcement/sources?jurisdiction_level=federal&is_enabled=value" \
-H "X-API-Key: alt_free_9f3c…"/v1/enforcement/categoriesThirteen closed vocabularies, 104 terms: matter_type, matter_status, forum_type, party_role, party_kind, relief_type, event_type, ai_role, law_relation, verification, jurisdiction_level, pii_class and redaction_policy. `code` is the API value; `label` and `description` are for display. These are the exact values the /enforcement/matters filters accept, which is why the endpoint is open: a documented filter whose valid values are undiscoverable is not a filter. TWO OF THEM DESCRIBE WHAT WE DO NOT PUBLISH. pii_class and redaction_policy are the terms behind the party gate that withholds 138 of 235 party rows. Publishing the vocabulary is how that policy becomes checkable rather than merely asserted.
| Param | In | Type | Description |
|---|---|---|---|
| kind | query | string | Return just one vocabulary. |
curl "https://ai-law-tracker.com/api/v1/enforcement/categories?kind=value" \
-H "X-API-Key: alt_free_9f3c…"/v1/enforcement/coverageCounts the registry rather than serving it: matters held, matters publishable, and how many are withheld as duplicates or for untranslated internal language — plus breakdowns by matter type, jurisdiction level and agency, and the de-duplicated monetary relief total. THE WITHHELD COUNTS ARE THE POINT. A caller who sees `total: 61` on /enforcement/matters would reasonably conclude the registry IS 61 matters. It is 91: 11 duplicates and 21 untranslated captions (overlapping) leave 30 withheld, and 6 of the published ones carry a nulled field. This is the same commitment /v1/us-law/taxonomy makes by publishing `records_placeholder`. The relief total is computed over PUBLISHABLE, de-duplicated matters only and says so in `relief.basis`. Summed naively across all 91 rows it is wrong by at least the $3.2M DOJ/OpenAI settlement, which is present twice under two matter_uids.
curl "https://ai-law-tracker.com/api/v1/enforcement/coverage" \
-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.