Quickstart
Make your first verification request in under five minutes.
The endpoint
Send a POST to https://app.rule26ai.com/api/v1/verify with a JSON body of items. Each item has an id (a client-supplied string echoed back on the matching result), a type, and the text to verify. You can mix item types in a single request.
Supported item types
The type field is a fixed v1 value set:
case: a case citation.quote: a quotation to locate in a resolved authority.statute: a statutory citation.rule: a court or procedural rule citation.constitution: a constitutional provision.link: a source URL to verify.
Most types carry their text in rawText. The exceptions are quote, which uses quoteText and links to its citation via parentCaseId, and link, which uses url. The API Reference is the authoritative schema for each type’s fields and constraints. The examples below cover the two most common types, case and quote.
1. Make a request
curl
curl https://app.rule26ai.com/api/v1/verify \
-H "Authorization: Bearer $GHOSTCITE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"items": [
{ "id": "r_1", "type": "case", "rawText": "Smith v. Jones, 200 F.3d 1 (2001)" }
]
}'
JavaScript (fetch)
const res = await fetch("https://app.rule26ai.com/api/v1/verify", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.GHOSTCITE_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
items: [
{ id: "r_1", type: "case", rawText: "Smith v. Jones, 200 F.3d 1 (2001)" },
],
}),
});
const data = await res.json();
console.log(data.results[0].verdict.status); // "warning"
Python (requests)
import os, requests
res = requests.post(
"https://app.rule26ai.com/api/v1/verify",
headers={"Authorization": f"Bearer {os.environ['GHOSTCITE_API_KEY']}"},
json={"items": [
{"id": "r_1", "type": "case", "rawText": "Smith v. Jones, 200 F.3d 1 (2001)"},
]},
)
data = res.json()
print(data["results"][0]["verdict"]["status"]) # "warning"
2. Read the response
{
"results": [
{
"id": "r_1",
"type": "case",
"citation": { "raw": "Smith v. Jones, 200 F.3d 1 (2001)" },
"verdict": {
"status": "warning",
"outcome": "mismatch",
"message": "Decision year does not match the resolved authority."
},
"opinion": {
"caseName": "Smith v. Jones",
"court": { "name": "9th Circuit" },
"year": 1999,
"documents": [
{ "provider": "courtlistener", "url": "https://www.courtlistener.com/opinion/..." }
]
},
"evidence": {
"comparisons": [
{ "attribute": "year", "cited": "2001", "found": "1999", "match": false }
]
}
}
],
"summary": {
"verified": 0, "warning": 1, "critical": 0, "total": 1,
"unique_citations": 1, "billed_citations": 1,
"is_fully_verified": false, "is_fully_accounted": true,
"overallStatus": "warning"
},
"usage": { "used": 1, "remaining": 99, "limit": 100 }
}
verdict: the answer
Every result carries a verdict. status is a closed set: verified, warning, or critical. outcome is a finer, open category (e.g. verified, mismatch, not_found), and message is human-readable prose you can surface to users. Above, the case resolved but the cited year is off, a warning.
evidence: the “why”
When the engine performed a deterministic comparison, evidence.comparisons lists each one as { attribute, cited, found, match }. Here, the year the user cited (2001) differs from the authority’s (1999), so match: false. Iterate the comparisons to show an “expected vs. found” view. Read Structured Evidence before you rely on this, because a missing comparison means “not compared,” never “mismatch.”
opinion: the authority
When an authority resolves, opinion gives you the resolved case name, court, year, and inspectable documents (links to the court record). Use it to let reviewers open the source.
usage: your quota
Every response includes usage with used, remaining, and limit for the current window. Watch usage.remaining to pace your calls; see Errors & Rate Limits for what happens when it hits zero.
Verify a quotation
A quote item checks whether a passage actually appears in a resolved authority. It attaches to the citation it came from through parentCaseId, so submit the parent case and the quote together:
curl https://app.rule26ai.com/api/v1/verify \
-H "Authorization: Bearer $GHOSTCITE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"items": [
{ "id": "r_1", "type": "case",
"rawText": "Brown v. Board of Education, 347 U.S. 483 (1954)" },
{ "id": "q_1", "type": "quote",
"quoteText": "separate educational facilities are inherently unequal",
"parentCaseId": "r_1" }
]
}'
The response carries one result per item. The quotation result adds a quote object:
{
"results": [
{
"id": "r_1",
"type": "case",
"citation": { "raw": "Brown v. Board of Education, 347 U.S. 483 (1954)", "normalized": "347 U.S. 483" },
"verdict": { "status": "verified", "outcome": "verified", "message": "Citation verified." },
"opinion": {
"caseName": "Brown v. Board of Education",
"court": { "name": "Supreme Court of the United States" },
"year": 1954
}
},
{
"id": "q_1",
"type": "quote",
"citation": { "raw": "347 U.S. 483" },
"verdict": { "status": "verified", "outcome": "verified", "message": "Quotation located in the authority." },
"quote": {
"matched": true,
"snippet": "separate educational facilities are inherently unequal"
}
}
],
"summary": {
"verified": 2, "warning": 0, "critical": 0, "total": 2,
"unique_citations": 1, "billed_citations": 1,
"is_fully_verified": true, "is_fully_accounted": true,
"overallStatus": "verified"
},
"usage": { "used": 1, "remaining": 99, "limit": 100 }
}
Reading the quotation result:
verdict.status: "verified"means the quotation was located in the resolved authority. Aquotethat could not be found comes backwarningorcritical, never an HTTP error.quote.matched: trueconfirms the match, andquote.snippetechoes the text you submitted.- The quotation does not add to
summary.unique_citationsorsummary.billed_citations. Only citations are billed; a quotation rides along with its parent case (see Quota & billing).
quote.passage), its location (quote.location), the response link back to the parent (citationId), and document position are reserved for a future version and are not emitted in v1.1. Treat their absence as “not yet available,” not as failure. The API Reference marks each reserved field.Reading a verification result
You know JSON; these are the GhostCite semantics to build on:
verdict.statusis the primary decision. It is a closed set,verified,warning, orcritical, and it is what your application should branch on. Everything else explains why.evidence.comparisonsappears only when a deterministic comparison exists. Iterate what is present; the absence of a comparison means “not compared on this path,” never “mismatch.” Read Structured Evidence before you rely on it.summaryis the request-level rollup. Counts plusoverallStatusgive you one headline across a whole batch without re-scanning every result.usagereports your quota (used,remaining,limit). Pace onusage.remaining; see Errors & Rate Limits.