Compliance Monitoring with Court Data

Guides  ·  Use Cases

Compliance teams and due diligence workflows often need to monitor known parties — counterparties, borrowers, vendors, or acquisition targets — for new litigation and adverse court filings. DocketLayer makes this tractable: define a watch list of known cases per subject, query them on a schedule, and surface new activity for review.

The Use Case

Court docket monitoring is a common input to counterparty risk workflows. A new civil judgment, a bankruptcy filing, or an enforcement action can materially affect a business relationship and may trigger obligations under credit agreements, vendor contracts, or regulatory frameworks. Catching these events as they happen — rather than on a quarterly review cycle — is the operational goal.

The prerequisite is a list of known case identifiers for each subject. DocketLayer queries by court_code and case_id — there is no name search. You need to know which courts a subject has active cases in and what those case numbers are. This information typically comes from an initial due diligence search, prior litigation history, or ongoing case tracking from counsel.

Building a Watch List

Structure your watch list around subjects, with each subject carrying a list of known cases and a risk tier that controls monitoring frequency and alert routing.

from dataclasses import dataclass, field

@dataclass
class ComplianceSubject:
    name: str                          # counterparty or client name
    known_cases: list[dict] = field(default_factory=list)  # {court_code, case_id, last_checked}
    risk_tier: str = "standard"        # e.g. "high", "standard", "watch"

# Example subject list
subjects = [
    ComplianceSubject(
        name="Acme Corporation",
        known_cases=[
            {
                "court_code": "nysd",
                "case_id": "1:24-cv-09822",
                "last_checked": "2025-01-01T00:00:00-05:00",
            },
            {
                "court_code": "deb",
                "case_id": "1-24-bk-10001",
                "last_checked": "2025-01-01T00:00:00-05:00",
            },
        ],
        risk_tier="high",
    ),
]

Common case types to include for counterparty monitoring: civil cases in the relevant federal district courts, bankruptcy cases in the corresponding bankruptcy courts, and any state court cases where you have known exposure. Use docketlayer_court_list or GET /v2/status to confirm court codes and coverage levels before adding a court to the list.

Monitoring Subjects

The monitoring function checks all known cases for each subject, collects new activity since the last check, and returns findings for further processing. It uses last_checked per case (see efficient polling) to pull only the delta — avoiding re-processing the full docket history on every run. Each case query uses the x402 probe-pay-retry pattern.

import httpx, json
from datetime import datetime, timezone

def check_subject(subject: ComplianceSubject) -> list[dict]:
    """Check all known cases for a subject and return any new activity."""
    findings = []
    now = datetime.now(timezone.utc).isoformat()

    for case in subject.known_cases:
        params = {
            "court_code": case["court_code"],
            "case_id":    case["case_id"],
            "last_checked": case["last_checked"],
        }

        try:
            probe = httpx.get("https://api.docketlayer.ai/v2/case", params=params)
            requirements = json.loads(probe.headers["X-Payment-Requirements"])
            encoded = build_payment_tx(
                solana_client, payer,
                requirements["payTo"],
                int(requirements["maxAmountRequired"]) / 1e6,
            )
            resp = httpx.get(
                "https://api.docketlayer.ai/v2/case",
                params=params,
                headers={"x402-payment": encoded},
            )
            resp.raise_for_status()
            result = resp.json()

            delta = result.get("delta", {})
            if delta.get("new_filings"):
                findings.append({
                    "subject": subject.name,
                    "court_code": case["court_code"],
                    "case_id": case["case_id"],
                    "new_filings": delta["new_filings"],
                    "risk_tier": subject.risk_tier,
                })

            case["last_checked"] = now

        except httpx.HTTPStatusError as e:
            if e.response.status_code in (422, 503):
                continue
            raise

    return findings

last_checked requires a timezone offset

The monitor and case query endpoints require last_checked as an ISO-8601 timestamp with an explicit timezone offset — for example 2025-03-01T00:00:00-05:00, not 2025-03-01T00:00:00. Store and pass timestamps with the offset for the relevant jurisdiction, or normalize to UTC (+00:00) consistently across your watch list.

Reporting

Aggregate findings across all subjects after each sweep and generate a report for your compliance team. Structure the report around risk tier so high-priority subjects surface first.

def generate_compliance_report(findings: list[dict]) -> str:
    """Generate a plain-text compliance report from sweep findings."""
    if not findings:
        return "Compliance sweep complete. No new docket activity detected."

    lines = ["COMPLIANCE DOCKET REPORT", "=" * 40, ""]

    # Group by risk tier
    high_risk    = [f for f in findings if f["risk_tier"] == "high"]
    standard     = [f for f in findings if f["risk_tier"] != "high"]

    if high_risk:
        lines.append("HIGH RISK SUBJECTS")
        for finding in high_risk:
            lines.append(
                f"  {finding['subject']}{finding['court_code']} {finding['case_id']}: "
                f"{len(finding['new_filings'])} new filing(s)"
            )
        lines.append("")

    if standard:
        lines.append("STANDARD SUBJECTS")
        for finding in standard:
            lines.append(
                f"  {finding['subject']}{finding['court_code']} {finding['case_id']}: "
                f"{len(finding['new_filings'])} new filing(s)"
            )

    return "\n".join(lines)

Coverage Considerations

DocketLayer covers federal courts and general jurisdiction courts across all 50 states, plus 25 Canadian federal, provincial, and territorial superior courts. For counterparty monitoring, federal district courts and bankruptcy courts cover the majority of material litigation and insolvency events. State court coverage varies by jurisdiction — check GET /v2/status for current coverage levels before relying on a specific state court.

Courts with coverage='planned' return 422 responses; those queries are not charged. If a court in your watch list returns consistent 422 responses, check the coverage status and consider whether that court is available yet. Maintain the case in your watch list — coverage may be added in a future update.