{"openapi":"3.1.0","info":{"title":"Lambert Planning Caselaw API","description":"\n**Lambert Planning Caselaw API** (Lambert 策划 判例数据服务) serves recent US court opinions from a local\nSQLite/FTS5 store that is continuously synced from CourtListener, GovInfo (USCOURTS) and the courts' own PDFs.\n\n* Authenticate with header `X-API-Key: <key>` (or `Authorization: Bearer <key>`). `/v1/health` is public.\n* Upstream CourtListener quota is scarce (5/min, 50/hour, 125/day). Local endpoints cost nothing; endpoints that\n  may call upstream report `quota_cost` and the header `X-Upstream-Quota-Remaining` on every response.\n* Errors always look like `{\"error\": {\"code\": \"...\", \"message\": \"...\"}}`.\n","version":"1.0.0"},"paths":{"/v1/health":{"get":{"tags":["system"],"summary":"Service health (no auth)","description":"Liveness plus data freshness: opinion counts, last sync times, and whether full texts are pending.","operationId":"health_v1_health_get","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{},"example":{"status":"ok","service":"Lambert Planning Caselaw API","version":"1.0.0","opinions":120,"with_text":80,"pending_text":40,"last_sync":{"courtlistener":"2026-10-13T06:00:00Z","govinfo":"2026-10-13T06:01:00Z"}}}}}}}},"/v1/opinions/recent":{"get":{"tags":["opinions"],"summary":"Recent opinions from the local store","description":"Newest opinions first (by `date_filed`), served from the local database - costs no upstream quota. Page with `cursor` from the previous response's `next_cursor`.","operationId":"recent_v1_opinions_recent_get","parameters":[{"name":"since","in":"query","required":false,"schema":{"anyOf":[{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},{"type":"null"}],"description":"Only opinions filed on/after this date (YYYY-MM-DD).","examples":["2026-10-01"],"title":"Since"},"description":"Only opinions filed on/after this date (YYYY-MM-DD)."},{"name":"court","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Court id, e.g. `michctapp`, `scotus`, `waed` (see /v1/courts).","examples":["michctapp"],"title":"Court"},"description":"Court id, e.g. `michctapp`, `scotus`, `waed` (see /v1/courts)."},{"name":"source","in":"query","required":false,"schema":{"anyOf":[{"type":"string","pattern":"^(courtlistener|govinfo)$"},{"type":"null"}],"description":"`courtlistener` or `govinfo`.","title":"Source"},"description":"`courtlistener` or `govinfo`."},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"description":"Page size (1-100).","default":20,"title":"Limit"},"description":"Page size (1-100)."},{"name":"cursor","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Opaque cursor from `next_cursor`.","title":"Cursor"},"description":"Opaque cursor from `next_cursor`."}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{},"example":{"items":[{"id":"cl:11499694","source":"courtlistener","court_id":"michctapp","court_name":"Michigan Court of Appeals","case_name":"People of Michigan v. Jimmy Lee Fuller","date_filed":"2026-10-12","docket_number":"372013","url":"https://www.courtlistener.com/opinion/11032004/people-of-michigan-v-jimmy-lee-fuller/","download_url":"https://www.courts.michigan.gov/.../20261012_c372013_90_372013.opn.pdf","text_source":"court_pdf","text_status":"ok","fetched_at":"2026-10-13T05:10:00Z","has_text":true,"text_length":59069}],"count":1}}}},"401":{"description":"Missing/invalid API key"},"429":{"description":"Rate limited or upstream quota exhausted (see Retry-After)"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/opinions/{opinion_id}":{"get":{"tags":["opinions"],"summary":"Get one opinion (local, else fetched on demand)","description":"`opinion_id` is `cl:<CourtListener opinion id>` or `gi:<GovInfo granule id>`. If it is not in the local store it is fetched upstream (costs CourtListener quota for `cl:` ids, reported in `quota_cost`) and stored. Full text prefers the court's original PDF (no quota), falling back to CourtListener text.","operationId":"get_opinion_v1_opinions__opinion_id__get","parameters":[{"name":"opinion_id","in":"path","required":true,"schema":{"type":"string","description":"Unified id, e.g. `cl:11499694` or `gi:USCOURTS-waed-2_06-cr-00035-0`.","examples":["cl:11499694"],"title":"Opinion Id"},"description":"Unified id, e.g. `cl:11499694` or `gi:USCOURTS-waed-2_06-cr-00035-0`."},{"name":"include_text","in":"query","required":false,"schema":{"type":"boolean","description":"Include the full opinion text (can be large).","default":false,"title":"Include Text"},"description":"Include the full opinion text (can be large)."}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{},"example":{"id":"cl:11499694","source":"courtlistener","court_id":"michctapp","court_name":"Michigan Court of Appeals","case_name":"People of Michigan v. Jimmy Lee Fuller","date_filed":"2026-10-12","docket_number":"372013","url":"https://www.courtlistener.com/opinion/11032004/people-of-michigan-v-jimmy-lee-fuller/","download_url":"https://www.courts.michigan.gov/.../20261012_c372013_90_372013.opn.pdf","text_source":"court_pdf","text_status":"ok","fetched_at":"2026-10-13T05:10:00Z","has_text":true,"text_length":59069,"text":"If this opinion indicates that it is ...","quota_cost":0}}}},"404":{"description":"Not found"},"401":{"description":"Missing/invalid API key"},"429":{"description":"Rate limited or upstream quota exhausted (see Retry-After)"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/search":{"get":{"tags":["search"],"summary":"Full-text search","description":"`source=local` (default) searches the local FTS5 index (case name + full text, BM25 ranked, free). `source=courtlistener` / `govinfo` search upstream; CourtListener searches consume 1 quota unit (cached 30 minutes) - see `quota_cost`.","operationId":"search_v1_search_get","parameters":[{"name":"q","in":"query","required":true,"schema":{"type":"string","minLength":1,"maxLength":500,"description":"Search terms (words are ANDed).","examples":["negligence duty of care"],"title":"Q"},"description":"Search terms (words are ANDed)."},{"name":"court","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Court id filter.","title":"Court"},"description":"Court id filter."},{"name":"since","in":"query","required":false,"schema":{"anyOf":[{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},{"type":"null"}],"description":"Filed on/after (YYYY-MM-DD).","title":"Since"},"description":"Filed on/after (YYYY-MM-DD)."},{"name":"until","in":"query","required":false,"schema":{"anyOf":[{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},{"type":"null"}],"description":"Filed on/before (YYYY-MM-DD).","title":"Until"},"description":"Filed on/before (YYYY-MM-DD)."},{"name":"source","in":"query","required":false,"schema":{"type":"string","pattern":"^(local|courtlistener|govinfo)$","description":"`local` (default, free), `courtlistener` or `govinfo`.","default":"local","title":"Source"},"description":"`local` (default, free), `courtlistener` or `govinfo`."},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"description":"Max results.","default":20,"title":"Limit"},"description":"Max results."}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{},"example":{"source":"local","query":"negligence","count":1,"quota_cost":0,"results":[{"id":"cl:11499694","source":"courtlistener","court_id":"michctapp","court_name":"Michigan Court of Appeals","case_name":"People of Michigan v. Jimmy Lee Fuller","date_filed":"2026-10-12","docket_number":"372013","url":"https://www.courtlistener.com/opinion/11032004/people-of-michigan-v-jimmy-lee-fuller/","download_url":"https://www.courts.michigan.gov/.../20261012_c372013_90_372013.opn.pdf","text_source":"court_pdf","text_status":"ok","fetched_at":"2026-10-13T05:10:00Z","has_text":true,"text_length":59069,"snippet":"...duty of care and <b>negligence</b>..."}]}}}},"401":{"description":"Missing/invalid API key"},"429":{"description":"Rate limited or upstream quota exhausted (see Retry-After)"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/courts":{"get":{"tags":["reference"],"summary":"Courts seen in the local store","description":"Courts that appear in synced opinions, with opinion counts and latest filing date.","operationId":"courts_v1_courts_get","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{},"example":{"count":1,"courts":[{"id":"michctapp","name":"Michigan Court of Appeals","source":"courtlistener","opinions":12,"latest":"2026-10-12"}]}}}},"401":{"description":"Missing/invalid API key"},"429":{"description":"Rate limited or upstream quota exhausted (see Retry-After)"}}}},"/v1/dockets/{cl_docket_id}":{"get":{"tags":["reference"],"summary":"CourtListener docket","description":"Proxy of CourtListener `dockets/<id>` (cached permanently; first fetch costs 1 quota unit).","operationId":"docket_v1_dockets__cl_docket_id__get","parameters":[{"name":"cl_docket_id","in":"path","required":true,"schema":{"type":"integer","minimum":1,"description":"CourtListener docket id.","examples":[74951954],"title":"Cl Docket Id"},"description":"CourtListener docket id."}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{},"example":{"id":74951954,"court_id":"michctapp","case_name":"People of Michigan v. Jimmy Lee Fuller","docket_number":"372013","quota_cost":1}}}},"401":{"description":"Missing/invalid API key"},"429":{"description":"Rate limited or upstream quota exhausted (see Retry-After)"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/citations/verify":{"post":{"tags":["search"],"summary":"Verify citations in text","description":"Proxies CourtListener citation-lookup: finds every reporter citation in `text` and reports whether it matches a real case (status 200 = found, 404 = not found, 300 = ambiguous). Costs 1 quota unit (cached 24h).","operationId":"verify_v1_citations_verify_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CitationReq"}}},"required":true},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{},"example":{"quota_cost":1,"results":[{"citation":"576 U.S. 644","status":200,"clusters":[{"case_name":"Obergefell v. Hodges"}]}]}}}},"401":{"description":"Missing/invalid API key"},"429":{"description":"Rate limited or upstream quota exhausted (see Retry-After)"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/govinfo/uscourts/recent":{"get":{"tags":["opinions"],"summary":"Recent GovInfo USCOURTS opinions","description":"Federal court opinions from GovInfo. Reads the local store; with `live=true` first pulls one page of packages modified since `since` from GovInfo (no CourtListener quota).","operationId":"gi_recent_v1_govinfo_uscourts_recent_get","parameters":[{"name":"since","in":"query","required":false,"schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Issued on/after (default: 7 days ago).","examples":["2026-10-01"],"title":"Since"},"description":"Issued on/after (default: 7 days ago)."},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":20,"title":"Limit"}},{"name":"live","in":"query","required":false,"schema":{"type":"boolean","description":"Also query GovInfo right now.","default":false,"title":"Live"},"description":"Also query GovInfo right now."}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{},"example":{"count":1,"items":[{"id":"gi:USCOURTS-waed-2_06-cr-00035-0","source":"govinfo","court_id":"michctapp","court_name":"Michigan Court of Appeals","case_name":"People of Michigan v. Jimmy Lee Fuller","date_filed":"2026-10-12","docket_number":"372013","url":"https://www.courtlistener.com/opinion/11032004/people-of-michigan-v-jimmy-lee-fuller/","download_url":"https://www.courts.michigan.gov/.../20261012_c372013_90_372013.opn.pdf","text_source":"court_pdf","text_status":"ok","fetched_at":"2026-10-13T05:10:00Z","has_text":true,"text_length":59069}]}}}},"401":{"description":"Missing/invalid API key"},"429":{"description":"Rate limited or upstream quota exhausted (see Retry-After)"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/quota":{"get":{"tags":["system"],"summary":"Upstream usage and local budget","description":"CourtListener's own `api-usage` view (not charged) plus this service's rolling-window counters and background budget.","operationId":"quota_v1_quota_get","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{},"example":{"courtlistener_local":{"minute":{"used":0,"remaining":4}},"courtlistener_upstream":{"current_usage":[]},"remaining":4}}}},"401":{"description":"Missing/invalid API key"},"429":{"description":"Rate limited or upstream quota exhausted (see Retry-After)"}}}},"/v1/admin/sync":{"post":{"tags":["admin"],"summary":"Trigger a sync round now (admin)","description":"Starts a background round: CourtListener incremental pages, GovInfo, then full-text fill. Returns immediately.","operationId":"admin_sync_v1_admin_sync_post","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{},"example":{"status":"started"}}}},"403":{"description":"Not an admin key"}}}},"/v1/admin/keys":{"get":{"tags":["admin"],"summary":"List API keys (admin)","description":"Key metadata only; secrets are never retrievable.","operationId":"keys_list_v1_admin_keys_get","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{},"example":{"keys":[{"id":1,"name":"acme-app","prefix":"lpc_abcd","is_admin":false,"created_at":"2026-10-13T00:00:00Z"}]}}}}}},"post":{"tags":["admin"],"summary":"Create a client key (admin)","description":"Creates a key and returns it **once**; only its sha256 is stored.","operationId":"keys_create_v1_admin_keys_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/KeyReq"}}},"required":true},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{},"example":{"id":2,"name":"acme-app","is_admin":false,"api_key":"lpc_...(shown once)"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/admin/keys/{key_id}":{"delete":{"tags":["admin"],"summary":"Revoke a key (admin)","description":"Revokes the key immediately.","operationId":"keys_delete_v1_admin_keys__key_id__delete","parameters":[{"name":"key_id","in":"path","required":true,"schema":{"type":"integer","minimum":1,"title":"Key Id"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{},"example":{"id":2,"revoked":true}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/admin/keys/{key_id}/revoke":{"post":{"tags":["admin"],"summary":"Revoke a key (admin, POST form)","description":"Same as DELETE; for clients that cannot send DELETE.","operationId":"keys_revoke_v1_admin_keys__key_id__revoke_post","parameters":[{"name":"key_id","in":"path","required":true,"schema":{"type":"integer","minimum":1,"title":"Key Id"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{},"example":{"id":2,"revoked":true}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}}},"components":{"schemas":{"CitationReq":{"properties":{"text":{"type":"string","maxLength":64000,"minLength":1,"title":"Text","description":"Free text containing citations to verify.","examples":["See Obergefell v. Hodges, 576 U.S. 644 (2015)."]}},"type":"object","required":["text"],"title":"CitationReq"},"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"KeyReq":{"properties":{"name":{"type":"string","maxLength":80,"minLength":1,"title":"Name","description":"Label of the client this key is for.","examples":["acme-app"]},"admin":{"type":"boolean","title":"Admin","description":"Create an admin key (can call /v1/admin/*).","default":false}},"type":"object","required":["name"],"title":"KeyReq"},"ValidationError":{"properties":{"loc":{"items":{"anyOf":[{"type":"string"},{"type":"integer"}]},"type":"array","title":"Location"},"msg":{"type":"string","title":"Message"},"type":{"type":"string","title":"Error Type"},"input":{"title":"Input"},"ctx":{"type":"object","title":"Context"}},"type":"object","required":["loc","msg","type"],"title":"ValidationError"}}},"tags":[{"name":"opinions"},{"name":"search"},{"name":"reference"},{"name":"admin"},{"name":"system"}]}