Skip to main content
Five patterns for integrating structured legal data, from lightweight pre-flight checks to enforcement monitoring pipelines.

Overview


Pattern 1: Pre-flight check

Call /check with just page_count and word_count while the user is still drafting. This catches the most common compliance failures (page/word limits, PMC requirements, filing gates) with minimal input.
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. Fast (sub-millisecond) 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. These require parsing the document.

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.
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. This 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 to display applicable rules proactively, before the user even starts drafting. Show them the requirements for their judge and motion type up front.
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 + Check pipeline

Upload a PDF to /classify, which extracts metadata and classifies the document automatically. The response includes a check_request with the extracted document metadata. Before sending to /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. This matches how courts count pages for limit enforcement.
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 endpoint handles the analysis and produces a ready-to-use /check request. Latency note: /classify takes 10-30 seconds. /check is deterministic and sub-millisecond. Plan your UX accordingly: show a loading state for classification, then instant results for the compliance check.

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_enforcement_actions via MCP, poll periodically Latency: Sub-second (MCP tool call) Use during: Ongoing compliance monitoring When a new enforcement event matches your criteria, call get_enforcement_details 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 guide.

Choosing a pattern

PatternInput neededLatencyCoverage
Pre-flightpage_count + word_count< 1msLimits + standing order checks
Full complianceParsed document structure< 1msAll checks
Rules lookupJudge + document type< 1msRule display (no pass/fail)
Classify + CheckPDF file (base64)10-30s + < 1msAll checks (extracted structure)
Enforcement monitoringJurisdiction + industrySub-secondEnforcement events via 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.