Maple Juris
API referenceChangelog

Maple Juris API.

Introduction

The Maple Juris API answers one question well: does this Canadian legal citation point at a real provision? You send a citation as free text; we resolve it against a structured graph of Canadian legislation and return the statutory target, a status, and a validity score.

The API is JSON over HTTPS. Every endpoint lives under https://api.maplejuris.com. The same capability is available to AI agents over MCP - see MCP server.

Technology-assisted information, not legal advice

Results are not legal advice, a legal opinion, or an official version of any statute, and using the API creates no solicitor-client or other professional relationship. Verify each citation, provision, version and in-force status against the official source with appropriately qualified human review before relying on it or publishing it. The API must not be the sole decision-maker where a decision could materially affect a person's legal rights, access to services, employment, health, safety or liberty.

Base URL
https://api.maplejuris.com

Authentication

Authenticate with an API key created on your API keys page. The secret is shown once, at creation. Keys are scoped to your account - or to an organization, whose keys use its owner's plan - count against that plan's monthly allowance, and stop working the moment you revoke them.

Send the key as a bearer token. The header X-API-Key is accepted as an alternative if a bearer token is awkward in your client. A missing, revoked, or expired key returns 401.

How you are required to hold a key

Store keys only in server-side systems or a secrets manager. Never ship one in client-side code, commit one to a public repository, or embed one in an application a user can download and unpack. If a key may have been exposed, revoke and replace it immediately and tell us at info@maplejuris.com - every request made with your key is attributed to the account that owns it and spends that account's credits - on an organization, the shared pool - including requests you did not make.

Authenticated request
curl https://api.maplejuris.com/v1/validate-citation \
  -H "Authorization: Bearer $MAPLEJURIS_KEY"

Token exchange and usage

High-volume callers can trade a key for a short-lived bearer token with POST /v1/token. Tokens are valid for 24 hours and verify locally on our servers - no auth-provider round trip - so they shave latency off every call. They spend the same monthly allowance as the key that minted them, and minting is free.

Use the returned access_token exactly like a key. When it expires you'll get a 401 - mint a new one.

GET /v1/usage returns your account's month-to-date consumption and remaining allowance, plus pricing - what each endpoint costs in credits and per what unit - and by_key, this month's requests and credits per API key, including the keys of organizations you own. Checking usage never burns quota.

Mint and use a token
curl -X POST https://api.maplejuris.com/v1/token \
  -H "X-API-Key: $MAPLEJURIS_KEY"
# {"access_token":"eyJ...","token_type":"Bearer",
#  "expires_in":86400,"plan":"non_commercial_free"}

curl https://api.maplejuris.com/v1/usage \
  -H "Authorization: Bearer $TOKEN"

Organizations

On the Commercial and Enterprise plans you can create an organization and invite teammates by email, from the account switcher at the top of your dashboard. A key created while the organization is selected belongs to the organization, not to the member who created it.

Every organization key uses the organization owner's plan and monthly credits - by default the owner is the member who created the organization - so the owner and all members draw on one shared pool. The owner's Usage page lists each key with the member who created it and what it spent; so does by_key on GET /v1/usage.

Organization keys work only while the owner is on Commercial or Enterprise. Otherwise every call answers 403, with a message naming the owner's plan. If the owner's last payment failed, the organization's keys pause with 402 along with the owner's own.

Removing a member from the organization revokes the organization keys that member created. Keys made with your personal account selected stay personal: they use your own plan, whatever organizations you belong to.

403 · owner's plan has no organizations
{
  "detail": "Organization API keys use the
    organization owner's plan, and
    organizations are included on the
    Commercial and Enterprise plans; the
    owner is on 'non_commercial_research'.
    Upgrade at https://maplejuris.com/pricing."
}

POST /v1/validate-citation

Validate a single citation. Returns 200 whenever your key is valid - a citation that does not resolve is a result, not an error.

What not to send

Send the citation and the minimum context the lookup needs - nothing more. Do not submit government identifiers, payment-card numbers, personal health information, biometric data, information about children, or other sensitive or specially regulated personal information. Do not submit privileged or confidential material unless you have satisfied yourself that doing so is consistent with your professional, confidentiality and privilege obligations. Enterprise customers who need to send regulated data require a data processing agreement first.

Body parameters
FieldDescription
query
string · required
The citation as free text, 1-500 characters. Mutually exclusive with structured.
structured
object · optional
Pre-parsed citation. Identify the statute by short_title, chapter, or id (the canonical public id returned as statute.id on a match, e.g. ca-act-rsc-1985-c-c-46--114997 - take it from a previous response rather than constructing one; the instrument slug and a provision id are accepted here too), plus pinpoint labels (section_label, subsection_label, …). Skips the language model entirely for a fully deterministic lookup. Leave target_node_type unset - it is inferred from the labels; an explicit value that contradicts them is ignored with a note in the response.
jurisdiction
string | string[] · optional
Scope the lookup - a code ("ON", "CA" for federal), a name ("Ontario"), or a list when the matter spans jurisdictions (["ON", "CA"]- matches within the listed ones only). Strongly recommended: statute titles repeat across Canada. The response's statute.jurisdiction reports where the match landed. Every Canadian jurisdiction code is a valid input; the corpus today is federal and Ontario, and citations scoped elsewhere come back unsupported.
Request
curl -X POST https://api.maplejuris.com/v1/validate-citation \
  -H "Authorization: Bearer $MAPLEJURIS_KEY" \
  -H "Content-Type: application/json" \
  -d '{"query": "Criminal Code s. 718"}'

The response object

Use valid for a strict pass/fail, or validity_score when you want to surface partial matches.

FieldDescription
valid
boolean
True only when the citation was verified against the graph at the depth it was written to - a provision citation needs its provision matched; a whole-Act citation needs the Act found. The section and pinpoint you wrote are checked against what was matched: if the matched section is not the one you cited, or the citation names levels below the section that were not read (s. 118(1)99), valid is false and the first note says why. A repealed provision is still a real provision, so valid stays true - check target.repealed before relying on it as law in force.
validity_score
float 0-1
≥ 0.75 verified (0.9 for a corroborated whole-Act citation) · 0.4-0.75 understood but unmatched, or ambiguous · 0.1-0.4 a provision wascited and is not in a statute we hold · < 0.1 nothing found.
status
enum
resolved · ambiguous · not_found · unsupported (out of corpus, e.g. a province other than Ontario, or foreign law).
resolution_level
enum | null
How deep the resolution goes. provision - a specific section was located. statute - the Act was located and the citation named nothing inside it, so target is null and that is the complete answer.
pinpoint_supplied
boolean | null
Did the citation name a location inside the statute - a section, subsection, paragraph, schedule, or defined term? false for Criminal Code, R.S.C. 1985, c. C-46, a common and entirely valid citation form. Before telling a user a cited provision does not exist, require this and score_breakdown.statute_in_corpus; the latter alone also describes a correct whole-Act citation.
pinpoint_verified
boolean | null
Was the match made at the depth the citation named? false means a shallower provision came back. The common case is an Ontario first subsection: e-Laws prints s X(1)as the section's own opening text, so the section is returned as target- with subsection (1)'s text and its paragraphs, and a paragraph pinpoint under it checked against the paragraphs that exist. It is also false when the citation names levels below the section that were not read; that result is not valid. Null when there was no pinpoint to verify or nothing matched.
statute
object | null
Identified statute - short title, chapter, jurisdiction, and two stable identifiers - populated even on partial resolves. id is the canonical public identifier (stable across instruments, unlike chapter, whose form varies by publisher; reusable as structured.id). slug is a canonical human-readable reference for the matched instrument (act or regulation) of the form {jurisdiction}/{act|reg}/{citation-token}, e.g. ca/act/rsc-1985-c-c-46 or ca/reg/sor-2002-227; a slug never changes once minted and is null when the instrument has no slug yet. Both are always graph facts, never an echo of your input.
target
object | null
The matched provision, including display_label and a tree breadcrumb from the statute root. Present whenever a node matched, including when valid is false, so you can see what was found. Null on a statute-level resolve - see resolution_level.
target.text
string | null
The whole provision: its own words followed by everything below it - subsections, paragraphs, clauses, definitions - in document order, each with its marker ((2), (a)). Headings and amendment notes printed beside the provision are left out. Cut at 8,000 characters, ending …[truncated].
target.repealed
boolean | null
truewhen the provision's current text is a repeal note (Repealed: 2021, c. 4, Sched. 9, s. 3.): the citation points at a real provision that is no longer in force. false otherwise; null when no text is held. Read from the current text, so a repealed Ontario subsection matched at section level, or a whole Act no longer published, is not flagged.
target.repealed_by
string | null
The repealing authority as printed in the note, e.g. 2021, c. 4, Sched. 9, s. 3.
alternatives
array
Up to five other candidates considered. Populated when status is ambiguous.
notes
array
Human-readable diagnostics: which jurisdiction was applied, why a citation failed, and - first in the list - a repeal or a pinpoint that does not match what you wrote. Free text for people; branch on the structured fields, not on notes.
What a score is not

validity_score and confidence describe how well the citation matched the graph. They are not a probability that a legal conclusion drawn from the provision is correct. A citation can score 0.99 and still be the wrong authority for the argument it is cited for - that judgment is not something this API makes.

What no result does not mean

not_found and unsupported mean the citation did not resolve within the corpus we currently hold. They do not establish that no such provision exists. The two are not interchangeable: not_found means we searched where the citation pointed and found nothing, while unsupported means the citation fell outside what we hold and we did not form a view either way.

Outside Federal and Ontario, the answer is unknown

Legislation coverage is Federal and Ontario, both complete. Every other province and territory is out of corpus: a citation there returns unsupported with coverage_gap: trueand is never matched against another jurisdiction's statute. Treat it as “unknown”, never as “invalid”, and never surface it to an end user as a finding that a provision is not real.

200 · application/json
{
  "query": "Criminal Code s. 718",
  "valid": true,
  "validity_score": 0.94,
  "status": "resolved",
  "resolution_level": "provision",
  "pinpoint_supplied": true,
  "confidence": 0.94,
  "statute": {
    "short_title": "Criminal Code",
    "chapter": "C-46",
    "id": "ca-act-rsc-1985-c-c-46--114997",
    "jurisdiction": "CA",
    "slug": "ca/act/rsc-1985-c-c-46"
  },
  "target": {
    "node_type": "Section",
    "label": "718",
    "display_label": "Criminal Code, RSC 1985, c C-46, s 718",
    "text": "The fundamental purpose of sentencing is ... one or more of the following objectives:\n\n(a) to denounce unlawful conduct ...\n\n(b) ...",
    "repealed": false,
    "repealed_by": null,
    "tree": [ /* Body -> Part -> Section */ ]
  },
  "alternatives": [],
  "notes": []
}

POST /v1/validate-citation/batch

Validate up to 100 legislation citations in one call. The body is an array of the same objects accepted by the single endpoint, and the response is an array of the same result objects in the same order. Each citation in the batch counts as one credit against your monthly quota - the same rate as validating them one at a time. Batching saves round trips and latency, not credits.

Request
curl -X POST https://api.maplejuris.com/v1/validate-citation/batch \
  -H "Authorization: Bearer $MAPLEJURIS_KEY" \
  -H "Content-Type: application/json" \
  -d '[{"query": "Criminal Code s. 718"},
       {"query": "PIPEDA s. 5"}]'

POST /v1/discover

Describe a situation in plain language; get back a ranked list of the Canadian provisions that bear on it. Discovery rephrases the situation into legal search language, narrows by CBA practice-area themes and responsible ministers, vector-searches provisions inside the surviving acts, and re-ranks the hits deterministically. It is the inverse of validate-citation: situation in, citations out.

When the situation is too thin to search, the call returns status: "needs_clarification" with a single question instead of guessing. The loop is stateless: re-POST the same situation with clarification_history extended by the { question, answer } pair, and continue until you get results. Each call spends 10 credits - Discovery runs an LLM rephrase, embeddings, and several vector searches per request, so it is weighted heavier than a one-credit validation.

Body parameters
FieldDescription
situation
string · required
Natural-language description of the situation, at least 3 characters. No legal phrasing required.
clarification_history
array · optional
Prior clarifying questions and the user's answers, each { question, answer }. Extend it and re-POST to resolve a needs_clarification response.
jurisdiction
string · optional
Jurisdiction filter, e.g. "Federal". Coverage today is federal Canada.
top_k
integer · optional
Maximum citations to return, 1-25. Defaults to 10.
Request
curl -X POST https://api.maplejuris.com/v1/discover \
  -H "Authorization: Bearer $MAPLEJURIS_KEY" \
  -H "Content-Type: application/json" \
  -d '{"situation": "An employee was fired the day after reporting a safety hazard", "top_k": 10}'

The discovery response

Branch on status first. On results the citations array is ordered best-first; on needs_clarification read clarifying_question and loop; no_results means the situation was understood but nothing in the corpus matched.

FieldDescription
status
enum
results · needs_clarification · no_results.
citations
array
Ranked provisions. Each carries id, statute_title, chapter, node_type, label, a path breadcrumb, a text_snippet, a score (0-1), and the theme_slugs it matched. Each entry also carries slug - the canonical stable reference for the act or regulation itself (ca/act/rsc-1985-c-l-2 form), not to be confused with theme_slugs, which name practice areas.
clarifying_question
string | null
The one question to answer. Present only when status is needs_clarification.
applied_themes
array
CBA practice-area themes used to narrow the search, each with a slug and score.
applied_ministers
array
Responsible ministers used to narrow the acts, each a slug and score.
rephrased_query
string | null
The situation rewritten as legal search language - useful for debugging why a given set of citations came back.
notes
array
Human-readable diagnostics about the run.
Discovery is not an exhaustive search

Discovery ranks what the corpus holds against the situation you described. It is not a complete legal search, and no_results does not mean no relevant provision exists - only that nothing in the corpus matched the query as phrased. Treat the ranked list as a starting point for research, never as the full set of provisions bearing on a matter.

200 · application/json
{
  "status": "results",
  "rephrased_query": "reprisal for occupational health and safety complaint; wrongful dismissal",
  "citations": [
    {
      "id": "ca-act-rsc-1985-c-l-2--339470",
      "statute_title": "Canada Labour Code",
      "chapter": "L-2",
      "slug": "ca/act/rsc-1985-c-l-2",
      "node_type": "Section",
      "label": "147",
      "path": ["Part II", "s. 147"],
      "text_snippet": "No employer shall dismiss ... an employee because the employee has ...",
      "score": 0.91,
      "theme_slugs": ["labour-employment"]
    }
  ],
  "applied_themes": [{"slug": "labour-employment", "score": 0.88}],
  "applied_ministers": [{"slug": "labour", "score": 0.70}],
  "clarifying_question": null,
  "notes": []
}

POST /v1/validate-case-citation

Does a case citation resolve to a real decision - and is that decision still good law? Send the citation as a lawyer would write it (neutral citation or Supreme Court Reports form, with or without a paragraph pinpoint). You get back the decision itself (title, neutral and reporter citations, court, date, official source URL, stable slug), whether the cited paragraph exists, and authority: a deterministic good-law verdict folded from every dated treatment of the case in the corpus. A citation that resolves but has been overruled is the most dangerous answer this API can give, so the two questions are answered in one call.

One endpoint, one or many. Send query (or structured) at the top level for a single citation, or citations for up to 100. The response shape never changes with the count: always results in request order plus a summary. Each item resolves independently - a bad citation yields a per-item error and never fails the others. POST /v1/validate-case-citation/batch is an alias with the identical body and response, so the routes mirror the legislation pair. Each citation costs 50 credits, one call or one hundred.

Corpus today: Supreme Court of Canada decisions from 1970 onward, ingested from the Court's official judgments site. A case those decisions cite but which is not itself ingested (a pre-1970 S.C.R. decision, a lower-court ruling) is a known citation target: it returns status: "coverage_gap" with the case identified and in_corpus: false, never a guess.

Body parameters
FieldDescription
query
string · one of query / structured / citations
The citation as written: R. v. Jordan, 2016 SCC 27, at para 46, [1959] S.C.R. 121, or a slug such as ca/case/2016-scc-27.
structured
object · optional
Pre-parsed citation: neutral_citation, style_of_cause, court, year, decision_number, pinpoint_paragraph. Skips the parse for a fully deterministic lookup.
citations
array · optional
Up to 100 items, each with the single-citation fields above. Mutually exclusive with the top-level shorthand.
as_of
date · optional
Replay the good-law verdict at a date. A case overruled in 2019 was good law in 2018, and a brief about 2018 conduct needs the 2018 answer.
include_treatments
boolean · optional
Also return treatments: the full dated ledger, worst-first, each event pinpointed and quoted from the treating decision. Off by default; authority carries the counts either way.
strict
boolean · optional
When the deterministic parser cannot read a citation the service asks a small language model for a second reading. strict: true refuses that fallback so the same input always produces the same answer. The deterministic parse always wins when it succeeds, and the model never mints an id.
Each result
FieldDescription
valid
boolean
True only when the citation resolved to a fully ingested decision and the cited paragraph, if any, exists. A graph fact, not a score threshold.
status
enum
resolved · coverage_gap (known citation target, decision not ingested) · not_found · unsupported (nothing parseable as a case citation).
case
object
title, neutral_citation, reporter_citation (how a pre-2000 decision is cited), court, decision_date, docket, source_url, slug, in_corpus. Feed slug straight back in as a query.
pinpoint
object · nullable
The cited paragraph - paragraph_number, anchor, and its verbatim text. Null when no paragraph was cited.
authority
object · nullable
status is one of overruled, overruled_in_part, negatively_treated, cautionary, positively_treated, no_treatment_found, with per-direction event counts and a coverage boundary stating exactly what corpus the verdict was computed against - so "nothing found" never reads as "nothing exists". Null when the citation did not resolve.
score_breakdown
object
The graph facts behind validity_score: graph_match, neutral_citation_verified, unique_match, decision_ingested, pinpoint_verified (null when no paragraph was cited - nothing verified, nothing claimed).
Request · response
curl -X POST https://api.maplejuris.com/v1/validate-case-citation \
  -H "Authorization: Bearer $MAPLEJURIS_KEY" \
  -H "Content-Type: application/json" \
  -d '{"query": "R. v. Jordan, 2016 SCC 27, at para 46"}'

# Many at once - same route, same response shape
curl -X POST https://api.maplejuris.com/v1/validate-case-citation \
  -H "Authorization: Bearer $MAPLEJURIS_KEY" \
  -H "Content-Type: application/json" \
  -d '{"citations": [{"query": "Dunsmuir v. New Brunswick, 2008 SCC 9"},
                     {"query": "Roncarelli v. Duplessis, [1959] S.C.R. 121"}],
       "as_of": "2018-12-31"}'

POST /v1/discover-cases

A legal situation in, ranked decisions out - at paragraph level. Discovery extracts the doctrinal concepts from your situation, then runs deterministic structural retrieval over the case-law graph: paragraph text, issues, and legislation anchors, re-ranked by how often the corpus itself relies on each decision. No vector similarity. Every returned case carries good_law and its treatments inline, for the same reason validation does: a discovered case that has since been overruled is worse than no result.

Send situation in prose, or concepts alone. The concepts-only form runs the whole path with no model in it - deterministic, replayable, auditable - and applied_concepts reports exactly what was executed either way. When the situation is too thin to search you get status: "needs_clarification" and one question; re-POST with clarification_history extended, exactly as with /v1/discover.

Priced per result returned: 100 credits each. A call that returns two cases costs a fraction of one that returns twenty. Because the count is not known until the pipeline has run, the call reserves top_k × 100 up front and refunds the difference once the real count is known. needs_clarification and no_results cost nothing - a question is not a result.

Body parameters
FieldDescription
situation
string · situation or concepts
Natural-language description of the legal issue. Optional when concepts is supplied.
concepts
array of strings · optional
Explicit doctrinal terms to match, e.g. ["unreasonable delay", "trial within a reasonable time"]. Overrides extraction; makes the call fully deterministic.
provision
string · optional
Legislation anchor, e.g. Criminal Code s 718 - find cases citing it.
jurisdiction
string · optional
Jurisdiction filter, e.g. "CA". The corpus today is the Supreme Court of Canada.
top_k
integer · optional
Maximum cases to return, 1-25. Defaults to 10. Also sets the credit reservation.
clarification_history
array · optional
Prior { question, answer } pairs from a needs_clarification response.
Each case
FieldDescription
good_law
enum
good · caution · negative · unknown.good_law_note states the coverage caveat every time: absence of negative treatment reflects only the ingested corpus.
treatments
array
How later decisions in the corpus treated this case - each with the treating case's citation, the relationship (overrules, distinguishes, follows…), the paragraph where it happens, the court's own words, and a source_url to verify against.
on_point
array
The paragraphs that matched, with verbatim text.
why
array of strings
Human-readable explanation of the match: which concepts hit which paragraphs, how often the corpus cites the case, and whether other results here rely on it.
score · authority_weight · matched_by
number · int · array
The rank, the in-corpus citation count, and the signals that fired (concept:paragraph, concept:issue, legislation_anchor).
Request · response
curl -X POST https://api.maplejuris.com/v1/discover-cases \
  -H "Authorization: Bearer $MAPLEJURIS_KEY" \
  -H "Content-Type: application/json" \
  -d '{"situation": "Criminal trial delayed 40 months between charge and trial; the accused says the delay is unreasonable under s. 11(b) of the Charter",
       "top_k": 5}'

# Deterministic, no model in the path
curl -X POST https://api.maplejuris.com/v1/discover-cases \
  -H "Authorization: Bearer $MAPLEJURIS_KEY" \
  -H "Content-Type: application/json" \
  -d '{"concepts": ["presumptive ceiling", "trial within a reasonable time"], "top_k": 5}'

Reading slugs and provision ids

Every response carries two stable identifiers alongside the human citation. The statute.slug is a canonical, human-readable reference for the matched instrument: {jurisdiction}/{act|reg}/{citation-token}, lowercase, where the token is the instrument's own citation. It reads the way a lawyer cites: the reporter, the year, and the chapter or regulation number are all in there.

FieldDescription
ca/act/rsc-1985-c-c-46
Criminal Code
RSC 1985, c C-46. Revised Statutes of Canada, chapter C-46.
ca/act/rsc-1985-c-1-5th-supp
Income Tax Act
RSC 1985, c 1 (5th Supp). Supplement volumes keep their marker.
ca/act/rsc-1985-c-41-4th-supp-part-i
ACOA Act
RSC 1985, c 41 (4th Supp), Part I. When several Acts share one chapter, a Part tail tells the instruments apart.
on/act/rso-1990-c-b16
Business Corporations Act (ON)
RSO 1990, c B.16. Ontario letter chapters drop the period in the token; the citation form is recoverable from it.
ca/reg/sor-2002-227
IRPR
SOR/2002-227. Federal regulations by their SOR / SI number.
ca/reg/crc-c-870
Food and Drug Regulations
CRC, c 870. The consolidated pre-1978 federal regulations.
on/reg/o-reg-4-00
Ontario regulation
O Reg 4/00. Number-first Ontario regulations.
on/reg/rro-1990-reg-194
Rules of Civil Procedure
RRO 1990, Reg 194. Revised Regulations of Ontario, 1990.

The reading rules: everything is lowercase, punctuation becomes dashes (periods between digits too, so chapter A-10.7 is a-10-7), and the jurisdiction and kind prefixes say what you are holding before you read the token. A slug never changes once minted - if a citation changes, a new instrument is minted rather than rewriting the slug.

statute.idis the same slug with dashes plus the publisher's own document id (ca-act-rsc-1985-c-c-46--114997). target.idextends it with the provision's type-tagged path: …--s-718-sub-2 is section 718, subsection (2). The tags are s section · sub subsection · p paragraph · sp subparagraph · cl clause · scl subclause · sch schedule · def definition · pt part.

The tags are what keep different law apart: s-16-1 is section 16.1 while s-16-sub-1is section 16(1) - opposite rules in the Access to Information Act. Treat both identifiers as opaque - match them, don't parse them - and send either back as structured.id to fetch exactly that instrument or provision again. Ids minted before the 2026-08-24 tag rename (-ss- for subsections) keep resolving.

Citation → slug → provision id
Criminal Code, RSC 1985, c C-46
  → slug ca/act/rsc-1985-c-c-46
  → id   ca-act-rsc-1985-c-c-46--114997

Criminal Code, RSC 1985, c C-46, s 718(2)
  → target.id ca-act-rsc-1985-c-c-46--114997--s-718-sub-2

Income Tax Act, RSC 1985, c 1 (5th Supp), s 110(1)(d)(i)(A)
  → slug ca/act/rsc-1985-c-1-5th-supp
  → target.id …--s-110-sub-1-p-d-sp-i-cl-a

O Reg 4/00, s 1
  → slug on/reg/o-reg-4-00
  → target.id on-reg-o-reg-4-00--000004--s-1

Citation styles we accept

The resolver interprets free-form text, so citations can be passed roughly as a lawyer would write them.

FieldDescription
Criminal Code s. 718
short title + section
The most common form.
Access to Information Act, s. 2(1)
subsection
Subsection and paragraph pinpoints are resolved to the exact node.
s. 718.2(a)(i) of the Criminal Code
paragraph
Trailing or leading statute references both parse.
R.S.C. 1985, c. C-46, s. 2
chapter form
Full McGill-style chapter citations.
PIPEDA s. 5
abbreviation
Common abbreviations - CDSA, ITA, and the like.
definition of "officer" in s. 2
defined term
Defined-term references inside a section.
Income Tax Act s. 18
long title
Full statute titles, with or without punctuation.
Immigration and Refugee Protection Regulations, SOR/2002-227, s 179
regulation
Regulations by instrument number - SOR/…, SI/…, C.R.C., c. …, O. Reg. n/yy, R.R.O. 1990, Reg. n. The number is treated as an exact identity - it derives the instrument's slugand is looked up as an id, so a generic title like “General” can never pull the match onto a different regulation.
Income Tax Act, s. 110(1)(d)(i)(A)
clause
Pinpoints resolve to the clause and subclause - (A), (I) - six levels deep.
Criminal Code, ss. 265-267
range / list
Every member of a span or list is looked up. All found → resolved with a note naming the members; any missing → the response says exactly which one.
Code criminel, LRC 1985, c C-46, art 718
French
French reporters - LRC, LC, DORS/…, TR/… - name the same instruments.

Coverage today is federal Canada - acts and regulations from Justice Laws - plus Ontario, from e-Laws. Citations from any other Canadian jurisdiction are recognized and return unsupported, with a note saying so, rather than a guess or a false negative.

One deliberate exclusion: constitutional instruments - the Constitution Acts, including the Canadian Charter of Rights and Freedoms - are outside the corpus permanently, and the response says so explicitly rather than inviting you to re-check as coverage grows.

Any of these work
{"query": "Criminal Code s. 718"}
{"query": "Access to Information Act, s. 2(1)"}
{"query": "s. 718.2(a)(i) of the Criminal Code"}
{"query": "R.S.C. 1985, c. C-46, s. 2"}
{"query": "PIPEDA s. 5"}
{"query": "Income Tax Act s. 18"}

Rate limits and errors

Usage is counted per account - all your keys and tokens share one allowance, and an organization's keys share its owner's - per calendar month, and resets on the first of the month. Unused credits do not carry forward:each month starts at your plan's full allowance, whatever was left of the last one. Check consumption any time with GET /v1/usage (never burns quota) or the meter on your API keys page. Upgrading on the pricing page applies the new quota within a few minutes.

What each call costs
FieldDescription
POST /v1/validate-citation
1 credit · per citation
The batch route bills the same: 100 citations, 100 credits. Only answers are paid for: a batch item that ends in an error, or a call that fails with a 5xx, is refunded, and the batch summary's credits_charged says what the batch cost.
POST /v1/discover
10 credits · per call
An LLM rephrase, embeddings, and several vector searches per request.
POST /v1/validate-case-citation
50 credits · per citation
One call or a hundred citations - per citation, never per request. The /batch alias bills identically.
POST /v1/discover-cases
100 credits · per result returned
Reserves top_k × 100, then refunds down to the real count. needs_clarification and no_results cost nothing.

Retrying safely. Send an Idempotency-Key header (a UUID works) with POST /v1/validate-citation or its batch route. A retry with the same key and the same body within 24 hours returns the first answer, marked Idempotent-Replayed: true, and is not billed again. The same key with a different body answers 422 (idempotency_key_reused); a retry while the first request is still running answers 409 (idempotency_in_progress) - retry shortly.

GET /v1/usage returns this same table as pricing, read from the constants the server bills with, so a client can display the price it will actually be charged. Each entry carries a unit- 50 "per citation" and 50 "per call" differ by two orders of magnitude on a 100-item batch.

Monthly allowance by plan
FieldDescription
Free
non-commercial
1,000 credits per month. REST only.
Research
non-commercial
10,000 credits per month. REST only.
Commercial
commercial
100,000 credits per month. REST and MCP. Organizations: invite teammates by email; they share your credits.
Enterprise
commercial
1,000,000 credits per month, with a dedicated Slack channel. REST and MCP. Organizations: invite teammates by email; they share your credits.
Error codes
FieldDescription
400
unsupported version
The MapleJuris-Version header names a version that was never released or is no longer supported; the response lists the supported versions.
401
unauthorized
Missing, revoked, or expired API key.
402
payment required
Your last payment failed. Your plan is kept, but API and MCP calls are paused until a payment succeeds - update your payment method on the Plan & billing page.
403
forbidden
The plan behind the key does not include what was asked for: the MCP server on Free or Research, or an organization key while the organization's owner is not on Commercial or Enterprise. The message names the plan.
422
unprocessable
Malformed body - the response names the offending field.
429
quota exceeded
Monthly allowance spent. The message states your plan and its limit.
429 · quota exceeded
{
  "detail": "Monthly API quota exceeded: plan
    'non_commercial_research' allows 10000
    credits per month"
}

API versions

Your account uses one API version, and keeps it: requests from its keys get that version's request and response shapes until you change it - also after a later version changes them - so an integration you have tested keeps working until you decide to move. New fields and new routes still reach you; nothing you rely on is renamed or removed under you.

Choose it on your dashboard. The API keys page shows the version your keys use and lets you pick any supported version, from 3.0.0 to the latest. A change applies to new requests within a minute. An organization's version applies to the organization's keys, and an organization admin chooses it. Until you choose, your account uses the version that was current at its first API call, saved automatically.

Or choose per request. To use another version for a single request - to try a newer one before you switch, for example - send it in the MapleJuris-Versionrequest header. The header always wins over your account's version, and every response names the version that answered in a MapleJuris-Version response header.

FieldDescription
3
major
The newest 3.x release.
3.8
major.minor
The newest 3.8.x release.
3.8.0
exact
Exactly that release.

A version that was never released, or one older than 3.0.0, answers 400 with code: "unsupported_api_version", supported_versions and latest - before anything runs or is charged. GET /v1/versions lists every version you can select and needs no key.

X-MapleJuris-Version, on every response, names the newest version the API runs. When it is newer than MapleJuris-Version, a newer version is available: the changelog says what changed. Try it with the header, then switch your account on the API keys page.

A change that could break an integration is announced in the changelog at least 30 days before it ships, and support for an older version ends only with at least 30 days' notice. Versions apply to the routes you call with an API key; the MCP server always runs the latest version.

Override the version for one request
# Without the header, a request runs at the version
# chosen for your account on the API keys page.
curl -i -X POST https://api.maplejuris.com/v1/validate-citation \
  -H "Authorization: Bearer $MAPLEJURIS_KEY" \
  -H "MapleJuris-Version: 3.8" \
  -H "Content-Type: application/json" \
  -d '{"query": "Criminal Code s. 718"}'
# MapleJuris-Version: 3.8.0     (the version that answered)
# X-MapleJuris-Version: 3.8.0   (the newest version)

# Which versions you can select (no key needed)
curl https://api.maplejuris.com/v1/versions
# {"latest": "3.8.0", "min_supported": "3.0.0",
#  "supported": ["3.8.0", "3.7.1", ...], ...}

Coverage, and its limits

§8.4 of the Terms points here for known coverage limitations. Stating what is not covered matters more than what is: a citation that does not resolve because we never held the instrument looks identical to one that does not resolve because it was invented.

Legislation
FieldDescription
Federal · Ontario
complete
Acts and regulations, with their hierarchy and current consolidated text. A citation that does not resolve here is good evidence the provision does not exist as cited. Earlier versions of a provision (its text on a past date) are not yet served.
Other provinces and territories
not covered
British Columbia, Alberta, Saskatchewan, Manitoba, New Brunswick, Nova Scotia, Prince Edward Island, Newfoundland and Labrador, Yukon, the Northwest Territories and Nunavut are out of corpus. Every citation there returns unsupported with coverage_gap: true - unknown, not invalid.
Québec
not covered
Not ingested. Every Québec citation returns unsupported.
Case law
FieldDescription
Partially ingested
treat as incomplete
Supreme Court of Canada, Federal Court, Federal Court of Appeal, Tax Court, Ontario Court of Appeal and Ontario Superior Court. A negative result is never evidence a decision does not exist.
Not covered
planned
Provincial appellate courts outside Ontario, and administrative tribunals.
Across everything
FieldDescription
Language
English only
We do not hold French-language versions, including where the French version is equally authoritative.
Currency
lags the official source
An amendment appears once it has been published by the Official Source and ingested. Always verify in-force status against the Official Source for anything consequential.
Treatment and good-law status
corpus-bound
Reflects only the treatments in the ingested corpus, not every treatment that exists.
How to use this in your product

Outside Federal and Ontario legislation, present a non-result as “not found in the available sources” rather than “this provision does not exist”. The difference costs you nothing and is the gap between a careful tool and a confidently wrong one.

Attribution

The Attribution section of the Terms requires attribution wherever results reach anyone outside your own organization, in the form specified here. This is that form.

When it is required
FieldDescription
Delivered by anyone but you
required
Where the API is white-labelled, or offered through an intermediary, distributor, reseller or any other party that is not the purchasing organization.
Shown or explained publicly
required
Marketing material, a product demonstration, a recorded walkthrough, a conference talk - anywhere the capability is presented to people outside your organization.
Named in an agreement
required
Where our technology is referred to in a contract, statement of work or other written agreement with your own client.
Internal use
not required
A tool your own people use, with results shown to nobody outside the organization.
The form

The words, linked to https://maplejuris.com, legible against its background and no smaller than the surrounding body text:

Citations verified by Maple Juris

Where a link is impossible - print, a slide, a PDF - the words alone are enough. You may use our name in plain text; you may not alter our name or wordmark, or present it as your own.

What attribution must not imply

Attribution says the citations were checked by us. It must not state or suggest that Maple Juris provides legal advice, has reviewed the matter, endorses your product, or is a partner or affiliate of yours. Phrasing such as “in partnership with” or “powered by Maple Juris AI” is not attribution and is not permitted.

Removing it. The right to use the API without visible attribution is available by negotiation. Write to info@maplejuris.com with where the product appears and who sees it.

MCP server

The same service is available to AI agents over the Model Context Protocol, using the same API key and drawing on the same credit allowance. It has its own documentation rather than living inside this REST reference:

MCP documentation →
Tools, connecting Claude Code, Codex, Cursor and Claude Desktop, and how MCP calls are metered.

Which plans include it

The MCP server is included on the Commercial, Enterprise and Custom plans. Free and Research are REST only.