{"openapi":"3.1.0","info":{"title":"Bill Commons API","description":"Public, read-only REST API for Bill Commons: nonpartisan legislative search and data across all 50 states + DC.","version":"v1"},"servers":[{"url":"https://api.billcommons.org","description":"production"},{"url":"http://localhost:8000","description":"local development"}],"paths":{"/api/v1/account/magic-link":{"post":{"tags":["account"],"summary":"Request Magic Link","operationId":"request_magic_link_api_v1_account_magic_link_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MagicLinkRequest"}}},"required":true},"responses":{"202":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MagicLinkResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/account/session":{"post":{"tags":["account"],"summary":"Consume Session Token","description":"D7: consumes a magic-link token (POST only -- a GET must never\nconsume it). Origin-checked like every other unsafe method on this\nrouter (B7). Sets the session cookie and returns either `204` (nothing\nnew to reveal) or `200 {\"key\": ...}` when this login just auto-minted\nthe customer's first Developer key (D5, revealed INLINE -- no\nreveal-ciphertext needed for a synchronous JSON response).\n\nItem 3 fix (part 1 of 3): the token is claimed with ONE atomic\n`UPDATE ... WHERE used_at IS NULL ... RETURNING`, replacing the pre-fix\ncheck-then-set (a `SELECT`, then `row.used_at = now` applied only at\n`db.commit()` much later) that let two concurrent calls with the SAME\ntoken both pass the \"is it unused\" check before either had committed.\n\nFixlist item 6 fix: `_session_secret()` is resolved FIRST, before any\nwrite. Pre-fix, a misconfigured instance (`ACCOUNT_SESSION_SECRET`\nunset -- startup only logs an ERROR for this, per item 20, and keeps\nserving) burned the magic-link token, upserted the customer, and\nauto-minted the customer's ONE Developer key (`mint_developer_key_if_\nfirst_login` never mints a second) all the way through `db.commit()`\nbelow -- and only THEN called `_sign_session` -> `_session_secret()`,\nwhich raises. The customer got an unhandled 500 with the token already\nconsumed, the key already minted, and no way to ever read that key's\nplaintext (`reveal_ciphertext` is null on this inline-reveal path by\ndesign, D5) -- permanently unreadable and burning one of two active\nkey slots, recoverable only via a second key from the account UI.\nFailing here, before any of that is written, turns a misconfiguration\ninto a clean, retriable failure instead of an unrecoverable one.","operationId":"consume_session_token_api_v1_account_session_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SessionRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/account/me":{"get":{"tags":["account"],"summary":"Get Account","operationId":"get_account_api_v1_account_me_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/v1/account/keys":{"post":{"tags":["account"],"summary":"Create Key","description":"Item 8 fix: the plan is DERIVED from the customer's current\nsubscription (same expression `GET /me` uses), not hardcoded to\n`\"developer\"`. Pre-fix, a paying Builder/Scale customer who minted a\nSECOND key from `/account` got that key metered at free-tier limits --\n`rotate_key` already correctly inherited `old.plan`; this was the one\npath that didn't, and it is a straight revenue leak, not a nit.","operationId":"create_key_api_v1_account_keys_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/KeyMintRequest"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/KeyRevealResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/account/keys/{key_id}/rotate":{"post":{"tags":["account"],"summary":"Rotate Key Endpoint","operationId":"rotate_key_endpoint_api_v1_account_keys__key_id__rotate_post","parameters":[{"name":"key_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Key Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/KeyRevealResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/account/keys/{key_id}/revoke":{"post":{"tags":["account"],"summary":"Revoke Key Endpoint","operationId":"revoke_key_endpoint_api_v1_account_keys__key_id__revoke_post","parameters":[{"name":"key_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Key Id"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/account/keys/{key_id}/reveal":{"post":{"tags":["account"],"summary":"Reveal Key Endpoint","description":"B1: return the plaintext exactly once, then null the reveal columns.\nCookie-authed + Origin-checked (B7).\n\nItem 5 fix: the expired-window branch now calls `expire_stale_reveal`\nitself (status='revoked' + revoked_at + cache invalidation) instead of\nonly nulling the reveal columns and leaving `status='active'` --\notherwise `expire_stale_reveal`'s own lazy auto-revoke (C7) can never\nfire again once `reveal_ciphertext` is already None, and the key stays\n`active` (occupying one of the 2 active slots) forever with no one who\ncan ever read it.\n\nItem 4 fix: decrypt BEFORE nulling anything. Pre-fix, the reveal\ncolumns were nulled and committed FIRST, and `plaintext is None`\n(decrypt failure) was only checked after -- so a rotated or\nmisconfigured `BILLCOMMONS_REVEAL_KEY` destroyed the only copy of a\nlive credential and then 404'd, leaving the key `active` and unreadable\nforever. Now a decrypt failure leaves the ciphertext INTACT and returns\n503 (retryable once the reveal key is fixed) instead of destroying\nit.\n\nFixlist item 9 fix: the initial `SELECT` now takes `FOR UPDATE` on the\nrow, and the eventual claim is a conditional\n`UPDATE ... WHERE reveal_ciphertext IS NOT NULL RETURNING id` rather\nthan an unconditional assignment + commit. Pre-fix, two concurrent\nauthenticated reveals for the same key could both observe\n`reveal_ciphertext IS NOT NULL` (no lock, no conditional consume), both\ndecrypt, both null, both commit, and both return 200 with the\nplaintext -- violating B1's \"shown to the caller exactly ONCE\". `FOR\nUPDATE` serializes concurrent callers on this row; the conditional\nUPDATE is the second, defense-in-depth guarantee (it also protects\ncorrectness if `FOR UPDATE` is ever a no-op, e.g. a dialect that\ndoesn't implement row locks) -- a second caller unblocked after the\nfirst commits re-reads `reveal_ciphertext IS NULL` and 404s\n`nothing_to_reveal` instead of double-revealing. Kept as a SEPARATE\nconditional UPDATE (not folded into one `UPDATE ... RETURNING`) so the\ndecrypt-before-destroy property from item 4 above still holds: a\ndecrypt failure leaves the ciphertext intact rather than being\ndestroyed by an all-in-one claim.","operationId":"reveal_key_endpoint_api_v1_account_keys__key_id__reveal_post","parameters":[{"name":"key_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Key Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/KeyRevealResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/usage":{"get":{"tags":["admin"],"summary":"Usage Report","operationId":"usage_report_api_v1_admin_usage_get","parameters":[{"name":"days","in":"query","required":false,"schema":{"type":"integer","maximum":90,"minimum":1,"default":7,"title":"Days"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/alerts/subscribe":{"post":{"tags":["alerts"],"summary":"Subscribe","description":"Subscribe an email to a topic's change digest.\n\nIdempotent on (email, kind, target). New and inactive rows enter the\nmailbox-confirmation queue; active rows remain unchanged. Every accepted\nrequest returns the same lifecycle shape so anonymous callers cannot use\nthe endpoint to test membership.","operationId":"subscribe_api_v1_alerts_subscribe_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlertSubscribeRequest"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlertSubscribeResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/alerts/confirm":{"post":{"tags":["alerts"],"summary":"Confirm","operationId":"confirm_api_v1_alerts_confirm_post","requestBody":{"content":{"application/json":{"schema":{"properties":{"token":{"type":"string","maxLength":200,"minLength":8,"pattern":"^[A-Za-z0-9_-]+$","title":"Token"}},"type":"object","required":["token"],"title":"AlertConfirmRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlertConfirmResponse"}}}}}}},"/api/v1/alerts/unsubscribe":{"get":{"tags":["alerts"],"summary":"Unsubscribe","description":"One-click unsubscribe from the link in every digest.\n\nA GET that mutates is deliberate here: the link must work from any mail\nclient with no login and no form. Idempotent -- clicking twice lands on\nthe same page. Returns HTML, not JSON: the person clicking is standing in\ntheir inbox, not in an API client.","operationId":"unsubscribe_api_v1_alerts_unsubscribe_get","parameters":[{"name":"token","in":"query","required":true,"schema":{"type":"string","minLength":8,"title":"Token"}}],"responses":{"200":{"description":"Successful Response","content":{"text/html":{"schema":{"type":"string"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/billing/checkout":{"post":{"tags":["billing"],"summary":"Create Checkout","description":"C2: guest-capable, Origin-checked only (plus E2/item 4's own strict\nrate limit -- this endpoint is an unauthenticated write against the\nshared Stripe account, `QuotaMiddleware` never sees it). A4/B4: 409 if\nthe (optional) logged-in customer already has an active/non-terminal\nsubscription (item 3: `incomplete_expired` counts as terminal, not\njust `canceled`) -- they should use the Portal to change plans, not\nopen a second Checkout.","operationId":"create_checkout_api_v1_billing_checkout_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CheckoutRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CheckoutResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/billing/checkout/snapshot":{"post":{"tags":["billing"],"summary":"Create Snapshot Checkout","description":"R2/A10: one-time snapshot purchase, guest-capable (C2, plus E2's\nstrict rate limit), no subscription conflict check -- a customer can\nbuy any number of snapshots.","operationId":"create_snapshot_checkout_api_v1_billing_checkout_snapshot_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SnapshotCheckoutRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CheckoutResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/billing/portal":{"post":{"tags":["billing"],"summary":"Create Portal Session","description":"Cookie-authed (unlike Checkout -- managing an existing subscription\nrequires knowing WHICH customer you are).","operationId":"create_portal_session_api_v1_billing_portal_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CheckoutResponse"}}}}}}},"/api/v1/billing/webhook":{"post":{"tags":["billing"],"summary":"Stripe Webhook","operationId":"stripe_webhook_api_v1_billing_webhook_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/v1/feedback":{"post":{"tags":["feedback"],"summary":"Submit Feedback","description":"Accept a feedback message from the site (or any API consumer).\n\n`website` is a honeypot: the form never shows it, so a filled value means\na bot. Those get the same 201 as everyone else -- returning an error just\nteaches the bot which field to skip -- but nothing is stored.","operationId":"submit_feedback_api_v1_feedback_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FeedbackRequest"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FeedbackResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/health":{"get":{"tags":["health"],"summary":"Health","operationId":"health_api_v1_health_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HealthOut"}}}}}}},"/api/v1/ready":{"get":{"tags":["health"],"summary":"Ready","operationId":"ready_api_v1_ready_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReadyOut"}}}}}}},"/api/v1/official-evidence/overview":{"get":{"tags":["official evidence"],"summary":"Overview","description":"Bounded inventory; discovery success never proves statewide freshness.","operationId":"overview_api_v1_official_evidence_overview_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Overview Api V1 Official Evidence Overview Get"}}}}}}},"/api/v1/official-evidence/observations":{"get":{"tags":["official evidence"],"summary":"Observations","operationId":"observations_api_v1_official_evidence_observations_get","parameters":[{"name":"jurisdiction","in":"query","required":true,"schema":{"type":"string","minLength":2,"maxLength":2,"title":"Jurisdiction"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":20,"title":"Limit"}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","maximum":10000,"minimum":0,"default":0,"title":"Offset"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Observations Api V1 Official Evidence Observations Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/official-evidence/reconciliations":{"get":{"tags":["official evidence"],"summary":"Reconciliations","operationId":"reconciliations_api_v1_official_evidence_reconciliations_get","parameters":[{"name":"observation_id","in":"query","required":true,"schema":{"type":"string","format":"uuid","title":"Observation Id"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":20,"title":"Limit"}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","maximum":10000,"minimum":0,"default":0,"title":"Offset"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Reconciliations Api V1 Official Evidence Reconciliations Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/official-evidence/blobs/{sha256}":{"get":{"tags":["official evidence"],"summary":"Blob","operationId":"blob_api_v1_official_evidence_blobs__sha256__get","parameters":[{"name":"sha256","in":"path","required":true,"schema":{"type":"string","title":"Sha256"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/corpus-updates/bulk":{"get":{"tags":["corpus update evidence"],"summary":"Bulk Updates","description":"List bounded transaction partitions; source archives remain in RawStore.","operationId":"bulk_updates_api_v1_corpus_updates_bulk_get","parameters":[{"name":"session_id","in":"query","required":true,"schema":{"type":"string","format":"uuid","title":"Session Id"}},{"name":"invocation_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Invocation Id"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":20,"title":"Limit"}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","maximum":10000,"minimum":0,"default":0,"title":"Offset"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Bulk Updates Api V1 Corpus Updates Bulk Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/corpus-updates/derived":{"get":{"tags":["corpus update evidence"],"summary":"Derived Updates","operationId":"derived_updates_api_v1_corpus_updates_derived_get","parameters":[{"name":"bill_id","in":"query","required":true,"schema":{"type":"string","format":"uuid","title":"Bill Id"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":20,"title":"Limit"}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","maximum":10000,"minimum":0,"default":0,"title":"Offset"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Derived Updates Api V1 Corpus Updates Derived Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/corpus-updates":{"get":{"tags":["corpus update evidence"],"summary":"Corpus Updates","operationId":"corpus_updates_api_v1_corpus_updates_get","parameters":[{"name":"bill_id","in":"query","required":true,"schema":{"type":"string","format":"uuid","title":"Bill Id"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":20,"title":"Limit"}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","maximum":10000,"minimum":0,"default":0,"title":"Offset"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Corpus Updates Api V1 Corpus Updates Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/corpus-updates/official-sessions":{"get":{"tags":["corpus update evidence"],"summary":"Official Session Updates","description":"Primary-source session evidence, including reviewed transcription facts.","operationId":"official_session_updates_api_v1_corpus_updates_official_sessions_get","parameters":[{"name":"session_id","in":"query","required":true,"schema":{"type":"string","format":"uuid","title":"Session Id"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":20,"title":"Limit"}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","maximum":10000,"minimum":0,"default":0,"title":"Offset"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Official Session Updates Api V1 Corpus Updates Official Sessions Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/corpus-updates/sessions":{"get":{"tags":["corpus update evidence"],"summary":"Session Updates","description":"Expose retained session metadata mutations through the existing byte API.","operationId":"session_updates_api_v1_corpus_updates_sessions_get","parameters":[{"name":"session_id","in":"query","required":true,"schema":{"type":"string","format":"uuid","title":"Session Id"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":20,"title":"Limit"}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","maximum":10000,"minimum":0,"default":0,"title":"Offset"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Session Updates Api V1 Corpus Updates Sessions Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/jurisdictions":{"get":{"tags":["jurisdictions"],"summary":"List Jurisdictions","operationId":"list_jurisdictions_api_v1_jurisdictions_get","parameters":[{"name":"page","in":"query","required":false,"schema":{"type":"integer","maximum":1000,"minimum":1,"default":1,"title":"Page"}},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"default":25,"title":"Per Page"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Page_Jurisdiction_"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/jurisdictions/{jurisdiction_id}":{"get":{"tags":["jurisdictions"],"summary":"Get Jurisdiction","description":"Accepts either a jurisdiction UUID or a 2-letter abbreviation\n(case-insensitive), e.g. /jurisdictions/NC -- the web's /states/{code}\npages link by abbreviation, not UUID.","operationId":"get_jurisdiction_api_v1_jurisdictions__jurisdiction_id__get","parameters":[{"name":"jurisdiction_id","in":"path","required":true,"schema":{"type":"string","title":"Jurisdiction Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Jurisdiction"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/sessions":{"get":{"tags":["sessions"],"summary":"List Sessions","operationId":"list_sessions_api_v1_sessions_get","parameters":[{"name":"jurisdiction","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Jurisdiction abbreviation, e.g. NC","title":"Jurisdiction"},"description":"Jurisdiction abbreviation, e.g. NC"},{"name":"active","in":"query","required":false,"schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Active"}},{"name":"page","in":"query","required":false,"schema":{"type":"integer","maximum":1000,"minimum":1,"default":1,"title":"Page"}},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"default":25,"title":"Per Page"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Page_Session_"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/bills":{"get":{"tags":["bills"],"summary":"List Bills","operationId":"list_bills_api_v1_bills_get","parameters":[{"name":"jurisdiction","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Jurisdiction abbreviation, e.g. NC","title":"Jurisdiction"},"description":"Jurisdiction abbreviation, e.g. NC"},{"name":"session","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Session identifier","title":"Session"},"description":"Session identifier"},{"name":"identifier","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Bill number, matched on the normalized form -- 'HB123', 'hb 123' and 'H.B. 123' all find HB 123. Combine with jurisdiction (and session) to resolve a single bill.","title":"Identifier"},"description":"Bill number, matched on the normalized form -- 'HB123', 'hb 123' and 'H.B. 123' all find HB 123. Combine with jurisdiction (and session) to resolve a single bill."},{"name":"q","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Free-text search over title/description; a bill-number-shaped value (e.g. 'S9008', 'HB 123') ALSO matches on the normalized identifier and those matches are returned first, so callers don't need to know about `identifier=` to look a bill up by number.","title":"Q"},"description":"Free-text search over title/description; a bill-number-shaped value (e.g. 'S9008', 'HB 123') ALSO matches on the normalized identifier and those matches are returned first, so callers don't need to know about `identifier=` to look a bill up by number."},{"name":"chamber","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Chamber"}},{"name":"status","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Status"}},{"name":"subject","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Subject/topic tag, matched case-insensitively","title":"Subject"},"description":"Subject/topic tag, matched case-insensitively"},{"name":"sponsor","in":"query","required":false,"schema":{"anyOf":[{"type":"string","minLength":2},{"type":"null"}],"description":"Sponsor name, case-insensitive substring. Sponsor names are stored as the source published them -- usually a bare surname ('Rouson'), sometimes a committee ('Appropriations Committee on Health'). There is no legislator directory behind this, so a surname shared by two members returns both, and party/district cannot be filtered on.","title":"Sponsor"},"description":"Sponsor name, case-insensitive substring. Sponsor names are stored as the source published them -- usually a bare surname ('Rouson'), sometimes a committee ('Appropriations Committee on Health'). There is no legislator directory behind this, so a surname shared by two members returns both, and party/district cannot be filtered on."},{"name":"page","in":"query","required":false,"schema":{"type":"integer","maximum":1000,"minimum":1,"default":1,"title":"Page"}},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"default":25,"title":"Per Page"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Page_BillSummary_"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/bills/batch":{"get":{"tags":["bills"],"summary":"Batch Lookup Bills","description":"Resolve up to 100 bills in one request.\n\nExists because watchlist monitoring -- the main reason to consume this API\n-- was one HTTP round trip per bill. A caller tracking 160 bills spent 160\nrequests to answer \"did anything move?\", which is both slow for them and\nthe single easiest way to walk into the rate limit.\n\nAnything requested but not resolved comes back in `not_found` rather than\nbeing silently absent; see BillBatchEnvelope.","operationId":"batch_lookup_bills_api_v1_bills_batch_get","parameters":[{"name":"ids","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Comma-separated bill UUIDs, e.g. `ids=<uuid>,<uuid>`","title":"Ids"},"description":"Comma-separated bill UUIDs, e.g. `ids=<uuid>,<uuid>`"},{"name":"keys","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Comma-separated `JURISDICTION:BILL_NUMBER` pairs, e.g. `keys=HI:SB2135,NY:S9417`. Bill numbers are normalized, so `HI:sb 2135` resolves the same bill. Append a session to disambiguate: `NY:S9417:2025-2026 Regular Session`.","title":"Keys"},"description":"Comma-separated `JURISDICTION:BILL_NUMBER` pairs, e.g. `keys=HI:SB2135,NY:S9417`. Bill numbers are normalized, so `HI:sb 2135` resolves the same bill. Append a session to disambiguate: `NY:S9417:2025-2026 Regular Session`."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BillBatchEnvelope"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/bills/lookup":{"get":{"tags":["bills"],"summary":"Lookup Bills Get","description":"GET alias of `/bills/batch` under the `/bills/lookup` name.","operationId":"lookup_bills_get_api_v1_bills_lookup_get","parameters":[{"name":"ids","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Comma-separated bill UUIDs, e.g. `ids=<uuid>,<uuid>`","title":"Ids"},"description":"Comma-separated bill UUIDs, e.g. `ids=<uuid>,<uuid>`"},{"name":"keys","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Comma-separated `JURISDICTION:BILL_NUMBER` pairs, e.g. `keys=HI:SB2135,NY:S9417`. Append a session to disambiguate: `NY:S9417:2025-2026 Regular Session`.","title":"Keys"},"description":"Comma-separated `JURISDICTION:BILL_NUMBER` pairs, e.g. `keys=HI:SB2135,NY:S9417`. Append a session to disambiguate: `NY:S9417:2025-2026 Regular Session`."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BillBatchEnvelope"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["bills"],"summary":"Lookup Bills","description":"Batch lookup with a structured JSON body. Same response shape as\n`GET /bills/batch`, which it supersedes for anything non-trivial.\n\nThe GET form encodes each lookup as `JUR:NUMBER:SESSION` in the query\nstring, which breaks in two ways that are not hypothetical: 100\nsession-qualified keys is 4-8KB of URL, past the default request-line limit\non common proxies (they return 414 before our own error can fire), and the\ncolon delimiter collides with session identifiers and OCD jurisdiction ids\nthat contain colons themselves.\n\nKeys are echoed back on each result so callers can correlate without\nre-implementing bill-number normalization.","operationId":"lookup_bills_api_v1_bills_lookup_post","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BillLookupRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BillBatchEnvelope"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/bills/{bill_id}":{"get":{"tags":["bills"],"summary":"Get Bill","operationId":"get_bill_api_v1_bills__bill_id__get","parameters":[{"name":"bill_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Bill Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BillDetail"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/bills/{bill_id}/versions":{"get":{"tags":["bills"],"summary":"List Bill Versions","operationId":"list_bill_versions_api_v1_bills__bill_id__versions_get","parameters":[{"name":"bill_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Bill Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/BillVersionOut"},"title":"Response List Bill Versions Api V1 Bills  Bill Id  Versions Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/bills/{bill_id}/actions":{"get":{"tags":["bills"],"summary":"List Bill Actions","operationId":"list_bill_actions_api_v1_bills__bill_id__actions_get","parameters":[{"name":"bill_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Bill Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/BillActionOut"},"title":"Response List Bill Actions Api V1 Bills  Bill Id  Actions Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/bills/{bill_id}/sponsors":{"get":{"tags":["bills"],"summary":"List Bill Sponsors","operationId":"list_bill_sponsors_api_v1_bills__bill_id__sponsors_get","parameters":[{"name":"bill_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Bill Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/SponsorshipOut"},"title":"Response List Bill Sponsors Api V1 Bills  Bill Id  Sponsors Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/bills/{bill_id}/votes":{"get":{"tags":["bills"],"summary":"List Bill Votes","operationId":"list_bill_votes_api_v1_bills__bill_id__votes_get","parameters":[{"name":"bill_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Bill Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/VoteEventOut"},"title":"Response List Bill Votes Api V1 Bills  Bill Id  Votes Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/bills/{bill_id}/related":{"get":{"tags":["bills"],"summary":"List Related Bills","description":"Companion, prior-session and superseded-bill cross-references.\n\nThese have been collected all along (~100k rows, of which ~47k are\n`prior-session`) and were never exposed -- the single most-requested thing\nfor multi-year policy tracking, because a bill that dies and returns next\nsession under a new number is otherwise untrackable.\n\nUpstream gives us only the related bill's IDENTIFIER, so the target is\nresolved here, scoped to the same jurisdiction. Same-session companions\nusually resolve; prior-session links usually do not, because that session\nis outside this corpus. Unresolved links still return their identifier\nrather than being dropped.","operationId":"list_related_bills_api_v1_bills__bill_id__related_get","parameters":[{"name":"bill_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Bill Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/RelatedBillOut"},"title":"Response List Related Bills Api V1 Bills  Bill Id  Related Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/bills/{bill_id}/subjects":{"get":{"tags":["bills"],"summary":"List Bill Subjects","description":"Subject/topic tags. 263,485 of these were already stored and reachable\nonly through /search?subject=; a consumer looking at one bill had no way to\nask what it is ABOUT.","operationId":"list_bill_subjects_api_v1_bills__bill_id__subjects_get","parameters":[{"name":"bill_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Bill Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"type":"string"},"title":"Response List Bill Subjects Api V1 Bills  Bill Id  Subjects Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/bills/{bill_id}/documents":{"get":{"tags":["bills"],"summary":"List Bill Documents","operationId":"list_bill_documents_api_v1_bills__bill_id__documents_get","parameters":[{"name":"bill_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Bill Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/BillDocumentOut"},"title":"Response List Bill Documents Api V1 Bills  Bill Id  Documents Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/bills/{bill_id}/compare":{"get":{"tags":["bills"],"summary":"Compare Bill Versions","description":"Deterministic diff of extracted text between two versions of a bill.\n\nMirrors apps/mcp compare_bill_versions (difflib), reimplemented locally\nper architecture: apps don't import across each other. DERIVED output,\nnot an official document -- see docs/SPEC.md \"Version diffing\".","operationId":"compare_bill_versions_api_v1_bills__bill_id__compare_get","parameters":[{"name":"bill_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Bill Id"}},{"name":"from","in":"query","required":true,"schema":{"type":"string","format":"uuid","description":"Bill version id to diff from","title":"From"},"description":"Bill version id to diff from"},{"name":"to","in":"query","required":true,"schema":{"type":"string","format":"uuid","description":"Bill version id to diff to","title":"To"},"description":"Bill version id to diff to"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BillCompareEnvelope"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/bills/{bill_id}/documents/{document_id}/text":{"get":{"tags":["bills"],"summary":"Get Bill Document Text","description":"Extracted full text of one document, as JSON.\n\nReads the same `bill_documents.extracted_text` column /compare diffs and\nMCP's `get_bill_record(include_full_text=True)` read (see\n`compare_bill_versions` above and apps/mcp/billcommons_mcp/tools.py) --\nexposed directly here rather than only reachable via a diff or the MCP\ntool. Heavy route: see `_HEAVY_ROUTE_PATTERNS` in rate_limit.py, same\nquota/rate-limit tier as /compare and /full.","operationId":"get_bill_document_text_api_v1_bills__bill_id__documents__document_id__text_get","parameters":[{"name":"bill_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Bill Id"}},{"name":"document_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Document Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BillDocumentTextOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/bills/{bill_id}/evidence":{"get":{"tags":["bills"],"summary":"Get Bill Evidence","description":"A citable evidence packet for one bill.\n\nThis is the endpoint the MCP tool's `permalink` and `download_url` point\nat, so a packet quoted in a report resolves for a human reader instead of\nbeing a UUID stranded in an agent transcript.\n\nThe `snapshot_id` is computed by `billcommons_shared.evidence`, the same\nmodule the MCP tool uses. That sharing is the point: if the two surfaces\ncomputed it independently they would eventually disagree about whether a\nbill had changed, which is worse than not offering the id at all.\n\nThe retained official comparison uses the same bounded reader as MCP.\nIts capture times describe retained evidence, not current freshness, and\nan unavailable comparison does not establish that the records match.\n\nReturned as a raw JSONResponse rather than through a response_model so the\npayload the caller downloads is byte-identical to the one that was hashed.","operationId":"get_bill_evidence_api_v1_bills__bill_id__evidence_get","parameters":[{"name":"bill_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Bill Id"}},{"name":"download","in":"query","required":false,"schema":{"type":"boolean","description":"Serve as a file attachment named after the bill and snapshot.","default":false,"title":"Download"},"description":"Serve as a file attachment named after the bill and snapshot."},{"name":"question","in":"query","required":false,"schema":{"anyOf":[{"type":"string","maxLength":500},{"type":"null"}],"description":"What this packet was assembled to answer; echoed back into the artifact.","title":"Question"},"description":"What this packet was assembled to answer; echoed back into the artifact."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/bills/{bill_id}/full":{"get":{"tags":["bills"],"summary":"Get Bill Full","description":"Every sub-resource for one bill in a single round trip.\n\nComposes the existing handlers rather than re-implementing their queries.\nDuplicating them would mean this envelope and the individual endpoints\ncould drift into disagreeing about the same bill -- and the sub-resource\nhandlers carry real logic worth not forking (related-bill identifier\nresolution, vote records grouped per event, the enrolled-outcome flag).\n\nThey each call _get_bill_or_404, which is `db.get` -- served from the\nsession identity map after the first, so the repeated existence check costs\nnothing.","operationId":"get_bill_full_api_v1_bills__bill_id__full_get","parameters":[{"name":"bill_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Bill Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BillFullEnvelope"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/people":{"get":{"tags":["people"],"summary":"List People","operationId":"list_people_api_v1_people_get","parameters":[{"name":"jurisdiction","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Jurisdiction abbreviation, e.g. NC","title":"Jurisdiction"},"description":"Jurisdiction abbreviation, e.g. NC"},{"name":"name","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Case-insensitive substring match on name","title":"Name"},"description":"Case-insensitive substring match on name"},{"name":"page","in":"query","required":false,"schema":{"type":"integer","maximum":1000,"minimum":1,"default":1,"title":"Page"}},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"default":25,"title":"Per Page"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Page_PersonSummary_"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/people/{person_id}":{"get":{"tags":["people"],"summary":"Get Person","operationId":"get_person_api_v1_people__person_id__get","parameters":[{"name":"person_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Person Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PersonDetail"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/committees":{"get":{"tags":["committees"],"summary":"List Committees","operationId":"list_committees_api_v1_committees_get","parameters":[{"name":"jurisdiction","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Jurisdiction abbreviation, e.g. NC","title":"Jurisdiction"},"description":"Jurisdiction abbreviation, e.g. NC"},{"name":"page","in":"query","required":false,"schema":{"type":"integer","maximum":1000,"minimum":1,"default":1,"title":"Page"}},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"default":25,"title":"Per Page"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Page_CommitteeOut_"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/committees/{committee_id}":{"get":{"tags":["committees"],"summary":"Get Committee","operationId":"get_committee_api_v1_committees__committee_id__get","parameters":[{"name":"committee_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Committee Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CommitteeOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/events":{"get":{"tags":["events"],"summary":"List Events","operationId":"list_events_api_v1_events_get","parameters":[{"name":"jurisdiction","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Jurisdiction abbreviation, e.g. NC","title":"Jurisdiction"},"description":"Jurisdiction abbreviation, e.g. NC"},{"name":"page","in":"query","required":false,"schema":{"type":"integer","maximum":1000,"minimum":1,"default":1,"title":"Page"}},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"default":25,"title":"Per Page"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Page_LegislativeEventOut_"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/search":{"get":{"tags":["search"],"summary":"Search","operationId":"search_api_v1_search_get","parameters":[{"name":"q","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Search text; bill-number, keyword, or phrase","title":"Q"},"description":"Search text; bill-number, keyword, or phrase"},{"name":"jurisdiction","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Jurisdiction abbreviation, e.g. NC","title":"Jurisdiction"},"description":"Jurisdiction abbreviation, e.g. NC"},{"name":"session","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Session identifier","title":"Session"},"description":"Session identifier"},{"name":"chamber","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Chamber"}},{"name":"status","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Status"}},{"name":"sponsor","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Sponsor"}},{"name":"subject","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Subject"}},{"name":"committee","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Committee"}},{"name":"date_from","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Date From"}},{"name":"date_to","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Date To"}},{"name":"sort","in":"query","required":false,"schema":{"type":"string","default":"relevance","title":"Sort"}},{"name":"page","in":"query","required":false,"schema":{"type":"integer","maximum":1000,"minimum":1,"default":1,"title":"Page"}},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"default":25,"title":"Per Page"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Page_SearchResult_"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/changes":{"get":{"tags":["changes"],"summary":"List Changes","description":"Bill changes in commit order, oldest first.\n\nPoll with the `next_cursor` from the previous response. `has_more` false\nmeans you are caught up; keep the cursor and poll again later.","operationId":"list_changes_api_v1_changes_get","parameters":[{"name":"cursor","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Opaque cursor from a previous response's `next_cursor`. Omit to start from the beginning of the log.","title":"Cursor"},"description":"Opaque cursor from a previous response's `next_cursor`. Omit to start from the beginning of the log."},{"name":"ids","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Comma-separated bill UUIDs -- returns changes only for these bills. Up to 200 per request. This is what makes the feed usable for a watchlist: without it a caller tracking 160 bills must page the entire national delta and filter client-side.","title":"Ids"},"description":"Comma-separated bill UUIDs -- returns changes only for these bills. Up to 200 per request. This is what makes the feed usable for a watchlist: without it a caller tracking 160 bills must page the entire national delta and filter client-side."},{"name":"jurisdiction","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Restrict to one jurisdiction abbreviation, e.g. NC","title":"Jurisdiction"},"description":"Restrict to one jurisdiction abbreviation, e.g. NC"},{"name":"kind","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Restrict to one change kind: created, status, actions, sponsors, text, metadata, votes.","title":"Kind"},"description":"Restrict to one change kind: created, status, actions, sponsors, text, metadata, votes."},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"default":100,"title":"Per Page"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChangeFeedEnvelope"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/feeds/{jurisdiction}.atom":{"get":{"tags":["feeds"],"summary":"Jurisdiction Atom Feed","operationId":"jurisdiction_atom_feed_api_v1_feeds__jurisdiction__atom_get","parameters":[{"name":"jurisdiction","in":"path","required":true,"schema":{"type":"string","title":"Jurisdiction"}},{"name":"kind","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Optional change kind, e.g. actions","title":"Kind"},"description":"Optional change kind, e.g. actions"},{"name":"topic","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Curated topic slug from /topics; requires kind=actions","title":"Topic"},"description":"Curated topic slug from /topics; requires kind=actions"},{"name":"bill_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"description":"Bill UUID; requires kind=actions","title":"Bill Id"},"description":"Bill UUID; requires kind=actions"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/sources":{"get":{"tags":["sources"],"summary":"List Sources","operationId":"list_sources_api_v1_sources_get","parameters":[{"name":"entity_type","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Entity Type"}},{"name":"entity_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Entity Id"}},{"name":"page","in":"query","required":false,"schema":{"type":"integer","maximum":1000,"minimum":1,"default":1,"title":"Page"}},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"default":25,"title":"Per Page"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Page_SourceRecordOut_"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/coverage":{"get":{"tags":["coverage"],"summary":"List Coverage","operationId":"list_coverage_api_v1_coverage_get","parameters":[{"name":"jurisdiction","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Jurisdiction abbreviation, e.g. NC","title":"Jurisdiction"},"description":"Jurisdiction abbreviation, e.g. NC"},{"name":"status","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Status"}},{"name":"page","in":"query","required":false,"schema":{"type":"integer","maximum":1000,"minimum":1,"default":1,"title":"Page"}},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"default":25,"title":"Per Page"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Page_CoverageRowOut_"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/data-health":{"get":{"tags":["coverage"],"summary":"Data Health","description":"Local ingestion evidence; official-source reconciliation may be unknown.\n\ngenerated_at is the observation time. Cached observations can be up to\nfive minutes old; this is not a guarantee of legislative freshness.","operationId":"data_health_api_v1_data_health_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Data Health Api V1 Data Health Get"}}}}}}},"/api/v1/sitemap/stats":{"get":{"tags":["sitemap"],"summary":"Sitemap Stats","description":"Chunk count for the sitemap index.\n\nSplit from the data route so the index can be built with one cheap count\ninstead of fetching a chunk just to read its metadata.","operationId":"sitemap_stats_api_v1_sitemap_stats_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Sitemap Stats Api V1 Sitemap Stats Get"}}}}}}},"/api/v1/sitemap/bills":{"get":{"tags":["sitemap"],"summary":"Sitemap Bills","operationId":"sitemap_bills_api_v1_sitemap_bills_get","parameters":[{"name":"chunk","in":"query","required":false,"schema":{"type":"integer","minimum":0,"description":"Zero-based chunk index","default":0,"title":"Chunk"},"description":"Zero-based chunk index"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Sitemap Bills Api V1 Sitemap Bills Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/stats/mortality":{"get":{"tags":["stats"],"summary":"Mortality Report","description":"Aggregate current bill statuses for public state/DC jurisdictions.\n\nThe report includes every stored bill in the public jurisdictions and does\nnot filter by calendar year or legislative session. Terminal statuses are\nreported separately and as the `did_not_pass` sum; missing or unrecognized\nstatuses remain in `unknown`.","operationId":"mortality_report_api_v1_stats_mortality_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MortalityReportEnvelope"}}}}}}},"/api/v1/stats/usage":{"get":{"tags":["stats"],"summary":"Usage Stats","description":"Aggregate MCP tool usage. Public, because the honest number is the point.\n\nThis exists because \"is anyone using this?\" was unanswerable. Over one log\nwindow the MCP server served 139 successful POSTs and exactly ONE tool\ncall: everything else connected, listed the tools, and disconnected --\ndirectory health probers, not researchers. Connections are not usage, and\nonly tool CALLS distinguish them.\n\nPublished rather than kept private: a project whose pitch is that it\nrefuses to dress up what it does not know should not quietly sit on its own\nadoption numbers. Aggregate only -- no IP, no query text, no bill ids.\n\nOur own read-path monitor calls a real tool every two minutes, on purpose:\na handshake succeeds against a dead database, so nothing cheaper detects\nthe outage that prompted it. That makes it ~720 synthetic calls a day, and\nfor the first hours of this table's life it was 61 of 63 rows. Those calls\nare tagged at the MCP edge and excluded here, and the count we subtracted\nis reported as `self_probe_calls` so the arithmetic is checkable.","operationId":"usage_stats_api_v1_stats_usage_get","parameters":[{"name":"days","in":"query","required":false,"schema":{"type":"integer","maximum":365,"minimum":1,"default":30,"title":"Days"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UsageStatsOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/topics":{"get":{"tags":["topics"],"summary":"List Topics","operationId":"list_topics_api_v1_topics_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TopicListEnvelope"}}}}}}},"/api/v1/topics/{slug}":{"get":{"tags":["topics"],"summary":"Topic Bills","operationId":"topic_bills_api_v1_topics__slug__get","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","title":"Slug"}},{"name":"jurisdiction","in":"query","required":false,"schema":{"anyOf":[{"type":"string","minLength":2,"maxLength":2,"pattern":"^[A-Za-z]{2}$"},{"type":"null"}],"description":"Optional two-letter state or DC abbreviation, e.g. NC","title":"Jurisdiction"},"description":"Optional two-letter state or DC abbreviation, e.g. NC"},{"name":"page","in":"query","required":false,"schema":{"type":"integer","maximum":1000,"minimum":1,"default":1,"title":"Page"}},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"default":25,"title":"Per Page"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Page_BillSummary_"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/webhooks":{"post":{"tags":["webhooks"],"summary":"Create Webhook","operationId":"create_webhook_api_v1_webhooks_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookCreateRequest"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookCreateResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/webhooks/{sub_id}":{"get":{"tags":["webhooks"],"summary":"Get Webhook","operationId":"get_webhook_api_v1_webhooks__sub_id__get","parameters":[{"name":"sub_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Sub Id"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookStatusResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["webhooks"],"summary":"Delete Webhook","operationId":"delete_webhook_api_v1_webhooks__sub_id__delete","parameters":[{"name":"sub_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Sub Id"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/webhooks/{sub_id}/reactivate":{"post":{"tags":["webhooks"],"summary":"Reactivate Webhook","operationId":"reactivate_webhook_api_v1_webhooks__sub_id__reactivate_post","parameters":[{"name":"sub_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Sub Id"}},{"name":"mode","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"resume: keep last_seq, the backlog since disable drains normally. skip: fast-forward last_seq to the current watermark, dropping the backlog. Required -- there is no default.","title":"Mode"},"description":"resume: keep last_seq, the backlog since disable drains normally. skip: fast-forward last_seq to the current watermark, dropping the backlog. Required -- there is no default."},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookReactivateResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/scout/jobs":{"post":{"tags":["scout"],"summary":"Create Job","operationId":"create_job_api_v1_scout_jobs_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateScoutJob"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/scout/jobs/{job_id}/monitor":{"post":{"tags":["scout"],"summary":"Save Monitor","operationId":"save_monitor_api_v1_scout_jobs__job_id__monitor_post","parameters":[{"name":"job_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Job Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SaveScoutMonitor"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/scout/monitors":{"get":{"tags":["scout"],"summary":"List Monitors","operationId":"list_monitors_api_v1_scout_monitors_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/v1/scout/monitors/{monitor_id}/runs":{"get":{"tags":["scout"],"summary":"List Monitor Runs","operationId":"list_monitor_runs_api_v1_scout_monitors__monitor_id__runs_get","parameters":[{"name":"monitor_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Monitor Id"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":50,"title":"Limit"}},{"name":"cursor","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Cursor"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/scout/monitors/{monitor_id}":{"patch":{"tags":["scout"],"summary":"Update Monitor","operationId":"update_monitor_api_v1_scout_monitors__monitor_id__patch","parameters":[{"name":"monitor_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Monitor Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateScoutMonitor"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/scout/jobs/{job_id}":{"get":{"tags":["scout"],"summary":"Get Job","operationId":"get_job_api_v1_scout_jobs__job_id__get","parameters":[{"name":"job_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Job Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/scout/jobs/{job_id}/cancel":{"post":{"tags":["scout"],"summary":"Cancel Job","operationId":"cancel_job_api_v1_scout_jobs__job_id__cancel_post","parameters":[{"name":"job_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Job Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/scout/jobs/{job_id}/evidence":{"get":{"tags":["scout"],"summary":"Get Evidence","operationId":"get_evidence_api_v1_scout_jobs__job_id__evidence_get","parameters":[{"name":"job_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Job Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/scout/jobs/{job_id}/browser-sessions/{session_id}/replay":{"get":{"tags":["scout"],"summary":"Get Replay","operationId":"get_replay_api_v1_scout_jobs__job_id__browser_sessions__session_id__replay_get","parameters":[{"name":"job_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Job Id"}},{"name":"session_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Session Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}}},"components":{"schemas":{"AlertConfirmResponse":{"properties":{"confirmed":{"type":"boolean","title":"Confirmed"},"lifecycle":{"type":"string","title":"Lifecycle","default":"active"},"meta":{"additionalProperties":true,"type":"object","title":"Meta"}},"type":"object","required":["confirmed","meta"],"title":"AlertConfirmResponse"},"AlertSubscribeRequest":{"properties":{"email":{"type":"string","maxLength":320,"title":"Email"},"kind":{"type":"string","title":"Kind","default":"topic"},"target":{"type":"string","maxLength":100,"title":"Target"},"jurisdiction":{"anyOf":[{"type":"string","maxLength":2},{"type":"null"}],"title":"Jurisdiction","description":"Narrow the digest to one jurisdiction, e.g. 'FL'. Omit for a national digest across all 50 states + DC."}},"type":"object","required":["email","target"],"title":"AlertSubscribeRequest"},"AlertSubscribeResponse":{"properties":{"subscribed":{"type":"boolean","title":"Subscribed"},"lifecycle":{"type":"string","title":"Lifecycle","default":"request_accepted"},"kind":{"type":"string","title":"Kind"},"target":{"type":"string","title":"Target"},"jurisdiction":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Jurisdiction"},"meta":{"additionalProperties":true,"type":"object","title":"Meta"}},"type":"object","required":["subscribed","kind","target","meta"],"title":"AlertSubscribeResponse"},"BillActionOut":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"bill_id":{"type":"string","format":"uuid","title":"Bill Id"},"description":{"type":"string","title":"Description"},"action_date":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Action Date"},"classification":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Classification"},"order":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Order"}},"type":"object","required":["id","bill_id","description"],"title":"BillActionOut"},"BillBatchEnvelope":{"properties":{"data":{"items":{"$ref":"#/components/schemas/BillSummary"},"type":"array","title":"Data"},"not_found":{"items":{"type":"string"},"type":"array","title":"Not Found"},"ambiguous":{"additionalProperties":{"items":{"type":"string"},"type":"array"},"type":"object","title":"Ambiguous","default":{}},"meta":{"additionalProperties":true,"type":"object","title":"Meta"}},"type":"object","required":["data","not_found","meta"],"title":"BillBatchEnvelope","description":"Response for the batch lookup.\n\n`not_found` is the point of the shape. A batch endpoint that just returns\nthe rows it managed to resolve makes a typo, a renumbered bill and a\njurisdiction we do not cover all look identical to a caller diffing counts\n-- and this project has already shipped two bugs where a short result was\nread as a complete one. Every requested key is accounted for in exactly\none of the three fields.\n\n`ambiguous` is kept separate from `not_found` because they call for\nopposite actions. Not-found means the bill is not here; ambiguous means it\nis here more than once (the same number in several sessions) and the\nrequest needs a session to pick one. It maps the key to the session\nidentifiers that matched, so the caller can re-ask without a second query.\nFolding these together would tell a consumer to drop a bill we hold."},"BillCompareEnvelope":{"properties":{"data":{"$ref":"#/components/schemas/BillCompareOut"},"meta":{"additionalProperties":true,"type":"object","title":"Meta"}},"type":"object","required":["data","meta"],"title":"BillCompareEnvelope"},"BillCompareOut":{"properties":{"bill_id":{"type":"string","format":"uuid","title":"Bill Id"},"from_version_id":{"type":"string","format":"uuid","title":"From Version Id"},"to_version_id":{"type":"string","format":"uuid","title":"To Version Id"},"diff_lines":{"items":{"$ref":"#/components/schemas/DiffLineOut"},"type":"array","title":"Diff Lines"}},"type":"object","required":["bill_id","from_version_id","to_version_id","diff_lines"],"title":"BillCompareOut"},"BillDetail":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"jurisdiction_id":{"type":"string","format":"uuid","title":"Jurisdiction Id"},"session_id":{"type":"string","format":"uuid","title":"Session Id"},"jurisdiction_abbreviation":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Jurisdiction Abbreviation"},"session_identifier":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Session Identifier"},"chamber":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Chamber"},"identifier":{"type":"string","title":"Identifier"},"identifier_norm":{"type":"string","title":"Identifier Norm"},"title":{"type":"string","title":"Title"},"short_title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Short Title"},"bill_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Bill Type"},"status":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Status"},"status_date":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Status Date"},"introduced_date":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Introduced Date"},"latest_action_text":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Latest Action Text"},"latest_action_date":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Latest Action Date"},"source_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Source Url"},"updated_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Updated At"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"source_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Source Name"},"retrieved_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Retrieved At"},"upstream_updated_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Upstream Updated At"},"enrolled_outcome_uncaptured":{"type":"boolean","title":"Enrolled Outcome Uncaptured","default":false},"replaces":{"items":{"$ref":"#/components/schemas/RelatedBillLink"},"type":"array","title":"Replaces"},"replaced_by":{"items":{"$ref":"#/components/schemas/RelatedBillLink"},"type":"array","title":"Replaced By"}},"type":"object","required":["id","jurisdiction_id","session_id","identifier","identifier_norm","title"],"title":"BillDetail"},"BillDocumentOut":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"bill_version_id":{"type":"string","format":"uuid","title":"Bill Version Id"},"media_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Media Type"},"url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Url"},"has_extracted_text":{"type":"boolean","title":"Has Extracted Text","default":false},"text_is_partial":{"type":"boolean","title":"Text Is Partial","description":"True when text was extracted from a malformed PDF with one or more unreadable pages -- the text is real but incomplete, so diffs/quotes against it may be missing sections.","default":false}},"type":"object","required":["id","bill_version_id"],"title":"BillDocumentOut"},"BillDocumentTextOut":{"properties":{"document_id":{"type":"string","format":"uuid","title":"Document Id"},"bill_id":{"type":"string","format":"uuid","title":"Bill Id"},"version_id":{"type":"string","format":"uuid","title":"Version Id"},"extracted_text":{"type":"string","title":"Extracted Text"},"char_count":{"type":"integer","title":"Char Count"},"fulltext_status":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Fulltext Status","description":"Parsed from bill_documents.license_note's `fulltext_status=<token>` encoding; null if the note doesn't carry one."}},"type":"object","required":["document_id","bill_id","version_id","extracted_text","char_count"],"title":"BillDocumentTextOut"},"BillFullEnvelope":{"properties":{"bill":{"$ref":"#/components/schemas/BillDetail"},"versions":{"items":{"$ref":"#/components/schemas/BillVersionOut"},"type":"array","title":"Versions"},"actions":{"items":{"$ref":"#/components/schemas/BillActionOut"},"type":"array","title":"Actions"},"sponsors":{"items":{"$ref":"#/components/schemas/SponsorshipOut"},"type":"array","title":"Sponsors"},"votes":{"items":{"$ref":"#/components/schemas/VoteEventOut"},"type":"array","title":"Votes"},"documents":{"items":{"$ref":"#/components/schemas/BillDocumentOut"},"type":"array","title":"Documents"},"related":{"items":{"$ref":"#/components/schemas/RelatedBillOut"},"type":"array","title":"Related"},"subjects":{"items":{"type":"string"},"type":"array","title":"Subjects"},"jurisdiction":{"anyOf":[{"$ref":"#/components/schemas/Jurisdiction"},{"type":"null"}]},"meta":{"additionalProperties":true,"type":"object","title":"Meta"}},"type":"object","required":["bill","versions","actions","sponsors","votes","documents","related","subjects","meta"],"title":"BillFullEnvelope","description":"Everything one bill page needs, in a single response.\n\nThe web bill page fanned out to NINE requests per render (detail, versions,\nactions, sponsors, votes, documents, related, subjects, jurisdiction). The\nsitemap exposed ~200,000 such pages, so one crawl was well over a million\nAPI requests -- and each one checked out its own pooled connection. That\nfan-out is the load half of the 2026-08-02 outage.\n\nOne request, one connection, one transaction. Sub-resource endpoints stay\nexactly as they are: they are a reasonable API for a consumer who wants one\nslice, and this is for the consumer who wants all of it."},"BillLookupKey":{"properties":{"id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Id"},"jurisdiction":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Jurisdiction"},"identifier":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Identifier"},"session":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Session"}},"type":"object","title":"BillLookupKey","description":"One structured lookup in a POST /bills/lookup body.\n\nStructured fields rather than a `JUR:NUMBER:SESSION` string. The colon\ngrammar cannot survive its own data: 14 of this corpus's 77 session\nidentifiers already contain colons (\"Alabama special: Congressional\nmaps\"), and OCD-style jurisdiction ids are colon-delimited throughout\n(`ocd-jurisdiction/country:us/state:ca`). Anything beyond US states makes\nthe delimiter ambiguous, and by then it is a frozen public contract."},"BillLookupRequest":{"properties":{"keys":{"items":{"$ref":"#/components/schemas/BillLookupKey"},"type":"array","title":"Keys"}},"type":"object","required":["keys"],"title":"BillLookupRequest"},"BillSummary":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"jurisdiction_id":{"type":"string","format":"uuid","title":"Jurisdiction Id"},"session_id":{"type":"string","format":"uuid","title":"Session Id"},"jurisdiction_abbreviation":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Jurisdiction Abbreviation"},"session_identifier":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Session Identifier"},"chamber":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Chamber"},"identifier":{"type":"string","title":"Identifier"},"identifier_norm":{"type":"string","title":"Identifier Norm"},"title":{"type":"string","title":"Title"},"short_title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Short Title"},"bill_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Bill Type"},"status":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Status"},"status_date":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Status Date"},"introduced_date":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Introduced Date"},"latest_action_text":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Latest Action Text"},"latest_action_date":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Latest Action Date"},"source_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Source Url"},"updated_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Updated At"}},"type":"object","required":["id","jurisdiction_id","session_id","identifier","identifier_norm","title"],"title":"BillSummary","description":"Row shape used in list/search results (lighter than the detail view)."},"BillVersionOut":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"bill_id":{"type":"string","format":"uuid","title":"Bill Id"},"note":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Note"},"date":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Date"}},"type":"object","required":["id","bill_id"],"title":"BillVersionOut"},"ChangeEvent":{"properties":{"cursor":{"type":"string","title":"Cursor"},"kind":{"type":"string","title":"Kind","description":"created | status | actions | sponsors | text | metadata | votes. `text` means document text became available -- the bill is now searchable and diffable. `votes` means one or more vote events were recorded; `detail` carries the tally when the source provides one."},"changed_at":{"type":"string","format":"date-time","title":"Changed At"},"detail":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Detail","description":"Human-readable specifics, e.g. 'in_committee -> enacted'."},"bill":{"anyOf":[{"$ref":"#/components/schemas/BillSummary"},{"type":"null"}]}},"type":"object","required":["cursor","kind","changed_at"],"title":"ChangeEvent","description":"One entry in the change feed.\n\nCarries the KIND of change, so a consumer knows which of its cached\ncollections to refetch instead of diffing the whole bill. `bill` is the\ncurrent state of the bill, not its state at the time of the event -- this\nis a change feed, not an audit log; several events for one bill in a page\nall show the same current row."},"ChangeFeedEnvelope":{"properties":{"data":{"items":{"$ref":"#/components/schemas/ChangeEvent"},"type":"array","title":"Data"},"next_cursor":{"type":"string","title":"Next Cursor"},"has_more":{"type":"boolean","title":"Has More"},"meta":{"additionalProperties":true,"type":"object","title":"Meta"}},"type":"object","required":["data","next_cursor","has_more","meta"],"title":"ChangeFeedEnvelope","description":"Response for `/changes`.\n\nPass `next_cursor` back verbatim to continue. It is opaque on purpose:\nconsumers persist cursors for months, so publishing the raw ordering key\nwould freeze it, and this way the ordering scheme can change later without\ninvalidating a single stored cursor.\n\nOn an empty page `next_cursor` echoes the cursor you sent, so a polling\nloop can store the response unconditionally and never accidentally rewind\nor skip."},"CheckoutRequest":{"properties":{"plan":{"type":"string","enum":["builder","scale"],"title":"Plan"},"interval":{"type":"string","enum":["monthly","annual"],"title":"Interval"}},"type":"object","required":["plan","interval"],"title":"CheckoutRequest"},"CheckoutResponse":{"properties":{"url":{"type":"string","title":"Url"}},"type":"object","required":["url"],"title":"CheckoutResponse"},"CommitteeOut":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"organization_id":{"type":"string","format":"uuid","title":"Organization Id"},"name":{"type":"string","title":"Name"},"classification":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Classification"}},"type":"object","required":["id","organization_id","name"],"title":"CommitteeOut"},"CoverageFreshnessOut":{"properties":{"official_freshness":{"type":"string","const":"unverified","title":"Official Freshness","description":"Statewide semantic freshness is unverified by this coverage response."},"reason":{"type":"string","title":"Reason"},"jurisdiction_scope":{"type":"string","enum":["public_registry","unlisted"],"title":"Jurisdiction Scope"},"coverage_status_scope":{"type":"string","const":"stored_bill_and_text_availability","title":"Coverage Status Scope"},"local_timestamp_scope":{"type":"string","const":"local_coverage_bookkeeping","title":"Local Timestamp Scope"},"assessed_at":{"type":"string","format":"date-time","title":"Assessed At"},"official_sources":{"$ref":"#/components/schemas/CoverageSourceHealthOut"},"data_health_url":{"type":"string","title":"Data Health Url"}},"type":"object","required":["official_freshness","reason","jurisdiction_scope","coverage_status_scope","local_timestamp_scope","assessed_at","official_sources","data_health_url"],"title":"CoverageFreshnessOut","description":"Stored coverage interpretation and bounded retained observation work.\n\nSuccessful observations can be landing-page captures. These operational\nstates do not establish statewide semantic legislative freshness."},"CoverageRowOut":{"properties":{"jurisdiction_code":{"type":"string","title":"Jurisdiction Code"},"jurisdiction_name":{"type":"string","title":"Jurisdiction Name"},"session_identifier":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Session Identifier"},"session_status":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Session Status"},"bill_count":{"type":"integer","title":"Bill Count"},"full_text_count":{"type":"integer","title":"Full Text Count"},"full_text_pct":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Full Text Pct"},"full_text_available_count":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Full Text Available Count"},"full_text_of_available_pct":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Full Text Of Available Pct"},"last_update":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Last Update"},"source_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Source Name"},"validation_sample":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Validation Sample"},"validation_pass_rate":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Validation Pass Rate"},"status":{"type":"string","title":"Status"},"known_gaps":{"items":{"type":"string"},"type":"array","title":"Known Gaps","default":[]},"freshness":{"anyOf":[{"$ref":"#/components/schemas/CoverageFreshnessOut"},{"type":"null"}],"description":"Interpretation of stored coverage and local timestamps, with bounded retained official-source operational evidence. Statewide semantic freshness remains unverified."}},"type":"object","required":["jurisdiction_code","jurisdiction_name","bill_count","full_text_count","status"],"title":"CoverageRowOut","description":"A row in the public coverage matrix (SPEC.md \"Coverage\"). Assembled by\njoining jurisdiction_coverage + jurisdictions + sessions -- not a direct\nORM projection of any single table."},"CoverageSourceHealthOut":{"properties":{"target_count":{"type":"integer","minimum":0.0,"title":"Target Count"},"targets_by_state":{"additionalProperties":{"type":"integer"},"type":"object","title":"Targets By State"},"sample_limit":{"type":"integer","minimum":1.0,"title":"Sample Limit"},"sampled_target_count":{"type":"integer","minimum":0.0,"title":"Sampled Target Count"},"sample_truncated":{"type":"boolean","title":"Sample Truncated"},"sampled_targets":{"items":{"$ref":"#/components/schemas/CoverageSourceTargetOut"},"type":"array","title":"Sampled Targets"},"evidence_url":{"type":"string","title":"Evidence Url"},"evidence_scope":{"type":"string","enum":["jurisdiction","public_registry_overview"],"title":"Evidence Scope"}},"type":"object","required":["target_count","targets_by_state","sample_limit","sampled_target_count","sample_truncated","sampled_targets","evidence_url","evidence_scope"],"title":"CoverageSourceHealthOut"},"CoverageSourceTargetOut":{"properties":{"target_id":{"type":"string","title":"Target Id"},"observation_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Observation Id"},"state":{"type":"string","title":"State"},"retrieved_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Retrieved At"},"upstream_updated_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Upstream Updated At"},"next_check_at":{"type":"string","format":"date-time","title":"Next Check At"}},"type":"object","required":["target_id","state","next_check_at"],"title":"CoverageSourceTargetOut"},"CreateScoutJob":{"properties":{"query":{"type":"string","maxLength":500,"minLength":1,"title":"Query"},"jurisdiction":{"type":"string","maxLength":2,"minLength":2,"title":"Jurisdiction","default":"FL"}},"type":"object","required":["query"],"title":"CreateScoutJob"},"DiffLineOut":{"properties":{"type":{"type":"string","title":"Type"},"text":{"type":"string","title":"Text"}},"type":"object","required":["type","text"],"title":"DiffLineOut"},"FeedbackRequest":{"properties":{"message":{"type":"string","maxLength":5000,"minLength":3,"title":"Message"},"email":{"anyOf":[{"type":"string","maxLength":320},{"type":"null"}],"title":"Email"},"page":{"anyOf":[{"type":"string","maxLength":2000},{"type":"null"}],"title":"Page"},"website":{"anyOf":[{"type":"string","maxLength":320},{"type":"null"}],"title":"Website"}},"type":"object","required":["message"],"title":"FeedbackRequest"},"FeedbackResponse":{"properties":{"received":{"type":"boolean","title":"Received"},"meta":{"additionalProperties":true,"type":"object","title":"Meta"}},"type":"object","required":["received","meta"],"title":"FeedbackResponse"},"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"HealthOut":{"properties":{"status":{"type":"string","title":"Status"},"database":{"type":"string","title":"Database"},"pool":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Pool"},"concurrency":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Concurrency"}},"type":"object","required":["status","database"],"title":"HealthOut"},"Jurisdiction":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"name":{"type":"string","title":"Name"},"abbreviation":{"type":"string","title":"Abbreviation"},"classification":{"type":"string","title":"Classification"},"openstates_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Openstates Id"}},"type":"object","required":["id","name","abbreviation","classification"],"title":"Jurisdiction"},"KeyMintRequest":{"properties":{"name":{"type":"string","maxLength":200,"title":"Name","default":"default"},"environment":{"type":"string","enum":["live","test"],"title":"Environment","default":"live"}},"type":"object","title":"KeyMintRequest"},"KeyRevealResponse":{"properties":{"key":{"type":"string","title":"Key"},"warning":{"type":"string","title":"Warning","default":"This is the only time this key will be shown. Store it now."}},"type":"object","required":["key"],"title":"KeyRevealResponse"},"LegislativeEventOut":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"jurisdiction_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Jurisdiction Id"},"jurisdiction_abbreviation":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Jurisdiction Abbreviation"},"bill_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Bill Id"},"committee_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Committee Id"},"name":{"type":"string","title":"Name"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"start_date":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Start Date"},"location":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Location"}},"type":"object","required":["id","name"],"title":"LegislativeEventOut"},"MagicLinkRequest":{"properties":{"email":{"type":"string","title":"Email"}},"type":"object","required":["email"],"title":"MagicLinkRequest"},"MagicLinkResponse":{"properties":{"accepted":{"type":"boolean","title":"Accepted","default":true}},"type":"object","title":"MagicLinkResponse"},"MortalityJurisdictionRow":{"properties":{"jurisdiction_code":{"type":"string","title":"Jurisdiction Code"},"jurisdiction_name":{"type":"string","title":"Jurisdiction Name"},"total":{"type":"integer","title":"Total"},"enacted":{"type":"integer","title":"Enacted"},"died_on_adjournment":{"type":"integer","title":"Died On Adjournment"},"killed":{"type":"integer","title":"Killed"},"pending":{"type":"integer","title":"Pending"},"unknown":{"type":"integer","title":"Unknown"},"enacted_pct":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Enacted Pct"},"died_on_adjournment_pct":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Died On Adjournment Pct"},"did_not_pass":{"type":"integer","title":"Did Not Pass","default":0},"did_not_pass_pct":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Did Not Pass Pct"},"killed_pct":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Killed Pct"},"terminal_split_is_degenerate":{"type":"boolean","title":"Terminal Split Is Degenerate","default":false},"has_active_session":{"type":"boolean","title":"Has Active Session"}},"type":"object","required":["jurisdiction_code","jurisdiction_name","total","enacted","died_on_adjournment","killed","pending","unknown","has_active_session"],"title":"MortalityJurisdictionRow","description":"Current status counts across this jurisdiction's tracked sessions.\n\n`did_not_pass` sums the disjoint `died_on_adjournment` and `killed`\ncategories. Combining them avoids comparing only one terminal recording\ncategory; it does not normalize differences in session mix, source\ncoverage, freshness, or reporting completeness between jurisdictions.\nNeither the split nor its sum establishes why a bill failed or provides\na like-for-like ranking of legislatures.\n\n`pending` contains recognized nonterminal statuses; `unknown` contains\nmissing or unrecognized statuses. `has_active_session` indicates whether\nany included session is marked active, not whether each pending bill is\nin that session. `terminal_split_is_degenerate` indicates that at least\none terminal category is empty while the other is nonempty; it does not\nestablish the cause."},"MortalityReportEnvelope":{"properties":{"data":{"items":{"$ref":"#/components/schemas/MortalityJurisdictionRow"},"type":"array","title":"Data"},"totals":{"$ref":"#/components/schemas/MortalityTotals"},"meta":{"additionalProperties":true,"type":"object","title":"Meta"}},"type":"object","required":["data","totals","meta"],"title":"MortalityReportEnvelope"},"MortalityTotals":{"properties":{"total":{"type":"integer","title":"Total"},"enacted":{"type":"integer","title":"Enacted"},"died_on_adjournment":{"type":"integer","title":"Died On Adjournment"},"killed":{"type":"integer","title":"Killed"},"did_not_pass":{"type":"integer","title":"Did Not Pass","default":0},"did_not_pass_pct":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Did Not Pass Pct"},"pending":{"type":"integer","title":"Pending"},"unknown":{"type":"integer","title":"Unknown"},"enacted_pct":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Enacted Pct"},"died_on_adjournment_pct":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Died On Adjournment Pct"}},"type":"object","required":["total","enacted","died_on_adjournment","killed","pending","unknown"],"title":"MortalityTotals"},"Page_BillSummary_":{"properties":{"data":{"items":{"$ref":"#/components/schemas/BillSummary"},"type":"array","title":"Data"},"pagination":{"$ref":"#/components/schemas/PaginationMeta"},"meta":{"$ref":"#/components/schemas/ResponseMeta"}},"type":"object","required":["data","pagination","meta"],"title":"Page[BillSummary]"},"Page_CommitteeOut_":{"properties":{"data":{"items":{"$ref":"#/components/schemas/CommitteeOut"},"type":"array","title":"Data"},"pagination":{"$ref":"#/components/schemas/PaginationMeta"},"meta":{"$ref":"#/components/schemas/ResponseMeta"}},"type":"object","required":["data","pagination","meta"],"title":"Page[CommitteeOut]"},"Page_CoverageRowOut_":{"properties":{"data":{"items":{"$ref":"#/components/schemas/CoverageRowOut"},"type":"array","title":"Data"},"pagination":{"$ref":"#/components/schemas/PaginationMeta"},"meta":{"$ref":"#/components/schemas/ResponseMeta"}},"type":"object","required":["data","pagination","meta"],"title":"Page[CoverageRowOut]"},"Page_Jurisdiction_":{"properties":{"data":{"items":{"$ref":"#/components/schemas/Jurisdiction"},"type":"array","title":"Data"},"pagination":{"$ref":"#/components/schemas/PaginationMeta"},"meta":{"$ref":"#/components/schemas/ResponseMeta"}},"type":"object","required":["data","pagination","meta"],"title":"Page[Jurisdiction]"},"Page_LegislativeEventOut_":{"properties":{"data":{"items":{"$ref":"#/components/schemas/LegislativeEventOut"},"type":"array","title":"Data"},"pagination":{"$ref":"#/components/schemas/PaginationMeta"},"meta":{"$ref":"#/components/schemas/ResponseMeta"}},"type":"object","required":["data","pagination","meta"],"title":"Page[LegislativeEventOut]"},"Page_PersonSummary_":{"properties":{"data":{"items":{"$ref":"#/components/schemas/PersonSummary"},"type":"array","title":"Data"},"pagination":{"$ref":"#/components/schemas/PaginationMeta"},"meta":{"$ref":"#/components/schemas/ResponseMeta"}},"type":"object","required":["data","pagination","meta"],"title":"Page[PersonSummary]"},"Page_SearchResult_":{"properties":{"data":{"items":{"$ref":"#/components/schemas/SearchResult"},"type":"array","title":"Data"},"pagination":{"$ref":"#/components/schemas/PaginationMeta"},"meta":{"$ref":"#/components/schemas/ResponseMeta"}},"type":"object","required":["data","pagination","meta"],"title":"Page[SearchResult]"},"Page_Session_":{"properties":{"data":{"items":{"$ref":"#/components/schemas/Session"},"type":"array","title":"Data"},"pagination":{"$ref":"#/components/schemas/PaginationMeta"},"meta":{"$ref":"#/components/schemas/ResponseMeta"}},"type":"object","required":["data","pagination","meta"],"title":"Page[Session]"},"Page_SourceRecordOut_":{"properties":{"data":{"items":{"$ref":"#/components/schemas/SourceRecordOut"},"type":"array","title":"Data"},"pagination":{"$ref":"#/components/schemas/PaginationMeta"},"meta":{"$ref":"#/components/schemas/ResponseMeta"}},"type":"object","required":["data","pagination","meta"],"title":"Page[SourceRecordOut]"},"PaginationMeta":{"properties":{"page":{"type":"integer","title":"Page"},"per_page":{"type":"integer","title":"Per Page"},"total":{"type":"integer","title":"Total"},"total_pages":{"type":"integer","title":"Total Pages"}},"type":"object","required":["page","per_page","total","total_pages"],"title":"PaginationMeta"},"PersonDetail":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"name":{"type":"string","title":"Name"},"party":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Party"},"jurisdiction_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Jurisdiction Id"},"openstates_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Openstates Id"}},"type":"object","required":["id","name"],"title":"PersonDetail"},"PersonSummary":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"name":{"type":"string","title":"Name"},"party":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Party"},"jurisdiction_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Jurisdiction Id"}},"type":"object","required":["id","name"],"title":"PersonSummary"},"ReadyOut":{"properties":{"ready":{"type":"boolean","title":"Ready"},"database":{"type":"string","title":"Database"}},"type":"object","required":["ready","database"],"title":"ReadyOut"},"RelatedBillLink":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"identifier":{"type":"string","title":"Identifier"},"jurisdiction_abbreviation":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Jurisdiction Abbreviation"},"session_identifier":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Session Identifier"},"status":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Status"}},"type":"object","required":["id","identifier"],"title":"RelatedBillLink","description":"A minimal cross-reference to another bill, used by\nBillDetail.replaces/replaced_by (see RelatedBillOut for the fuller\n/related shape this is a lighter sibling of)."},"RelatedBillOut":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"relation_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Relation Type"},"related_identifier":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Related Identifier"},"related_bill_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Related Bill Id"}},"type":"object","required":["id"],"title":"RelatedBillOut","description":"A cross-reference from one bill to another.\n\n`related_bill_id` is resolved at read time where we can find the target in\nthis corpus, and is null otherwise -- most commonly for `prior-session`\nlinks, whose target sits in a session we do not hold. Returning the\nidentifier regardless is deliberate: knowing a bill HAS a prior-session\npredecessor called \"A 4171\" is the answer to a multi-year tracking question\neven when we cannot serve that bill ourselves."},"ResponseMeta":{"properties":{"source_freshness":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Source Freshness"},"api_version":{"type":"string","title":"Api Version"},"request_id":{"type":"string","title":"Request Id"},"data_status":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Data Status"},"notice":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Notice"}},"type":"object","required":["api_version","request_id"],"title":"ResponseMeta"},"SaveScoutMonitor":{"properties":{"cadence_seconds":{"anyOf":[{"type":"integer","maximum":604800.0,"minimum":21600.0},{"type":"null"}],"title":"Cadence Seconds"}},"type":"object","title":"SaveScoutMonitor"},"SearchResult":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"jurisdiction_id":{"type":"string","format":"uuid","title":"Jurisdiction Id"},"session_id":{"type":"string","format":"uuid","title":"Session Id"},"jurisdiction_abbreviation":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Jurisdiction Abbreviation"},"session_identifier":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Session Identifier"},"chamber":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Chamber"},"identifier":{"type":"string","title":"Identifier"},"identifier_norm":{"type":"string","title":"Identifier Norm"},"title":{"type":"string","title":"Title"},"short_title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Short Title"},"bill_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Bill Type"},"status":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Status"},"status_date":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Status Date"},"introduced_date":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Introduced Date"},"latest_action_text":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Latest Action Text"},"latest_action_date":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Latest Action Date"},"source_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Source Url"},"updated_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Updated At"},"rank":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Rank"},"highlight":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Highlight","description":"Plain text (never HTML) with matched fragments wrapped in the sentinel tokens '⟦H⟧'...'⟦/H⟧' (see billcommons_api.search HIGHLIGHT_START_SENTINEL/HIGHLIGHT_STOP_SENTINEL). Source titles/descriptions/document text come from upstream jurisdictions and are not sanitized -- clients must split on the sentinels and render their own emphasis (e.g. <mark>); never render this field with dangerouslySetInnerHTML or any raw-HTML sink."},"match_type":{"type":"string","title":"Match Type"}},"type":"object","required":["id","jurisdiction_id","session_id","identifier","identifier_norm","title","match_type"],"title":"SearchResult"},"Session":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"jurisdiction_id":{"type":"string","format":"uuid","title":"Jurisdiction Id"},"jurisdiction_abbreviation":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Jurisdiction Abbreviation"},"jurisdiction_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Jurisdiction Name"},"identifier":{"type":"string","title":"Identifier"},"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name"},"classification":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Classification"},"start_date":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Start Date"},"end_date":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"End Date"},"active":{"type":"boolean","title":"Active"},"data_status":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Data Status"},"notice":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Notice"},"canonical_session_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Canonical Session Id"},"canonical_session_identifier":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Canonical Session Identifier"}},"type":"object","required":["id","jurisdiction_id","identifier","active"],"title":"Session"},"SessionRequest":{"properties":{"token":{"type":"string","title":"Token"}},"type":"object","required":["token"],"title":"SessionRequest"},"SnapshotCheckoutRequest":{"properties":{"scope":{"type":"string","enum":["state","full"],"title":"Scope"},"jurisdiction":{"anyOf":[{"type":"string","pattern":"^[A-Za-z]{2}$"},{"type":"null"}],"title":"Jurisdiction"}},"type":"object","required":["scope"],"title":"SnapshotCheckoutRequest"},"SourceRecordOut":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"entity_type":{"type":"string","title":"Entity Type"},"entity_id":{"type":"string","format":"uuid","title":"Entity Id"},"source_name":{"type":"string","title":"Source Name"},"source_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Source Url"},"upstream_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Upstream Id"},"retrieved_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Retrieved At"}},"type":"object","required":["id","entity_type","entity_id","source_name"],"title":"SourceRecordOut"},"SponsorshipOut":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"bill_id":{"type":"string","format":"uuid","title":"Bill Id"},"person_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Person Id"},"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name"},"classification":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Classification"},"primary":{"type":"boolean","title":"Primary"}},"type":"object","required":["id","bill_id","primary"],"title":"SponsorshipOut"},"ToolUsageRow":{"properties":{"tool":{"type":"string","title":"Tool"},"ok":{"type":"integer","title":"Ok","default":0},"error":{"type":"integer","title":"Error","default":0},"median_ms":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Median Ms"}},"type":"object","required":["tool"],"title":"ToolUsageRow"},"TopicListEnvelope":{"properties":{"data":{"items":{"$ref":"#/components/schemas/TopicOut"},"type":"array","title":"Data"},"meta":{"additionalProperties":true,"type":"object","title":"Meta"}},"type":"object","required":["data","meta"],"title":"TopicListEnvelope"},"TopicOut":{"properties":{"slug":{"type":"string","title":"Slug"},"name":{"type":"string","title":"Name"},"description":{"type":"string","title":"Description"},"bill_count":{"type":"integer","title":"Bill Count"}},"type":"object","required":["slug","name","description","bill_count"],"title":"TopicOut"},"UpdateScoutMonitor":{"properties":{"active":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Active"},"cadence_seconds":{"anyOf":[{"type":"integer","maximum":604800.0,"minimum":21600.0},{"type":"null"}],"title":"Cadence Seconds"}},"type":"object","title":"UpdateScoutMonitor"},"UsageStatsOut":{"properties":{"window_days":{"type":"integer","title":"Window Days"},"total_tool_calls":{"type":"integer","title":"Total Tool Calls"},"tools":{"items":{"$ref":"#/components/schemas/ToolUsageRow"},"type":"array","title":"Tools"},"error_codes":{"additionalProperties":{"type":"integer"},"type":"object","title":"Error Codes"},"self_probe_calls":{"type":"integer","title":"Self Probe Calls","default":0},"note":{"type":"string","title":"Note"},"meta":{"additionalProperties":true,"type":"object","title":"Meta"}},"type":"object","required":["window_days","total_tool_calls","tools","error_codes","note","meta"],"title":"UsageStatsOut","description":"Aggregate MCP tool usage.\n\nCounts CALLS, not connections. A directory health prober connects, lists\nthe tools and disconnects -- that is not usage, and conflating the two is\nhow a project convinces itself it has adoption it does not have."},"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"},"VoteEventOut":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"bill_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Bill Id"},"motion_text":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Motion Text"},"motion_classification":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Motion Classification"},"start_date":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Start Date"},"result":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Result"},"yes_count":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Yes Count"},"no_count":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"No Count"},"other_count":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Other Count"},"votes":{"items":{"$ref":"#/components/schemas/VoteRecordOut"},"type":"array","title":"Votes","default":[]}},"type":"object","required":["id"],"title":"VoteEventOut"},"VoteRecordOut":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"person_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Person Id"},"voter_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Voter Name"},"option":{"type":"string","title":"Option"}},"type":"object","required":["id","option"],"title":"VoteRecordOut"},"WebhookCreateRequest":{"properties":{"url":{"type":"string","maxLength":2000,"title":"Url"},"email":{"type":"string","maxLength":320,"title":"Email"},"kind":{"type":"string","title":"Kind","description":"topic | jurisdiction | bills"},"target":{"type":"string","maxLength":10000,"title":"Target","description":"topic: a topic slug. jurisdiction: a jurisdiction abbreviation. bills: comma-separated bill UUIDs (at most 64, and the combined url/kind/target/event_kinds must fit a shared byte budget -- see docs/api/webhooks.md)."},"jurisdiction":{"anyOf":[{"type":"string","maxLength":2},{"type":"null"}],"title":"Jurisdiction","description":"Only used with kind='topic', to scope the topic to one state, e.g. 'FL'."},"event_kinds":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}],"title":"Event Kinds","description":"Comma-separated subset of created,status,actions,sponsors,text,metadata,votes. Omit for all kinds."}},"type":"object","required":["url","email","kind","target"],"title":"WebhookCreateRequest"},"WebhookCreateResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"manage_token":{"type":"string","title":"Manage Token","description":"Shown once. Bearer token for GET/DELETE/reactivate -- store it now."},"signing_secret":{"type":"string","title":"Signing Secret","description":"HMAC key for verifying delivery signatures."},"verified":{"type":"boolean","title":"Verified"},"note":{"type":"string","title":"Note"}},"type":"object","required":["id","manage_token","signing_secret","verified","note"],"title":"WebhookCreateResponse"},"WebhookDeliveryOut":{"properties":{"delivery_id":{"type":"string","format":"uuid","title":"Delivery Id"},"first_seq":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"First Seq"},"last_seq":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Last Seq"},"event_count":{"type":"integer","title":"Event Count"},"status":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Status"},"error":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Error"},"duration_ms":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Duration Ms"},"attempted_at":{"type":"string","format":"date-time","title":"Attempted At"}},"type":"object","required":["delivery_id","event_count","attempted_at"],"title":"WebhookDeliveryOut"},"WebhookReactivateResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"active":{"type":"boolean","title":"Active"},"mode":{"type":"string","title":"Mode"},"meta":{"additionalProperties":true,"type":"object","title":"Meta"}},"type":"object","required":["id","active","mode","meta"],"title":"WebhookReactivateResponse"},"WebhookStatusResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"url":{"type":"string","title":"Url"},"kind":{"type":"string","title":"Kind"},"target":{"type":"string","title":"Target"},"event_kinds":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Event Kinds"},"verified":{"type":"boolean","title":"Verified"},"active":{"type":"boolean","title":"Active"},"last_success_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Last Success At"},"last_status":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Last Status"},"last_error":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Last Error"},"consecutive_failures":{"type":"integer","title":"Consecutive Failures"},"failing_since":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Failing Since"},"disabled_reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Disabled Reason"},"disabled_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Disabled At"},"cursor_lag_seq":{"type":"integer","title":"Cursor Lag Seq"},"recent_deliveries":{"items":{"$ref":"#/components/schemas/WebhookDeliveryOut"},"type":"array","title":"Recent Deliveries"},"meta":{"additionalProperties":true,"type":"object","title":"Meta"}},"type":"object","required":["id","url","kind","target","verified","active","consecutive_failures","cursor_lag_seq","recent_deliveries","meta"],"title":"WebhookStatusResponse"}}}}