Effective dates are the part of AI regulation that actually lands in someone’s quarter. GET /v1/deadlines returns them as JSON or as a subscribable .ics — free at every tier — with the verbatim source text alongside every parsed date so you can audit the extraction instead of trusting it.
Published · AI Law Tracker Editorial Team
If all you want is the dates in your calendar app, you do not need to write any code. The same endpoint serves an RFC 5545 feed, and calendar clients will re-poll it on their own schedule.
# Everything, upcoming only (the default)
https://ai-law-tracker.com/api/v1/deadlines?format=ical
# One jurisdiction
https://ai-law-tracker.com/api/v1/deadlines?format=ical&jurisdiction=california
# One scope (state | federal | eu | global)
https://ai-law-tracker.com/api/v1/deadlines?format=ical&scope=eu
# Most clients also accept the webcal:// scheme for "subscribe", not "import"
webcal://ai-law-tracker.com/api/v1/deadlines?format=icalformat=ics and format=icalendar are accepted aliases of format=ical. The response is text/calendar with the filename ai-law-deadlines.ics; each entry is an all-day event carrying the verbatim source deadline text and the primary-source URL.The default shape is JSON. Parameters: scope, jurisdiction (exact slug), upcoming (default true), all (an alias for upcoming=false), and format. No key is required, and no tier is gated off this endpoint.
curl -s -G "https://ai-law-tracker.com/api/v1/deadlines" \
-H "X-API-Key: alt_free_your_key_here" \
--data-urlencode "scope=state" \
--data-urlencode "upcoming=true"{
"api_version": "v1",
"data": [
{
"scope": "eu",
"jurisdiction": "European Union",
"jurisdiction_slug": "eu",
"laws": ["EU AI Act (Regulation 2024/1689)"],
"status": "In force — phased application",
"raw_deadline": "High-risk obligations apply from August 2, 2026",
"date": "2026-08-02",
"date_precision": "day",
"is_upcoming": true,
"dates": [{ "iso": "2026-08-02", "precision": "day", "sort": "2026-08-02" }],
"source_url": "https://eur-lex.europa.eu/eli/reg/2024/1689/oj",
"source_tier": "primary"
}
],
"meta": {
"count": 1,
"undated": 9,
"upcoming_only": true,
"generated_at": "2026-08-06T00:00:00.000Z",
"ical": "https://ai-law-tracker.com/api/v1/deadlines?format=ical",
"upgrade": "These are the public effective dates. For the derived \"what must I do about each deadline\"…",
"attribution": "Data by AI Law Tracker (CC BY 4.0) — https://ai-law-tracker.com",
"disclaimer": "Informational only — not legal advice…"
}
}This is the part of the endpoint worth understanding before you build anything on it, because it is where a compliance calendar usually goes wrong.
Source deadline text is prose. Real examples read like “August 2, 2026”, “In effect since July 31, 2025”, or “Layered; AI content-labeling effective Sept 1, 2025”. A naive Date.parse() over that prose will happily return *a* date — frequently the wrong one, and always without telling you how much of the string it understood.
So the feed does three separate things instead of one lossy thing:
dates[] carries all of them and date is the earliest upcoming one.day, month, or year. A month precision entry means the source said “July 2027” — the 2027-07-01 in date is a sort key, not a claim that something is due on the 1st.meta counts jurisdictions whose deadline text contains no explicit date at all. They are counted, never given an invented date, and never appear in data.date, but never *display* a date whose date_precision is not day without qualifying it. Rendering “2027-07-01” for a source that said “July 2027” is how a team ends up planning against a deadline nobody set.A daily job is plenty: these dates move on a legislative timescale, not a market one. The example below alerts at fixed horizons and respects date_precision in what it says.
0 8 * * * /usr/bin/python3 /opt/alt/deadline_alerts.py >> /var/log/alt-deadlines.log 2>&1import datetime as dt
import os
import requests
BASE = "https://ai-law-tracker.com/api/v1"
HORIZONS = {90: "90 days", 30: "30 days", 7: "1 week"}
PRECISION_NOTE = {
"day": "",
"month": " (source states the month only — day is not specified)",
"year": " (source states the year only — month and day are not specified)",
}
def upcoming_deadlines(scope=None, jurisdiction=None):
params = {"upcoming": "true"}
if scope:
params["scope"] = scope
if jurisdiction:
params["jurisdiction"] = jurisdiction
r = requests.get(
f"{BASE}/deadlines",
params=params,
headers={"X-API-Key": os.environ["ALT_API_KEY"]},
timeout=30,
)
r.raise_for_status()
return r.json()
def main():
payload = upcoming_deadlines(scope="state")
today = dt.date.today()
for entry in payload["data"]:
due = dt.date.fromisoformat(entry["date"])
days_out = (due - today).days
if days_out not in HORIZONS:
continue
note = PRECISION_NOTE[entry["date_precision"]]
alert(
f"{entry['jurisdiction']} — {HORIZONS[days_out]} out ({entry['date']}){note}\n"
# ALWAYS carry the verbatim source text and the source link.
f"Source text: \"{entry['raw_deadline']}\"\n"
f"Primary source ({entry['source_tier']}): {entry['source_url']}\n"
f"Laws: {', '.join(entry['laws']) or 'n/a'}"
)
if payload["meta"]["undated"]:
alert(
f"FYI: {payload['meta']['undated']} tracked jurisdictions have deadline text "
"with no explicit date. They are not on the calendar — review them by hand."
)
if __name__ == "__main__":
main()undated count turns an invisible gap into a review task.The feed is forward-looking by default. For an audit trail — “which obligations were already in force on this date” — include past effective dates:
is_upcoming so you can split the two sets client-side from one call.source_tier tells you what backs the entry: primary (an official government source), secondary, or unverified. Weight your review accordingly.# both spellings do the same thing
curl -s "https://ai-law-tracker.com/api/v1/deadlines?upcoming=false"
curl -s "https://ai-law-tracker.com/api/v1/deadlines?all=true"A deadline calendar tells you *when*. It does not tell you *what you must do* — that is the interpreted layer, and it lives on separate endpoints: GET /v1/obligations (duties for a jurisdiction and/or sector) and POST /v1/assess (a business profile in, applicable obligations plus a reproducible 1–10 risk score out). Both are Pro-and-above; lower tiers receive a one-item preview with an upgrade hint rather than a blank wall.
/v1/deadlinesThe calendar. Params: scope, jurisdiction, upcoming, all, format=json|ical|ics. Free at every tier./v1/jurisdictionsValid jurisdiction slugs for the filter./v1/obligationsThe derived "what must I do" layer. Pro+ for the full list./v1/assessProfile → applicable obligations + risk score. Pro+.Full reference in the developer docs. Plans and limits on pricing.
Yes — free at every tier, including anonymous. These are public primary-source effective dates. The paid layer is the interpretation of them (obligations and risk), not the dates themselves.
Most likely its deadline text carries no explicit calendar date. Those are counted in meta.undated and deliberately excluded from data rather than given a fabricated date. Fetch with upcoming=false as well, in case its date has already passed.
That the source named a month but not a day. The ISO date pins the 1st purely so entries can be sorted and rendered — treat it as "sometime in that month" and say so in whatever you show a human.
Daily is more than enough. The calendar is derived deterministically from the curated corpus and meta.generated_at tells you when the snapshot you hold was built.
Data by AI Law Tracker, licensed CC BY 4.0 — attribution required: “Data by AI Law Tracker (CC BY 4.0) — https://ai-law-tracker.com”. AI Law Tracker provides informational data, not legal advice. Verify every record against its official source before relying on it.