# Check a document Source: https://docs.courtrules.app/api-reference/check POST /api/v1/check Run deterministic compliance checks against a federal court filing, checking page limits, formatting, required sections, and judge-specific standing order rules **judge\_slug** `string` *required* Judge slug identifier (e.g. `gary-r-brown`) **district\_id** `string` *required* District identifier (e.g. `edny`) **document\_scope** `string` *required* Document type. One of: `brief_support`, `brief_reply`, `brief_opposition`, `reconsideration_support`, `reconsideration_reply`, `letter`, `discovery_letter`, `proposed_findings`, `affidavit`, `settlement_statement`, `objection_response`, `rule_56_1_statement` **motion\_type** `string` Motion type. One of: `Rule_12`, `Rule_56`, `Rule_50`, `Rule_59`, `Rule_60`, `Daubert`, `TRO`, `preliminary_injunction`, `reconsideration`, `discovery`, `motion_to_amend`, `motion_in_limine`, `general` **is\_pro\_se** `boolean` *required* Whether the filing party is pro se **pmc\_completed** `boolean` *required* Whether a pre-motion conference has been completed for this motion **opposing\_party\_pro\_se** `boolean` *required* Whether the opposing party is pro se (triggers additional notice requirements) **filing\_role** `string` *required* Filing role. One of: `movant`, `opponent`, `reply` **document** `object` *required* Document metadata. Only `page_count` and `word_count` are required. See [Document structure](/concepts/document-structure) for all optional fields. **Required fields** **document.page\_count** `integer` *required* Total page count (must be >= 1) **document.word\_count** `integer` *required* Total word count (must be >= 0) **Optional sections** **document.caption** `object` Caption analysis results **document.signature\_block** `object` Signature block analysis results **document.sections** `object` Document section analysis results **document.format** `object` Formatting analysis results (font size, margins, spacing) **document.privacy** `object` Privacy/PII analysis results ```bash Minimal theme={"theme":{"light":"github-light","dark":"github-dark"}} curl -X POST https://api.courtrules.app/api/v1/check \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "judge_slug": "gary-r-brown", "district_id": "edny", "document_scope": "brief_support", "motion_type": "Rule_56", "is_pro_se": false, "pmc_completed": true, "opposing_party_pro_se": false, "filing_role": "movant", "document": { "page_count": 22, "word_count": 7200 } }' ``` ```bash Full theme={"theme":{"light":"github-light","dark":"github-dark"}} curl -X POST https://api.courtrules.app/api/v1/check \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "judge_slug": "gary-r-brown", "district_id": "edny", "document_scope": "brief_support", "motion_type": "Rule_56", "is_pro_se": false, "pmc_completed": true, "opposing_party_pro_se": false, "filing_role": "movant", "document": { "page_count": 18, "word_count": 7200, "caption": { "present": true, "has_court_name": true, "has_case_title": true, "has_docket_number": true, "has_document_designation": true }, "signature_block": { "present": true, "has_attorney_name": true, "has_firm_name": true, "has_address": true, "has_email": true, "has_phone": true, "is_electronic_signature": true }, "sections": { "has_toc": true, "has_toa": true, "has_certificate_of_compliance": true, "certificate_word_count": 7200, "has_certificate_of_service": true, "has_numbered_paragraphs": true, "has_56_1_statement": true, "has_56_1_counterstatement": false, "has_proposed_amended_pleading": false, "has_verbatim_discovery_text": false, "has_conferral_certification": false, "has_notice_of_motion": true, "has_memorandum_of_law": true, "has_supporting_affidavits": true, "has_pro_se_sj_notice": false }, "format": { "primary_font_size_pt": 12, "footnote_font_size_pt": 10, "margin_inches": 1.0, "line_spacing": "double" }, "privacy": { "contains_full_ssn": false, "contains_full_dob": false, "contains_minor_full_name": false, "contains_full_financial_account": false } } }' ``` ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} { "judge": { "slug": "gary-r-brown", "name": "Gary R. Brown" }, "summary": { "status": "NON_COMPLIANT", "failures": 1, "warnings": 0, "passes": 1, "action_items": 3 }, "results": [ { "severity": "CRITICAL", "category": "PAGE_LIMIT", "message": "22 pages exceeds 20-page limit", "source": "Brown SO §2.B", "status": "FAIL" }, { "severity": "INFO", "category": "WORD_LIMIT", "message": "7,200 words within 8,750-word limit", "source": "EDNY LR 7.1(c)", "status": "PASS" }, { "severity": "WARNING", "category": "COURTESY_COPY", "message": "Courtesy copy required", "source": "Brown SO §1", "status": "ACTION_REQUIRED" }, { "severity": "INFO", "category": "PMC", "message": "Pre-motion conference completed", "source": "Brown SO §3.A", "status": "PASS" }, { "severity": "WARNING", "category": "BUNDLING", "message": "Do NOT file until motion is fully briefed", "source": "Brown SO §3.B", "status": "ACTION_REQUIRED" } ], "meta": { "checks_run": 5, "checks_skipped": 16 } } ``` ## Response fields **summary** `object` **Summary** **status** `string` Overall compliance status: - `COMPLIANT`: No failures, no action items - `REVIEW`: No failures, but action items require attention - `NON_COMPLIANT`: At least one rule violation **failures** `integer` Count of FAIL results **warnings** `integer` Count of WARNING-severity failures **passes** `integer` Count of PASS results **action\_items** `integer` Count of ACTION\_REQUIRED results **results** `array` Individual check results **LintResult** **severity** `string` `CRITICAL`, `WARNING`, or `INFO` **category** `string` Check category (e.g. `PAGE_LIMIT`, `WORD_LIMIT`, `CAPTION`, `PMC`, `FORMAT`) **message** `string` Human-readable explanation **source** `string` Rule citation (e.g. `FRCP 10(a)`, `EDNY LR 7.1(c)`, `Brown SO §2.B`) **status** `string` `FAIL`, `PASS`, or `ACTION_REQUIRED` **meta** `object` **Meta** **checks\_run** `integer` Total number of checks that produced results **checks\_skipped** `integer` Checks that apply to this filing but were skipped because their document section was not provided # Classify a document Source: https://docs.courtrules.app/api-reference/classify POST /api/v1/classify Upload a PDF and receive document classification, extracted metadata, and a partial /check request body when supported ``` POST /api/v1/classify ``` Upload a PDF and receive document classification (scope, motion type) plus a partial request body for the [`/check`](/api-reference/check) endpoint when the PDF is a supported federal filing. The API extracts page count, word count, structural metadata, and document type from the PDF automatically. You must add filing context fields (`is_pro_se`, `pmc_completed`, `opposing_party_pro_se`, `filing_role`) before sending to `/check`. The response includes a `supported` boolean indicating whether the document is a classifiable federal court filing. Non-federal documents, blank templates, court rules or practices, and non-legal documents return `supported: false` with `confidence: "low"` and no `check_request`. Uploaded PDFs are stored to improve quality. The response can take 10 to 30 seconds. For fillable forms and some interactive PDFs, the font, margin and line spacing details can't always be read in time. When that happens, the format checks are skipped and the response includes a warning. ## Try it A sample filing PDF is available in the [console playground](https://console.courtrules.app/playground?tab=classify). Upload it to see classification, extracted metadata, and a ready-to-run `/check` request body. ## Request **judge\_slug** `string` *required* Judge slug identifier (e.g. `gary-r-brown`) **district\_id** `string` *required* District identifier (e.g. `edny`) **pdf\_base64** `string` *required* Base64-encoded PDF file, 10 MB or less before encoding. A larger request is refused with `413`; split a larger filing and classify the parts. **filename** `string` Original filename of the PDF (e.g. `motion_for_summary_judgment.pdf`). Recommended: always include if available. Filenames like `memo_in_support_sj.pdf` provide a strong classification signal; generic names like `document.pdf` are still accepted but add no value. ```bash cURL theme={"theme":{"light":"github-light","dark":"github-dark"}} # Base64-encode the PDF, then send it PDF_B64=$(base64 -i motion_for_sj.pdf) curl -X POST https://api.courtrules.app/api/v1/classify \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d "{ \"judge_slug\": \"carol-bagley-amon\", \"district_id\": \"edny\", \"pdf_base64\": \"$PDF_B64\", \"filename\": \"memo_in_support_sj.pdf\" }" ``` ```python Python theme={"theme":{"light":"github-light","dark":"github-dark"}} import base64 from pathlib import Path import requests headers = {"Authorization": "Bearer YOUR_API_KEY"} # Read and encode the PDF pdf_b64 = base64.b64encode(Path("motion_for_sj.pdf").read_bytes()).decode() # Classify the PDF resp = requests.post( "https://api.courtrules.app/api/v1/classify", headers=headers, json={ "judge_slug": "carol-bagley-amon", "district_id": "edny", "pdf_base64": pdf_b64, "filename": "memo_in_support_sj.pdf", }, ) result = resp.json() # Add filing context, then send to /check check_body = { **result["check_request"], "is_pro_se": False, "pmc_completed": True, "opposing_party_pro_se": False, "filing_role": "movant", } check_resp = requests.post( "https://api.courtrules.app/api/v1/check", headers=headers, json=check_body, ) ``` ```typescript Node.js theme={"theme":{"light":"github-light","dark":"github-dark"}} import { readFileSync } from "fs"; const pdfBase64 = readFileSync("motion_for_sj.pdf").toString("base64"); const classifyResp = await fetch("https://api.courtrules.app/api/v1/classify", { method: "POST", headers: { Authorization: "Bearer YOUR_API_KEY", "Content-Type": "application/json", }, body: JSON.stringify({ judge_slug: "carol-bagley-amon", district_id: "edny", pdf_base64: pdfBase64, filename: "memo_in_support_sj.pdf", }), }); const { check_request } = await classifyResp.json(); // Add filing context, then send to /check const checkResp = await fetch("https://api.courtrules.app/api/v1/check", { method: "POST", headers: { Authorization: "Bearer YOUR_API_KEY", "Content-Type": "application/json", }, body: JSON.stringify({ ...check_request, is_pro_se: false, pmc_completed: true, opposing_party_pro_se: false, filing_role: "movant", }), }); ``` ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} { "classification": { "document_scope": "brief_support", "motion_type": "Rule_56", "confidence": "high", "supported": true, "reasoning": "Document is titled 'Memorandum of Law in Support of Motion for Summary Judgment', contains Rule 56 references, and includes a statement of undisputed material facts." }, "document": { "page_count": 31, "word_count": 10000, "caption": { "present": true, "has_court_name": true, "has_case_title": true, "has_docket_number": true, "has_document_designation": true }, "sections": { "has_toc": true, "has_toa": true, "has_certificate_of_compliance": false, "has_certificate_of_service": true, "has_numbered_paragraphs": false, "has_56_1_statement": true, "has_56_1_counterstatement": false, "has_proposed_amended_pleading": false, "has_verbatim_discovery_text": false, "has_conferral_certification": false, "has_notice_of_motion": true, "has_memorandum_of_law": true, "has_supporting_affidavits": true, "has_pro_se_sj_notice": false } }, "check_request": { "judge_slug": "carol-bagley-amon", "district_id": "edny", "document_scope": "brief_support", "motion_type": "Rule_56", "document": { "page_count": 31, "word_count": 10000, "caption": { "present": true, "has_court_name": true, "has_case_title": true, "has_docket_number": true, "has_document_designation": true }, "sections": { "has_toc": true, "has_toa": true, "has_certificate_of_compliance": false, "has_certificate_of_service": true, "has_numbered_paragraphs": false, "has_56_1_statement": true, "has_56_1_counterstatement": false, "has_proposed_amended_pleading": false, "has_verbatim_discovery_text": false, "has_conferral_certification": false, "has_notice_of_motion": true, "has_memorandum_of_law": true, "has_supporting_affidavits": true, "has_pro_se_sj_notice": false } } }, "page_count_analysis": { "total_pdf_pages": 35, "front_matter_pages": 2, "back_matter_pages": 2, "body_page_count": 31, "method": "llm_structural_analysis" }, "format_detection": { "confidence": "high", "confidence_reason": "Font and margin data extracted successfully from PDF structure", "warning": null, "font_family": "TimesNewRoman", "font_name_raw": "ABCDEF+TimesNewRomanPSMT", "margins_per_side": { "top": 1.0, "bottom": 1.0, "left": 1.0, "right": 1.0 }, "line_spacing_pt": 24.0 } } ``` ## Response fields **classification** `object` Document type classification **Classification** **document\_scope** `string` Detected document type (e.g. `brief_support`, `letter`, `affidavit`). Omitted when `supported` is `false`. **motion\_type** `string` Detected motion type, if applicable (e.g. `Rule_56`, `discovery`). Omitted for non-motion documents. **confidence** `string` Classification confidence: `high`, `medium`, or `low`. A value of `low` means the document is not a supported filing type. **supported** `boolean` Whether the document is a classifiable federal court filing. Derived from confidence: `true` when confidence is `high` or `medium`, `false` when `low`. **reasoning** `string` Brief explanation of how the document was classified **document** `object` Extracted document metadata including page count, word count, and structural elements detected in the PDF (caption, sections, format, privacy). **check\_request** `object` Present only when `supported` is `true`. A partial request body for [`POST /api/v1/check`](/api-reference/check). Includes `judge_slug`, `district_id`, `document_scope`, `motion_type` (if detected), and the full `document` object. You must add `is_pro_se`, `pmc_completed`, `opposing_party_pro_se`, and `filing_role` before sending. **page\_count\_analysis** `object` Breakdown of how body page count was computed from total PDF pages. **Page count analysis** **total\_pdf\_pages** `integer` Total pages in the uploaded PDF. **front\_matter\_pages** `integer` Pages of front matter (cover, TOC, TOA) excluded from body count. **back\_matter\_pages** `integer` Pages of back matter (cert of service, cert of compliance, exhibits list) excluded from body count. **body\_page\_count** `integer` Effective body page count used for limit checks (total minus front minus back). **method** `string` Analysis method used for page counting. **format\_detection** `object` Detected font, margin, and line spacing from the PDF. Used for formatting compliance checks. **Format detection** **confidence** `string` `high`, `medium`, or `low`. When `low`, format checks are skipped. **confidence\_reason** `string` Why the confidence level was assigned. **warning** `string | null` Human-readable warning when format checks will be skipped or uncertain. **font\_family** `string | null` Font family name (e.g. `TimesNewRoman`). Null when detection failed. **font\_name\_raw** `string | null` Original font name as embedded in the PDF. **margins\_per\_side** `object | null` Margin measurements per side in inches (`top`, `bottom`, `left`, `right`). Null when detection failed. **line\_spacing\_pt** `number | null` Median line spacing in points. Null when detection failed. **warnings** `string[]` Conditions that may affect result quality. Present only when something noteworthy occurred during analysis (e.g., format extraction failed, document was truncated). ## Error responses | Code | Meaning | | - | - | | `400` | Invalid request (missing `pdf_base64`, invalid `judge_slug`, etc.) | | `404` | Court not found, or judge not found in the court | | `413` | The PDF is larger than 10 MB | | `422` | The court has no compliance profile yet (only `edny` today), or the PDF could not be read: password-protected, not a valid PDF, or scanned pages were rejected | | `429` | Rate limit exceeded (5 requests per minute) | | `500` | Internal error while reading the PDF | | `502` | Classification failed (timeout, upstream error). Safe to retry | | `503` | The PDF has scanned pages and text recognition is unavailable right now. Text-based PDFs still work | PDFs exported from a word processor are read directly from their text layer. Scanned pages (images of paper) go through text recognition, and only those pages do. When a scanned page cannot be read, the error body includes `scanned_pages`, the 1-based page numbers that needed text recognition, so you can tell the user which pages to replace. ## Usage pattern The typical supported-document flow is classify, then check: ``` POST /classify → get check_request → POST /check ``` When present, the `check_request` field contains everything the classifier can extract from the PDF. Before sending it to [`/check`](/api-reference/check), add the filing context fields that only the filer knows: `is_pro_se`, `pmc_completed`, `opposing_party_pro_se`, and `filing_role`. When `supported` is `false`, show the classification reasoning to the user and do not call `/check`. # List courts Source: https://docs.courtrules.app/api-reference/courts GET /api/v1/courts Returns every court we map, with coverage status Returns every court we map: federal district courts and state trial courts, with circuit, state, coverage status, and roster size. The full list comes back in one response, and the example below shows three courts of it. Each court in the list counts as one row against your [daily row limit](/api-reference/rate-limits), so keep the list instead of reading it for every request. To read one court, use [`GET /api/v1/courts/{district_id}`](/api-reference/get-court). Courts with `status: live` have rules you can read with [`/rules`](/api-reference/rules) and [`/extracted-rules`](/api-reference/extracted-rules). Any valid API key can query any court. ```bash cURL theme={"theme":{"light":"github-light","dark":"github-dark"}} curl 'https://api.courtrules.app/api/v1/courts' \ -H "Authorization: Bearer YOUR_API_KEY" ``` ```python Python theme={"theme":{"light":"github-light","dark":"github-dark"}} import requests resp = requests.get( "https://api.courtrules.app/api/v1/courts", headers={"Authorization": "Bearer YOUR_API_KEY"}, ) live = [c for c in resp.json()["courts"] if c["status"] == "live"] ``` ```typescript Node.js theme={"theme":{"light":"github-light","dark":"github-dark"}} const resp = await fetch("https://api.courtrules.app/api/v1/courts", { headers: { Authorization: "Bearer YOUR_API_KEY" }, }); const { courts } = await resp.json(); const live = courts.filter((c) => c.status === "live"); ``` ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} { "courts": [ { "district_id": "ca-los-angeles-superior", "name": "Superior Court of California, County of Los Angeles", "circuit": null, "state": "California", "status": "live", "judges_mapped": 116 }, { "district_id": "edny", "name": "Eastern District of New York", "circuit": "2nd Circuit", "state": "New York", "status": "live", "judges_mapped": 47, "judges_profiled": 47 }, { "district_id": "dc-superior", "name": "Superior Court of the District of Columbia", "circuit": null, "state": "District of Columbia", "status": "coming_soon", "judges_mapped": 11 } ], "meta": { "total_districts": 3, "districts_with_data": 2, "total_judges_mapped": 174 } } ``` ## Response fields **courts** `array` Array of court objects **Court object** **district\_id** `string` Unique court identifier. Federal district courts use short codes (`edny`, `sdny`, `cdca`). State courts start with the state's two-letter code (`ca-los-angeles-superior`, `il-cook-circuit`). **name** `string` Full court name **circuit** `string | null` Federal circuit (e.g. "2nd Circuit"). `null` for state courts, which sit outside the federal circuits. **state** `string | null` State or territory. `null` for courts not tied to one state, such as a federal court of appeals. **status** `string` `live` or `coming_soon` (see below) **judges\_mapped** `integer` Number of current judges on the court's roster. In some state courts the roster lists departments or courtrooms rather than individual judges. **judges\_profiled** `integer` Number of judges with compliance profiles used by [`/check`](/api-reference/check). Only present for courts with compliance profiles (`edny` today). **meta** `object` **Meta** **total\_districts** `integer` Number of courts in the list **districts\_with\_data** `integer` Number of courts with rules (`status: live`) **total\_judges\_mapped** `integer` Sum of `judges_mapped` across all courts ## Status field | Status | Meaning | | - | - | | `live` | Rules are available. `/judges`, `/rules`, and `/extracted-rules` return data. | | `coming_soon` | The court is mapped, but we hold no rules for it yet. | Compliance checks ([`/check`](/api-reference/check) and [`/classify`](/api-reference/classify)) need a compliance profile, which exists for `edny` today. Other live courts return `422` from those two endpoints. # Search extracted rules Source: https://docs.courtrules.app/api-reference/extracted-rules GET /api/v1/extracted-rules Query validated extracted filing rules from active source documents, including state court e-filing, timing, service, fee, courtesy-copy, and courtroom rules Search and page through every rule we hold, across all courts. Filter by court, judge, rule type, workflow phase, case type, or text. Results are newest first and paged with `limit` and `offset`. To read the requirements of an official rulebook such as the California Rules of Court instead, send `rulebook_id` (see [Rulebook requirements](#rulebook-requirements) below). **district\_id** `string` Court identifier, such as `il-cook-circuit`, `ca-los-angeles-superior`, or `edny`. **judge\_slug** `string` Judge, calendar, department, or courtroom slug. Court-level rules use `court`. **include\_court\_rules** `boolean` When `judge_slug` is supplied, include court-level rules where `judge_slug` is `court`. Defaults to `true`. **logic\_type** `string` Filter by structured rule type, such as `ElectronicFilingRule`, `FilingTimingRule`, `ServiceRule`, `FilingFeeRule`, or `CourtesyCopyRule`. **workflow\_phase** `string` Filter by workflow phase, such as `FILING`, `CASE_INITIATION`, or `MOTION_PRACTICE`. **case\_type** `string` Filter by case type. General rules and rules without an explicit case-type limit are included. **q** `string` Search summary, source text, tags, and structured data. Every word must appear in the rule. Example: `rejected cure`. **rulebook\_id** `string` Rulebook identifier from [`/rulebooks`](/api-reference/rulebooks), such as `california-rules-of-court`. Returns the requirements read from that rulebook's current rules instead of a court's documents. Cannot be combined with `district_id`, `judge_slug` or `include_court_rules`. **rule\_number** `string` With `rulebook_id`: only the requirements read from this rule, by its official number, such as `3.1113`. Requires `rulebook_id`. **limit** `number` Maximum rules per page. Defaults to `100`, maximum `500`. **offset** `number` Number of matching rules to skip. Defaults to `0`. Pass `meta.next_offset` from the previous page to read the next one. ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}} curl 'https://api.courtrules.app/api/v1/extracted-rules?district_id=il-cook-circuit&logic_type=ElectronicFilingRule&case_type=civil&limit=25' \ -H "Authorization: Bearer YOUR_API_KEY" ``` ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} { "rules": [ { "rule_id": "7c8b4dd2-1df6-4c34-b33f-0fdf3f4b6734", "district_id": "il-cook-circuit", "judge_slug": "court", "source_url": "https://www.cookcountycourtil.gov/about/circuit-court-rules", "source_url_key": "cook-county-circuit-rules", "document_version_id": "4b2c4f3a-b31e-47fd-9d8b-6e8c6d3eb7e0", "doc_kind": "local_rules", "logic_type": "ElectronicFilingRule", "workflow_phase": "FILING", "content": { "source_text": "Verbatim source text from the official rule document.", "summary": "Civil filings must be submitted electronically unless an exception applies.", "rule_tags": ["e_filing", "civil"], "workflow_phase": "FILING", "visual_severity": "CRITICAL", "structured_data": { "logic_type": "ElectronicFilingRule", "description": "Civil filings must use the court-approved electronic filing system." }, "citation_source": { "section": "General Administrative Order" } } } ], "meta": { "total": 1, "returned": 1, "limit": 25, "offset": 0, "next_offset": null, "district_id": "il-cook-circuit", "include_court_rules": true, "logic_type": "ElectronicFilingRule", "case_type": "civil" } } ``` ## Response fields **rules** `array` Validated extracted filing rules with provenance. **content** `object` The validated extracted rule payload. It includes source text, summary, tags, workflow phase, severity, structured data, and citation details when captured. **source\_url** `string` Official source URL for the rule. **document\_version\_id** `string` Source document version used for the extraction. **meta** `object` **Meta** **total** `integer` Number of rules matching the filters, across all pages **returned** `integer` Number of rules in this page **limit** `integer` Page size requested **offset** `integer` Number of matching rules skipped **next\_offset** `integer | null` Offset of the next page, or `null` on the last page ## Paging Read a whole court by following `next_offset` until it is `null`: ```python theme={"theme":{"light":"github-light","dark":"github-dark"}} import requests rules, offset = [], 0 while offset is not None: page = requests.get( "https://api.courtrules.app/api/v1/extracted-rules", headers={"Authorization": "Bearer YOUR_API_KEY"}, params={"district_id": "ca-los-angeles-superior", "limit": 500, "offset": offset}, ).json() rules += page["rules"] offset = page["meta"]["next_offset"] ``` Rules are ordered newest first. If the court's documents are re-checked while you page, a rule can move between pages; re-read from `offset=0` when you need an exact snapshot. ## Filtering behavior When `judge_slug` is provided, the endpoint returns rules for that unit. With `include_court_rules=true`, the response also includes court-level rules for the same court, so a client can combine the court's rules with the rules of a judge, calendar, department or courtroom. The endpoint returns the extracted rules as they are. It does not yet resolve conflicts between rules or work out the final set of rules that applies to a filing. ## Rulebook requirements Send `rulebook_id` to read the requirements of a rulebook: the filing requirements we read from the text of its rules, with the rule that sets each one. Add `rule_number` for one rule. The other filters work the same way: `logic_type`, `workflow_phase`, `case_type`, `q`, `limit` and `offset`. See [Rulebooks](/concepts/rulebooks) for the rulebook, rule and requirement terms. ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}} curl 'https://api.courtrules.app/api/v1/extracted-rules?rulebook_id=california-rules-of-court&rule_number=3.1113&logic_type=PageWordLimitRule&limit=1' \ -H "Authorization: Bearer YOUR_API_KEY" ``` ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} { "rules": [ { "rule_id": "c3a7f1d4-52e8-4b69-a0d1-8e4f6b9c2d57", "logic_type": "PageWordLimitRule", "workflow_phase": "MOTION_PRACTICE", "content": { "source_text": "Except in a summary judgment or summary adjudication motion, no opening or responding memorandum may exceed 15 pages.", "summary": "An opening or responding memorandum may not exceed 15 pages, except in a summary judgment or summary adjudication motion.", "document_type": "memorandum", "case_type_applicability": ["civil"], "rule_tags": ["page_limit", "memorandum"], "workflow_phase": "MOTION_PRACTICE", "visual_severity": "CRITICAL", "structured_data": { "logic_type": "PageWordLimitRule", "document_type": "memorandum", "role_limits": [{ "role": "all", "limit_type": "pages", "limit_value": 15 }] }, "citation_source": { "section": "Rule 3.1113(d)" } }, "rulebook_rule": { "rulebook_id": "california-rules-of-court", "number": "3.1113", "citation": "Cal. Rules of Court, rule 3.1113", "revision_id": "50dd0291-ae07-48d0-b490-23555244dcf1", "site_url": "https://www.courtrules.app/rules/california-rules-of-court/3.1113" } } ], "meta": { "total": 3, "returned": 1, "limit": 1, "offset": 0, "next_offset": 1, "rulebook_id": "california-rules-of-court", "rule_number": "3.1113", "logic_type": "PageWordLimitRule" } } ``` What differs from the court results above: * **`rulebook_rule` names the source.** It holds the rulebook, the rule number, how to cite the rule, a link to the rule's page, and the `revision_id` of the version of the rule the requirement was read from. While that version is current, it equals the `revision_id` of [the rule](/api-reference/get-rulebook-rule). * **No court or judge fields.** A rulebook's requirements belong to a rule, so results carry no `district_id`, `judge_slug`, `source_url` or `doc_kind`. * **Order.** Results are ordered by rule number as text, then by id. The order is stable between calls but is not the order of the rules in the rulebook; get that from [`/rulebooks/{rulebook_id}/rules`](/api-reference/rulebook-rules). * **No page numbers.** Rule text is not paginated, so `content.citation_source` never carries a page. * **A rule with no requirements** returns `200` and an empty `rules` array. Its `extraction_status` on the rule says whether the text has been read. * **Meta** echoes `rulebook_id` and `rule_number` instead of the court filters. A request cannot name both a rulebook and a court or judge: ```json 400 theme={"theme":{"light":"github-light","dark":"github-dark"}} { "error": "rulebook_id cannot be combined with district_id.", "suggestion": "The requirements of a rulebook do not belong to a court or a judge. Remove district_id to read the rulebook, or remove rulebook_id to read a court's rules.", "docs_url": "https://docs.courtrules.app/api-reference/extracted-rules" } ``` `rule_number` without `rulebook_id` is also a `400`. An unknown rulebook, or a rule number the rulebook does not have, is a `404`. ## Limits * **Text and case-type searches:** `q` and `case_type` read every candidate rule before matching, up to 10,000 candidates. The limit covers any single court. A search across all courts with a common word returns `422`; add `district_id`, `judge_slug`, `logic_type`, `workflow_phase`, or more specific words. * **Unknown court:** a `district_id` we do not map returns `404`. * **Unknown rulebook or rule:** a `rulebook_id` that is not in [`/rulebooks`](/api-reference/rulebooks), or a `rule_number` the rulebook does not have, returns `404`. For one judge's complete rule set in a single call, grouped into court-wide and judge layers, use [`/rules`](/api-reference/rules). # Get court Source: https://docs.courtrules.app/api-reference/get-court GET /api/v1/courts/{district_id} Returns detailed information for a single court Returns one court's circuit, state, coverage status, and roster size. Works for every court in [`/courts`](/api-reference/courts), federal or state. **district\_id** `string` *required* Court identifier (e.g. `edny`, `ca-los-angeles-superior`) ```bash cURL theme={"theme":{"light":"github-light","dark":"github-dark"}} curl 'https://api.courtrules.app/api/v1/courts/ca-los-angeles-superior' \ -H "Authorization: Bearer YOUR_API_KEY" ``` ```python Python theme={"theme":{"light":"github-light","dark":"github-dark"}} import requests resp = requests.get( "https://api.courtrules.app/api/v1/courts/ca-los-angeles-superior", headers={"Authorization": "Bearer YOUR_API_KEY"}, ) court = resp.json() ``` ```typescript Node.js theme={"theme":{"light":"github-light","dark":"github-dark"}} const resp = await fetch("https://api.courtrules.app/api/v1/courts/ca-los-angeles-superior", { headers: { Authorization: "Bearer YOUR_API_KEY" }, }); const court = await resp.json(); ``` ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} { "district_id": "ca-los-angeles-superior", "name": "Superior Court of California, County of Los Angeles", "circuit": null, "state": "California", "status": "live", "judges_mapped": 116 } ``` ## Response fields **district\_id** `string` Unique court identifier **name** `string` Full court name **circuit** `string | null` Federal circuit (e.g. "2nd Circuit"). `null` for state courts. **state** `string | null` State or territory. `null` for courts not tied to one state. **status** `string` `live` when rules are available, `coming_soon` when the court is mapped but has no rules yet **judges\_mapped** `integer` Number of current judges on the court's roster **judges\_profiled** `integer` Number of judges with compliance profiles used by [`/check`](/api-reference/check). Only present for courts with compliance profiles (`edny` today). ## Error responses ### 404: Court not found Returned when the court ID is not recognized. ```json 404 theme={"theme":{"light":"github-light","dark":"github-dark"}} { "error": "District 'xyz' not found.", "suggestion": "Use GET /api/v1/courts to list all valid district identifiers.", "docs_url": "https://docs.courtrules.app/api-reference/courts/list-courts" } ``` # Get rulebook Source: https://docs.courtrules.app/api-reference/get-rulebook GET /api/v1/rulebooks/{rulebook_id} Returns one official rulebook with its rule count and when it was last checked Returns one rulebook: its name and abbreviations, where it applies, who issues it, its official page, how many rules are in force, and when we last read the official source. The fields are the same as one item of [`/rulebooks`](/api-reference/rulebooks). Call this when you already know the rulebook's `id` and want its current `rule_count` or `last_checked_at`. To read its rules, use [`/rulebooks/{rulebook_id}/rules`](/api-reference/rulebook-rules). **rulebook\_id** `string` *required* Rulebook identifier from [`/rulebooks`](/api-reference/rulebooks), such as `california-rules-of-court`. Lowercase words joined by hyphens. ```bash cURL theme={"theme":{"light":"github-light","dark":"github-dark"}} curl 'https://api.courtrules.app/api/v1/rulebooks/california-rules-of-court' \ -H "Authorization: Bearer YOUR_API_KEY" ``` ```python Python theme={"theme":{"light":"github-light","dark":"github-dark"}} import requests resp = requests.get( "https://api.courtrules.app/api/v1/rulebooks/california-rules-of-court", headers={"Authorization": "Bearer YOUR_API_KEY"}, ) rulebook = resp.json() ``` ```typescript Node.js theme={"theme":{"light":"github-light","dark":"github-dark"}} const resp = await fetch("https://api.courtrules.app/api/v1/rulebooks/california-rules-of-court", { headers: { Authorization: "Bearer YOUR_API_KEY" }, }); const rulebook = await resp.json(); ``` ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} { "id": "california-rules-of-court", "name": "California Rules of Court", "aliases": ["CRC", "Cal. Rules of Court", "Cal. Rules Ct."], "jurisdiction": "CA", "scope": "statewide", "kind": "court_rules", "governed_court_ids": [], "issuer": "Judicial Council of California", "official_url": "https://courts.ca.gov/forms-rules/rules-court", "rule_count": 1488, "last_checked_at": "2026-10-19T08:20:21.677476+00:00", "site_url": "https://www.courtrules.app/rules/california-rules-of-court" } ``` ## Response fields **id** `string` Rulebook identifier. It does not change: if the official name changes, the name changes and the id stays. **name** `string` Official name **aliases** `string[]` Other names and abbreviations readers use, such as `CRC` **jurisdiction** `string` Where the rulebook applies: a two-letter state code, `DC`, or `US` for national federal rules **scope** `string` `national`, `statewide` or `court`. A statewide rulebook applies across its state. **kind** `string` `court_rules`, `statute` or `administrative_code` **governed\_court\_ids** `string[]` Courts a court rulebook names. Empty for statewide and national rulebooks, which apply across their jurisdiction without naming courts; each rule says which courts it covers. **issuer** `string` The body that adopts and publishes the rules **official\_url** `string` The issuer's official page for the rulebook **rule\_count** `integer` Rules in force that the official source still lists. Repealed, reserved and removed rules are not counted. **last\_checked\_at** `string | null` When we last read the official source. `null` before the first read. **site\_url** `string` The rulebook's page on courtrules.app ## Errors ### 400: Invalid rulebook identifier Returned when `rulebook_id` cannot be an identifier: capital letters, underscores, or more than 80 characters. ```json 400 theme={"theme":{"light":"github-light","dark":"github-dark"}} { "error": "Invalid request", "details": [ { "path": "rulebook_id", "message": "Use lowercase words joined by hyphens, such as california-rules-of-court" } ], "docs_url": "https://docs.courtrules.app/api-reference/get-rulebook" } ``` ### 404: Rulebook not found Returned when no rulebook has this identifier. Rulebooks that are not in [`/rulebooks`](/api-reference/rulebooks) read as not found. ```json 404 theme={"theme":{"light":"github-light","dark":"github-dark"}} { "error": "Rulebook 'no-such-rulebook' not found.", "suggestion": "Use GET /api/v1/rulebooks to list the rulebooks you can read.", "docs_url": "https://docs.courtrules.app/api-reference/rulebooks" } ``` One rulebook counts as one row against your [daily row limit](/api-reference/rate-limits). # Get rulebook rule Source: https://docs.courtrules.app/api-reference/get-rulebook-rule GET /api/v1/rulebooks/{rulebook_id}/rules/{number} Returns one rule of a rulebook with its official text as structured blocks and plain text Returns one rule: its number, citation, heading, place in the rulebook and status, and its official text both as structured `blocks` and as `plain_text`. Use it to open a rule from a citation, to show the official wording next to a requirement, or to check whether a stored copy of a rule is still current. The answer does not include the rule's requirements. Read them with [`/extracted-rules`](/api-reference/extracted-rules) using `rulebook_id` and `rule_number`; `requirement_count` tells you how many to expect. **rulebook\_id** `string` *required* Rulebook identifier from [`/rulebooks`](/api-reference/rulebooks), such as `california-rules-of-court`. **number** `string` *required* The rule's official number, exactly as the rulebook prints it and without the word Rule: `3.1113`, `4:46-2`, `21a`. It must match exactly: `21a` and `21A` are different rules, and `3.111` does not find `3.1113`. URL-encode numbers that hold spaces or slashes (`1/2` is `1%2F2`). Leading and trailing spaces are not allowed. At most 40 characters. ```bash cURL theme={"theme":{"light":"github-light","dark":"github-dark"}} curl 'https://api.courtrules.app/api/v1/rulebooks/california-rules-of-court/rules/3.1113' \ -H "Authorization: Bearer YOUR_API_KEY" ``` ```python Python theme={"theme":{"light":"github-light","dark":"github-dark"}} import requests from urllib.parse import quote number = "3.1113" resp = requests.get( f"https://api.courtrules.app/api/v1/rulebooks/california-rules-of-court/rules/{quote(number, safe='')}", headers={"Authorization": "Bearer YOUR_API_KEY"}, ) rule = resp.json() ``` ```typescript Node.js theme={"theme":{"light":"github-light","dark":"github-dark"}} const number = "3.1113"; const resp = await fetch( `https://api.courtrules.app/api/v1/rulebooks/california-rules-of-court/rules/${encodeURIComponent(number)}`, { headers: { Authorization: "Bearer YOUR_API_KEY" } }, ); const rule = await resp.json(); ``` The real response lists subdivisions (a) through (m) of Rule 3.1113. The example keeps (d), the page limits, and the notes printed with the rule. ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} { "number": "3.1113", "slug": "3.1113", "citation": "Cal. Rules of Court, rule 3.1113", "revision_id": "50dd0291-ae07-48d0-b490-23555244dcf1", "heading": "Memorandum", "outline": [ { "label": "Title Three", "heading": "Civil Rules" }, { "label": "Division 11", "heading": "Law and Motion" }, { "label": "Chapter 2", "heading": "Format of Motion Papers" } ], "legal_status": "in_force", "effective_from": "2017-01-01", "observed_at": "2026-10-19T04:34:37.532+00:00", "removed": false, "requirement_count": 27, "extraction_status": "succeeded", "site_url": "https://www.courtrules.app/rules/california-rules-of-court/3.1113", "current": { "revision_id": "50dd0291-ae07-48d0-b490-23555244dcf1", "heading": "Memorandum", "blocks": [ { "type": "item", "label": "(d)", "heading": "Length of memorandum", "children": [ { "type": "paragraph", "text": "Except in a summary judgment or summary adjudication motion, no opening or responding memorandum may exceed 15 pages. In a summary judgment or summary adjudication motion, no opening or responding memorandum may exceed 20 pages. No reply or closing memorandum may exceed 10 pages. The page limit does not include the caption page, the notice of motion and motion, exhibits, declarations, attachments, the table of contents, the table of authorities, or the proof of service." }, { "type": "note", "role": "history", "blocks": [ { "type": "paragraph", "text": "(Subd (d) amended effective January 1, 2017; adopted as part of a longer subd (d); previously amended effective July 1, 1984, January 1, 1992, July 1, 1997, and January 1, 2004.)" } ] } ] }, { "type": "note", "role": "comment", "title": "Advisory Committee Comment", "blocks": [ { "type": "paragraph", "text": "See also rule 1.200 concerning the format of citations." } ] } ], "plain_text": "(d) Length of memorandum\nExcept in a summary judgment or summary adjudication motion, no opening or responding memorandum may exceed 15 pages. In a summary judgment or summary adjudication motion, no opening or responding memorandum may exceed 20 pages. No reply or closing memorandum may exceed 10 pages. The page limit does not include the caption page, the notice of motion and motion, exhibits, declarations, attachments, the table of contents, the table of authorities, or the proof of service.", "source_url": "https://courts.ca.gov/cms/rules/index/three/rule3_1113", "captured_at": "2026-10-19T04:34:37.532+00:00" } } ``` ## Response fields The fields before `current` are the ones [`/rulebooks/{rulebook_id}/rules`](/api-reference/rulebook-rules) returns for each rule. **number** `string` Official rule number, as printed **slug** `string` URL form of the number, as used in `site_url` **citation** `string` How to cite the rule **revision\_id** `string` Identifier of this version of the rule. It changes when the rule's heading, place in the rulebook, text, status or effective date changes. The requirements read from the rule carry the same id in `rulebook_rule.revision_id`. **heading** `string` The rule's heading **outline** `array` Where the rule sits in the rulebook, from the top level down **legal\_status** `string` `in_force`, `repealed` or `reserved`. Repealed and reserved rules usually carry only a history note. **effective\_from** `string | null` Date the current text took effect, as the official source states it. `null` when it gives none. **observed\_at** `string` When we first saw this version of the rule on the official source **removed** `boolean` `true` when the official source no longer lists the rule. The rule keeps the text it had when it was last listed and has no requirements. **requirement\_count** `integer` Requirements read from the current text. Check `extraction_status` before reading `0` as none. **extraction\_status** `string` `succeeded`, `pending`, `failed` or `skipped`; see [List rulebook rules](/api-reference/rulebook-rules) **site\_url** `string` The rule's page on courtrules.app **current** `object | null` The rule's latest official text. For a removed rule, the text it had when it was last listed. `null` when no text is available. **Current** **revision\_id** `string` The version of the rule this text belongs to. Equals the rule's `revision_id`. **heading** `string` The rule's heading in this version **blocks** `array` The official text as structured blocks, in document order. See the block types below. **plain\_text** `string` The operative text as lines: every paragraph, item and table row in order, with item labels. History notes and committee comments are left out. Empty for a rule with no operative text. **source\_url** `string` The official page the text was read from **captured\_at** `string` When we fetched that page for this version ### Block types Every block has a `type`. Blocks nest: an item can hold paragraphs, other items and notes, and a note holds paragraphs. | `type` | Fields | What it is | | - | - | - | | `paragraph` | `text` | A paragraph of rule text | | `item` | `label`, `heading` (optional), `text` (optional), `children` (optional) | A labeled part: a subdivision such as `(d)` with its heading, or a numbered paragraph such as `(1)` | | `table` | `rows`, each with `cells` (`text`, optional `header`, `colspan`, `rowspan`) | A table printed in the rule | | `note` | `role` (`history`, `comment` or `editor`), `title` (optional), `blocks` | Text printed with the rule that is not part of it: amendment history, committee comments | ## Notes and plain text Notes are shown in `blocks` and left out of `plain_text`, out of [search](/api-reference/rulebook-rules), and out of the requirements. A history note such as "Subd (d) amended effective January 1, 2017" tells you when a part changed; it is not an instruction to a filer. ## Errors ### 400: Invalid parameters Returned when `rulebook_id` cannot be an identifier, or when `number` could not be any stored number: a space at either end, two spaces in a row, a control character, or more than 40 characters. ```json 400 theme={"theme":{"light":"github-light","dark":"github-dark"}} { "error": "Invalid request", "details": [ { "path": "number", "message": "A rule number cannot start or end with a space or hold two spaces in a row" } ], "docs_url": "https://docs.courtrules.app/api-reference/get-rulebook-rule" } ``` ### 404: Rulebook or rule not found Returned when no rulebook has this identifier, or the rulebook has no rule with exactly this number. ```json 404 theme={"theme":{"light":"github-light","dark":"github-dark"}} { "error": "Rule '9.999' not found in the California Rules of Court.", "suggestion": "Rule numbers match exactly as the rulebook prints them, without the word Rule. Find a rule with GET /api/v1/rulebooks/california-rules-of-court/rules?q=.", "docs_url": "https://docs.courtrules.app/api-reference/get-rulebook-rule" } ``` One rule counts as one row against your [daily row limit](/api-reference/rate-limits), however long its text. # Court holidays Source: https://docs.courtrules.app/api-reference/holidays GET /api/v1/holidays Returns court holidays and closure dates Returns court holidays and closure dates with official source URLs. Holidays are updated monthly. Use this endpoint to power deadline calculators, court closure checks, and calendar exports. For a single court, you can also call `GET /api/v1/courts/{district_id}/holidays` with the same `year`, `date_from`, `date_to`, and `limit` query parameters. ```bash cURL theme={"theme":{"light":"github-light","dark":"github-dark"}} curl 'https://api.courtrules.app/api/v1/holidays?district_id=edny&year=2026' \ -H "Authorization: Bearer YOUR_API_KEY" ``` ```python Python theme={"theme":{"light":"github-light","dark":"github-dark"}} import requests resp = requests.get( "https://api.courtrules.app/api/v1/holidays", params={"district_id": "edny", "year": 2026}, headers={"Authorization": "Bearer YOUR_API_KEY"}, ) holidays = resp.json() ``` ```typescript Node.js theme={"theme":{"light":"github-light","dark":"github-dark"}} const params = new URLSearchParams({ district_id: "edny", year: "2026" }); const resp = await fetch(`https://api.courtrules.app/api/v1/holidays?${params}`, { headers: { Authorization: "Bearer YOUR_API_KEY" }, }); const holidays = await resp.json(); ``` ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} { "holidays": [ { "district_id": "edny", "calendar_year": 2026, "holiday_date": "2026-01-01", "holiday_name": "New Year's Day", "source_url": "https://www.nyed.uscourts.gov/holiday-schedule", "last_checked_at": "2026-05-13T12:00:00.000Z" }, { "district_id": "edny", "calendar_year": 2026, "holiday_date": "2026-01-19", "holiday_name": "Birthday of Martin Luther King, Jr.", "source_url": "https://www.nyed.uscourts.gov/holiday-schedule", "last_checked_at": "2026-05-13T12:00:00.000Z" } ], "meta": { "total": 2, "district_id": "edny", "year": 2026, "limit": 100 } } ``` ## Query parameters **district\_id** `string` Optional court identifier, such as `edny`. **year** `integer` Optional calendar year filter, such as `2026`. **date\_from** `string` Optional lower date bound in `YYYY-MM-DD` format. **date\_to** `string` Optional upper date bound in `YYYY-MM-DD` format. **limit** `integer` Maximum number of holidays to return. Defaults to `100`; maximum is `500`. ## Response fields **holidays** `array` Array of court holiday objects. **Holiday object** **district\_id** `string` Court identifier for the holiday calendar. **calendar\_year** `integer` Calendar year for the holiday. **holiday\_date** `string` Closure date in `YYYY-MM-DD` format. **holiday\_name** `string` Holiday or closure name as published by the court. **source\_url** `string` Official source URL for the court holiday schedule. **last\_checked\_at** `string` Timestamp when Court Rules last checked the source. **meta** `object` Response metadata, including the applied filters and number of holidays returned. # List judges Source: https://docs.courtrules.app/api-reference/judges GET /api/v1/judges Returns the current judges for a court, with name, type, bio, chambers address, and whether we hold their own rules Returns the judges on a court's current roster. Use a judge's `slug` with [`/rules`](/api-reference/rules) or [`/extracted-rules`](/api-reference/extracted-rules). Works for every court in [`/courts`](/api-reference/courts), federal or state. In some state courts the roster lists departments or courtrooms rather than individual judges. Their slugs work the same way. **district\_id** `string` *required* Court identifier (e.g. `edny`, `ca-los-angeles-superior`) ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}} curl 'https://api.courtrules.app/api/v1/judges?district_id=ca-los-angeles-superior' \ -H "Authorization: Bearer YOUR_API_KEY" ``` ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} { "district_id": "ca-los-angeles-superior", "judges": [ { "slug": "judge-teresa-a-beaudet", "name": "Judge Teresa A. Beaudet", "has_profile": false, "has_rules": true, "status": "active", "judge_type": "district", "bio": null, "chambers": null, "profile_url": null } ], "meta": { "total": 116, "profiled": 0, "with_rules": 113, "court_level_rules": true } } ``` ## Response fields **district\_id** `string` The court ID from the request **judges** `array` Array of judge objects **Judge object** **slug** `string` URL-safe identifier used in [`/rules`](/api-reference/rules), [`/extracted-rules`](/api-reference/extracted-rules), and [`/check`](/api-reference/check) calls **name** `string` Full display name **has\_profile** `boolean` Whether the judge has a compliance profile used by [`/check`](/api-reference/check). Only `edny` judges have one today. **has\_rules** `boolean` Whether we hold the judge's own rules (standing orders, individual practices, courtroom rules). A judge without their own rules still has the court-wide rules; see `meta.court_level_rules`. **status** `string | null` `active` for a judge on the current roster, `coming_soon` for a judge on the roster whose own documents are not processed yet. `null` when the roster has no record for the judge. **judge\_type** `string | null` Judge type (e.g. `"district"`, `"magistrate"`, `"senior"`), or `null` **bio** `string | null` Short biography excerpt, if available **chambers** `string | null` Chambers address, if available **profile\_url** `string | null` Link to the judge's official court profile, if available **meta** `object` **Meta object** **total** `integer` Number of judges returned **profiled** `integer` Number of judges with compliance profiles **with\_rules** `integer` Number of judges whose own rules we hold **court\_level\_rules** `boolean` Whether the court has court-wide rules. They are served with `judge_slug=court` and included in every judge's [`/rules`](/api-reference/rules) response. ## Errors | Status | Meaning | | - | - | | `404` | The court ID is not known. | # Overview Source: https://docs.courtrules.app/api-reference/overview API Reference for Court Rules and Enforcement Data Base URL: `https://api.courtrules.app` The REST API covers court rules (compliance checks, judge rules, document classification). Enforcement data is available through the [MCP server](/guides/mcp-enforcement) at `mcp.courtrules.app`, which also exposes [court rules tools](/guides/mcp-court-rules). ## Endpoints | Method | Path | Description | | - | - | - | | `GET` | [`/api/v1/courts`](/api-reference/courts) | List all courts | | `GET` | [`/api/v1/courts/:id`](/api-reference/get-court) | Get a single court's details | | `GET` | [`/api/v1/holidays`](/api-reference/holidays) | List court holidays and closure dates | | `GET` | [`/api/v1/judges`](/api-reference/judges) | List judges for a district | | `GET` | [`/api/v1/rules`](/api-reference/rules) | Get applicable rules for a judge | | `GET` | [`/api/v1/extracted-rules`](/api-reference/extracted-rules) | Search filing rules, or a rulebook's requirements | | `GET` | [`/api/v1/rulebooks`](/api-reference/rulebooks) | List official rulebooks | | `GET` | [`/api/v1/rulebooks/:id`](/api-reference/get-rulebook) | Get a single rulebook | | `GET` | [`/api/v1/rulebooks/:id/rules`](/api-reference/rulebook-rules) | List a rulebook's rules | | `GET` | [`/api/v1/rulebooks/:id/rules/:number`](/api-reference/get-rulebook-rule) | Get one rule with its text | | `GET` | `/api/v1/profile` | Get a judge's full compliance profile | | `GET` | `/api/v1/documents` | List source documents for a judge | | `GET` | `/api/v1/documents/{id}/pdf` | Download a source document PDF | | `POST` | [`/api/v1/check`](/api-reference/check) | Check document compliance | | `POST` | [`/api/v1/classify`](/api-reference/classify) | Classify a PDF and extract metadata | | `GET` | `/openapi.json` | Download the OpenAPI specification | ## Authentication All endpoints require a Bearer token in the `Authorization` header: ``` Authorization: Bearer YOUR_API_KEY ``` See [Authentication](/authentication) for details on obtaining and using API keys. ## Interactive playground Each endpoint page in this section includes a live request builder. Select an endpoint from the sidebar, fill in parameters, and send real requests against `https://api.courtrules.app`. You'll need your API key from [console.courtrules.app](https://console.courtrules.app). ## OpenAPI specification The complete OpenAPI 3.1 spec is available as a public endpoint (no authentication required): ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}} curl 'https://api.courtrules.app/openapi.json' -o openapi.json ``` Use this with Postman, code generators, or AI agents. See [Building with AI agents](/guides/building-with-ai-agents) for integration examples. ## Content type All `POST` requests must use `Content-Type: application/json`. Most responses are `application/json`. Document PDF endpoints (`/documents/{id}/pdf`) return `application/pdf`. ## Error responses Error responses follow a consistent format with actionable guidance: ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} { "error": "Judge \"john-doe\" not found in edny.", "suggestion": "Use GET /api/v1/judges?district_id=edny to list valid judge slugs.", "docs_url": "https://docs.courtrules.app/api-reference/judges/list-judges" } ``` Validation errors include field-level details: ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} { "error": "Invalid request", "details": [{ "path": "document.page_count", "message": "Required" }], "docs_url": "https://docs.courtrules.app/api-reference/check/check-document" } ``` Compliance checks need a compliance profile, which exists for `edny` today. `/check` and `/classify` on any other court return `422` and point to that court's rules: ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} { "error": "Compliance checks are not available for Superior Court of California, County of Los Angeles yet.", "suggestion": "Compliance checks run for the Eastern District of New York (edny) today. For this court, read the judge's rules with GET /api/v1/rules?district_id=ca-los-angeles-superior&judge_slug= or search them with GET /api/v1/extracted-rules?district_id=ca-los-angeles-superior.", "docs_url": "https://docs.courtrules.app/api-reference/extracted-rules", "district_id": "ca-los-angeles-superior" } ``` ## Rate limits All endpoints are rate-limited per API key using a sliding window: | Endpoint | Limit | | - | - | | `POST /classify` | 5 RPM | | `POST /check` | 60 RPM | | `GET /courts`, `/judges`, `/rules`, `/rulebooks` | 300 RPM | Keys without a plan of their own are on the free limits, which are lower: 30 calls a minute, 300 calls a day and 3,000 rows returned a day. A list counts one row for each item it returns, so a full `GET /courts` uses many rows at once. Every response includes `X-RateLimit-Limit`, `X-RateLimit-Remaining`, and `X-RateLimit-Reset` headers. When exceeded, the API returns `429` with a `Retry-After` header. See [Rate limits](/api-reference/rate-limits) for retry guidance and common mistakes. ## HTTP status codes | Code | Meaning | | - | - | | `200` | Success | | `400` | Invalid request (missing params, validation failure) | | `401` | Missing or invalid Authorization header | | `403` | Invalid API key | | `404` | Resource not found (judge not in court, unknown court ID, unknown rulebook or rule) | | `415` | Requested a PDF for a document stored in another format | | `422` | Compliance check requested for a court without a compliance profile, or a search too broad to run | | `429` | Rate limit exceeded | | `502` | Classification failed (timeout or upstream error on `/classify`) | # Rate limits Source: https://docs.courtrules.app/api-reference/rate-limits Per-minute and daily limits, response headers, and retry guidance Every API key has per-minute request limits that vary by endpoint, and a daily limit on calls and on rows returned. ## Daily limits Keys without a plan of their own are on the free limits: | Limit | Free | | - | - | | Calls a minute | 30 | | Calls a day | 300 | | Rows returned a day | 3,000 | A list counts one row for each item it returns. A single rulebook or rule counts as one row, however long its text. For example, a full [`GET /api/v1/courts`](/api-reference/courts) counts one row for every court in the list, so a few full lists use a whole day's rows. Keep the list, or read one court with [`GET /api/v1/courts/{district_id}`](/api-reference/get-court). Days run from 00:00 UTC. A key that is shared by several people (the console key) is counted per network address, and all of its callers also share one daily total. The MCP server counts the same way, per signed-in user or per key. When a daily limit is reached the API answers `429` with `"error": "Usage limit reached"`, a `reason` (`minute`, `day`, `rows` or `shared`) and a `Retry-After` header. Keys for production integrations have higher limits: write to [api@courtrules.app](mailto:api@courtrules.app). ## Limits by endpoint | Endpoint | Limit | Why | | - | - | - | | `POST /api/v1/classify` | 5 RPM | Reading a PDF takes 10 to 30 seconds per request | | `POST /api/v1/check` | 60 RPM | Applies stored rules to the details you send | | `GET /api/v1/courts`, `/judges`, `/rules`, `/rulebooks` | 300 RPM | Read-only lookups | RPM = requests per minute, per API key. The endpoint limits use a sliding window. The daily limits above, and the 30 calls a minute on the free limits, count in fixed windows: the clock minute and the UTC day. ## Response headers Responses from the endpoint limits include rate limit headers. A response refused by the daily limits carries `Retry-After` and a `reason` instead: | Header | Description | Example | | - | - | - | | `X-RateLimit-Limit` | Maximum requests allowed in the window | `5` | | `X-RateLimit-Remaining` | Requests remaining in the current window | `3` | | `X-RateLimit-Reset` | Unix epoch (seconds) when the window resets | `1709913600` | ## 429 response When the limit is exceeded, the API returns `429 Too Many Requests`: ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} { "error": "Rate limit exceeded", "suggestion": "Wait 30 seconds before retrying. See rate limit headers for usage details.", "docs_url": "https://docs.courtrules.app/api-reference/rate-limits", "contact": "api@courtrules.app" } ``` The response also includes a `Retry-After` header with the number of seconds to wait. ## MCP server The MCP server at `mcp.courtrules.app` uses the same limits, counted for each signed-in user or for each API key. Accounts that sign in from one network address also share a larger total for that network, so a call can be refused because the network has reached it. When a call goes over a limit, the tool returns an error whose text names the limit and how long to wait, and it tells the assistant to stop instead of retrying in a loop. One answer holds at most 500 rows on the free limits. A longer list is cut, and the answer says how many rows it held and how to narrow the query, for example with `district_id`, `judge_slug` or `year`. ## Retry guidance 1. **Read `Retry-After`** and wait at least that many seconds before retrying. 2. **Use exponential backoff** if you receive multiple 429s in a row: wait 1s, 2s, 4s, etc. 3. **Check `X-RateLimit-Remaining`** before sending requests to avoid hitting the limit in the first place. ## Common mistakes **Tight-loop classify calls.** `/classify` is limited to 5 RPM because each request takes 10 to 30 seconds to read a PDF. If you need to process a batch, space requests at least 12 seconds apart or queue them server-side. **Ignoring `Retry-After`.** Retrying immediately after a 429 wastes your remaining budget and delays recovery. Always respect the header value. **Polling `/check` on every keystroke.** While `/check` has a generous 60 RPM limit, calling it on every form change in a UI can still exhaust it. Debounce to at most once per second. ## Higher limits Contact [api@courtrules.app](mailto:api@courtrules.app) with your use case. We can increase limits for production integrations. # List rulebook rules Source: https://docs.courtrules.app/api-reference/rulebook-rules GET /api/v1/rulebooks/{rulebook_id}/rules Lists the rules of one rulebook in book order, with search, status filters and paging Returns the rules of one rulebook in the order the rulebook prints them, without their text. Each rule carries its number, citation, heading, place in the rulebook, status, and how many requirements we read from it. Search the number, heading and text with `q`, then read a rule's text with [`/rulebooks/{rulebook_id}/rules/{number}`](/api-reference/get-rulebook-rule) and its requirements with [`/extracted-rules`](/api-reference/extracted-rules). Results are paged with `limit` and `offset`: `meta.total` is the number of matching rules, and `meta.next_offset` is the offset of the next page, or `null` on the last page. **rulebook\_id** `string` *required* Rulebook identifier from [`/rulebooks`](/api-reference/rulebooks), such as `california-rules-of-court`. **q** `string` Words to find in a rule's number, heading or operative text. Every word must appear; a word may appear in any of the three. Not case-sensitive. History notes and committee comments are not searched. Example: `opening memorandum`. **legal\_status** `string` Only rules with this status: `in_force`, `repealed` or `reserved`. **has\_requirements** `boolean` `true`: only rules whose current text has at least one requirement. `false`: only rules with none, including rules whose requirements have not been read yet. Leave it out for both. **limit** `number` Maximum rules per page. Defaults to `100`, maximum `500`. **offset** `number` Number of matching rules to skip. Defaults to `0`. Pass `meta.next_offset` from the previous page to read the next one. ```bash cURL theme={"theme":{"light":"github-light","dark":"github-dark"}} curl 'https://api.courtrules.app/api/v1/rulebooks/california-rules-of-court/rules?q=opening%20memorandum&has_requirements=true' \ -H "Authorization: Bearer YOUR_API_KEY" ``` ```python Python theme={"theme":{"light":"github-light","dark":"github-dark"}} import requests resp = requests.get( "https://api.courtrules.app/api/v1/rulebooks/california-rules-of-court/rules", headers={"Authorization": "Bearer YOUR_API_KEY"}, params={"q": "opening memorandum", "has_requirements": "true"}, ) rules = resp.json()["rules"] ``` ```typescript Node.js theme={"theme":{"light":"github-light","dark":"github-dark"}} const params = new URLSearchParams({ q: "opening memorandum", has_requirements: "true" }); const resp = await fetch( `https://api.courtrules.app/api/v1/rulebooks/california-rules-of-court/rules?${params}`, { headers: { Authorization: "Bearer YOUR_API_KEY" } }, ); const { rules } = await resp.json(); ``` ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} { "rules": [ { "number": "3.764", "slug": "3.764", "citation": "Cal. Rules of Court, rule 3.764", "revision_id": "87a3abf3-5690-421d-8c21-e64305fefbf3", "heading": "Motion to certify or decertify a class or amend or modify an order certifying a class", "outline": [ { "label": "Title Three", "heading": "Civil Rules" }, { "label": "Division 7", "heading": "Civil Case Management" }, { "label": "Chapter 6", "heading": "Management of Class Actions" } ], "legal_status": "in_force", "effective_from": "2026-01-01", "observed_at": "2026-10-19T04:31:34.421+00:00", "removed": false, "requirement_count": 16, "extraction_status": "succeeded", "site_url": "https://www.courtrules.app/rules/california-rules-of-court/3.764" }, { "number": "3.1113", "slug": "3.1113", "citation": "Cal. Rules of Court, rule 3.1113", "revision_id": "50dd0291-ae07-48d0-b490-23555244dcf1", "heading": "Memorandum", "outline": [ { "label": "Title Three", "heading": "Civil Rules" }, { "label": "Division 11", "heading": "Law and Motion" }, { "label": "Chapter 2", "heading": "Format of Motion Papers" } ], "legal_status": "in_force", "effective_from": "2017-01-01", "observed_at": "2026-10-19T04:34:37.532+00:00", "removed": false, "requirement_count": 27, "extraction_status": "succeeded", "site_url": "https://www.courtrules.app/rules/california-rules-of-court/3.1113" } ], "meta": { "total": 2, "returned": 2, "limit": 100, "offset": 0, "next_offset": null, "rulebook_id": "california-rules-of-court", "q": "opening memorandum", "has_requirements": true } } ``` ## Response fields **rules** `array` The rules on this page, in rulebook order: by position in the book, then by id. Empty when nothing matches. **Rule** **number** `string` Official rule number without the word Rule, exactly as the rulebook prints it. Numbers can hold dots, colons, hyphens and letters. **slug** `string` URL form of the number, as used in `site_url` **citation** `string` How to cite the rule **revision\_id** `string` Identifier of this version of the rule. It changes when the rule's heading, place in the rulebook, text, status or effective date changes. **heading** `string` The rule's heading **outline** `array` Where the rule sits in the rulebook, from the top level down. Each level has a `label` such as `Division 11` and a `heading`. **legal\_status** `string` `in_force`, `repealed` or `reserved` **effective\_from** `string | null` Date the current text took effect, as the official source states it (`YYYY-MM-DD`). `null` when the source gives no date. **observed\_at** `string` When we first saw this version of the rule on the official source **removed** `boolean` `true` when the official source no longer lists the rule. A removed rule keeps the heading, status and text it had when it was last listed, and it has no requirements. **requirement\_count** `integer` Requirements read from the rule's current text: the number of results [`/extracted-rules`](/api-reference/extracted-rules) returns for this rule. Check `extraction_status` before reading `0` as none. **extraction\_status** `string` `succeeded`: the text was read, and `requirement_count` is final. `0` means the text states none of the requirements that are read: limits, deadlines, formats, copies, filing, service, fees, sealing and contact with the court. A definition, a statement of scope and a rule about mediators, court staff or a court program often have none; the text is still in the rule. `pending`: not read yet, so the count is `0` for now. `failed`: reading did not work, so the count is `0`. `skipped`: nothing is read from this rule, because it has no operative text or is too long to process. **site\_url** `string` The rule's page on courtrules.app **meta** `object` **Meta** **total** `integer` Number of rules matching the filters, across all pages **returned** `integer` Number of rules in this page **limit** `integer` Page size requested **offset** `integer` Number of matching rules skipped **next\_offset** `integer | null` Offset of the next page, or `null` on the last page **rulebook\_id** `string` The rulebook listed **q** `string` The search you sent, when present **legal\_status** `string` The `legal_status` filter you sent, when present **has\_requirements** `boolean` The `has_requirements` filter you sent, when present ## Paging Read a whole rulebook by following `next_offset` until it is `null`: ```python theme={"theme":{"light":"github-light","dark":"github-dark"}} import requests rules, offset = [], 0 while offset is not None: page = requests.get( "https://api.courtrules.app/api/v1/rulebooks/california-rules-of-court/rules", headers={"Authorization": "Bearer YOUR_API_KEY"}, params={"limit": 500, "offset": offset}, ).json() rules += page["rules"] offset = page["meta"]["next_offset"] ``` An offset at or past the last rule returns `200` with an empty `rules` array and the true `meta.total`. If the official source changes while you page, a rule can move between pages; read again from `offset=0` when you need a consistent copy. ## Filtering behavior * **Search.** Every word in `q` must appear in the rule's number, heading or operative text. A `%` or `_` in `q` matches itself. * **Status and requirements.** `legal_status` and `has_requirements` combine with each other and with `q`. `has_requirements=true` and `has_requirements=false` together cover every rule exactly once. * **Removed rules** stay in the list, with `removed: true`. They never match `has_requirements=true`. ## Errors ### 400: Invalid parameters Returned for a value the endpoint cannot use, such as `limit=0` or `has_requirements=yes`. Each failing parameter is named. ```json 400 theme={"theme":{"light":"github-light","dark":"github-dark"}} { "error": "Invalid request", "details": [ { "path": "limit", "message": "Number must be greater than or equal to 1" } ], "docs_url": "https://docs.courtrules.app/api-reference/rulebook-rules" } ``` ### 404: Rulebook not found Returned when no rulebook has this identifier. A search with no match is `200` with an empty list, not a `404`. ```json 404 theme={"theme":{"light":"github-light","dark":"github-dark"}} { "error": "Rulebook 'no-such-rulebook' not found.", "suggestion": "Use GET /api/v1/rulebooks to list the rulebooks you can read.", "docs_url": "https://docs.courtrules.app/api-reference/rulebooks" } ``` Each rule in the answer counts as one row against your [daily row limit](/api-reference/rate-limits). # List rulebooks Source: https://docs.courtrules.app/api-reference/rulebooks GET /api/v1/rulebooks Lists the official rulebooks you can read, such as the California Rules of Court Returns the official rulebooks you can read. A rulebook is an official set of numbered rules published as one book, such as the California Rules of Court; see [Rulebooks](/concepts/rulebooks) for how rulebooks, rules and requirements fit together. The full list comes back in one response. Use a rulebook's `id` to read the rulebook with [`/rulebooks/{rulebook_id}`](/api-reference/get-rulebook), list its rules with [`/rulebooks/{rulebook_id}/rules`](/api-reference/rulebook-rules), or read the requirements of its rules with [`/extracted-rules`](/api-reference/extracted-rules). **jurisdiction** `string` Only rulebooks that apply in this jurisdiction: a two-letter state code in capitals such as `CA`, `DC` for the District of Columbia, or `US` for national federal rules. **scope** `string` Only rulebooks of this scope: `national`, `statewide` or `court`. A statewide rulebook applies across one state. A court rulebook applies in the courts it names in `governed_court_ids`. **district\_id** `string` Court identifier, such as `il-cook-circuit`. Returns the rulebooks that name this court in `governed_court_ids`. Statewide and national rulebooks name no courts, so find them with `jurisdiction` and `scope`. A court we do not map returns `404`. **q** `string` Words to find in a rulebook's name, abbreviations, identifier or issuer. Every word must appear. Not case-sensitive. Example: `CRC`. ```bash cURL theme={"theme":{"light":"github-light","dark":"github-dark"}} curl 'https://api.courtrules.app/api/v1/rulebooks?jurisdiction=CA&scope=statewide' \ -H "Authorization: Bearer YOUR_API_KEY" ``` ```python Python theme={"theme":{"light":"github-light","dark":"github-dark"}} import requests resp = requests.get( "https://api.courtrules.app/api/v1/rulebooks", headers={"Authorization": "Bearer YOUR_API_KEY"}, params={"jurisdiction": "CA", "scope": "statewide"}, ) rulebooks = resp.json()["rulebooks"] ``` ```typescript Node.js theme={"theme":{"light":"github-light","dark":"github-dark"}} const resp = await fetch( "https://api.courtrules.app/api/v1/rulebooks?jurisdiction=CA&scope=statewide", { headers: { Authorization: "Bearer YOUR_API_KEY" } }, ); const { rulebooks } = await resp.json(); ``` ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} { "rulebooks": [ { "id": "california-rules-of-court", "name": "California Rules of Court", "aliases": ["CRC", "Cal. Rules of Court", "Cal. Rules Ct."], "jurisdiction": "CA", "scope": "statewide", "kind": "court_rules", "governed_court_ids": [], "issuer": "Judicial Council of California", "official_url": "https://courts.ca.gov/forms-rules/rules-court", "rule_count": 1488, "last_checked_at": "2026-10-19T08:20:21.677476+00:00", "site_url": "https://www.courtrules.app/rules/california-rules-of-court" } ], "meta": { "total": 1, "jurisdiction": "CA", "scope": "statewide" } } ``` ## Response fields **rulebooks** `array` The rulebooks that match, ordered by name. Empty when none match. **Rulebook** **id** `string` Rulebook identifier. It does not change: if the official name changes, the name changes and the id stays. **name** `string` Official name. **aliases** `string[]` Other names and abbreviations readers use, such as `CRC`. **jurisdiction** `string` Where the rulebook applies: a state code, `DC`, or `US`. **scope** `string` `national`, `statewide` or `court`. **kind** `string` `court_rules`, `statute` or `administrative_code`. **governed\_court\_ids** `string[]` Court identifiers of the courts a court rulebook names, as listed by [`/courts`](/api-reference/courts). Empty for statewide and national rulebooks. **issuer** `string` The body that adopts and publishes the rules. **official\_url** `string` The issuer's official page for the rulebook. **rule\_count** `integer` Rules in force that the official source still lists. Repealed, reserved and removed rules are not counted. **last\_checked\_at** `string | null` When we last read the official source. `null` before the first read. **site\_url** `string` The rulebook's page on courtrules.app. **meta** `object` **Meta** **total** `integer` Number of rulebooks returned **jurisdiction** `string` The `jurisdiction` filter you sent, when present **scope** `string` The `scope` filter you sent, when present **district\_id** `string` The `district_id` filter you sent, when present **q** `string` The search you sent, when present ## Finding the rulebook you need * **A state's rules of court:** `jurisdiction=CA&scope=statewide`. * **A court's local rules:** `district_id=`. Only rulebooks that name the court match. * **A rulebook you know by its short name:** `q=CRC`. Combine filters to narrow the list. A request with no match returns `200` with an empty `rulebooks` array. A rulebook that is not in the list reads as not found everywhere else in the API. ## Errors ### 400: Invalid parameters Returned for a value the endpoint cannot use, such as `jurisdiction=California` or `scope=local`. Each failing parameter is named. ```json 400 theme={"theme":{"light":"github-light","dark":"github-dark"}} { "error": "Invalid request", "details": [ { "path": "scope", "message": "Invalid enum value. Expected 'national' | 'statewide' | 'court', received 'local'" } ], "docs_url": "https://docs.courtrules.app/api-reference/rulebooks" } ``` ### 404: Court not found Returned when `district_id` is not a court we map. ```json 404 theme={"theme":{"light":"github-light","dark":"github-dark"}} { "error": "District 'nowhere-court' not found.", "suggestion": "Use GET /api/v1/courts to list all valid district identifiers.", "docs_url": "https://docs.courtrules.app/api-reference/courts/list-courts" } ``` Each rulebook in the answer counts as one row against your [daily row limit](/api-reference/rate-limits). # Get rules Source: https://docs.courtrules.app/api-reference/rules GET /api/v1/rules Returns every rule that applies to a judge, from the court-wide layer down to the judge's own standing orders Returns the rules that apply to one judge. The response shape depends on the court: * **Courts with compliance profiles (`edny` today):** the hierarchical rule set used by [`/check`](/api-reference/check), organized as FRCP, local rules, and standing order. Optionally filtered by `document_scope` and `motion_type`. * **Every other court:** the court-wide rules plus the judge's own rules, each with the judge's quoted source text and structured fields. See [Courts without compliance profiles](#courts-without-compliance-profiles). **judge\_slug** `string` *required* Judge slug from [`/judges`](/api-reference/judges) (e.g. `gary-r-brown`, `judge-teresa-a-beaudet`). Use `court` for a court's court-wide rules only. **district\_id** `string` *required* Court identifier (e.g. `edny`, `ca-los-angeles-superior`) **document\_scope** `string` Filter rules relevant to this document type. See [Document Structure](/concepts/document-structure) for values. Courts with compliance profiles only; other courts return `400`. **motion\_type** `string` Filter rules relevant to this motion type (e.g. `Rule_56`, `discovery`, `Rule_12`). Courts with compliance profiles only; other courts return `400`. ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}} curl 'https://api.courtrules.app/api/v1/rules?judge_slug=gary-r-brown&district_id=edny&document_scope=brief_support&motion_type=Rule_56' \ -H "Authorization: Bearer YOUR_API_KEY" ``` ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} { "judge": { "slug": "gary-r-brown", "name": "Gary R. Brown" }, "rules": { "frcp": [ { "rule_key": "FormatConstraint:caption", "citation": "FRCP 10(a)", "label": "Federal Rules of Civil Procedure", "summary": "Every pleading must include a caption with court name, case title, docket number, and document designation.", "severity": "CRITICAL" }, { "rule_key": "DocumentRequirement:sj_no_genuine_dispute", "citation": "FRCP 56(a)", "label": "Federal Rules of Civil Procedure", "summary": "SJ motion must identify each claim/defense and show no genuine dispute of material fact.", "severity": "CRITICAL", "applies_to": ["Rule_56"] } ], "local_rules": [ { "rule_key": "PageWordLimitRule:memo_support", "citation": "LR 7.1(c)", "label": "EDNY Local Civil Rule", "summary": "Support/opposition briefs: 8,750 words max. Reply briefs: 3,500 words max.", "severity": "CRITICAL", "applies_to": ["brief_support", "brief_opposition", "brief_reply"] } ], "standing_order": [ { "category": "PAGE_LIMIT", "summary": "Brief Support limited to 20 pages", "source": "Brown SO §2.B" }, { "category": "COURTESY_COPY", "summary": "Courtesy copy always required", "source": "Brown SO §1" }, { "category": "PMC", "summary": "Pre-motion conference required. Letter <= 3pp.", "source": "Brown SO §3.A" }, { "category": "BUNDLING", "summary": "Do NOT file until motion is fully briefed", "source": "Brown SO §3.B" } ] }, "meta": { "total_rules": 25 } } ``` ## Response fields **judge** `object` Judge identification **rules** `object` Hierarchical rule set organized by source **Rules object** **frcp** `array` Federal Rules of Civil Procedure applicable to this context **local\_rules** `array` District local rules applicable to this context **standing\_order** `array` Judge-specific standing order rules ## Filtering behavior When `document_scope` and/or `motion_type` are provided, rules are filtered to show only those relevant to the specified context. Rules with no `applies_to` field are always included (they apply universally). ## Courts without compliance profiles For every court other than `edny`, the response carries two layers: * **`rules.court`:** court-wide rules that apply in every courtroom (local rules, general orders, court-wide filing requirements). * **`rules.judge`:** the judge's own rules (standing orders, individual practices, courtroom rules). Each rule has the same shape as a rule from [`/extracted-rules`](/api-reference/extracted-rules): a plain-English summary, the judge's quoted source text, structured fields keyed by `logic_type`, a page or section citation, and the official source URL. ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}} curl 'https://api.courtrules.app/api/v1/rules?district_id=ca-los-angeles-superior&judge_slug=judge-teresa-a-beaudet' \ -H "Authorization: Bearer YOUR_API_KEY" ``` ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} { "judge": { "slug": "judge-teresa-a-beaudet", "name": "Judge Teresa A. Beaudet", "status": "active" }, "district_id": "ca-los-angeles-superior", "rules": { "court": [/* 188 court-wide rules */], "judge": [ { "rule_id": "0135e5a3-4c3d-4feb-bc55-5bb44aa36981", "district_id": "ca-los-angeles-superior", "judge_slug": "judge-teresa-a-beaudet", "source_url": "https://www.lacourt.ca.gov/web3/courthouse/api/courthouses/courtroom-information/courthouse/LAM/courtrooms/508/documents", "logic_type": "CourtesyCopyRule", "workflow_phase": "FILING", "content": { "summary": "Courtesy conformed copies of filings with points and authorities or exceeding 15 pages must be lodged in Dept. 508 on the filing date (next business day if efiled on a holiday or weekend).", "source_text": "Courtesy conformed copies of any filings with a points and authorities or that exceed 15 pages must be lodged in Dept. 508 on the date of filing or, if the filing is efiled on a holiday or weekend, on the next business day.", "structured_data": { "logic_type": "CourtesyCopyRule", "trigger": { "type": "page_threshold", "value": 15, "operator": ">" }, "requirement": { "delivery_method": "chambers_drop_off", "delivery_timing": "upon_filing" } }, "citation_source": { "page": 3 } } } ] }, "meta": { "total_rules": 253, "court_rules": 188, "judge_rules": 65 } } ``` **`judge.status`:** `active` or `coming_soon` for judges on the current roster. `inactive` or `retired` means the judge has left the roster: `rules.judge` comes back empty, and `rules.court` still lists the court-wide rules. **Response size:** the court-wide layer is returned in full, which can be over a thousand rules in a large court. To page or filter by rule type, use [`/extracted-rules`](/api-reference/extracted-rules) with `judge_slug` and `logic_type`. ## Errors | Status | Meaning | | - | - | | `400` | Missing parameters, or `document_scope` / `motion_type` sent for a court without compliance profiles | | `404` | The court or the judge is not known. List valid slugs with [`/judges`](/api-reference/judges). | # Authentication Source: https://docs.courtrules.app/authentication How to authenticate with the Court Rules API All API endpoints require a Bearer token in the `Authorization` header. ## Request format ``` Authorization: Bearer ``` ## Getting an API key API keys are issued through the console dashboard at [console.courtrules.app](https://console.courtrules.app). Sign in with your organization account to view and manage your keys. Keys follow the format `crm__` (e.g. `crm_prod_...`). ## Example request ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}} curl -X GET 'https://api.courtrules.app/api/v1/judges?district_id=edny' \ -H "Authorization: Bearer YOUR_API_KEY" ``` ## Error responses ### 401: Missing or malformed header Returned when the `Authorization` header is missing or doesn't use the `Bearer` scheme. ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} { "error": "Missing or invalid Authorization header. Expected: Bearer " } ``` ### 403: Invalid key Returned when the key is present and well-formed but not recognized. ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} { "error": "Invalid API key" } ``` ## MCP authentication The MCP server at `https://mcp.courtrules.app/mcp` requires a credential on every request. There are two ways to get one, and neither makes you sign in again later. | Method | How it works | Use it for | | - | - | - | | Sign in | Your MCP client opens console.courtrules.app, you approve once, the client refreshes its token | Claude Code, Claude Desktop, claude.ai, Cursor, VS Code, Codex | | API key | `Authorization: Bearer ` header; keys do not expire | Scripts, backends, CI, and clients without sign-in | ### Sign in Add the server URL to your client and sign in when it asks. Per-client steps are in the [MCP: Court Rules quick start](/guides/mcp-court-rules#quick-start). How it works: a request without a credential gets `401` with a `WWW-Authenticate` header that points to `https://mcp.courtrules.app/.well-known/oauth-protected-resource`. Clients that support MCP sign-in (OAuth 2.1) read that, register themselves, and open the consent page. The access token they receive lasts one hour, and the client trades its refresh token for a new one in the background, so you are not asked again. ### API key Your API key is on the dashboard at [console.courtrules.app](https://console.courtrules.app). It is the same key the REST API takes. Claude Code: ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}} claude mcp add --transport http court-rules https://mcp.courtrules.app/mcp \ --header "Authorization: Bearer $COURT_RULES_API_KEY" ``` Cursor, Windsurf, and other clients with a JSON config: ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} { "mcpServers": { "court-rules": { "url": "https://mcp.courtrules.app/mcp", "headers": { "Authorization": "Bearer YOUR_API_KEY" } } } } ``` Your own application, with the MCP TypeScript SDK: ```typescript theme={"theme":{"light":"github-light","dark":"github-dark"}} const transport = new StreamableHTTPClientTransport(new URL("https://mcp.courtrules.app/mcp"), { requestInit: { headers: { Authorization: `Bearer ${process.env.COURT_RULES_API_KEY}` }, }, }); ``` ### Errors Every rejected request returns `401` with a `WWW-Authenticate` header. ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} { "error": "invalid_token", "error_description": "Token expired" } ``` | `error` | `error_description` | Cause | | - | - | - | | `unauthorized` | `Sign in through your MCP client, or send an API key as Authorization: Bearer ` | No credential sent | | `invalid_token` | `Token expired` | An access token past its one-hour lifetime that the client did not refresh | | `invalid_token` | `Not a valid API key or OAuth access token` | A mistyped key, a revoked key, or a token not issued for this server | ### Common mistakes * **Copying an access token into a static header.** Nothing refreshes it, so it stops working after an hour. Static headers should hold the API key. * **Setting a header and expecting sign-in.** Claude Code skips sign-in for any server with an `Authorization` header configured. Use one method per server entry. ### Getting access Sign in at [console.courtrules.app](https://console.courtrules.app) with Google or email. Contact [api@courtrules.app](mailto:api@courtrules.app) if your organization needs access provisioned. ## Security notes * API keys are sensitive credentials. Do not commit them to version control or expose them in client-side code. * Use environment variables to store keys in your application: ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}} export COURT_RULES_API_KEY="crm_prod_..." ``` ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}} curl -X GET 'https://api.courtrules.app/api/v1/judges?district_id=edny' \ -H "Authorization: Bearer $COURT_RULES_API_KEY" ``` # Check categories Source: https://docs.courtrules.app/concepts/check-categories What the /check endpoint validates and when each check applies The [`/check`](/api-reference/check) endpoint runs your filing through every applicable rule. The result is deterministic, so the same input always gives the same output. Every result tells you exactly where the rule comes from (e.g., "FRCP 10(a)", "EDNY LR 7.1(c)", "Brown SO §2.B") so you can look it up in the original document yourself. ## Key terms | Term | What it means | | - | - | | **FRCP** | Federal Rules of Civil Procedure, the national baseline, identical for every federal judge | | **LR** | Local Rules, published by each district, applying to every judge in that district | | **SO** | Standing Orders, issued by individual judges; they override LR and FRCP where they conflict | | **PMC** | Pre-motion conference: a letter to the judge requesting permission to file a dispositive motion | | **ECF** | Electronic Case Filing, the federal court docketing system where documents are submitted | | **Filing gate** | A standing order requirement that all motion papers (motion, opposition, reply) be complete before anything is filed on ECF | | **Bundling** | A standing order requirement that motion, opposition, and reply be submitted as a single package | ## What gets checked | Category | What it catches | Rule source | | - | - | - | | Page limits | Your document has too many pages for this judge | Standing orders | | Word limits | Your document exceeds the district's word count cap | Local rules | | Formatting | Font is too small, margins are too narrow, or line spacing is wrong | Local rules | | Structural requirements | Missing pieces like caption, signature block, table of contents, certificate of service, or motion-specific documents (21 checks total) | FRCP + local rules | | Privacy redactions | Full SSN, date of birth, minor's name, or financial account number appears in the filing | FRCP 5.2(a) | | Word count consistency | The word count in your certificate of compliance is off by more than 5% from the actual count | Local rules | | Courtesy copies | Whether the judge wants a printed courtesy copy (always, never, or only above a page threshold) | Standing orders | | Pre-motion conference | The judge wants a PMC letter before you file dispositive motions | Standing orders | | Filing gate | The judge wants all motion papers fully briefed before anything gets filed | Standing orders | | Bundling | The judge wants the motion, opposition, and reply filed together as a single package | Standing orders | ## How limits work Page limits and word limits are **independent**. Both apply at the same time. You can pass the word limit but fail the page limit, or the other way around. Opposition briefs use the same limits as support briefs. When you send `document_scope: "brief_opposition"`, the API checks limits under `brief_support` automatically. ``` brief_support: 25 pages / 8,750 words (EDNY local rules) brief_reply: 10 pages / 3,500 words (EDNY local rules) ``` Individual judges can set stricter limits in their standing orders. In EDNY: Judge Brown caps support briefs at 20 pages (5 below the district default). Judge Amon imposes no judge-specific page limit, so the district's 25-page cap applies. Same district, same document, different outcome depending on the judge assigned. ## When structural checks apply Not every structural check runs on every filing. Each check has a trigger condition: | Trigger | When it runs | | - | - | | `always` | Every filing | | `motion` | Any motion filing | | `Rule_56` | Summary judgment motions | | `Rule_12` | Rule 12 motions | | `discovery` | Discovery motions | | `motion_to_amend` | Motions to amend | | `motion_in_limine` | Motions in limine | | `pages_gte_10` | Documents with 10 or more pages | | `opposing_pro_se_Rule_56` | SJ motions against pro se parties | | `opposing_pro_se_Rule_12` | Rule 12 motions against pro se parties | If you don't include a particular section in your request (for example, you skip the `format` object), checks that depend on it are silently skipped. You only get results for what you send. ## Pre-motion conference logic Some judges require a pre-motion conference (PMC) before you can file certain motions. The API walks through a decision tree to figure out whether PMC applies to your filing: ```mermaid theme={"theme":{"light":"github-light","dark":"github-dark"}} flowchart TD A[Dispositive motion] --> B{Judge requires PMC?} B -- No --> Z([Check skipped]) B -- Yes --> C{Filing party is pro se\nand judge exempts pro se?} C -- Yes --> D([INFO: PMC not required\nfor pro se parties]) C -- No --> E{Motion type exempt\nfor this judge?} E -- Yes --> F([INFO: Motion type\nexempt from PMC]) E -- No --> G{pmc_completed: true?} G -- Yes --> H([PASS]) G -- No --> I([FAIL: PMC required\nbefore filing]) ``` In EDNY: Judge Amon requires a PMC letter before any dispositive motion. Judge Block does not. A Rule 56 motion that passes PMC with Block would fail with Amon if `pmc_completed: false`. A few details: some judges require the opposing party to respond within a set number of days (`response_required`, `response_days`). Some judges only require PMC for represented counsel, not pro se parties (`requires_represented_counsel`). ## Result statuses Every check result comes back with one of three statuses: | Status | What it means | | - | - | | `FAIL` | A rule is violated. The document is non-compliant and needs to be fixed. | | `PASS` | The rule is satisfied. Included so you can see what passed as well as what failed. | | `ACTION_REQUIRED` | Not a violation, but something you need to do (e.g., "submit a courtesy copy to chambers"). | # Coverage Source: https://docs.courtrules.app/concepts/coverage-levels What the API covers and how to check coverage for a court in code Coverage is the set of courts, judges and rulebooks the API holds rules for, and how much it holds for each one. It differs from court to court, so a client should read it from the API instead of assuming it. Counts change as courts are added, so this page gives none. The [coverage page](https://www.courtrules.app/coverage) on courtrules.app lists today's counts by court, state and judge, with the date they were counted. [`GET /api/v1/courts`](/api-reference/courts) returns totals in its `meta` object. The coverage page counts a court only when it has at least one current rule and leaves out listings that redirect to another court, so its totals can differ from the API's. ## Why teams read coverage * **Before building:** find out whether the courts your customers file in are covered, and how deeply. * **In the product:** tell a filer when a judge has no rules of their own, so an empty list is not read as "no requirements". * **In the interface:** show the court's own sentence and a link to its document beside each requirement. ## How coverage works Coverage has three levels, and each level has a field that says where it stands. 1. A **court** is covered when its `status` in [`/courts`](/api-reference/courts) is `live`. A `coming_soon` court is mapped and has a roster, but the API holds no rules for it yet. 2. A **judge** on a live court is covered when `has_rules` is `true` in [`/judges`](/api-reference/judges), which means the API holds the judge's own standing orders, individual practices or courtroom rules. A judge without rules of their own still has the court-wide rules whenever the court has any, and `meta.court_level_rules` reports that. 3. A **rule** is one requirement. It carries the court's own sentence in `content.source_text`, a plain-English `content.summary`, a rule type, and `source_url`, the official address the rule was read from. Every API key can query every court, and each endpoint answers one coverage question: * [`GET /api/v1/courts`](/api-reference/courts) lists every court we map, with its status and roster size. * [`GET /api/v1/judges`](/api-reference/judges) lists a court's current roster and marks the judges whose own rules we hold. * [`GET /api/v1/rules`](/api-reference/rules) returns a judge's rules. For courts without a compliance profile, that is the court-wide rules plus the judge's own rules, each with its quoted source text. * [`GET /api/v1/extracted-rules`](/api-reference/extracted-rules) searches and pages rules across every court. * [`GET /api/v1/rulebooks`](/api-reference/rulebooks) lists official rulebooks, such as the California Rules of Court, whose rules you read one by one with their official text. * [`GET /api/v1/holidays`](/api-reference/holidays) lists court holidays and closure dates with their official sources. To read the rules of a court in three calls, follow [Read a court's rules](/guides/read-court-rules). ## Key terms | Term | Meaning | Where you see it | | - | - | - | | Court | A federal district court or a state trial court that the API maps. | `district_id`, such as `edny` or `ca-los-angeles-superior` | | Live | The API holds rules for the court. | `status: live` in `/courts` | | Coming soon | The court is mapped and its roster is listed, but the API holds no rules for it yet. | `status: coming_soon` | | Roster | The judges currently listed for a court. In some state courts the roster lists departments or courtrooms instead of people. | `judges_mapped`, `/judges` | | Judge with own rules | A roster entry for which the API holds the judge's own standing orders, individual practices or courtroom rules. | `has_rules`, `meta.with_rules` | | Court-wide rules | Rules that apply in every courtroom of the court, such as local rules and general orders. | `judge_slug` of `court` | | Rule | One requirement, with the court's own sentence, a plain-English summary and a link to the source. | `/rules`, `/extracted-rules` | | Rule type | The kind of requirement a rule states. [The list](#rule-types) is fixed. | `logic_type` | | Compliance profile | A prepared set of rules that lets `/check` and `/classify` run for a court. The Eastern District of New York has one today. | `has_profile`, `judges_profiled` | | Rulebook | An official set of numbered rules published as one book. See [Rulebooks](/concepts/rulebooks). | `/rulebooks` | | Partial coverage | A live court where some roster entries have no rules of their own, or a rulebook rule whose text has not been read yet. | `meta.with_rules` and `meta.total`; `extraction_status` | ## Check coverage in code Two calls answer most coverage questions. The first reads the court, and the second reads its roster. ```bash cURL theme={"theme":{"light":"github-light","dark":"github-dark"}} # The court curl 'https://api.courtrules.app/api/v1/courts/ca-los-angeles-superior' \ -H "Authorization: Bearer YOUR_API_KEY" # The roster curl 'https://api.courtrules.app/api/v1/judges?district_id=ca-los-angeles-superior' \ -H "Authorization: Bearer YOUR_API_KEY" ``` ```python Python theme={"theme":{"light":"github-light","dark":"github-dark"}} import requests BASE = "https://api.courtrules.app/api/v1" HEADERS = {"Authorization": "Bearer YOUR_API_KEY"} def describe_coverage(district_id): court = requests.get(f"{BASE}/courts/{district_id}", headers=HEADERS) court.raise_for_status() if court.json()["status"] != "live": return "The court is mapped, but we hold no rules for it yet." judges = requests.get( f"{BASE}/judges", headers=HEADERS, params={"district_id": district_id} ) judges.raise_for_status() meta = judges.json()["meta"] return f"{meta['with_rules']} of {meta['total']} roster entries have rules of their own." print(describe_coverage("ca-los-angeles-superior")) ``` The court answers with its status and roster size. The roster answers with a `meta` object that counts the judges. ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} { "district_id": "ca-los-angeles-superior", "name": "Superior Court of California, County of Los Angeles", "circuit": null, "state": "California", "status": "live", "judges_mapped": 116 } ``` ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} { "meta": { "total": 116, "profiled": 0, "with_rules": 113, "court_level_rules": true } } ``` The responses above are a sample, and the counts change as rosters change, so read them from the response instead of copying them from this page. The sample court is `live`. Its `with_rules` is lower than its `total`, and a roster entry without rules of its own receives the court-wide rules, which exist when `court_level_rules` is `true`. The second response is shortened to its `meta` object. ## Rule types A rule's `logic_type` names the kind of requirement it states, and the fields in its `content.structured_data` depend on that type. The `workflow_phase` of a rule names the stage of a case it applies to, which is one of `CASE_INITIATION`, `FILING`, `MOTION_PRACTICE`, `TRIAL_PREP` or `POST_JUDGMENT`. | `logic_type` | What it covers | | - | - | | `CourtesyCopyRule` | When and how to deliver courtesy copies to chambers, including triggers and timing | | `PageWordLimitRule` | Page and word limits for motions, briefs and other filings, including limits by role | | `PreMotionConferenceRule` | Conference and letter requirements before a motion, including steps that must come first | | `AdjournmentRequirementRule` | How to ask for an adjournment, extension or continuance | | `BundlingRule` | Whether to file related papers together or promptly as each is completed | | `FormatConstraint` | Font, margin, spacing and file format requirements | | `DocumentRequirement` | Required elements, certificates and structure for court documents | | `CommunicationRule` | How, when and why to contact chambers | | `SealingProcedure` | How to file sealed or redacted documents, including required motions and formats | | `ElectronicFilingRule` | Electronic filing requirements, permitted filing channels and exceptions | | `FilingTimingRule` | Filing cutoffs, deemed-filed rules, rejection handling, cure periods and outages | | `ServiceRule` | E-service, mail and personal service, proof of service, and service timing | | `FilingFeeRule` | Filing fees, payment methods, fee waivers and deferrals | | `JuniorLawyerIncentive` | Rules that encourage junior lawyers to take part in oral argument and court proceedings | Pass a type to [`/extracted-rules`](/api-reference/extracted-rules) as `logic_type` to read only that kind of rule. ## Freshness Courts rarely change their rules more than a few times a year, so every source is read again at least once a quarter. Court holidays are updated monthly. Each rule carries `source_url`, the official address it was read from, so you can open the court's own document and confirm the wording. The [cadence section of the coverage page](https://www.courtrules.app/coverage#cadence) lists each kind of source. To follow new court documents as we find them, subscribe to the Atom feed at [courtrules.app/changes.xml](https://www.courtrules.app/changes.xml). Each entry names the court and links to the new copy and the copy it replaced, and each court's entries are also on its changes page at `courtrules.app/courts//changes`. A new version does not always change a rule, so compare the two copies. ## Rule layers For courts with compliance profiles (the Eastern District of New York today), every judge is checked against three rule layers: **FRCP** (15 national rules), **Local Rules** (district-specific rules), and **Standing Orders** (judge-specific rules extracted from each judge's chambers standing order). ```mermaid theme={"theme":{"light":"github-light","dark":"github-dark"}} graph TD FRCP["FRCP
national, 15 rules, identical for every judge"] LR["Local Rules
district-wide, covering formatting, word limits and timing"] SO["Standing Orders
judge-specific, covering page limits, PMC, courtesy copies and filing gates"] FRCP --> LR --> SO style FRCP fill:#eff6ff,stroke:#3b82f6,color:#1e3a8a style LR fill:#dbeafe,stroke:#3b82f6,color:#1e3a8a style SO fill:#bfdbfe,stroke:#1e40af,color:#1e3a8a ``` Each layer adds to the one above it and can override it. FRCP is the national baseline, Local Rules add district-specific requirements, and Standing Orders are the most specific. Standing orders are also the hardest to find and track. ### FRCP (applies to every judge) 15 rules covering captions, signatures, privacy redactions, motion content, discovery conferral, and summary judgment requirements. They are national rules, identical regardless of judge or district. ### Local Rules (applies to every judge in the district) District-specific local rules covering formatting (font, margins, spacing), word limits, filing timing, required documents, and letter motions. The number of local rules varies by district. ### Standing Orders (judge-specific) Judge-specific rules extracted from individual chambers standing orders cover: * **Page limits**: judge-specific page limits that may differ from district word limits * **Courtesy copies**: whether required, format, and timing * **Pre-motion conferences**: whether required before filing, letter format, exemptions * **Filing gates**: whether all papers must be fully briefed before docketing * **Bundling**: whether motion, opposition, and reply must be filed together * **Briefing schedules**: whether changes require court approval ### How the layers appear in the API [`GET /api/v1/rules`](/api-reference/rules) returns all three layers for a judge in a court with a compliance profile, including the judge's standing order rules. For every other court, it returns the court-wide rules and the judge's own rules. [`POST /api/v1/check`](/api-reference/check) checks a document against all three layers: page and word limits, formatting, structural requirements, privacy redactions, PMC requirements, filing gates, bundling, and courtesy copies. It returns `422` for courts without a compliance profile. ## Official rulebooks Rules from courts and judges are one kind of coverage. Rulebooks are another: the official, numbered rules a court system publishes as one book, such as the California Rules of Court. The API returns each rule with its official text and the filing requirements we read from it. See [Rulebooks](/concepts/rulebooks). Rulebooks sit beside the three layers above, not inside them. A statewide rulebook applies across its state, but the API does not yet merge it into a judge's rules or a court's rules. [`/rules`](/api-reference/rules) and `/extracted-rules?district_id=...` answer as they did before and do not include the California Rules of Court, and [`/check`](/api-reference/check) does not use rulebooks. To see a judge's rules and the statewide rules together, read both and combine them yourself. ## Limits * **Compliance checks:** `/check` and `/classify` run for the Eastern District of New York only. Every other court returns `422` from them, and the error points to that court's rules. * **No merged answer:** the API returns the rules each source states. It does not resolve conflicts between rules, and it does not compute the final rule set for a filing. * **Empty results:** an empty list means the API holds no matching rule. It does not mean the court has no such requirement. * **Departed judges:** a judge who has left the roster returns an empty `rules.judge` from `/rules`, and `rules.court` still lists the court-wide rules. ## Common mistakes * **Treating `live` as complete.** A live court can have roster entries with no rules of their own. Read `has_rules` for one judge or `meta.with_rules` for the court. * **Counting people with `judges_mapped`.** In some state courts the roster lists departments or courtrooms, so the number is not a head count. * **Listing every court for every request.** Each court in `GET /courts` counts as one row against your [daily row limit](/api-reference/rate-limits). Keep the list, or read one court with `GET /courts/`. * **Running `/check` for any live court.** Only the Eastern District of New York has a compliance profile. Read the rules of other courts with [`/rules`](/api-reference/rules) or [`/extracted-rules`](/api-reference/extracted-rules). ## Related * [Read a court's rules](/guides/read-court-rules) * [Rulebooks](/concepts/rulebooks) * [Check categories](/concepts/check-categories) * [Rate limits](/api-reference/rate-limits) * [List courts](/api-reference/courts) * [List judges](/api-reference/judges) # Document structure Source: https://docs.courtrules.app/concepts/document-structure What document metadata to provide and what checks it enables The [`/check`](/api-reference/check) endpoint accepts a `document` object describing the filing. Only `page_count` and `word_count` are required. All other fields are optional. The more you provide, the more checks run. ## Required fields | Field | Type | Description | | - | - | - | | `page_count` | integer | Total page count of the document | | `word_count` | integer | Total word count (excluding TOC, TOA, certificates) | With these two fields, the API checks page limits, word limits and courtesy copy requirements, and it checks word count consistency when `certificate_word_count` is also provided. ## Optional sections ### `caption` Enables FRCP 10(a) caption checks. | Field | Type | Check | | - | - | - | | `present` | boolean | Caption exists | | `has_court_name` | boolean | Court name in caption | | `has_case_title` | boolean | Case title present | | `has_docket_number` | boolean | Docket number present | | `has_document_designation` | boolean | Document type designated | ### `signature_block` Enables FRCP 11(a) signature checks. | Field | Type | Check | | - | - | - | | `present` | boolean | Signature block exists | | `has_attorney_name` | boolean | Attorney name included | | `has_firm_name` | boolean | Firm name included | | `has_address` | boolean | Address included | | `has_email` | boolean | Email included | | `has_phone` | boolean | Phone number included | | `is_electronic_signature` | boolean | Electronic (vs. wet) signature | ### `sections` Enables structural checks: required documents, certificates, motion-specific requirements. | Field | Type | When checked | | - | - | - | | `has_toc` | boolean | Documents >= 10 pages | | `has_toa` | boolean | Documents >= 10 pages | | `has_certificate_of_compliance` | boolean | Always (attorney filings) | | `certificate_word_count` | number | Compared to `word_count` for consistency | | `has_certificate_of_service` | boolean | Always | | `has_numbered_paragraphs` | boolean | Always | | `has_56_1_statement` | boolean | Rule 56 motions (movant) | | `has_56_1_counterstatement` | boolean | Rule 56 motions (opponent) | | `has_proposed_amended_pleading` | boolean | Motions to amend | | `has_verbatim_discovery_text` | boolean | Discovery motions | | `has_conferral_certification` | boolean | Discovery motions | | `has_notice_of_motion` | boolean | All motions | | `has_memorandum_of_law` | boolean | All motions | | `has_supporting_affidavits` | boolean | All motions | | `has_pro_se_sj_notice` | boolean | Rule 56 vs. pro se opponent | ### `format` Enables district local rule formatting checks (font, margins, line spacing). | Field | Type | Rule | | - | - | - | | `primary_font_size_pt` | number | Must be >= 12pt | | `footnote_font_size_pt` | number | Must be >= 10pt | | `margin_inches` | number | Must be >= 1.0" | | `line_spacing` | `"single"` \| `"1.5"` \| `"double"` | Must be double-spaced | ### `privacy` Enables FRCP 5.2(a) privacy redaction checks. | Field | Type | Violation if true | | - | - | - | | `contains_full_ssn` | boolean | Must redact to last 4 digits | | `contains_full_dob` | boolean | Must redact to year only | | `contains_minor_full_name` | boolean | Must use initials only | | `contains_full_financial_account` | boolean | Must redact to last 4 digits | ## Omission principle When an optional section is omitted, the corresponding checks are silently skipped. You can start with minimal input (just page and word count) and add detail as your document analysis improves. The `meta.checks_skipped` field in the response tells you how many checks were skipped due to missing input. # Enforcement data Source: https://docs.courtrules.app/concepts/enforcement-data Privacy enforcement events from federal and state regulators, with the company, the fine, the violation types, the laws cited and a link to the official source. The enforcement data holds privacy enforcement events from federal and state regulators, such as settlements, fines, consent decrees and investigations. Each event names the company and the violation types, lists the laws cited and the remedies, gives the fine amount when one was announced, and links to the official source. ## Why teams use enforcement data In-house legal teams need to know when regulators take action in their industry. An event against a competitor or a vendor can lead to a contract review, a policy update or a report to the board. Each event is a structured, searchable record with a link to its press release, so it can feed your legal workflows directly. Common uses: * Watch the enforcement events that affect your industry. * Scan vendor contracts when a new type of violation appears, using the `search_terms` of an event. * Create a matter in your legal workspace when a high-risk event appears. * Track enforcement by jurisdiction or violation type for compliance reports. ## What an event contains | Field | Type | Description | | - | - | - | | `title` | string | The official title of the event | | `event_date` | date | The date the event was announced | | `jurisdiction` | string | The regulator, such as CA, FTC, NY or TX | | `event_type` | string | The kind of event, such as settlement, consent\_decree, fine or investigation | | `entity_name` | string | The company or organization involved | | `fine_amount` | number or null | The monetary penalty, or null when none was announced | | `violation_types` | string\[] | One or more of the [violation types](#violation-types) | | `risk_level` | string | critical, high, medium or low, as set out in [risk levels](#risk-levels) | | `summary` | string | A plain-English summary of the event | | `laws_cited` | string\[] | The statutes referenced, such as CCPA, the FTC Act or COPPA | | `remedy_types` | string\[] | The remedies required, such as monetary\_penalty, injunction or compliance\_program | | `search_terms` | string\[] | Terms for finding the same issue in your contracts. It can be null | | `primary_source_url` | string | A link to the official source, usually the regulator's press release | | `document_urls` | string\[] | Links to complaints, judgments and consent orders | | `is_multistate` | boolean | Whether several states took part | | `co_enforcers` | string\[] | The other agencies in a multistate action | ## Example search Call `search_privacy_enforcement_actions` with filters to find the events you need: ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} { "jurisdiction": "CA", "violation_type": "opt_out_failure", "date_from": "2026-01-01", "limit": 10 } ``` The response is shortened here: ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} { "results": [ { "id": "evt_001", "title": "Attorney General Bonta Announces $2.75M CCPA Settlement with Disney", "event_date": "2026-02-11", "jurisdiction": "CA", "event_type": "settlement", "entity_name": "The Walt Disney Company", "fine_amount": 2750000, "violation_types": ["opt_out_failure"], "risk_level": "high", "summary": "Disney's opt-out processes failed to stop data sharing across devices. $2.75M penalty.", "primary_source_url": "https://oag.ca.gov/news/press-releases/..." } ], "total": 1 } ``` See [MCP: enforcement data](/guides/mcp-enforcement) for the full `search_privacy_enforcement_actions` reference. ## Jurisdictions The data covers the FTC and state regulators. To list the jurisdictions available today, call `get_privacy_enforcement_stats` with `group_by` set to `jurisdiction`. Use the codes it returns in the `jurisdiction` filter. ## Violation types Each event carries one or more violation types, in four groups: | Group | Types | | - | - | | Consumer data | opt\_out\_failure, notice\_failure, consent\_failure, dark\_patterns, data\_sharing\_unauthorized, data\_broker\_noncompliance | | Sensitive data | children\_data, student\_data, health\_data, employee\_data, biometric\_data, geolocation\_data | | Security | data\_breach, security\_failure, breach\_notification\_delay | | Other | record\_retention, ai\_automated\_decisions, surveillance\_pricing | ## Risk levels Each event has a risk level, which depends on the fine and the remedies: | Level | Criteria | | - | - | | Critical | Fine exceeds \$10M or involves industry-wide injunction | | High | Fine exceeds \$1M | | Medium | Fine between $100K and $1M | | Low | Fine under \$100K or no monetary penalty | ## Access methods You can reach the enforcement data in two ways. 1. The MCP server has three tools, `search_privacy_enforcement_actions`, `get_privacy_enforcement_action` and `get_privacy_enforcement_stats`. See [MCP: enforcement data](/guides/mcp-enforcement). 2. The web console lets you browse and filter events at [courtrules.app/enforcement](https://www.courtrules.app/enforcement). ## Data freshness The enforcement data is updated daily, and a new event appears after the next daily check. To get only the events since your last check, call `search_privacy_enforcement_actions` with `date_from`. One call a day is enough: ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} { "date_from": "2026-03-20", "limit": 50 } ``` The API has no webhooks, so poll with `date_from` to find new events. # Rulebooks Source: https://docs.courtrules.app/concepts/rulebooks Read the official text of a court rulebook rule by rule, and the filing requirements we read from each rule A rulebook is an official set of numbered rules that a court system or rule maker publishes as one book, such as the California Rules of Court. The API returns each rule's official text, its status and its place in the book, and the filing requirements we read from it, with the rule that sets each one. ## Three terms | Term | Meaning | Example | | - | - | - | | **Rulebook** | An official set of numbered rules, published as one book. | The California Rules of Court (`california-rules-of-court`) | | **Rule** | One numbered rule in a rulebook, with its heading, official text and status. | Rule 3.1113, Memorandum | | **Requirement** | One filing requirement read from a rule's text, in the same structure as the results of [`/extracted-rules`](/api-reference/extracted-rules). | A memorandum may not exceed 15 pages, with the exceptions given | A rule is the official text. A requirement is what that text asks of a filer. Rule 3.1113 is one rule; its page limits are separate requirements. ## Why teams use rulebooks * **Open a rule from a citation.** A docketing tool that sees "rule 3.1113" in a motion can show the official text and link to the official page. * **Cite the rule behind a limit.** Show a filer that a 15-page limit comes from Rule 3.1113(d), next to any limit a judge adds. * **Search a rulebook by topic.** Find every rule whose number, heading or text mentions a word, such as "memorandum". * **Keep a stored copy current.** A rule's `revision_id` changes whenever the rule does, so a stored copy can be checked against it. ## How a rulebook relates to courts Every rulebook has a `scope`: * `statewide`: applies across one state. The California Rules of Court is statewide. It applies in the state's courts without naming them, so `governed_court_ids` is empty, and a rule's own text says which courts it covers. * `court`: applies in the courts listed in `governed_court_ids`, such as one court's local rules. * `national`: applies across the country. Find rulebooks by place with `jurisdiction` and `scope`. Find a court's own rulebooks with `district_id`, which matches only the courts a rulebook names. **No layering yet.** The API does not combine a rulebook with a court's rules, a judge's rules or another rulebook. `/rules` and `/extracted-rules?district_id=...` return what they returned before, and they do not include the California Rules of Court. [`/check`](/api-reference/check) does not use rulebooks. To see a judge's rules and the statewide rules together, call both and combine them yourself. ## Read a rulebook in four calls The examples read Rule 3.1113 of the California Rules of Court. They are shortened where a response is long. ### 1. Find the rulebook [`GET /api/v1/rulebooks`](/api-reference/rulebooks) lists the rulebooks you can read. Filter by `jurisdiction`, `scope`, `district_id` or words in the name with `q`. Read one rulebook by id with [`GET /api/v1/rulebooks/{rulebook_id}`](/api-reference/get-rulebook). ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}} curl 'https://api.courtrules.app/api/v1/rulebooks?jurisdiction=CA&scope=statewide' \ -H "Authorization: Bearer YOUR_API_KEY" ``` ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} { "rulebooks": [ { "id": "california-rules-of-court", "name": "California Rules of Court", "aliases": ["CRC", "Cal. Rules of Court", "Cal. Rules Ct."], "jurisdiction": "CA", "scope": "statewide", "kind": "court_rules", "governed_court_ids": [], "issuer": "Judicial Council of California", "official_url": "https://courts.ca.gov/forms-rules/rules-court", "rule_count": 1488, "last_checked_at": "2026-10-19T08:20:21.677476+00:00", "site_url": "https://www.courtrules.app/rules/california-rules-of-court" } ], "meta": { "total": 1, "jurisdiction": "CA", "scope": "statewide" } } ``` `rule_count` counts the rules in force that the official source still lists. `last_checked_at` is when we last read the official source. ### 2. Search its rules [`GET /api/v1/rulebooks/{rulebook_id}/rules`](/api-reference/rulebook-rules) lists a rulebook's rules in book order, without their text. Search the number, heading and text with `q`, filter with `legal_status` and `has_requirements`, and page with `limit` and `offset`. ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}} curl 'https://api.courtrules.app/api/v1/rulebooks/california-rules-of-court/rules?q=opening%20memorandum' \ -H "Authorization: Bearer YOUR_API_KEY" ``` ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} { "rules": [ { "number": "3.764", "slug": "3.764", "citation": "Cal. Rules of Court, rule 3.764", "revision_id": "87a3abf3-5690-421d-8c21-e64305fefbf3", "heading": "Motion to certify or decertify a class or amend or modify an order certifying a class", "outline": [ { "label": "Title Three", "heading": "Civil Rules" }, { "label": "Division 7", "heading": "Civil Case Management" }, { "label": "Chapter 6", "heading": "Management of Class Actions" } ], "legal_status": "in_force", "effective_from": "2026-01-01", "observed_at": "2026-10-19T04:31:34.421+00:00", "removed": false, "requirement_count": 16, "extraction_status": "succeeded", "site_url": "https://www.courtrules.app/rules/california-rules-of-court/3.764" }, { "number": "3.1113", "slug": "3.1113", "citation": "Cal. Rules of Court, rule 3.1113", "revision_id": "50dd0291-ae07-48d0-b490-23555244dcf1", "heading": "Memorandum", "outline": [ { "label": "Title Three", "heading": "Civil Rules" }, { "label": "Division 11", "heading": "Law and Motion" }, { "label": "Chapter 2", "heading": "Format of Motion Papers" } ], "legal_status": "in_force", "effective_from": "2017-01-01", "observed_at": "2026-10-19T04:34:37.532+00:00", "removed": false, "requirement_count": 27, "extraction_status": "succeeded", "site_url": "https://www.courtrules.app/rules/california-rules-of-court/3.1113" } ], "meta": { "total": 2, "returned": 2, "limit": 100, "offset": 0, "next_offset": null, "rulebook_id": "california-rules-of-court", "q": "opening memorandum" } } ``` ### 3. Read one rule [`GET /api/v1/rulebooks/{rulebook_id}/rules/{number}`](/api-reference/get-rulebook-rule) returns one rule with its official text. The number is the rulebook's own, URL-encoded, and must match exactly. ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}} curl 'https://api.courtrules.app/api/v1/rulebooks/california-rules-of-court/rules/3.1113' \ -H "Authorization: Bearer YOUR_API_KEY" ``` The real response lists subdivisions (a) through (m). The example keeps (d), the page limits, and the notes printed with the rule. ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} { "number": "3.1113", "slug": "3.1113", "citation": "Cal. Rules of Court, rule 3.1113", "revision_id": "50dd0291-ae07-48d0-b490-23555244dcf1", "heading": "Memorandum", "outline": [ { "label": "Title Three", "heading": "Civil Rules" }, { "label": "Division 11", "heading": "Law and Motion" }, { "label": "Chapter 2", "heading": "Format of Motion Papers" } ], "legal_status": "in_force", "effective_from": "2017-01-01", "observed_at": "2026-10-19T04:34:37.532+00:00", "removed": false, "requirement_count": 27, "extraction_status": "succeeded", "site_url": "https://www.courtrules.app/rules/california-rules-of-court/3.1113", "current": { "revision_id": "50dd0291-ae07-48d0-b490-23555244dcf1", "heading": "Memorandum", "blocks": [ { "type": "item", "label": "(d)", "heading": "Length of memorandum", "children": [ { "type": "paragraph", "text": "Except in a summary judgment or summary adjudication motion, no opening or responding memorandum may exceed 15 pages. In a summary judgment or summary adjudication motion, no opening or responding memorandum may exceed 20 pages. No reply or closing memorandum may exceed 10 pages. The page limit does not include the caption page, the notice of motion and motion, exhibits, declarations, attachments, the table of contents, the table of authorities, or the proof of service." }, { "type": "note", "role": "history", "blocks": [ { "type": "paragraph", "text": "(Subd (d) amended effective January 1, 2017; adopted as part of a longer subd (d); previously amended effective July 1, 1984, January 1, 1992, July 1, 1997, and January 1, 2004.)" } ] } ] }, { "type": "note", "role": "comment", "title": "Advisory Committee Comment", "blocks": [ { "type": "paragraph", "text": "See also rule 1.200 concerning the format of citations." } ] } ], "plain_text": "(d) Length of memorandum\nExcept in a summary judgment or summary adjudication motion, no opening or responding memorandum may exceed 15 pages. In a summary judgment or summary adjudication motion, no opening or responding memorandum may exceed 20 pages. No reply or closing memorandum may exceed 10 pages. The page limit does not include the caption page, the notice of motion and motion, exhibits, declarations, attachments, the table of contents, the table of authorities, or the proof of service.", "source_url": "https://courts.ca.gov/cms/rules/index/three/rule3_1113", "captured_at": "2026-10-19T04:34:37.532+00:00" } } ``` ### 4. Read the rule's requirements [`GET /api/v1/extracted-rules`](/api-reference/extracted-rules) with `rulebook_id` and `rule_number` returns the requirements read from that rule. Each result names the rulebook rule it came from. The example asks for the page limits, one per page. ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}} curl 'https://api.courtrules.app/api/v1/extracted-rules?rulebook_id=california-rules-of-court&rule_number=3.1113&logic_type=PageWordLimitRule&limit=1' \ -H "Authorization: Bearer YOUR_API_KEY" ``` ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} { "rules": [ { "rule_id": "c3a7f1d4-52e8-4b69-a0d1-8e4f6b9c2d57", "logic_type": "PageWordLimitRule", "workflow_phase": "MOTION_PRACTICE", "content": { "source_text": "Except in a summary judgment or summary adjudication motion, no opening or responding memorandum may exceed 15 pages.", "summary": "An opening or responding memorandum may not exceed 15 pages, except in a summary judgment or summary adjudication motion.", "document_type": "memorandum", "case_type_applicability": ["civil"], "rule_tags": ["page_limit", "memorandum"], "workflow_phase": "MOTION_PRACTICE", "visual_severity": "CRITICAL", "structured_data": { "logic_type": "PageWordLimitRule", "document_type": "memorandum", "role_limits": [{ "role": "all", "limit_type": "pages", "limit_value": 15 }] }, "citation_source": { "section": "Rule 3.1113(d)" } }, "rulebook_rule": { "rulebook_id": "california-rules-of-court", "number": "3.1113", "citation": "Cal. Rules of Court, rule 3.1113", "revision_id": "50dd0291-ae07-48d0-b490-23555244dcf1", "site_url": "https://www.courtrules.app/rules/california-rules-of-court/3.1113" } } ], "meta": { "total": 3, "returned": 1, "limit": 1, "offset": 0, "next_offset": 1, "rulebook_id": "california-rules-of-court", "rule_number": "3.1113", "logic_type": "PageWordLimitRule" } } ``` Rule 3.1113(d) sets three page limits: the opening or responding memorandum (15 pages), the same memorandum in a summary judgment or summary adjudication motion (20 pages), and the reply (10 pages). Follow `meta.next_offset` for the rest. ## Behavior details * **Numbers match exactly.** A rule number is the rulebook's own, without the word Rule, and matches as printed: `3.1113`, `4:46-2`, `21a`. `21a` and `21A` are different rules, and `3.111` does not find `3.1113`. URL-encode numbers that hold spaces or slashes. A number with a space at either end, two spaces in a row, a control character, or more than 40 characters is a 400. * **Two forms of the text.** `blocks` keeps the structure: items with their labels and headings, paragraphs, tables, and notes. `plain_text` is the operative text as lines, in order, with item labels. * **Notes are not rule text.** History lines and committee comments arrive in `blocks` as `note` blocks. They are left out of `plain_text`, left out of search, and no requirement is read from them. * **Status.** `legal_status` is `in_force`, `repealed` or `reserved`. Repealed and reserved rules usually carry only a history note, so their `plain_text` is empty and their `extraction_status` is `skipped`. * **Removed rules.** `removed: true` means the official source no longer lists the rule. It keeps the heading, status and text it had when it was last listed, has no requirements, and is not in `rule_count`. * **Requirements and `extraction_status`.** `requirement_count` is the number of results `/extracted-rules` returns for the rule. `extraction_status` says whether the count is final: `succeeded` means the text was read (0 means it states none of the requirements that are read, as with a definition or a rule about mediators or court staff; the text is still in the rule), `pending` means it has not been read yet, `failed` means reading did not work, and `skipped` means there is nothing to read. * **One version at a time.** A rule's `revision_id` names the version of the rule you are looking at. The requirements of a rule carry the same id in `rulebook_rule.revision_id`. If the two differ, the rule changed between your calls: read it again. * **Order.** Rules come in book order. Requirements come ordered by rule number as text, then by id. The order is stable between calls but is not book order, so use the rule list for book order. * **Citations.** Rule text is not paginated, so `citation_source` on a rulebook requirement never carries a page number. Cite with `rulebook_rule.citation` and link `rulebook_rule.site_url`. ## Errors and limits | Status | When | | - | - | | `400` | A bad parameter, such as `limit=0`, `scope=local`, a rulebook id with capital letters, or a rule number with a space at an end. | | `400` | On `/extracted-rules`: `rule_number` without `rulebook_id`, or `rulebook_id` with `district_id`, `judge_slug` or `include_court_rules`. | | `404` | A rulebook id that is not in the list, a rule number the rulebook does not have, or a `district_id` we do not map. | | `200` | No match: an empty list. A rule with no requirements returns an empty list from `/extracted-rules`, not a 404. | Rulebook calls count against your daily rows like other calls: a list counts one row per item returned, and one rulebook or one rule counts as one row, however long its text. See [Rate limits](/api-reference/rate-limits). ## Common mistakes * **Sending `Rule 3.1113` or `rule-3.1113`.** Send the number alone: `3.1113`. * **Reading `requirement_count: 0` as "no requirements".** Check `extraction_status` first. `pending` and `failed` also show 0. * **Looking for the California Rules of Court by court.** Statewide rulebooks name no courts. Use `jurisdiction=CA&scope=statewide`. * **Expecting a judge's rules to include the rulebook.** Rulebooks are not merged into `/rules` or into `/extracted-rules?district_id=...`. * **Treating notes as the rule.** Read `plain_text`, or skip `note` blocks in `blocks`. * **Sorting requirements by position.** `/extracted-rules` does not return book order. Look up each rule's place with the rule list. ## Related * [List rulebooks](/api-reference/rulebooks) * [Get a rulebook](/api-reference/get-rulebook) * [List the rules of a rulebook](/api-reference/rulebook-rules) * [Get a rule](/api-reference/get-rulebook-rule) * [Search extracted rules](/api-reference/extracted-rules) * [Coverage](/concepts/coverage-levels) # Building with AI agents Source: https://docs.courtrules.app/guides/building-with-ai-agents How to use the Court Rules API and enforcement data with AI agents and LLMs An AI agent can use Court Rules in two ways. The OpenAPI spec describes every endpoint, so an LLM can read it and call the API, and the MCP server offers court rules and enforcement data as agent tools. ## MCP vs REST API If your AI tool supports the Model Context Protocol (MCP), you can connect directly to the hosted MCP server instead of using the REST API. MCP provides the same data through a standardized tool-calling interface that works natively with Claude Desktop, Cursor, and other MCP-enabled clients. See the [MCP: Court Rules](/guides/mcp-court-rules) and [MCP: enforcement data](/guides/mcp-enforcement) guides for setup instructions. The REST API approach below works with any HTTP client or agent framework. ## Quick start: copy a prompt from the console The [console dashboard](https://console.courtrules.app/dashboard) has ready-to-paste prompts for v0, Bolt, Replit, Lovable, Claude Code, Cursor, and Windsurf. Select your tool, copy the prompt, and paste it. The prompt includes the API endpoint, example request bodies, and instructions for building a compliance checker UI. For local tools (Claude Code, Cursor, Windsurf), your API key is included automatically. ## Step 1: Download the OpenAPI spec The spec is available as a public endpoint (no authentication required): ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}} curl 'https://api.courtrules.app/openapi.json' -o openapi.json ``` The response is the OpenAPI 3.1 specification, with every endpoint, its request and response schemas, and examples. The API generates the spec from its route definitions, so it matches the running API. ## Step 2: Feed the spec to your agent Give the OpenAPI spec to your LLM as context. Most AI agent frameworks support this natively: * **Claude:** Attach the JSON file as context or paste it into the system prompt * **ChatGPT:** Upload the file or use the Actions/Functions feature * **LangChain / LlamaIndex:** Use their OpenAPI tool loader * **Custom agents:** Parse the spec and register each endpoint as a tool ## Step 3: Example agent prompt Here's a system prompt that turns an LLM into a court rules compliance assistant: ``` You are a federal court filing compliance assistant. You have access to the Court Rules API. When the user describes a document they plan to file, do the following: 1. Ask for the judge name (or slug), district, document type, and motion type if not provided. 2. Call GET /api/v1/rules to show the user what rules apply BEFORE they finalize their document. 3. Once they have page count and word count, call POST /api/v1/check to run the compliance check. 4. Explain each result in plain English. For FAIL results, state exactly what needs to change and cite the rule source. 5. For ACTION_REQUIRED items, explain what the filer needs to do (e.g., prepare courtesy copies, complete a pre-motion conference). Always cite the rule source (e.g., "FRCP 10(a)", "EDNY LR 7.1(c)", "Amon SO") when explaining a result. If the user provides a PDF instead of metadata, call POST /api/v1/classify with the base64-encoded PDF to analyze it. The response includes a check_request with extracted metadata. Add the filing context fields (is_pro_se, pmc_completed, opposing_party_pro_se, filing_role) before sending the merged body to POST /api/v1/check. ``` ## Agent workflow ```mermaid theme={"theme":{"light":"github-light","dark":"github-dark"}} sequenceDiagram participant User participant Agent as AI Agent participant API as Court Rules API User->>Agent: Filing SJ motion with Judge Brown, 22pp Agent->>API: GET /rules (judge, motion context) API-->>Agent: Rules by layer Agent->>API: POST /check (page_count, word_count) API-->>Agent: NON_COMPLIANT (22pp > 20pp limit) Agent->>User: Exceeds Brown's 20-page limit. Cut 2 pages. User->>Agent: What about Judge Amon? Agent->>API: POST /check (same doc, different judge) API-->>Agent: REVIEW (action items only) Agent->>User: No page limit issue. Courtesy copy required. ``` ## Enforcement data in agent workflows AI agents can monitor enforcement actions, answer regulatory questions, and trigger compliance reviews using the enforcement tools available through MCP. ### Example: regulatory monitoring agent ``` System prompt: You are a regulatory monitoring assistant for an in-house legal team. When asked about enforcement actions, use the MCP tools: 1. Call search_privacy_enforcement_actions to find relevant events 2. For high-risk events, call get_privacy_enforcement_action for full context 3. Highlight: what law was violated, what the remedy requires, and what contract clauses the team should review (using search_terms) ``` ### Example agent conversation ``` User: "What enforcement actions involved children's data this year?" Agent calls: search_privacy_enforcement_actions({ violation_type: "children_data", date_from: "2026-01-01" }) Agent responds: "Two major actions in 2026: Epic Games paid $275M for COPPA violations involving Fortnite (dark patterns + children's data collection without consent), and Jam City settled for $1.4M over selling minors' data without opt-in consent. Both cases flag these contract terms to review: COPPA compliance, parental consent mechanisms, age verification." ``` For the full list of enforcement tools and their parameters, see the [MCP: enforcement data](/guides/mcp-enforcement) guide. *** ## Tips for agent builders ### Use [`/rules`](/api-reference/rules) for context Before running a compliance check, call [`/rules`](/api-reference/rules) to give your agent and the user the rules that apply, so the agent's explanations can cite them: ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}} # Get all rules for a judge + document context curl 'https://api.courtrules.app/api/v1/rules?judge_slug=carol-bagley-amon&district_id=edny&document_scope=brief_support&motion_type=Rule_56' \ -H "Authorization: Bearer YOUR_API_KEY" ``` ### Use [`/check`](/api-reference/check) for validation The [`/check`](/api-reference/check) endpoint is deterministic, so the same input always gives the same result and your agent can call it again each time the user changes the document. Each call counts against your rate limits: ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}} # Check compliance (fast, deterministic, idempotent) curl -X POST https://api.courtrules.app/api/v1/check \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "judge_slug": "carol-bagley-amon", "district_id": "edny", "document_scope": "brief_support", "motion_type": "Rule_56", "is_pro_se": false, "pmc_completed": false, "opposing_party_pro_se": false, "filing_role": "movant", "document": { "page_count": 25, "word_count": 7200 } }' ``` ### Use [`/classify`](/api-reference/classify) for PDF analysis If the user uploads a PDF, use [`/classify`](/api-reference/classify) to extract metadata and classify it before checking: ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}} # Classify a PDF (10 to 30 seconds) PDF_B64=$(base64 -i motion_for_sj.pdf) curl -X POST https://api.courtrules.app/api/v1/classify \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d "{ \"judge_slug\": \"carol-bagley-amon\", \"district_id\": \"edny\", \"pdf_base64\": \"$PDF_B64\" }" ``` The response includes a `check_request` field with extracted document metadata. Before sending to [`/check`](/api-reference/check), merge in the filing context fields that only the filer knows: `is_pro_se`, `pmc_completed`, `opposing_party_pro_se`, and `filing_role`. ### Use [`/courts`](/api-reference/courts) for discovery Let the agent browse available courts and judges: ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}} # List all courts curl 'https://api.courtrules.app/api/v1/courts' \ -H "Authorization: Bearer YOUR_API_KEY" # List judges in a district curl 'https://api.courtrules.app/api/v1/judges?district_id=edny' \ -H "Authorization: Bearer YOUR_API_KEY" ``` ## Example conversation flow ``` User: I'm filing a summary judgment motion with Judge Brown in EDNY. My brief is 22 pages and about 7,200 words. Agent: Let me check that against Judge Brown's requirements. [calls POST /check with page_count=22, word_count=7200] Your filing is NON-COMPLIANT. Here's what I found: FAIL: 22 pages exceeds Judge Brown's 20-page limit (Source: Brown SO section 2.B) You need to cut 2 pages. Judge Brown's standing order limits support briefs to 20 pages. Also note: - Courtesy copies are always required (Brown SO section 1) - Motion papers must NOT be filed until fully briefed (Brown SO section 3.B) User: What if I was filing with Judge Amon instead? Agent: [calls POST /check with judge_slug=carol-bagley-amon] With Judge Amon, the same document gets a different result: no page limit violation. The 22 pages are within Amon's 25-page limit (the EDNY district default). However, you'd still need: - Courtesy copies: tabbed binder, double-sided (Amon SO) - Wait for full briefing before filing (Amon SO) ``` ## Framework-specific examples ### Claude tool use ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} { "name": "check_court_compliance", "description": "Check a legal document for compliance with federal court rules", "input_schema": { "type": "object", "properties": { "judge_slug": { "type": "string" }, "district_id": { "type": "string" }, "document_scope": { "type": "string" }, "motion_type": { "type": "string" }, "page_count": { "type": "integer" }, "word_count": { "type": "integer" } }, "required": ["judge_slug", "district_id", "document_scope", "page_count", "word_count"] } } ``` ### OpenAI function calling ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} { "type": "function", "function": { "name": "check_court_compliance", "description": "Check a legal document for compliance with federal court rules", "parameters": { "type": "object", "properties": { "judge_slug": { "type": "string", "description": "Judge identifier slug" }, "district_id": { "type": "string", "description": "Federal district ID" }, "document_scope": { "type": "string", "enum": ["brief_support", "brief_reply", "brief_opposition", "letter", "discovery_letter"] }, "motion_type": { "type": "string", "enum": ["Rule_12", "Rule_56", "Rule_50", "Rule_59", "discovery", "general"] }, "page_count": { "type": "integer" }, "word_count": { "type": "integer" } }, "required": ["judge_slug", "district_id", "document_scope", "page_count", "word_count"] } } } ``` ## Further reading * [MCP: Court Rules](/guides/mcp-court-rules): Court rules tools for filing compliance via MCP * [MCP: enforcement data](/guides/mcp-enforcement): Enforcement tools for regulatory monitoring via MCP * [Integration patterns](/guides/integration-patterns): Five patterns including enforcement monitoring * [Enforcement data](/concepts/enforcement-data): Data coverage, violation types, jurisdictions, and field reference * [Deadline Calculation in Federal Court is Harder Than You Think](https://courtrules.app/blog/building-deadline-calculator-court-rules-api): A developer walkthrough for building deadline calculation on top of the Court Rules API # Integration patterns Source: https://docs.courtrules.app/guides/integration-patterns How to integrate court rules and enforcement data into your application Court Rules fits into a product in several ways, from a quick pre-flight check while a user drafts to a monitor that watches for new enforcement events. The sections below describe each pattern, and the table at the end helps you choose one. ## Overview ```mermaid theme={"theme":{"light":"github-light","dark":"github-dark"}} flowchart LR subgraph input["What you have"] counts["Page + word count"] parsed["Parsed document"] display["Judge + doc type"] raw["PDF file"] schedule["Monitoring schedule"] end subgraph api["API / MCP"] p1["POST /check
pre-flight"] p2["POST /check
full compliance"] p3["GET /rules
show requirements"] p4["POST /classify
then POST /check"] p5["search_privacy_enforcement_actions
via MCP"] end counts --> p1 parsed --> p2 display --> p3 raw --> p4 schedule --> p5 ``` *** ## Pattern 1: Pre-flight check Call [`/check`](/api-reference/check) with just `page_count` and `word_count` while the user is still drafting. The check then catches the most common compliance failures (page and word limits, PMC requirements, filing gates) with minimal input. ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}} curl -X POST https://api.courtrules.app/api/v1/check \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "judge_slug": "frederic-block", "district_id": "edny", "document_scope": "brief_support", "motion_type": "Rule_56", "is_pro_se": false, "pmc_completed": false, "opposing_party_pro_se": false, "filing_role": "movant", "document": { "page_count": 28, "word_count": 8500 } }' ``` **When to use:** During drafting, on document save, or before the user starts formatting. It needs only two fields and catches the failures that waste the most time. **What you get:** Page limit, word limit, courtesy copy, PMC, filing gate, and bundling checks. **What you miss:** Structural checks (caption, signature, sections), formatting checks (font, margins), and privacy checks. The document must be parsed for those checks. *** ## Pattern 2: Full compliance check After your application parses the document (e.g., extracting caption fields, checking for a table of contents, measuring font sizes), send the full document structure to [`/check`](/api-reference/check). ```python theme={"theme":{"light":"github-light","dark":"github-dark"}} import requests result = requests.post( "https://api.courtrules.app/api/v1/check", headers={"Authorization": "Bearer YOUR_API_KEY"}, json={ "judge_slug": "gary-r-brown", "district_id": "edny", "document_scope": "brief_support", "motion_type": "Rule_56", "is_pro_se": False, "pmc_completed": True, "opposing_party_pro_se": False, "filing_role": "movant", "document": { "page_count": 18, "word_count": 7200, "caption": { "present": True, "has_court_name": True, "has_case_title": True, "has_docket_number": True, "has_document_designation": True, }, "signature_block": { "present": True, "has_attorney_name": True, "has_firm_name": True, "has_address": True, "has_email": True, "has_phone": True, "is_electronic_signature": True, }, "sections": { "has_toc": True, "has_toa": True, "has_certificate_of_compliance": True, "certificate_word_count": 7200, "has_certificate_of_service": True, "has_numbered_paragraphs": True, "has_56_1_statement": True, "has_56_1_counterstatement": False, "has_proposed_amended_pleading": False, "has_verbatim_discovery_text": False, "has_conferral_certification": False, "has_notice_of_motion": True, "has_memorandum_of_law": True, "has_supporting_affidavits": True, "has_pro_se_sj_notice": False, }, "format": { "primary_font_size_pt": 12, "footnote_font_size_pt": 10, "margin_inches": 1.0, "line_spacing": "double", }, "privacy": { "contains_full_ssn": False, "contains_full_dob": False, "contains_minor_full_name": False, "contains_full_financial_account": False, }, }, }, ).json() # Show results to user for r in result["results"]: icon = {"FAIL": "X", "PASS": "OK", "ACTION_REQUIRED": "!"}[r["status"]] print(f"[{icon}] {r['message']} ({r['source']})") ``` **When to use:** Before filing, after the document is finalized. The call runs every available check. **What you get:** All checks: limits, formatting, structure, privacy, consistency, and judge-specific standing order rules. *** ## Pattern 3: Rules lookup Call [`/rules`](/api-reference/rules) to display applicable rules proactively, before the user even starts drafting. Show them the requirements for their judge and motion type up front. ```typescript theme={"theme":{"light":"github-light","dark":"github-dark"}} const resp = await fetch( "https://api.courtrules.app/api/v1/rules?" + new URLSearchParams({ judge_slug: "carol-bagley-amon", district_id: "edny", document_scope: "brief_support", motion_type: "Rule_56", }), { headers: { Authorization: "Bearer YOUR_API_KEY" } }, ); const { rules } = await resp.json(); // Display standing order highlights if (rules.standing_order) { console.log("Judge-specific requirements:"); for (const rule of rules.standing_order) { console.log(` - ${rule.summary} (${rule.source})`); } } ``` **When to use:** When the user selects a judge or starts a new filing. Show them the rules before they draft, not after. **What you get:** The complete rule set organized by authority layer (FRCP, Local Rules, Standing Order), filtered to the relevant document type and motion. *** ## Pattern 4: Classify, then check Upload a PDF to [`/classify`](/api-reference/classify), which extracts metadata and classifies the document automatically. The response includes a `check_request` with the extracted document metadata. Before sending to [`/check`](/api-reference/check), add the filing context fields that only the filer knows. **Important:** `page_count` in the `/classify` response is **body pages**, not total PDF pages. Front matter (cover page, table of contents, table of authorities) and back matter (certificate of service, signature pages) are automatically excluded, which is how courts count pages for limits. ```python theme={"theme":{"light":"github-light","dark":"github-dark"}} import base64 from pathlib import Path import requests headers = {"Authorization": "Bearer YOUR_API_KEY"} # Step 1: Classify the PDF pdf_b64 = base64.b64encode(Path("motion_sj_support.pdf").read_bytes()).decode() classify_resp = requests.post( "https://api.courtrules.app/api/v1/classify", headers=headers, json={ "judge_slug": "gary-r-brown", "district_id": "edny", "pdf_base64": pdf_b64, "filename": "motion_sj_support.pdf", }, ).json() print(f"Detected: {classify_resp['classification']['document_scope']}") print(f"Confidence: {classify_resp['classification']['confidence']}") # Step 2: Add filing context, then check compliance check_body = { **classify_resp["check_request"], "is_pro_se": False, "pmc_completed": True, "opposing_party_pro_se": False, "filing_role": "movant", } check_resp = requests.post( "https://api.courtrules.app/api/v1/check", headers=headers, json=check_body, ).json() print(f"Status: {check_resp['summary']['status']}") ``` **When to use:** When you have a PDF but haven't built your own document parser. The [`/classify`](/api-reference/classify) endpoint handles the analysis and produces a ready-to-use [`/check`](/api-reference/check) request. **Latency note:** `/classify` takes 10 to 30 seconds because a model reads the PDF, while `/check` applies fixed rules and uses no model. Plan your UX accordingly: show a loading state for classification, then show the check results when they arrive. *** ## Pattern 5: Enforcement monitoring Monitor privacy enforcement actions and trigger compliance reviews when relevant events appear. **Input needed:** Jurisdiction filters, industry, date range **What you call:** `search_privacy_enforcement_actions` via MCP, polled once a day **Use during:** Ongoing compliance monitoring ```mermaid theme={"theme":{"light":"github-light","dark":"github-dark"}} flowchart LR schedule["Scheduled poll"] --> search["search_privacy_enforcement_actions\ndate_from: last_check"] search --> filter["Filter by industry\nand risk_level"] filter --> details["get_privacy_enforcement_action\nfor high-risk events"] details --> action["Create matter\nAssign reviewer\nFlag contracts"] ``` When a new enforcement event matches your criteria, call `get_privacy_enforcement_action` to get the full context including `search_terms` (contract clauses to review) and `contract_impact` (what to check in vendor agreements). For the full enforcement tool reference and parameters, see the [MCP: enforcement data](/guides/mcp-enforcement) guide. *** ## Choosing a pattern | Pattern | Input needed | Coverage | | - | - | - | | Pre-flight | page\_count + word\_count | Limits and standing order checks | | Full compliance | Parsed document structure | All checks | | Rules lookup | Judge + document type | Rule display, with no pass or fail | | Classify, then check | PDF file (base64) | All checks, from the PDF's content | | Enforcement monitoring | Jurisdiction + industry | Enforcement events through MCP | Most integrations use pattern 1 during drafting and pattern 2 before filing. Pattern 3 is for proactive UIs. Pattern 4 is for applications that accept PDF uploads and don't have their own document parser. Pattern 5 runs alongside the court rules patterns for teams that also need regulatory monitoring. # MCP: Court Rules Source: https://docs.courtrules.app/guides/mcp-court-rules Connect AI agents to judge-specific filing rules and compliance checks using the Model Context Protocol. # MCP: Court Rules The Court Rules MCP server gives AI agents access to structured filing rules for federal and state courts and their judges. Six tools let you list courts, search judges, retrieve rules, search filing requirements, look up court holidays, and check a draft filing against a judge's rules. [Coverage](/concepts/coverage-levels) explains which courts and judges are covered. ## What you get Six court rules tools: | Tool | Purpose | | - | - | | `list_courts` | Page through courts with active judge counts, or find one by name | | `search_judges` | Search judges by district, name, or type | | `get_judge_rules` | Get all rules for a specific judge (page limits, format, procedures) | | `search_filing_rules` | Search filing requirements: e-filing, service, timing, fees, courtesy copies | | `list_court_holidays` | List court holidays and closure dates with official source URLs | | `check_filing_against_judge_rules` | Check a draft filing against a judge's rules before it is filed | > [!NOTE] > > The same MCP server also provides three enforcement data tools for monitoring privacy enforcement > actions from the FTC and state attorneys general. See [MCP: Enforcement > Data](/guides/mcp-enforcement). ## Quick start Add the server to your AI client, then sign in when the client asks. It opens [console.courtrules.app](https://console.courtrules.app) in your browser, you sign in and approve the connection once, and the client keeps you signed in after that. ### Claude Code ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}} claude mcp add --transport http court-rules https://mcp.courtrules.app/mcp ``` Then run `/mcp` in Claude Code, select `court-rules`, and choose **Authenticate**. ### Claude Desktop and claude.ai Open **Settings > Connectors > Add custom connector**. Enter `Court Rules` as the name and `https://mcp.courtrules.app/mcp` as the URL, click **Add**, then click **Connect** and sign in. ### Cursor Add to `~/.cursor/mcp.json`, then open **Cursor Settings > MCP** and click the sign-in prompt next to `court-rules`: ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} { "mcpServers": { "court-rules": { "url": "https://mcp.courtrules.app/mcp" } } } ``` ### VS Code Add to `.vscode/mcp.json`. VS Code asks you to sign in the first time it starts the server. ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} { "servers": { "court-rules": { "type": "http", "url": "https://mcp.courtrules.app/mcp" } } } ``` ### Codex CLI ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}} codex mcp add court-rules --url https://mcp.courtrules.app/mcp codex mcp login court-rules ``` ### Scripts, backends, and clients without sign-in Send the API key from your [console](https://console.courtrules.app) dashboard as `Authorization: Bearer `. Keys do not expire. See [Authentication](/authentication#mcp-authentication) for header configs and an SDK example. Once connected, try asking your agent: *"What are Judge Beaudet's courtesy copy rules at LA Superior Court?"* ## Tool reference ### list\_courts List courts with their judge counts. The list is long, so results come in pages: pass `query` to find a court, and pass `next_offset` back as `offset` to read the next page. `judge_count` counts judges currently sitting on the court. **Parameters:** | Parameter | Type | Description | | - | - | - | | `query` | string | Optional. Case-insensitive match on court name or ID (e.g., "alaska", "edny") | | `limit` | number | Courts per page. Default 100, max 500 | | `offset` | number | Courts to skip. Pass `next_offset` from the previous page. Default 0 | **Example request:** `{ "query": "district of new york", "limit": 3 }` **Example response:** ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} { "courts": [ { "district_id": "edny", "name": "Eastern District of New York", "judge_count": 47 }, { "district_id": "ndny", "name": "Northern District of New York", "judge_count": 3 }, { "district_id": "sdny", "name": "Southern District of New York", "judge_count": 67 } ], "total": 12, "limit": 3, "offset": 0, "next_offset": 3 } ``` `next_offset` is `null` on the last page. ### search\_judges Search for judges by district, name, or type. **Parameters:** | Parameter | Type | Description | | - | - | - | | `district_id` | string | District identifier (e.g., "ca-los-angeles-superior", "edny") | | `name` | string | Partial name match | | `judge_type` | string | "district", "senior", "magistrate", "chief\_district", etc. | | `limit` | number | Max results (default 20, max 500) | **Example request:** `{"district_id": "ca-los-angeles-superior", "name": "beaudet"}` **Example response:** ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} [ { "judge_slug": "judge-teresa-a-beaudet", "judge_name": "Judge Teresa A. Beaudet", "judge_type": "district", "district_id": "ca-los-angeles-superior", "status": "active" } ] ``` ### get\_judge\_rules Get all extracted rules for a specific judge. **Parameters:** | Parameter | Type | Required | Description | | - | - | - | - | | `judge_slug` | string | Yes | Judge identifier from search\_judges (e.g., "judge-teresa-a-beaudet") | | `district_id` | string | Yes | District identifier (e.g., "ca-los-angeles-superior") | **Example request:** `{"judge_slug": "judge-teresa-a-beaudet", "district_id": "ca-los-angeles-superior"}` **Example response:** ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} [ { "rule_id": "0067714a-7bfd-4642-86cf-4e2d9190b15d", "content": { "summary": "Motions in limine must comply with L.A. Superior Court Rule 3.57 and Kelly v. New West Federal Savings.", "rule_tags": ["document_requirement", "motion_in_limine"], "source_text": "Motions in limine must comply with L.A. Superior Court Rule 3.57 and Kelly v. New West Federal Savings, 49 Cal.App.4th 659, 670-71 (1996).", "workflow_phase": "TRIAL_PREP", "citation_source": { "page": 4, "section": "All Motions" }, "structured_data": { "logic_type": "DocumentRequirement", "document_type": "motion_in_limine", "specific_language": "Must comply with L.A. Superior Court Rule 3.57 and Kelly v. New West Federal Savings, 49 Cal.App.4th 659, 670-71 (1996)." }, "visual_severity": "CRITICAL", "case_type_applicability": ["civil"] }, "doc_kind": "individual_rules", "document_date": null, "source_url": "https://www.lacourt.ca.gov/web3/courthouse/api/courthouses/courtroom-information/courthouse/LAM/courtrooms/508/documents" }, { "rule_id": "0135e5a3-4c3d-4feb-bc55-5bb44aa36981", "content": { "summary": "Courtesy conformed copies of filings with points and authorities or exceeding 15 pages must be lodged in Dept. 508 on the filing date (next business day if efiled on a holiday or weekend).", "rule_tags": ["courtesy_copy"], "source_text": "Courtesy conformed copies of any filings with a points and authorities or that exceed 15 pages must be lodged in Dept. 508 on the date of filing or, if the filing is efiled on a holiday or weekend, on the next business day.", "workflow_phase": "MOTION_PRACTICE", "citation_source": { "page": 3 }, "structured_data": { "trigger": { "type": "page_threshold", "value": 15, "operator": ">" }, "exemptions": { "description": "If the filing is efiled on a holiday or weekend, courtesy copies must be lodged on the next business day. Filings with points and authorities also require courtesy copies regardless of length." }, "logic_type": "CourtesyCopyRule", "requirement": { "delivery_method": "chambers_drop_off", "delivery_timing": "upon_filing" } }, "visual_severity": "CRITICAL", "case_type_applicability": ["civil"] }, "doc_kind": "individual_rules", "document_date": null, "source_url": "https://www.lacourt.ca.gov/web3/courthouse/api/courthouses/courtroom-information/courthouse/LAM/courtrooms/508/documents" } ] ``` ### search\_filing\_rules Search extracted filing rules across active source documents. Use this for e-filing requirements, service and proof of service, filing timing, fees, courtesy copies, rejection and cure windows, and courtroom preferences. Unlike `get_judge_rules`, which returns everything for one judge, this searches across courts and judges by keyword and rule type. **Parameters:** | Parameter | Type | Required | Description | | - | - | - | - | | `q` | string | No | Search terms matched against summary, source text, tags, and structured data | | `district_id` | string | No | Court identifier (e.g., "il-cook-circuit", "ca-los-angeles-superior") | | `judge_slug` | string | No | Judge, calendar, department, or courtroom slug. Use `"court"` for court-level rules | | `logic_type` | string | No | Rule type, e.g. `ElectronicFilingRule`, `FilingTimingRule`, `ServiceRule`, `FilingFeeRule` | | `workflow_phase` | string | No | One of `FILING`, `CASE_INITIATION`, `MOTION_PRACTICE`, `TRIAL_PREP`, `POST_JUDGMENT` | | `case_type` | string | No | Filter by case type. General rules and rules without a case-type limit are always included | | `include_court_rules` | boolean | No | When `judge_slug` is set, also include court-level rules. Default `true` | | `include_raw_content` | boolean | No | Include the full validated rule object. Default `false` | | `limit` | number | No | Max results (default 100, max 500) | **Example response:** ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} { "rules": [ { "rule_id": "8f2c1a4e-...", "district_id": "edny", "judge_slug": "court", "logic_type": "ElectronicFilingRule", "summary": "All documents must be filed electronically through ECF unless the filer is pro se", "citation": "Local Civil Rule 5.2", "source_text": "Except as otherwise provided, all documents shall be filed electronically...", "provenance": { "source_url": "https://www.nyed.uscourts.gov/local-rules", "document_version_id": "3b91..." } } ], "meta": { "total": 1, "limit": 100, "include_court_rules": true } } ``` ### list\_court\_holidays List court holidays and closure dates. Returns the official source URL and the last time Court Rules checked that source, so you can show provenance alongside a deadline calculation. **Parameters:** | Parameter | Type | Required | Description | | - | - | - | - | | `district_id` | string | No | Court identifier (e.g., "edny") | | `year` | number | No | Calendar year (e.g., 2026) | | `date_from` | string | No | Start date filter (YYYY-MM-DD) | | `date_to` | string | No | End date filter (YYYY-MM-DD) | | `limit` | number | No | Max results (default 50, max 200) | **Example response:** ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} { "holidays": [ { "district_id": "edny", "calendar_year": 2026, "holiday_date": "2026-01-19", "holiday_name": "Birthday of Martin Luther King, Jr.", "source_url": "https://www.nyed.uscourts.gov/holiday-schedule", "last_checked_at": "2026-05-13T12:00:00.000Z" } ], "meta": { "total": 1, "limit": 50 } } ``` ### check\_filing\_against\_judge\_rules Check a draft filing against a judge's rules before it is filed. The assistant reads the draft, measures it (pages, words, which sections it has), and passes those measurements. Court Rules compares them with the judge's limits and requirements and returns a pass or fail for each rule, with the rule it comes from. The draft itself is never sent. Only the measurements are, so the check works in any client, including ones that cannot attach files to a tool call. **Coverage:** judges in the Eastern District of New York (`edny`). For another court, the tool returns an error that says so; read that court's rules with `get_judge_rules` instead. **Parameters:** | Parameter | Type | Required | Description | | - | - | - | - | | `judge_slug` | string | Yes | Judge identifier from search\_judges (e.g., "carol-bagley-amon") | | `district_id` | string | Yes | Court identifier (e.g., "edny") | | `document_scope` | string | Yes | Document type: `brief_support`, `brief_opposition`, `brief_reply`, `letter`, `proposed_findings`, ... | | `motion_type` | string | No | Rule the motion is under (e.g., `Rule_56`). Omit if the filing is not a motion | | `is_pro_se` | boolean | Yes | Whether the filer is self-represented | | `pmc_completed` | boolean | Yes | Whether a pre-motion conference was held or waived | | `opposing_party_pro_se` | boolean | Yes | Whether the opposing party is self-represented | | `filing_role` | string | Yes | `movant`, `opponent`, or `reply` | | `document` | object | Yes | Measurements of the draft. Only `page_count` and `word_count` are required | `document` also accepts `caption`, `signature_block`, `sections`, `format` and `privacy`, with the same fields as [`/api/v1/check`](/api-reference/check). A section left out is not guessed: its checks are skipped and named in `warnings`. **Example request:** a 5-page pre-motion letter to Judge Amon. ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} { "judge_slug": "carol-bagley-amon", "district_id": "edny", "document_scope": "letter", "is_pro_se": false, "pmc_completed": false, "opposing_party_pro_se": false, "filing_role": "movant", "document": { "page_count": 5, "word_count": 1400 } } ``` **Example response:** ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} { "judge": { "slug": "carol-bagley-amon", "name": "Carol Bagley Amon" }, "summary": { "status": "NON_COMPLIANT", "failures": 1, "warnings": 0, "passes": 1, "action_items": 0 }, "results": [ { "severity": "CRITICAL", "category": "PAGE_LIMIT", "message": "5pp exceeds 3pp limit", "source": "Amon SO §3.A", "status": "FAIL" }, { "severity": "INFO", "category": "COURTESY_COPY", "message": "5pp does not exceed 5pp threshold, no courtesy copy needed", "source": "Amon SO §1.D / §3.D.iii", "status": "PASS" } ], "meta": { "checks_run": 2, "checks_skipped": 11 }, "warnings": [ "The following document sections were not provided: caption, signature_block, sections, format, privacy. Related compliance checks were skipped." ] } ``` `summary.status` is `NON_COMPLIANT` when any rule fails, `REVIEW` when a rule needs an action from the filer (such as requesting a pre-motion conference), and `COMPLIANT` otherwise. The response matches [`/api/v1/check`](/api-reference/check) for the same input. **Common mistakes:** * **Counting every page.** `page_count` is body pages only. Leave out the cover, tables of contents and authorities, signature page and certificates. * **Filling sections that were not read.** A guessed `format` or `privacy` block produces a confident result about something nobody measured. Leave it out. ## Integration patterns ### Pre-filing requirements Show judge-specific rules while a document is drafted: ``` 1. search_judges (district_id, name) -> resolve the judge 2. get_judge_rules (judge_slug, district_id) -> show requirements during drafting 3. Link each requirement to its source document 4. check_filing_against_judge_rules (judge_slug, district_id, measurements) -> check the draft before it is filed ``` Call `get_judge_rules` early in the drafting process so users see requirements before they finish writing, then `check_filing_against_judge_rules` on the finished draft. From a backend without an assistant, call the REST API at [`/api/v1/check`](/api-reference/check) with the same input. ## Error handling MCP tool calls return errors as text content, not HTTP error codes. If a tool encounters an error (invalid parameters, database unavailable), the response will contain a descriptive error message in the `content` array: ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} { "content": [ { "type": "text", "text": "Error: No judge found with slug \"invalid-slug\" in district \"edny\"." } ] } ``` Common error patterns: * **Invalid judge\_slug**: `"No judge found with slug \"...\" in district \"...\"."` * **Invalid district\_id**: `"No court found with ID \"...\"."` * **Database error**: `"Error querying courts: ..."` or `"Error searching judges: ..."` ## Limits The hosted server at `mcp.courtrules.app` counts calls and rows for each signed-in user or API key, with the same limits as the REST API. [Rate limits](/api-reference/rate-limits) gives the numbers. When a tool call goes over a limit, it returns an error that names the limit and how long to wait, and the error tells the assistant to stop instead of retrying in a loop. One answer holds at most 500 rows on the free limits. A longer list is cut, and the answer says how many rows it held and how to narrow the query. ## Next steps * [REST API Quickstart](/quickstart) to run compliance checks directly via HTTP * [Coverage](/concepts/coverage-levels) to see which courts, judges and rulebooks are covered, and how the three rule layers (FRCP, Local Rules, Standing Orders) fit together * [MCP: enforcement data](/guides/mcp-enforcement) for privacy enforcement tools on the same MCP server # MCP: enforcement data Source: https://docs.courtrules.app/guides/mcp-enforcement Connect AI agents to structured privacy enforcement data from federal and state regulators using the Model Context Protocol. The Court Rules MCP server gives AI agents access to structured privacy enforcement events from federal and state regulators. Three tools let you search events, get full details and count events by group. ## What you get Three enforcement-focused tools: | Tool | Purpose | | - | - | | `search_privacy_enforcement_actions` | Search enforcement events by jurisdiction, date, industry, violation type | | `get_privacy_enforcement_action` | Full event details with laws cited, remedies, and source quotes | | `get_privacy_enforcement_stats` | Summary statistics by jurisdiction, violation type, or time period | The same MCP server also provides six court rules tools for filing compliance. See [MCP: Court Rules](/guides/mcp-court-rules). ## Quick start Add the server to your AI client, then sign in when the client asks. It opens [console.courtrules.app](https://console.courtrules.app) in your browser, you sign in and approve the connection once, and the client keeps you signed in after that. ### Claude Code ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}} claude mcp add --transport http court-rules https://mcp.courtrules.app/mcp ``` Then run `/mcp` in Claude Code, select `court-rules`, and choose **Authenticate**. ### Claude Desktop and claude.ai Open **Settings > Connectors > Add custom connector**. Enter `Court Rules` as the name and `https://mcp.courtrules.app/mcp` as the URL, click **Add**, then click **Connect** and sign in. ### Cursor Add to `~/.cursor/mcp.json`, then open **Cursor Settings > MCP** and click the sign-in prompt next to `court-rules`: ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} { "mcpServers": { "court-rules": { "url": "https://mcp.courtrules.app/mcp" } } } ``` ### VS Code Add to `.vscode/mcp.json`. VS Code asks you to sign in the first time it starts the server. ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} { "servers": { "court-rules": { "type": "http", "url": "https://mcp.courtrules.app/mcp" } } } ``` ### Codex CLI ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}} codex mcp add court-rules --url https://mcp.courtrules.app/mcp codex mcp login court-rules ``` ### Scripts, backends, and clients without sign-in Send the API key from your [console](https://console.courtrules.app) dashboard as `Authorization: Bearer `. Keys do not expire. See [Authentication](/authentication#mcp-authentication) for header configs and an SDK example. Once connected, try asking your agent: *"What privacy enforcement actions happened in California this year?"* ## Tool reference ### search\_privacy\_enforcement\_actions Search privacy and regulatory enforcement events. Filters combine with AND logic. **Parameters:** | Parameter | Type | Description | | - | - | - | | `jurisdiction` | string | Filter by jurisdiction: CA, FTC, NY, TX, HHS, CT, CO, OR, NJ, VA, MN, etc. | | `date_from` | string | Start date (YYYY-MM-DD) | | `date_to` | string | End date (YYYY-MM-DD) | | `industry` | string | Entity industry: technology, healthcare, gaming, education, financial\_services, etc. | | `violation_type` | string | Violation category: data\_breach, opt\_out\_failure, children\_data, security\_failure, etc. | | `entity_name` | string | Partial match on entity name | | `risk_level` | string | critical, high, medium, or low | | `limit` | number | Max results (default 20, max 100) | **Example request:** `{"jurisdiction": "CA", "limit": 1}` **Example response:** ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} { "results": [ { "id": "14875044-3259-4cce-95c2-7d7e97b18118", "slug": "ca-california-state-legislature-2026-08-28-60e39f", "title": "California Legislature Passes SB 923 (Expanding Privacy Rights Act) to Expand CCPA Deletion Rights", "event_date": "2026-08-28", "jurisdiction": "CA", "event_type": "new_law", "entity_name": "California State Legislature", "fine_amount": null, "violation_types": ["record_retention"], "risk_level": "low", "summary": "The California Privacy Protection Agency announced that the California State Legislature approved the Expanding Privacy Rights Act (SB 923), which expands the CCPA's right to delete to cover all non-exempt personal information a business...", "primary_source_url": "https://privacy.ca.gov/2026/08/california-legislature-advances-bill-to-strengthen-deletion-rights/", "public_url": "https://www.courtrules.app/enforcement/ca-california-state-legislature-2026-08-28-60e39f" } ], "total": 78 } ``` ### get\_privacy\_enforcement\_action Get full details for a specific enforcement event, including laws cited, remedies, and verbatim source quotes. **Parameters:** | Parameter | Type | Required | Description | | - | - | - | - | | `event_id` | string | Yes | Event UUID | **Example response:** ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} { "id": "evt_001", "title": "Attorney General Bonta Announces $2.75 Million CCPA Settlement with Disney", "event_date": "2026-02-11", "jurisdiction": "CA", "event_type": "settlement", "entity_name": "The Walt Disney Company", "entity_industry": "media_entertainment", "fine_amount": "$2,750,000", "consumers_affected": null, "violation_types": ["opt_out_failure"], "risk_level": "high", "summary": "California AG secured a $2.75M settlement after finding Disney's streaming platforms failed to honor consumer opt-out requests for the sale and sharing of personal information under CCPA.", "laws_cited": ["California Consumer Privacy Act (CCPA)", "California Privacy Rights Act (CPRA)"], "statute_sections": ["Cal. Civ. Code §1798.120"], "remedy_types": ["monetary_penalty", "injunction"], "remedy_summary": "Disney must pay $2.75 million in civil penalties and implement opt-out methods that fully stop the sale or sharing of consumers' personal information across all platforms and devices.", "document_urls": ["https://oag.ca.gov/system/files/attachments/press-docs/...pdf"], "primary_source_url": "https://oag.ca.gov/news/press-releases/...", "is_multistate": false, "co_enforcers": [], "search_terms": ["opt-out", "do not sell", "right to opt out", "GPC", "global privacy control"], "contract_impact": "Review vendor agreements for opt-out mechanism requirements.", "source_quotes": [], "sources": [ { "source_id": "src_001", "source_url": "https://oag.ca.gov/news/press-releases/...", "scraped_at": "2026-02-12T08:30:00Z" } ] } ``` ### get\_privacy\_enforcement\_stats Counts events and totals their fines by jurisdiction, violation type, risk level or month. **Parameters:** | Parameter | Type | Required | Description | | - | - | - | - | | `group_by` | string | Yes | "jurisdiction", "violation\_type", "risk\_level", or "month" | | `date_from` | string | No | Start date filter | | `date_to` | string | No | End date filter | **Example request:** `{"group_by": "jurisdiction"}` The numbers in this example are illustrative: ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} { "stats": [ { "group": "CT", "count": 12, "total_fines": "$4,250,000" }, { "group": "NJ", "count": 9, "total_fines": "$1,100,000" }, { "group": "TX", "count": 7, "total_fines": "$2,300,000" } ], "total_events": 28 } ``` ## Integration patterns ### Regulatory feed widget Use `search_privacy_enforcement_actions` with jurisdiction and industry filters to surface relevant enforcement events in your legal workspace. Poll periodically for new events. ``` Agent prompt: "Search for new enforcement actions in [jurisdiction] since [last_check_date] relevant to [industry]" -> Calls: search_privacy_enforcement_actions -> Returns: New events with structured data -> Your platform: Creates feed items or notifications ``` ### Auto-matter creation When a relevant enforcement event appears, automatically create a matter in your legal workspace: ``` 1. search_privacy_enforcement_actions (filtered by jurisdiction + industry) 2. For each new event: get_privacy_enforcement_action 3. Map fields to your matter schema: - Matter title <- event title - Assigned team <- based on jurisdiction - Priority <- risk_level mapping - Description <- summary + laws_cited - Attachments <- document_urls ``` ### Agent-powered research Combine tools for research queries: ``` "Which companies in the technology industry were fined for data breaches in the last 6 months, and what remedies were required?" Agent calls: 1. search_privacy_enforcement_actions(industry: "technology", violation_type: "data_breach", date_from: "2025-09-25") 2. For each result: get_privacy_enforcement_action(event_id) 3. Synthesizes: entity names, fine amounts, remedy details, with source citations ``` ### Polling for new events The MCP server does not push notifications when new enforcement events are added. To check for new events, poll `search_privacy_enforcement_actions` with a `date_from` filter set to your last check time: ``` Tool: search_privacy_enforcement_actions Arguments: { "date_from": "2026-03-20", "limit": 50 } ``` For platform integrations that auto-create matters, run this once a day and process any new events. No source is checked more often than daily, so a faster poll finds nothing new. ## Response field reference Key fields in enforcement event responses, with types and null semantics: | Field | Type | Description | | - | - | - | | `fine_amount` | string or null | Formatted currency (e.g., "\$2,750,000"). Null when no monetary penalty was imposed (consent decree or injunction only) | | `consumers_affected` | number or null | Null when the count was not quantified in the official source | | `entity_industry` | string or null | Industry classification (e.g., "gaming", "education", "social\_media") | | `violation_types` | string\[] | One or more violation categories from a fixed set of 18 types | | `risk_level` | string | One of: "critical", "high", "medium", "low" | | `laws_cited` | string\[] | Full names of laws referenced (e.g., "California Consumer Privacy Act (CCPA)") | | `statute_sections` | string\[] | Specific statutory references (e.g., "Cal. Civ. Code §1798.120") | | `remedy_types` | string\[] | Categories of remedies imposed (e.g., "monetary\_penalty", "injunction") | | `search_terms` | string\[] | Contract-relevant keywords for vendor agreement scanning | | `contract_impact` | string or null | What to check in your contracts based on this enforcement action | | `source_quotes` | array | Verbatim quotes from the official source (may be empty) | | `co_enforcers` | string\[] | Other agencies involved in multistate actions (empty if single-state) | | `is_multistate` | boolean | Whether the action involved multiple jurisdictions | ## Error handling MCP tool calls return errors as text content, not HTTP error codes. If a tool encounters an error (invalid parameters, database unavailable), the response will contain a descriptive error message in the `content` array: ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} { "content": [ { "type": "text", "text": "Error: No enforcement event found with ID \"invalid-id\"." } ] } ``` Common error patterns: * **Invalid event\_id**: `"No enforcement event found with ID \"...\"."` * **Invalid group\_by or risk\_level**: the server rejects a value outside the listed choices before the tool runs. `group_by` takes `jurisdiction`, `violation_type`, `risk_level` or `month`; `risk_level` takes `critical`, `high`, `medium` or `low` * **Temporary error**: `"Error querying enforcement data: ..."`. Retry the call The hosted server at `mcp.courtrules.app` counts calls and rows for each signed-in user or API key, with the same limits as the REST API. See [Rate limits](/api-reference/rate-limits). A call that goes over a limit returns an error that names the limit and how long to wait, and one answer holds at most 500 rows on the free limits. ## Current limitations * **No webhooks**: Poll for new events using `date_from` filters * **No real-time streaming**: The data is updated daily, so a new event appears after the next daily check. See [Enforcement data](/concepts/enforcement-data#data-freshness) * **Read-only**: The MCP server provides data access only, no write operations For higher throughput or custom filtering, use the [REST API](/api-reference/overview) directly. ## Next steps * [Browse enforcement data](https://www.courtrules.app/enforcement) to see the events * [Try the MCP playground](https://www.courtrules.app/mcp) to test tools interactively * [MCP: Court Rules](/guides/mcp-court-rules) for filing compliance tools on the same MCP server # Read a court's rules Source: https://docs.courtrules.app/guides/read-court-rules Find a court and a judge, then read their filing rules with the court's own wording and a link to the document Every court with `status: live` serves its rules through the same three calls. First, find the court. Second, find the judge. Third, read the rules. Each rule comes back with the court's own sentence, a plain-English summary, structured fields and the address of the document it came from. The example reads the courtesy copy rule of one judge at the Superior Court of California, County of Los Angeles, and the same calls work for any other live court. All requests need a Bearer token, which [Authentication](/authentication) explains. Compliance checks are separate and run for the Eastern District of New York only, as the [Quickstart](/quickstart) shows. ## 1. Find the court A court is identified by its `district_id`. Federal district courts use short codes such as `edny`, and state courts start with the state's two-letter code, such as `ca-los-angeles-superior` or `il-cook-circuit`. To find the id of a court, list the courts once and search the names: ```bash cURL theme={"theme":{"light":"github-light","dark":"github-dark"}} curl 'https://api.courtrules.app/api/v1/courts' \ -H "Authorization: Bearer YOUR_API_KEY" ``` ```python Python theme={"theme":{"light":"github-light","dark":"github-dark"}} import requests headers = {"Authorization": "Bearer YOUR_API_KEY"} resp = requests.get("https://api.courtrules.app/api/v1/courts", headers=headers) courts = resp.json()["courts"] for court in courts: if "Los Angeles" in court["name"] and court["status"] == "live": print(court["district_id"], court["name"]) ``` Each court in the list counts as one row against your daily row limit, so keep the list instead of reading it again. Once you know the id, read one court with `GET /api/v1/courts/{district_id}`. The counts in the samples on this page change as rosters change. ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} { "district_id": "ca-los-angeles-superior", "name": "Superior Court of California, County of Los Angeles", "circuit": null, "state": "California", "status": "live", "judges_mapped": 116 } ``` A `live` court has rules. A `coming_soon` court is mapped but has none yet. [Coverage](/concepts/coverage-levels) explains how to check how deeply a live court is covered. ## 2. Find the judge ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}} curl 'https://api.courtrules.app/api/v1/judges?district_id=ca-los-angeles-superior' \ -H "Authorization: Bearer YOUR_API_KEY" ``` The response lists the court's current roster, shortened here to a single judge. ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} { "district_id": "ca-los-angeles-superior", "judges": [ { "slug": "judge-teresa-a-beaudet", "name": "Judge Teresa A. Beaudet", "has_profile": false, "has_rules": true, "status": "active", "judge_type": "district", "bio": null, "chambers": null, "profile_url": null } ], "meta": { "total": 116, "profiled": 0, "with_rules": 113, "court_level_rules": true } } ``` Use the `slug` of a judge whose `has_rules` is `true`. A roster entry without rules of its own still has the court-wide rules. In some state courts the roster lists departments or courtrooms instead of people, and their slugs work the same way. ## 3. Read the rules Send the court, the judge and, to narrow the answer, a rule type. The [list of rule types](/concepts/coverage-levels#rule-types) names all of them. ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}} curl 'https://api.courtrules.app/api/v1/extracted-rules?district_id=ca-los-angeles-superior&judge_slug=judge-teresa-a-beaudet&logic_type=CourtesyCopyRule' \ -H "Authorization: Bearer YOUR_API_KEY" ``` The response holds the rules that match. Because `include_court_rules` defaults to `true`, it can also hold court-wide rules of the same type. The example keeps only the judge's own rule and shortens its fields. ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} { "rules": [ { "rule_id": "0135e5a3-4c3d-4feb-bc55-5bb44aa36981", "district_id": "ca-los-angeles-superior", "judge_slug": "judge-teresa-a-beaudet", "source_url": "https://www.lacourt.ca.gov/web3/courthouse/api/courthouses/courtroom-information/courthouse/LAM/courtrooms/508/documents", "logic_type": "CourtesyCopyRule", "content": { "summary": "Courtesy conformed copies of filings with points and authorities or exceeding 15 pages must be lodged in Dept. 508 on the filing date (next business day if efiled on a holiday or weekend).", "source_text": "Courtesy conformed copies of any filings with a points and authorities or that exceed 15 pages must be lodged in Dept. 508 on the date of filing or, if the filing is efiled on a holiday or weekend, on the next business day.", "structured_data": { "logic_type": "CourtesyCopyRule", "trigger": { "type": "page_threshold", "value": 15, "operator": ">" }, "requirement": { "delivery_method": "chambers_drop_off", "delivery_timing": "upon_filing" } }, "citation_source": { "page": 3 } } } ] } ``` Each part of a rule has a use: * **`content.source_text`:** the court's own sentence. Show it to filers. * **`content.summary`:** a plain-English summary of the sentence. * **`content.structured_data`:** the rule as fields, so software can act on it. The fields depend on `logic_type`. Here the trigger is a document longer than 15 pages, and the requirement is a drop-off at chambers on the filing date. * **`content.citation_source`:** the page, section, paragraph or sentence of the document, when the document has them. * **`source_url`:** the official address the rule was read from. * **`judge_slug`:** whose rule it is. A court-wide rule has the slug `court`. To read every rule of the judge, leave out `logic_type` and page through the results with `limit` and `offset`, as [Search extracted rules](/api-reference/extracted-rules#paging) shows. ## Behavior details * **Court-wide rules come with the judge's rules.** Send `judge_slug=court` to read only the court-wide rules, or `include_court_rules=false` to leave them out. * **The API does not pick a winner.** A judge's rule can add to or differ from a court-wide rule. The API returns both and does not work out which one governs a filing. * **One call returns everything.** [`GET /api/v1/rules`](/api-reference/rules) returns a judge's whole rule set, grouped as court-wide and judge rules. The court-wide layer comes back in full, which can be over a thousand rules in a large court, so page with `/extracted-rules` when you need only part of it. * **Rows add up.** Each rule in a list counts as one row against your daily row limit. See [Rate limits](/api-reference/rate-limits). ## Common mistakes * **Showing the summary without the quote.** The summary is a plain-English reading of the rule. Show the court's sentence and the link with it, so a filer can check the wording. * **Reading an empty list as "no requirement".** An empty list means the API holds no matching rule. It does not mean the court has none. * **Assuming every roster entry has rules of its own.** Check `has_rules` before you tell a filer that a judge has no requirements. ## Related * [Coverage](/concepts/coverage-levels) * [List courts](/api-reference/courts) * [List judges](/api-reference/judges) * [Get rules](/api-reference/rules) * [Search extracted rules](/api-reference/extracted-rules) # Same document, different judge Source: https://docs.courtrules.app/guides/same-document-different-judge How the same filing gets different compliance results depending on the assigned judge Two judges in the same courthouse can have different requirements for the same filing, and keeping track of those differences is the problem Court Rules addresses. ## The scenario You have a memorandum of law in support of a motion for summary judgment. The PDF is 31 pages total, but after stripping front matter (cover page, table of contents, table of authorities) and back matter (certificate of service), the body is 25 pages: * **Body page count:** 25 (what courts count for limit enforcement) * **Word count:** 7,200 * **Document type:** `brief_support` * **Motion type:** `Rule_56` * **District:** EDNY > [!NOTE] > > When you use [`/classify`](/api-reference/classify) to analyze a PDF, the returned `page_count` is > body pages, not total PDF pages. Front matter and back matter are automatically excluded. The > `page_count_analysis` field in the response shows the full breakdown. When calling `/check` > manually, use body page count, not the raw PDF page count. Let's check this document against two EDNY judges. ```mermaid theme={"theme":{"light":"github-light","dark":"github-dark"}} flowchart TD doc["Same 25-page brief
(31pp PDF, 6pp front/back matter)"] doc --> amon["Judge Amon"] doc --> brown["Judge Brown"] amon --> review["REVIEW
25pp within 25pp limit"] brown --> fail["NON_COMPLIANT
25pp exceeds 20pp limit"] ``` ## Judge Amon: REVIEW (action items, no failures) ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}} curl -X POST https://api.courtrules.app/api/v1/check \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "judge_slug": "carol-bagley-amon", "district_id": "edny", "document_scope": "brief_support", "motion_type": "Rule_56", "is_pro_se": false, "pmc_completed": true, "opposing_party_pro_se": false, "filing_role": "movant", "document": { "page_count": 25, "word_count": 7200 } }' ``` Result: **REVIEW**: within page and word limits, but action items to handle. ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} { "summary": { "status": "REVIEW", "failures": 0, "warnings": 0, "passes": 2, "action_items": 3 }, "results": [ { "severity": "INFO", "category": "PAGE_LIMIT", "message": "25 pages within 25-page limit", "source": "EDNY LR 7.1(c)", "status": "PASS" }, { "severity": "INFO", "category": "WORD_LIMIT", "message": "7,200 words within 8,750-word limit", "source": "EDNY LR 7.1(c)", "status": "PASS" }, { "severity": "INFO", "category": "COURTESY_COPY", "message": "Courtesy copy required: tabbed binder, double-sided", "source": "Amon SO", "status": "ACTION_REQUIRED" }, { "severity": "INFO", "category": "FILING_GATE", "message": "Must wait for full briefing before filing", "source": "Amon SO", "status": "ACTION_REQUIRED" }, { "severity": "INFO", "category": "PMC", "message": "Pre-motion conference completed", "source": "Amon SO", "status": "PASS" } ] } ``` Judge Amon applies the **EDNY district default of 25 pages** for support briefs (she imposes no stricter judge-specific limit). The 25 body pages are within that limit. But she requires: * Courtesy copies in a **tabbed binder, double-sided** * Motions must be **fully briefed before filing** * A pre-motion conference (which we indicated was completed) ## Judge Brown: NON\_COMPLIANT (hard failure) Same document. Same district. Different judge. ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}} curl -X POST https://api.courtrules.app/api/v1/check \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "judge_slug": "gary-r-brown", "district_id": "edny", "document_scope": "brief_support", "motion_type": "Rule_56", "is_pro_se": false, "pmc_completed": true, "opposing_party_pro_se": false, "filing_role": "movant", "document": { "page_count": 25, "word_count": 7200 } }' ``` Result: **NON\_COMPLIANT**: the same document fails. ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} { "summary": { "status": "NON_COMPLIANT", "failures": 1, "warnings": 0, "passes": 1, "action_items": 2 }, "results": [ { "severity": "CRITICAL", "category": "PAGE_LIMIT", "message": "25 pages exceeds 20-page limit", "source": "Brown SO §2.B", "status": "FAIL" }, { "severity": "INFO", "category": "WORD_LIMIT", "message": "7,200 words within 8,750-word limit", "source": "EDNY LR 7.1(c)", "status": "PASS" }, { "severity": "INFO", "category": "COURTESY_COPY", "message": "Courtesy copy always required", "source": "Brown SO §1", "status": "ACTION_REQUIRED" }, { "severity": "INFO", "category": "FILING_GATE", "message": "Must wait for full briefing before filing", "source": "Brown SO §3.B", "status": "ACTION_REQUIRED" } ] } ``` Judge Brown imposes a **20-page limit** on support briefs, 5 pages below the EDNY default. Your 25-page memo is 5 pages over. The court will reject it, not on the merits, but on formatting. ## The difference | Check | Judge Amon | Judge Brown | | - | - | - | | Page limit | 25pp (district default): **PASS** | 20pp (standing order): **FAIL** | | Courtesy copies | Tabbed binder, double-sided | Always required | | PMC | Required (all parties) | Required | | Filing gate | Must wait for full briefing | Must wait for full briefing | The same document in the same courthouse passes for one judge and fails for the other, because Amon's limit is the EDNY default of 25 pages and Brown's standing order sets a stricter cap of 20. ## Why this happens: three rule layers Federal court compliance is governed by three layers of authority, each of which can impose different requirements: 1. **FRCP (Federal Rules of Civil Procedure):** National baseline. Covers captions, signatures, privacy redactions, motion content requirements. Same for every federal judge in every district. 15 rules. 2. **Local Rules:** District-wide. Formatting (font, margins, spacing), word limits, timing, and required documents. Every judge in the district shares these. 3. **Standing Orders:** Judge-specific. Each judge publishes a PDF with their personal requirements. Page limits, courtesy copy policies, pre-motion conference rules and filing gates live here, so the differences between judges come from this layer. The API checks all three layers together and tells you which rule, from which layer, applies to your filing. ## Try it yourself Pick any two full-coverage judges (Amon, Block, Brown) and run the same document against both. Each result cites the standing order or rule it comes from, so you can check it against the court's own document. ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}} # Check available judges curl 'https://api.courtrules.app/api/v1/judges?district_id=edny' \ -H "Authorization: Bearer YOUR_API_KEY" # See the rules for each judge curl 'https://api.courtrules.app/api/v1/rules?judge_slug=carol-bagley-amon&district_id=edny' \ -H "Authorization: Bearer YOUR_API_KEY" curl 'https://api.courtrules.app/api/v1/rules?judge_slug=gary-r-brown&district_id=edny' \ -H "Authorization: Bearer YOUR_API_KEY" ``` # Introduction Source: https://docs.courtrules.app/introduction Filing rules for federal and state courts, each with the court's own wording and a link to its source, plus privacy enforcement data. Available through a REST API and an MCP server. Court Rules is a data service for legal software. The API returns the filing rules of federal and state courts and their judges, each with the court's own wording and a link to the document it came from. For the Eastern District of New York it also checks a filing against a judge's rules before the filing is made. A second feed covers privacy enforcement events from federal and state regulators. Both feeds are available through a REST API and an MCP server. ## Two data domains ### Court rules Filing rules for federal district courts and state trial courts, down to the judge or courtroom where the court publishes them. The rules include local rules, general orders, standing orders, individual practices and courtroom rules. Each rule comes with the court's own sentence, a plain-English summary, a rule type from a fixed list, and a link to the document it came from, with the page and section when the document has them. For the Eastern District of New York, the API also checks a filing against the judge's rules. You send the document's details and the filing context, and the API checks them against three rule layers (FRCP, Local Rules and Standing Orders) and returns pass or fail results that cite the specific rule. [Try the quickstart](/quickstart) ### Enforcement data Privacy enforcement events from federal and state regulators, such as settlements, fines, consent decrees and investigations. Each event names the company, the violation types, the laws cited and the remedies, and it gives the fine amount when one was announced. Every event links to an official government source. Search by jurisdiction, date, industry, risk level or violation type. The data is available through MCP and the console. [Browse the data model](/concepts/enforcement-data) > **[Court Rules quickstart](/quickstart)** > > Run a compliance check in under a minute. > **[Read a court's rules](/guides/read-court-rules)** > > Find a court and a judge, then read their rules with a link to the source. > **[Enforcement data](/concepts/enforcement-data)** > > Search privacy enforcement events from federal and state regulators. > **[MCP: Court Rules](/guides/mcp-court-rules)** > > Tools for court rules and filing checks through the Model Context Protocol. > **[MCP: enforcement data](/guides/mcp-enforcement)** > > Tools for enforcement data through the Model Context Protocol. > **[API reference](/api-reference/overview)** > > Full endpoint documentation. ## Start here 1. Read [Coverage](/concepts/coverage-levels) to see which courts and judges the API holds rules for, and how to check a court in code. The [coverage page](https://www.courtrules.app/coverage) on courtrules.app lists today's counts. 2. Get an API key at [console.courtrules.app](https://console.courtrules.app). Sign in with Google or email, copy the key, and send it as a Bearer token. [Authentication](/authentication) shows the header. 3. Read a court's rules with [Read a court's rules](/guides/read-court-rules), or run a compliance check with the [Quickstart](/quickstart). Every key has limits on calls a minute, calls a day and rows returned a day. [Rate limits](/api-reference/rate-limits) gives the numbers, explains how rows are counted, and says how to ask for higher limits. ## Coverage | Data | Courts it covers | Endpoints | | - | - | - | | Filing rules with the court's wording and a source link | Federal district courts and state trial courts with `status: live` | `/rules`, `/extracted-rules` | | Compliance checks | Eastern District of New York | `/check`, `/classify` | | Official rulebooks | The rulebooks that `GET /rulebooks` lists | `/rulebooks` | | Enforcement | Federal and state regulators | MCP, console | Every API key can query every court we cover. Counts of courts and judges change as courts are added, so they are not listed here. The [coverage page](https://www.courtrules.app/coverage) on courtrules.app shows today's counts, and [Coverage](/concepts/coverage-levels) shows how to read them from the API. Enforcement data is available through [MCP](/guides/mcp-enforcement) and the [console](https://console.courtrules.app). ## Data freshness **Court rules:** Courts rarely change their rules more than a few times a year, so every source is read again at least once a quarter. Court holidays are updated monthly. When a page has changed, we update its rules. Each rule links to the court's own document, so you can confirm the wording at the source, and an Atom feed lists new versions of court documents as we find them. The [coverage page](https://www.courtrules.app/coverage#cadence) lists each kind of source, and [Coverage](/concepts/coverage-levels#freshness) explains how to follow new documents. **Enforcement:** the data is updated daily, and a new event appears after the next daily check. [Enforcement data](/concepts/enforcement-data#data-freshness) shows how to poll for new events. ## What's next Pick a path based on what you're building: * **Filing rules for litigation software:** Start with [Read a court's rules](/guides/read-court-rules), then explore [Integration patterns](/guides/integration-patterns) * **Filing compliance checks:** Start with the [Quickstart](/quickstart) * **Enforcement monitoring for in-house legal platforms:** Start with [MCP: enforcement data](/guides/mcp-enforcement), then browse [Enforcement data](/concepts/enforcement-data) * **AI agent integration:** See [Building with AI agents](/guides/building-with-ai-agents) * **Evaluating Court Rules:** See how the [same brief gets different results](/guides/same-document-different-judge) depending on the judge # Quickstart Source: https://docs.courtrules.app/quickstart Get compliance results in under a minute Court Rules has two kinds of data. Court rules are the filing rules of federal district courts and state trial courts, down to the judge or courtroom. Enforcement data is privacy enforcement events from the FTC and state regulators. The quickstart covers court rules via the REST API, and it ends with a compliance check, which runs for the Eastern District of New York. To read the rules of any other court, see [Read a court's rules](/guides/read-court-rules). For enforcement data, see [Enforcement data](/concepts/enforcement-data) and [MCP: enforcement data](/guides/mcp-enforcement). By the end of this quickstart, you will have: * Listed available courts and judges * Retrieved judge-specific filing rules * Run a compliance check against those rules All from your terminal in under 5 minutes. The guide walks through four calls: discover courts, list judges, get applicable rules, and check a document. All requests require a Bearer token. See [Authentication](/authentication) for details. ``` Authorization: Bearer YOUR_API_KEY ``` ## 1. List the courts Start by listing the courts to see what the API covers: ```bash cURL theme={"theme":{"light":"github-light","dark":"github-dark"}} curl 'https://api.courtrules.app/api/v1/courts' \ -H "Authorization: Bearer YOUR_API_KEY" ``` ```python Python theme={"theme":{"light":"github-light","dark":"github-dark"}} import requests headers = {"Authorization": "Bearer YOUR_API_KEY"} resp = requests.get("https://api.courtrules.app/api/v1/courts", headers=headers) courts = resp.json() print(f"{courts['meta']['total_districts']} districts, {courts['meta']['districts_with_data']} with data") ``` ```typescript Node.js theme={"theme":{"light":"github-light","dark":"github-dark"}} const headers = { Authorization: "Bearer YOUR_API_KEY" }; const resp = await fetch("https://api.courtrules.app/api/v1/courts", { headers }); const { courts, meta } = await resp.json(); console.log(`${meta.total_districts} districts, ${meta.districts_with_data} with data`); ``` Every court is open to any API key. Courts with `status: live` have rules you can read with [`/rules`](/api-reference/rules) and [`/extracted-rules`](/api-reference/extracted-rules), state courts included. Compliance checks (step 4) run for `edny` today; for other courts, `/check` returns `422` and points you to their rules. The list is long, and each court in it counts as one row against your daily row limit, so call it once and keep the result. To read one court, call `GET /api/v1/courts/{district_id}`. [Rate limits](/api-reference/rate-limits) explains how rows are counted, and [Coverage](/concepts/coverage-levels) explains how to check how deeply a court is covered. ## 2. List judges in a district ```bash cURL theme={"theme":{"light":"github-light","dark":"github-dark"}} curl 'https://api.courtrules.app/api/v1/judges?district_id=edny' \ -H "Authorization: Bearer YOUR_API_KEY" ``` ```python Python theme={"theme":{"light":"github-light","dark":"github-dark"}} resp = requests.get( "https://api.courtrules.app/api/v1/judges", headers=headers, params={"district_id": "edny"}, ) judges = resp.json() for j in judges["judges"]: print(f"{j['name']} - {j['slug']}") ``` ```typescript Node.js theme={"theme":{"light":"github-light","dark":"github-dark"}} const resp = await fetch("https://api.courtrules.app/api/v1/judges?district_id=edny", { headers }); const { judges } = await resp.json(); judges.forEach((j) => console.log(`${j.name} - ${j.slug}`)); ``` Returns all judges for the district. Use the `slug` field when calling [`/rules`](/api-reference/rules) or [`/check`](/api-reference/check). ## 3. Get rules for a judge ```bash cURL theme={"theme":{"light":"github-light","dark":"github-dark"}} curl 'https://api.courtrules.app/api/v1/rules?judge_slug=gary-r-brown&district_id=edny&document_scope=brief_support&motion_type=Rule_56' \ -H "Authorization: Bearer YOUR_API_KEY" ``` ```python Python theme={"theme":{"light":"github-light","dark":"github-dark"}} resp = requests.get( "https://api.courtrules.app/api/v1/rules", headers=headers, params={ "judge_slug": "gary-r-brown", "district_id": "edny", "document_scope": "brief_support", "motion_type": "Rule_56", }, ) rules = resp.json() ``` ```typescript Node.js theme={"theme":{"light":"github-light","dark":"github-dark"}} const resp = await fetch( "https://api.courtrules.app/api/v1/rules?" + new URLSearchParams({ judge_slug: "gary-r-brown", district_id: "edny", document_scope: "brief_support", motion_type: "Rule_56", }), { headers }, ); const { rules } = await resp.json(); ``` Returns the full rule set organized by authority layer: FRCP, Local Rules, and Standing Order. ## 4. Check a document Send document metadata to the [`/check`](/api-reference/check) endpoint: ```bash cURL theme={"theme":{"light":"github-light","dark":"github-dark"}} curl -X POST https://api.courtrules.app/api/v1/check \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "judge_slug": "gary-r-brown", "district_id": "edny", "document_scope": "brief_support", "motion_type": "Rule_56", "is_pro_se": false, "pmc_completed": true, "opposing_party_pro_se": false, "filing_role": "movant", "document": { "page_count": 18, "word_count": 7200 } }' ``` ```python Python theme={"theme":{"light":"github-light","dark":"github-dark"}} resp = requests.post( "https://api.courtrules.app/api/v1/check", headers=headers, json={ "judge_slug": "gary-r-brown", "district_id": "edny", "document_scope": "brief_support", "motion_type": "Rule_56", "is_pro_se": False, "pmc_completed": True, "opposing_party_pro_se": False, "filing_role": "movant", "document": {"page_count": 18, "word_count": 7200}, }, ) result = resp.json() print(f"Status: {result['summary']['status']}") for r in result["results"]: print(f" [{r['status']}] {r['message']} ({r['source']})") ``` ```typescript Node.js theme={"theme":{"light":"github-light","dark":"github-dark"}} const resp = await fetch("https://api.courtrules.app/api/v1/check", { method: "POST", headers: { ...headers, "Content-Type": "application/json" }, body: JSON.stringify({ judge_slug: "gary-r-brown", district_id: "edny", document_scope: "brief_support", motion_type: "Rule_56", is_pro_se: false, pmc_completed: true, opposing_party_pro_se: false, filing_role: "movant", document: { page_count: 18, word_count: 7200 }, }), }); const { summary, results } = await resp.json(); console.log(`Status: ${summary.status}`); results.forEach((r) => console.log(` [${r.status}] ${r.message} (${r.source})`)); ``` ## Minimal vs. full document input The `document` object only requires `page_count` and `word_count`. With just these two fields, the API checks: * Page and word limits (judge-specific and local rules) * Courtesy copy requirements * Pre-motion conference requirements * Filing gate and bundling rules To get structural checks (caption, signature, required sections), provide the optional fields. See [Document structure](/concepts/document-structure) for the full schema. ## Understanding results Each result has: | Field | Description | | - | - | | `severity` | `CRITICAL`, `WARNING`, or `INFO` | | `category` | What kind of rule (e.g. `PAGE_LIMIT`, `CAPTION`, `PMC`) | | `message` | Human-readable explanation | | `source` | Citation (e.g. `FRCP 10(a)`, `EDNY LR 7.1(c)`, `Brown SO §2.B`) | | `status` | `FAIL`, `PASS`, or `ACTION_REQUIRED` | The summary `status` is: * **`COMPLIANT`:** No failures, no action items * **`REVIEW`:** No failures, but action items exist (e.g. courtesy copy reminder) * **`NON_COMPLIANT`:** At least one FAIL result ## Next steps * [API Reference](/api-reference/overview): Full endpoint reference with schemas, parameters, and live playground * [Same document, different judge](/guides/same-document-different-judge): See why the same filing gets different results for different judges * [Integration patterns](/guides/integration-patterns): How to integrate the API into your application * [Building with AI agents](/guides/building-with-ai-agents): Use the OpenAPI spec with LLMs