Qc APIcitoyens.soquij.qc.ca ↗
Search and retrieve Quebec court and tribunal decisions from SOQUIJ's public portal. Full decision text, monthly court listings, and court catalogue via 4 endpoints.
What is the Qc API?
The SOQUIJ Citoyens API provides access to Quebec court and tribunal decisions published on citoyens.soquij.qc.ca through 4 endpoints. Use search_decisions to query decisions by keyword, party name, judge, or docket number and receive decision IDs, party names, dates, and jurisdiction data. Companion endpoints cover full decision text retrieval, monthly browse by court, and the complete catalogue of indexed courts and organisations.
curl -X GET 'https://api.parse.bot/scraper/6153111f-c442-4c77-92ec-9a9ee3e55273/search_decisions?sort=relevance&query=pension+alimentaire&court_id=0&search_type=full_text' \ -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 citoyens-soquij-qc-ca-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: SOQUIJ Citoyens — search decisions, browse monthly lists, read full text."""
from parse_apis.citoyens_soquij_qc_ca_api import (
Soquij, SearchSort, SearchType, DecisionNotFound,
)
client = Soquij()
# Browse the court catalogue and pick the first real court (skip "Tous").
courts = list(client.courts.list(limit=5))
court = courts[1] if len(courts) > 1 else courts[0]
print(f"Court: {court.name} (id={court.court_id})")
# Search that court's decisions for a common term.
hit = court.search(
query="pension alimentaire",
sort=SearchSort.DATE,
search_type=SearchType.FULL_TEXT,
limit=3,
).first()
if hit is not None:
print(f"Found: {hit.parties} ({hit.date})")
# Fetch the full decision text using the id from the search hit.
try:
decision = client.decisions.get(decision_id=hit.decision_id)
except DecisionNotFound:
print("Decision no longer available")
else:
print(f"Citation: {decision.neutral_citation}")
print(f"Bank: {decision.bank}")
print(f"Versions: {', '.join(v.label for v in decision.versions)}")
print(f"Text preview: {decision.text[:120]}…")
# Monthly browse: list decisions rendered by the same court in a given month.
for row in court.list_monthly(year="2026", month="1", limit=3):
print(f" {row.date} {row.parties}")
print("exercised: courts.list / court.search / decisions.get / court.list_monthly")
Searches decisions by keywords and returns one row per matching decision (decision_id, parties, date, jurisdiction). The site returns at most the 200 most relevant (or most recent, with sort=date) decisions in one response and offers no page numbers; total_found is the site's full match count and capped_at is the fixed 200 display cap. To walk a large result set, use sort=date: when the 200-row cap is reached, next_date_to carries the decision date of the last (200th, oldest) row in YYYYMMDD form, ready to be passed unchanged as date_to on the next call (keep date_from and the other criteria identical). Because the date bound is inclusive, the next call repeats the rows dated exactly next_date_to, so de-duplicate on decision_id; if more than 200 decisions share one date the walk cannot advance past it. next_date_to is null when fewer than 200 rows are returned (last page) and always null with sort=relevance, where the last row's date is not a continuation point. Keywords accept the site's ET / OU / SAUF operators and quoted phrases; the underscore character is not allowed. jurisdiction is populated only when court_id is 0 (all courts); when a single court is selected the site omits that column and jurisdiction is null. A query with no matches returns total_found 0 and an empty results list. criteria echoes the search criteria as displayed by the site.
| Param | Type | Description |
|---|---|---|
| sort | string | Result ordering; the 200-row cap is applied after sorting. Only sort=date yields a next_date_to continuation. |
| queryrequired | string | Search terms (e.g. a phrase in quotes, party name, judge name or docket number depending on search_type). Must not contain '_'. |
| date_to | string | Latest decision date, YYYYMMDD, inclusive. Omitted = today. Accepts the next_date_to value of a previous response unchanged. When given without date_from, the lower bound is set to the site's floor (1985-10-01), which the site requires for the upper bound to apply. |
| court_id | string | Numeric court/organisation id from list_courts.courts[*].court_id; 0 searches all courts. |
| date_from | string | Earliest decision date, YYYYMMDD, inclusive. Omitted = no lower bound (the site's floor is 1985-10-01). |
| search_type | string | Which field the keywords are matched against. |
{
"type": "object",
"fields": {
"results": "array of decision rows: decision_id (32-char hex, input of get_decision), parties (case title), date (YYYY-MM-DD), jurisdiction (court abbreviation, null when a single court_id is selected)",
"criteria": "array of strings, the search criteria as the site echoes them",
"capped_at": "integer, fixed maximum number of rows the site displays (200)",
"total_found": "integer, the site's total number of matching decisions (may exceed the rows returned)",
"next_date_to": "string or null, YYYYMMDD date of the last (oldest) returned row when sort=date and the 200-row cap was reached; pass it as date_to to continue. null on the last page and with sort=relevance"
},
"sample": {
"data": {
"results": [
{
"date": "2026-10-09",
"parties": "Centre de la petite enfance Le Jardin de Robi inc. et Syndicat des travailleuses des centres de la petite enfance et des bureaux coordonnateurs du Saguenay — Lac-Saint-Jean - FSSS-CSN",
"decision_id": "8B46AF1145C4AFD1AB9879641A328DA8",
"jurisdiction": "T.A.T."
},
{
"date": "2026-10-08",
"parties": "Cedar c. Institut de recherche du Centre universitaire de santé McGill",
"decision_id": "94171006D19D6E57EC109ADAFBCCAB39",
"jurisdiction": "T.A.T."
},
{
"date": "2026-05-13",
"parties": "Commission des normes, de l'équité, de la santé et de la sécurité du travail et Gp Strategies Canada",
"decision_id": "EF60EAFA04C7B7D48DE63AE6550597C4",
"jurisdiction": "C.N.E.S.S.T."
}
],
"criteria": [
"Tribunal ou organisme : Tous",
"Type de recherche : Plein texte",
"Seules les 200 décisions les plus récentes sont affichées. Raffiner la recherche."
],
"capped_at": 200,
"total_found": 9993,
"next_date_to": "20260513"
},
"status": "success"
}
}About the Qc API
Searching and Browsing Decisions
The search_decisions endpoint accepts a required query string and optional filters including court_id, date_from (YYYYMMDD), date_to, and search_type to control which field the query matches against (party name, judge, docket number, etc.). Results are sorted by relevance or date via the sort parameter. The response includes an array of decision rows — each with a 32-character hex decision_id, parties (case title), date, and jurisdiction — alongside a total_found count and a capped_at value fixed at 200. When total_found exceeds 200, narrowing the date range or query is the only way to surface additional results.
Monthly Listings and Court Catalogue
list_monthly_decisions browses all decisions a specific court rendered in a given calendar month. It requires a court_id (not 0), a year, and a month (1–12). The full month's decisions are returned in one response — up to several hundred rows — with each row carrying the same decision_id, parties, and date fields as search results. To know which court_id values are valid, call list_courts first: it returns the full ordered catalogue of courts and organisations as {court_id, name} pairs in French, including the special value 0 (Tous / all courts) which is accepted only by search_decisions.
Full Decision Text
get_decision takes a single decision_id from either search or monthly listing results and returns the complete plain-text body of the decision in the text field, with paragraph breaks preserved. Additional fields include bank (the SOQUIJ collection code, e.g. TAQ), neutral_citation (null for older documents), decision_date as written in the French-language document, and a versions array listing the text variants the site offers for that document. Older decisions — particularly Court of Appeal judgments predating the neutral citation convention — may return null for neutral_citation and decision_date.
The Qc API is a managed, monitored endpoint for citoyens.soquij.qc.ca — not a raw scraper you maintain. Every endpoint is automatically health-checked on a schedule, and when citoyens.soquij.qc.ca 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 citoyens.soquij.qc.ca 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 full-text search index over Quebec court decisions filtered by jurisdiction and date range using
search_decisions - Tracking all decisions issued by a specific tribunal in a given month via
list_monthly_decisionsfor compliance monitoring - Extracting neutral citations and bank codes from
get_decisionto build a structured citation database - Aggregating party-name data across decisions to identify litigation patterns for a specific organisation or individual
- Populating a court-selection dropdown in a legal research tool using the
courtsarray fromlist_courts - Archiving monthly decision text for a specific court using
list_monthly_decisionscombined withget_decisioncalls - Alerting on new decisions mentioning a particular keyword or judge name by running periodic
search_decisionsqueries with a narrowdate_from/date_towindow
| Tier | Price | Credits/month | Rate limit |
|---|---|---|---|
| Free | $0/mo | 200 | 5 req/min |
| Hobby | $30/mo | 1,000 | 20 req/min |
| Developer | $100/mo | 5,000 | 100 req/min |
| Team | $300/mo | 20,000 | 300 req/min |
| Company | $1,000/mo | 100,000 | 500 req/min |
Each endpoint has a fixed posted price per successful call — most fall between 1 and 10 credits — shown on this API's page before you run it. Exceeding the rate limit returns a 429 response. Authenticate with the X-API-Key header.
Does SOQUIJ offer an official developer API for citoyens.soquij.qc.ca?+
What happens when more than 200 decisions match a search query?+
search_decisions returns at most 200 rows regardless of total_found. The capped_at field in the response always reflects this 200-row ceiling. To retrieve decisions beyond that limit, narrow the query with date_from and date_to to break the result set into smaller date windows, or switch to list_monthly_decisions for exhaustive monthly coverage of a specific court.Does `get_decision` return formatted or structured metadata fields beyond the decision text?+
neutral_citation, decision_date, bank, and a versions array alongside the plain text. However, structured metadata such as judge names, docket numbers, or cited-cases lists are not returned as discrete fields — they appear only within the free text. You can fork the API on Parse and revise it to parse those fields from the text body if you need them as structured data.Does the API cover decisions from all Quebec courts, including administrative tribunals?+
list_courts to see the full catalogue. Decisions from bodies not listed there — including certain specialised federal tribunals sitting in Quebec — are not available. You can fork the API on Parse and revise it to add an endpoint targeting another SOQUIJ portal or data source if you need broader coverage.Are there limitations on how far back the decision date range goes?+
date_from is supplied. Decisions predating that boundary are not reachable through search_decisions or list_monthly_decisions. Older documents that are present may also return null for neutral_citation and decision_date in get_decision responses.