CanLII APIcanlii.org ↗
Access Canadian case law, legislation, and tribunal decisions across all provinces and territories via the CanLII API. Search, filter, and retrieve full document text.
What is the CanLII API?
The CanLII API provides structured access to Canadian legal information across 14 provinces, territories, and federal jurisdictions through 6 endpoints. Use search_documents to query case law and legislation by keyword, jurisdiction, and document type, or use get_document_detail to retrieve the full text and metadata of any specific decision or statute. Results include citations, court identifiers, dates, and document snippets.
No input parameters required.
curl -X GET 'https://api.parse.bot/scraper/f5ae8751-4f27-48d0-9a68-b080c35b492e/get_jurisdiction_list' \ -H 'X-API-Key: $PARSE_API_KEY'
Typed, relational, agent-ready
A generated client with real types, enums, and the links between objects — the structure a flat JSON response can't carry. Autocompletes in your editor and reads cleanly to coding agents.
- Fully typed · autocompletes
- Objects link to objects
- Typed errors & pagination
Typed Python client. Set up the SDK in your uv project, then pull this API’s typed client:
uv add parse-sdk uv run parse init uv run parse add --marketplace canlii-org-api
uv run parse add --marketplace pulls a pinned snapshot of this canonical API — it won’t change underneath you. To customize it, subscribe and swap to your own copy.
"""Walkthrough: CanLII Legal API — search Canadian case law, explore jurisdictions, read documents."""
from parse_apis.canlii_legal_api import CanLII, DocumentType, JurisdictionId, ResourceNotFound
client = CanLII()
# List all Canadian jurisdictions and their document counts.
for j in client.jurisdictions.list(limit=5):
print(j.name, j.count)
# Search for case law about "wrongful dismissal" filtered to decisions in Ontario.
doc = client.documents.search(
query="wrongful dismissal",
type_id=DocumentType.DECISION,
j_id=JurisdictionId.ON,
limit=1
).first()
if doc:
print(doc.title, doc.citation, doc.court)
# Drill into the full text of that document.
detail = doc.detail()
print(detail.title, detail.full_text[:120])
# Explore databases available in a specific jurisdiction via sub-resource.
alberta = client.jurisdiction("ab")
for section in alberta.databases.list(limit=5):
print(section.category, len(section.databases))
# Search arbitration awards in Ontario using the enum.
for award in client.awards.search(j_id=JurisdictionId.ON, limit=3):
print(award.name, award.date, award.court)
# Typed error handling for a non-existent document.
try:
client.documentdetails.get(url="https://www.canlii.org/en/xx/nonexistent/doc/0000/0000xx0/0000xx0.html")
except ResourceNotFound as exc:
print(f"Document not found: {exc}")
print("exercised: jurisdictions.list / documents.search / doc.detail / jurisdiction.databases.list / awards.search / documentdetails.get")
Get list of all available Canadian jurisdictions with their IDs and document counts. Returns all 14 provinces/territories plus a commentary category.
No input parameters required.
{
"type": "object",
"fields": {
"jurisdictions": "array of jurisdiction objects with id, name, count, and short_text"
},
"sample": {
"data": {
"jurisdictions": [
{
"id": "ca",
"name": "Canada (Federal)",
"count": "272,134",
"short_text": "CA"
},
{
"id": "on",
"name": "Ontario",
"count": "721,149",
"short_text": "ON"
}
]
},
"status": "success"
}
}About the CanLII API
Jurisdiction and Database Discovery
The get_jurisdiction_list endpoint returns every available jurisdiction with its ID, display name, and document count. These IDs (e.g. ab for Alberta, on for Ontario, ca for Canada Federal) are the input currency for all other endpoints. Once you have a jurisdiction ID, get_jurisdiction_databases returns the full list of databases organized by category — Legislation, Courts, Boards and Tribunals — along with coverage date ranges and per-database document counts.
Searching Legal Documents
search_documents accepts a required query string plus optional filters: j_id to scope by jurisdiction, type_id to limit to decision or legislation, and page for pagination. Results are paginated at 25 items per page and include title, citation, date, court, jurisdiction, url, and a snippet from the matched document. The total_count field in the response tells you how many documents matched across all pages. Omitting j_id or passing all searches every jurisdiction at once.
Document Retrieval
get_document_detail takes a full CanLII document URL and returns title, url, and full_text — the complete text of the decision or statute. This is the endpoint to use when you need the body of a specific ruling beyond what a snippet provides. The related get_employment_standards_code endpoint is a convenience wrapper that retrieves a named legislation statute for a given jurisdiction, returning the same title, url, and full_text fields.
Tribunal and Arbitration Awards
get_arbitration_awards targets board and tribunal decisions for a given jurisdiction. Each result in the awards array includes name, date, citation, url, court, and a synopsis. The optional limit parameter controls how many results are returned, up to 25 per request.
The CanLII API is a managed, monitored endpoint for canlii.org — not a raw scraper you maintain. Every endpoint is automatically health-checked on a schedule, and when canlii.org changes and a check fails, the API is automatically queued for repair and re-verified. It is built to keep working as the site underneath it changes.
This isn't an official canlii.org API — it's an independent, maintained REST wrapper over public data. Where the source has no official API (or only a limited one), Parse gives you a stable contract over a source that never promised one, and keeps it current. Need a new endpoint or field? You can revise it yourself in plain English and the agent rebuilds it against the live site in minutes — contributing the change back to the shared API is free.
Will this API break when the source site changes?+
Is this an official API from the source site?+
Can I fix or extend this API myself if I need a new endpoint or field?+
What happens if I call an endpoint that has an issue?+
- Building a Canadian employment law research tool that retrieves jurisdiction-specific statutes via
get_employment_standards_code - Aggregating arbitration and tribunal decisions by province using
get_arbitration_awardsfor labour relations analysis - Powering a full-text legal search interface with
search_documentsfiltered bytype_idandj_id - Extracting citation metadata from search results to construct a case law citation graph
- Retrieving the full text of court decisions for NLP training or summarization pipelines via
get_document_detail - Auditing what courts and tribunals exist under a jurisdiction using
get_jurisdiction_databasescoverage dates
| Tier | Price | Credits/month | Rate limit |
|---|---|---|---|
| Free | $0/mo | 100 | 5 req/min |
| Hobby | $30/mo | 1,000 | 20 req/min |
| Developer | $100/mo | 5,000 | 100 req/min |
One credit = one API call regardless of which marketplace API you call. Exceeding the rate limit returns a 429 response. Authenticate with the X-API-Key header.
Does CanLII have an official developer API?+
What does `search_documents` return, and how do I filter by document type?+
items array includes title, citation, date, court, jurisdiction, url, and a snippet. Pass type_id as either decision or legislation to restrict results to that category. Omit type_id or pass all to return both. The total_count field reflects the full match set regardless of the current page.Does the API return decisions from all Canadian jurisdictions, including federal courts?+
get_jurisdiction_list endpoint returns 14 provinces and territories plus federal (ca), and any of these IDs can be passed to search_documents or get_jurisdiction_databases. A commentary category is also available as a separate entry in that list.Does the API expose cited-by relationships or cross-references between cases?+
Is there a way to retrieve all decisions from a specific court or tribunal rather than searching by keyword?+
get_jurisdiction_databases endpoint lists all courts and tribunals for a jurisdiction, but bulk listing of a database's contents without a search query is not currently supported. You can fork the API on Parse and revise it to add a browsable database-listing endpoint using a specific database ID.