{"openapi":"3.1.0","info":{"title":"Formation GTM API","description":"GoodLeads Formation Data Platform — scored, enriched, campaign-ready leads.","version":"0.1.0"},"paths":{"/health":{"get":{"tags":["health"],"summary":"Health","description":"Liveness — process is alive. Never touches the DB.\n\nUsed by ECS HEALTHCHECK and any caller that wants to confirm the API\nprocess is reachable. Stays 200 during transient DB issues so ECS\ndoesn't replace tasks on every RDS hiccup.","operationId":"health_health_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/ready":{"get":{"tags":["health"],"summary":"Ready","description":"Readiness — process is alive AND DB is reachable.\n\nUsed by the ALB target group: tasks that can't reach the DB are\ndrained from rotation. Returns 503 on DB failure so the ALB stops\nsending traffic to this task while the DB recovers.","operationId":"ready_ready_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/v1/pipeline/stages":{"get":{"tags":["pipeline","pipeline"],"summary":"List Stages","description":"Canonical pipeline stage order. The frontend trigger UI fetches this so\nthe checkbox list always matches the backend's `STAGE_ORDER` — adding a\nnew stage to the orchestrator no longer requires a parallel frontend edit.","operationId":"list_stages_api_v1_pipeline_stages_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/v1/pipeline/upload-bulk-file":{"post":{"tags":["pipeline"],"summary":"Upload a weekly bulk file for a portal-download state (e.g. TX)","description":"Validate and stage a manually downloaded SOS bulk file.\n\nAccepts the original `.zip` from the portal (CW….zip fixed-width, or BFD_W….zip JSON shards) or the unzipped `.txt` / `.json`.\nValidates the file against the state's data contract (fixed-width line\nlength, presence of entity records) and rejects look-alike products —\ne.g. uploading the TX comma-delimited \"List\" CSV fails here with a clear\nmessage instead of failing mid-pipeline.\n\nReturns `input_file`: pass it to POST /api/v1/pipeline/trigger along with\na stage list that includes `pull`.","operationId":"upload_bulk_file_api_v1_pipeline_upload_bulk_file_post","requestBody":{"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_upload_bulk_file_api_v1_pipeline_upload_bulk_file_post"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BulkUploadResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"APIKeyHeader":[]}]}},"/api/v1/pipeline/trigger":{"post":{"tags":["pipeline"],"summary":"Trigger a pipeline run (scoped to 1, some, or all records)","description":"Submit a pipeline run. Returns immediately with `job_id` for polling.\n\n**Scoping the run (1/some/all):**\n\n- **One record** — pass `entity_id` as a single UUID or GLID (e.g. `\"GL-CO-00042\"`)\n- **N specific records** — pass `entity_id` as a comma/space/newline-separated list\n  of UUIDs or GLIDs (e.g. `\"GL-CO-1, GL-CO-2, GL-FL-99\"`)\n- **A previously-stamped batch** — pass `batch_id` (UUID)\n- **A filter expression** — pass `filters` (same shape as `/leads/browse`)\n- **The exact entity set of a previous run** — pass `manifest_id` (UUID from\n  `GET /jobs/{id}/results`); the recovery gesture for re-running a failed run\n- **All records in a state** — pass none of the above\n\nMutually exclusive: pick at most one of `entity_id`, `batch_id`, `filters`,\n`manifest_id` — two selectors is a 422, and so is any unknown field (a typo\nmust fail loudly, never silently widen the run to the whole state).\n\n**Finding a record's GLID:** call `POST /api/v1/leads/browse` with\n`{\"filters\":[{\"field\":\"lead_ref\",\"op\":\"eq\",\"value\":\"GL-CO-00042\"}]}` to verify a\nGLID resolves to a real entity. The full filter field list lives at\n`GET /api/v1/schema/attributes`.\n\n**Stages:** pass `stages=\"all\"` (default), a single stage name, the shortcut\n`\"enrich\"` (= skip_trace + gapfill + validate), or a comma-separated list.\nCanonical stage order at `GET /api/v1/pipeline/stages`.\n\nReturns 202 with a `job_id`. Poll `GET /api/v1/pipeline/jobs/{job_id}` for status.","operationId":"trigger_pipeline_api_v1_pipeline_trigger_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TriggerRequest"}}},"required":true},"responses":{"202":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TriggerResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"APIKeyHeader":[]}]}},"/api/v1/pipeline/trigger-multi/preview":{"post":{"tags":["pipeline","pipeline"],"summary":"Per-state breakdown of a cross-state selection, before spending anything","description":"Read-only. Resolve a cross-state selection into per-state counts and say\nwhich states can actually start right now.\n\nThe confirm step for a fan-out that includes paid stages: vendor credits are\nspent per record, so the operator approves the *shape* of the spend\n(CO 41 · FL 28 · VA 9) rather than one lump total. Stamps no batches,\nlaunches nothing — a preview must never be a way to trigger a run.\n\nScope only: which states a selection touches does not depend on what you\nintend to run on them, so `stages` is rejected here as an unknown field.","operationId":"preview_pipeline_multi_api_v1_pipeline_trigger_multi_preview_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MultiStateScopeRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MultiStatePreviewResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"APIKeyHeader":[]}]}},"/api/v1/pipeline/trigger-multi":{"post":{"tags":["pipeline","pipeline"],"summary":"Run one scoped pipeline job per state for a selection that spans states","description":"Fan a cross-state selection out into one ordinary scoped run per state.\n\nEach leg goes through the same `POST /trigger` code path it would have taken\nif you had picked that state by hand — same validation, same Run Manifest,\nsame per-entity COGS attribution, same concurrency lock.\n\n**Partial success is the normal outcome, not an error.** A state whose lock\nis held by the overnight harvest cannot start a second run, and silently\ndropping it is how an operator comes to believe they enriched records they\ndid not. Every leg is reported with its own `status` and `job_id`; the call\nfails (409 / 400) only when *nothing* started.\n\nScope with `entity_id` (IDs may span states — they are grouped) or `filters`\n(no state clause; each leg adds its own). `limit` is per state; `pull` is\nrefused because it ignores record scope.","operationId":"trigger_pipeline_multi_api_v1_pipeline_trigger_multi_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MultiStateTriggerRequest"}}},"required":true},"responses":{"202":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MultiStateTriggerResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"APIKeyHeader":[]}]}},"/api/v1/pipeline/jobs":{"get":{"tags":["pipeline"],"summary":"List Jobs","description":"List recent pipeline jobs, optionally filtered by state and/or status.\n\n`verbose` defaults to False: each `stage_runs[].metrics` is trimmed to a\nsmall set of counters (records_in, records_out, matched, no_match, error).\nThis keeps the response small enough for agent consumers — a full state\npull's raw metrics can exceed 1MB of token context. The dashboard passes\n`?verbose=true` to get the full metrics blob.","operationId":"list_jobs_api_v1_pipeline_jobs_get","parameters":[{"name":"state","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"State"}},{"name":"status","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Status"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","default":20,"title":"Limit"}},{"name":"verbose","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"Verbose"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/pipeline/vendor-usage":{"get":{"tags":["pipeline"],"summary":"Vendor Usage","description":"Queries sent and matches returned per paid vendor, for invoice reconciliation.\n\n`start_date` inclusive, `end_date` inclusive (UTC days). Per vendor: runs,\nqueries (records sent), matches (records returned usable), match_rate,\n`billed_on` (the column that vendor invoices on — Enformion bills per match,\nTracerfy/ZeroBounce per query) and a by_state split. Read from completed\nstage runs, so it covers jobs the manifest ledger never costed.","operationId":"vendor_usage_api_v1_pipeline_vendor_usage_get","parameters":[{"name":"start_date","in":"query","required":true,"schema":{"type":"string","format":"date","title":"Start Date"}},{"name":"end_date","in":"query","required":true,"schema":{"type":"string","format":"date","title":"End Date"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/pipeline/jobs/{job_id}":{"get":{"tags":["pipeline"],"summary":"Get Job","description":"Get a pipeline job with its stage_runs.\n\nDetail view defaults to verbose=True (full metrics). Agents fetching a\nspecific job (e.g. the results endpoint walks entity_ids from metrics\non pre-manifest jobs) need the full dict; callers only wanting a summary\ncan pass `?verbose=false`.","operationId":"get_job_api_v1_pipeline_jobs__job_id__get","parameters":[{"name":"job_id","in":"path","required":true,"schema":{"type":"string","title":"Job Id"}},{"name":"verbose","in":"query","required":false,"schema":{"type":"boolean","default":true,"title":"Verbose"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/pipeline/jobs/{job_id}/results":{"get":{"tags":["pipeline"],"summary":"Get Job Results","description":"Browse or export the entities touched by a pipeline job.\n\nUses the run manifest (preferred) or falls back to stage_run.metrics for\npre-manifest jobs. Returns lead data inline (browse) or as a presigned\ndownload URL (export).\n\nQuery params:\n    stage: Filter to a specific stage (e.g. 'skip_trace', 'geocode'). Default: all stages.\n    format: 'browse' returns lead data inline, 'export' returns a presigned download URL.\n    export_format: 'csv' or 'json' (only used when format=export).","operationId":"get_job_results_api_v1_pipeline_jobs__job_id__results_get","parameters":[{"name":"job_id","in":"path","required":true,"schema":{"type":"string","title":"Job Id"}},{"name":"stage","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Stage"}},{"name":"format","in":"query","required":false,"schema":{"type":"string","default":"browse","title":"Format"}},{"name":"export_format","in":"query","required":false,"schema":{"type":"string","default":"csv","title":"Export Format"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/pipeline/recompute-signals":{"post":{"tags":["pipeline"],"summary":"Recompute Signals","description":"Force-recompute RA Intelligence, Contact Relevance, and/or Classification on a scope.\n\nADR-004 Phase 3 surface. Runs inline — for targeted recomputes (typically\n1–200 entities after an operator/agent change). Whole-state recomputes\nshould go through the normal pipeline trigger with filters.\n\nBypasses the ADR-004 Phase 1 skip-if-current filter so entities already\nstamped at the current service version still get recomputed. That's the\nwhole point — the operator has reason to distrust the current stamp and\nwants the service to run anew.\n\n`service=\"classify\"` exists because the classification service VERSION\n(classification_v1) has never been bumped by a keyword/taxonomy batch —\nshipping a new keyword does not, by itself, retroactively reclassify any\nentity that was already stamped (including ones stamped \"unclassified\").\nThis is the small-batch path to actually apply a shipped keyword/taxonomy\nchange to the specific records it should have caught, without a\nwhole-state pipeline run.","operationId":"recompute_signals_api_v1_pipeline_recompute_signals_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RecomputeSignalsRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RecomputeSignalsResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"APIKeyHeader":[]}]}},"/api/v1/pipeline/jobs/{job_id}/cancel":{"post":{"tags":["pipeline"],"summary":"Cancel Job","description":"Cancel a running or pending pipeline job and clean up its staging artifacts.","operationId":"cancel_job_api_v1_pipeline_jobs__job_id__cancel_post","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"job_id","in":"path","required":true,"schema":{"type":"string","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/pipeline/internal/ecs-task-stopped":{"post":{"tags":["pipeline"],"summary":"Ecs Task Stopped","description":"EventBridge target — invoked when an ECS task in our cluster transitions\nto STOPPED. Marks any matching pipeline.job row as 'failed' with ECS's\nactual stoppedReason as the error message, and — whether the task exited\ncleanly or died — hands the job to settlement so a paid order whose check\nruns just finished settles in seconds instead of waiting for the sweep.\n\nReplaces the polling-cron approach that PR #179 proposed (and closed). ECS\npublishes Task State Change events to EventBridge automatically; listening\nis strictly better than polling — seconds of latency vs. minutes, zero\nFargate cost, and we get ECS's structured failure reason (\"OutOfMemory\",\nexit codes, etc.) instead of \"ECS task stopped unexpectedly.\"\n\nIdempotent and safe by construction:\n- Tasks not matching any pipeline.job row → no-op (State GMs, Platform EM\n  sessions live in the same cluster but have no row here).\n- Jobs already in a terminal state → the row is left exactly as it is; only\n  the settlement check runs, and it is itself idempotent.\n- Events with lastStatus != STOPPED → ignored (the rule filters these out\n  at EventBridge; this is defense-in-depth).\n- EventBridge is at-least-once, so a replayed delivery re-runs both halves;\n  neither bills or mutates twice.\n\nThe trigger-path sweep in has_running_job remains as a backstop for the\nrare case where an EventBridge delivery is lost, and the two-hourly\nstuck-order sweep remains the backstop for settlement.","operationId":"ecs_task_stopped_api_v1_pipeline_internal_ecs_task_stopped_post","requestBody":{"content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Event"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"APIKeyHeader":[]}]}},"/api/v1/leads":{"get":{"tags":["leads","leads"],"summary":"Browse Leads","description":"Browse leads with dynamic filters and pagination.\n\nFilters are passed as a JSON-encoded query parameter:\n?filters=[{\"field\":\"reachability_tier\",\"op\":\"eq\",\"value\":\"On Fire\"}]\n\nBy default, non-operating entities (enrichment_strategy='hold') are\nexcluded. Set include_non_operating=true to see the full inventory,\nor pass an explicit enrichment_strategy filter to audit just the\nheld cohort.\n\nCommerce free/paid boundary: when ENABLE_COMMERCE=True, contact fields\n(email, phone, contact_name) are masked unless the caller presents a\nvalid X-API-Key. The response includes `access_level` so the frontend\ncan render an \"unlock\" affordance.","operationId":"browse_leads_api_v1_leads_get","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"state","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"State"}},{"name":"filters","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"JSON-encoded filter array","title":"Filters"},"description":"JSON-encoded filter array"},{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"default":1,"title":"Page"}},{"name":"page_size","in":"query","required":false,"schema":{"type":"integer","maximum":200,"minimum":1,"default":50,"title":"Page Size"}},{"name":"sort","in":"query","required":false,"schema":{"type":"string","description":"Sort column (legacy, paired with sort_dir) OR a JSON array of sort keys [{\"field\": \"reachability_tier\", \"dir\": \"desc\"}, {\"field\": \"formation_date\", \"dir\": \"desc\"}] for multi-key sort. Any field flagged sortable on /schema/attributes; tier fields sort by rank. Unknown field or direction → 422 listing the sortable fields.","default":"reachability_score","title":"Sort"},"description":"Sort column (legacy, paired with sort_dir) OR a JSON array of sort keys [{\"field\": \"reachability_tier\", \"dir\": \"desc\"}, {\"field\": \"formation_date\", \"dir\": \"desc\"}] for multi-key sort. Any field flagged sortable on /schema/attributes; tier fields sort by rank. Unknown field or direction → 422 listing the sortable fields."},{"name":"sort_dir","in":"query","required":false,"schema":{"type":"string","description":"asc or desc (legacy; ignored when sort is a JSON array)","default":"desc","title":"Sort Dir"},"description":"asc or desc (legacy; ignored when sort is a JSON array)"},{"name":"include_non_operating","in":"query","required":false,"schema":{"type":"boolean","description":"Include records the Contact Intelligence brain marked enrichment_strategy='hold' (shell LLCs, single-asset holdings, vehicles for real estate or a car). Default False — sellable inventory only.","default":false,"title":"Include Non Operating"},"description":"Include records the Contact Intelligence brain marked enrichment_strategy='hold' (shell LLCs, single-asset holdings, vehicles for real estate or a car). Default False — sellable inventory only."},{"name":"include_existing","in":"query","required":false,"schema":{"type":"boolean","description":"Include existing businesses with a new filing: companies opening a location here, local owners who formed their company in another state, businesses back in business, established businesses under a new entity, moved, or with a new trade name. Default False — Just started only (a brand-new business), matching every file sold as new businesses. Naming a filing_kind in `filters` implies it.","default":false,"title":"Include Existing"},"description":"Include existing businesses with a new filing: companies opening a location here, local owners who formed their company in another state, businesses back in business, established businesses under a new entity, moved, or with a new trade name. Default False — Just started only (a brand-new business), matching every file sold as new businesses. Naming a filing_kind in `filters` implies it."},{"name":"include_registrations","in":"query","required":false,"schema":{"type":"boolean","description":"Deprecated alias of include_existing (kept one release so saved links resolve).","deprecated":true,"default":false,"title":"Include Registrations"},"description":"Deprecated alias of include_existing (kept one release so saved links resolve).","deprecated":true},{"name":"include_channels","in":"query","required":false,"schema":{"type":"boolean","description":"Attach ranked alternate contact channels to each row: phone_2..phone_5 (+ per-phone line type), email_2..email_3 (+ per-email deliverability status), and the primary email's activity recency. Ordered by the same ranking the primary-selection brains use. Default False — the Browse grid doesn't pay for the extra query.","default":false,"title":"Include Channels"},"description":"Attach ranked alternate contact channels to each row: phone_2..phone_5 (+ per-phone line type), email_2..email_3 (+ per-email deliverability status), and the primary email's activity recency. Ordered by the same ranking the primary-selection brains use. Default False — the Browse grid doesn't pay for the extra query."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/leads/geo":{"get":{"tags":["leads","leads"],"summary":"Geo Leads","description":"Trimmed map-plotting payload — lat/lon + minimum columns for pin rendering.\n\nPowers the Map View page (docs/product/prds/MAP_VIEW_FL_MVP.md). Same\nfilter contract as ``GET /leads`` so the shared filter chip-bar wires\ninto both pages identically (Rule 12 — one filter contract, three\ninterfaces).\n\nRequires ``latitude IS NOT NULL`` — records without geocoded coordinates\nare summarized in the response's ``no_coords_total`` so the map footer\ncan show \"X entities not shown — no coordinates\" without a second call.\n\nNo pagination: returns the full filter scope in one shot (capped at\nGEO_LEADS_CAP per services.leads_query). Coordinates are rounded to\n5 decimals (~1m precision) to shave ~10% off the wire size without\nvisible map degradation.\n\nCached privately for 60s. The URL — including the filters JSON — is\nthe cache key, so same-scope re-navigations within a minute (tab\nrefresh, state switch back) hit the browser cache instead of re-\ntransferring the full payload. Filter changes naturally bust by\nproducing a different URL.","operationId":"geo_leads_api_v1_leads_geo_get","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"state","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"State"}},{"name":"filters","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"JSON-encoded filter array","title":"Filters"},"description":"JSON-encoded filter array"},{"name":"include_non_operating","in":"query","required":false,"schema":{"type":"boolean","description":"Include records the Contact Intelligence brain marked enrichment_strategy='hold'. Default False — sellable inventory only, matching Browse.","default":false,"title":"Include Non Operating"},"description":"Include records the Contact Intelligence brain marked enrichment_strategy='hold'. Default False — sellable inventory only, matching Browse."},{"name":"include_existing","in":"query","required":false,"schema":{"type":"boolean","description":"Include existing businesses with a new filing: companies opening a location here, local owners who formed their company in another state, businesses back in business, established businesses under a new entity, moved, or with a new trade name. Default False — Just started only (a brand-new business), matching every file sold as new businesses. Naming a filing_kind in `filters` implies it.","default":false,"title":"Include Existing"},"description":"Include existing businesses with a new filing: companies opening a location here, local owners who formed their company in another state, businesses back in business, established businesses under a new entity, moved, or with a new trade name. Default False — Just started only (a brand-new business), matching every file sold as new businesses. Naming a filing_kind in `filters` implies it."},{"name":"include_registrations","in":"query","required":false,"schema":{"type":"boolean","description":"Deprecated alias of include_existing (kept one release so saved links resolve).","deprecated":true,"default":false,"title":"Include Registrations"},"description":"Deprecated alias of include_existing (kept one release so saved links resolve).","deprecated":true},{"name":"bbox","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Viewport bbox as 'west,south,east,north' (lon,lat lon,lat). When set, restricts pins to lat/lon inside the rectangle. Map View sends the current viewport on every moveend/zoomend; agents fetching whole-state payloads should omit it.","title":"Bbox"},"description":"Viewport bbox as 'west,south,east,north' (lon,lat lon,lat). When set, restricts pins to lat/lon inside the rectangle. Map View sends the current viewport on every moveend/zoomend; agents fetching whole-state payloads should omit it."},{"name":"include_no_coords","in":"query","required":false,"schema":{"type":"boolean","description":"Compute no_coords_total (count of matching leads without coordinates). Constant per filter scope — the Map View passes false on viewport-only refreshes to skip the COUNT; the response then has no_coords_total=null.","default":true,"title":"Include No Coords"},"description":"Compute no_coords_total (count of matching leads without coordinates). Constant per filter scope — the Map View passes false on viewport-only refreshes to skip the COUNT; the response then has no_coords_total=null."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/leads/geo-shortcuts":{"get":{"tags":["leads","leads"],"summary":"Geo Shortcuts","description":"Top MSAs + cities by lead count for the Map View's state-aware chips.\n\nReplaces the hardcoded \"Tampa Bay / Miami / Orlando / Jacksonville\"\nchips from PR #305 — those made no sense once a buyer switched to\na non-FL state. This endpoint returns the actual top territories\nby inventory, with counts that the chip labels surface so the buyer\nsees \"New York metro · 8.4K\" instead of guessing.\n\nEach shortcut item is the same `{field, op, value}` shape as the rest\nof the filter system, plus `label` (chip display text) and `count`\n(entities matching that filter under the current sellable predicate).\n\nCached for 5 minutes — top-MSA distributions move slowly and the\naggregation is the same for every buyer on the same state.","operationId":"geo_shortcuts_api_v1_leads_geo_shortcuts_get","parameters":[{"name":"state","in":"query","required":true,"schema":{"type":"string","description":"State code (e.g. FL, NY, CO, VA)","title":"State"},"description":"State code (e.g. FL, NY, CO, VA)"},{"name":"include_non_operating","in":"query","required":false,"schema":{"type":"boolean","description":"Mirror the /leads/geo semantics — sellable-only counts by default.","default":false,"title":"Include Non Operating"},"description":"Mirror the /leads/geo semantics — sellable-only counts by default."},{"name":"include_existing","in":"query","required":false,"schema":{"type":"boolean","description":"Include existing businesses with a new filing: companies opening a location here, local owners who formed their company in another state, businesses back in business, established businesses under a new entity, moved, or with a new trade name. Default False — Just started only (a brand-new business), matching every file sold as new businesses. Naming a filing_kind in `filters` implies it.","default":false,"title":"Include Existing"},"description":"Include existing businesses with a new filing: companies opening a location here, local owners who formed their company in another state, businesses back in business, established businesses under a new entity, moved, or with a new trade name. Default False — Just started only (a brand-new business), matching every file sold as new businesses. Naming a filing_kind in `filters` implies it."},{"name":"include_registrations","in":"query","required":false,"schema":{"type":"boolean","description":"Deprecated alias of include_existing (kept one release so saved links resolve).","deprecated":true,"default":false,"title":"Include Registrations"},"description":"Deprecated alias of include_existing (kept one release so saved links resolve).","deprecated":true}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/leads/name-distribution":{"get":{"tags":["leads","leads"],"summary":"Name Distribution","description":"Top industry *names* (finer than sector) for the Inventory name treemap.\n\nA dedicated, cached aggregation — kept off the `/leads/summary` fast path\n(state_stats) on purpose. Each item carries the same `{field, op, value}`\nfilter shape as the rest of the system (Rule 12), so a treemap tile\ndeep-links straight into a Browse cohort. Cached 5 minutes — the\ndistribution moves slowly and is identical for every buyer on the state.","operationId":"name_distribution_api_v1_leads_name_distribution_get","parameters":[{"name":"state","in":"query","required":true,"schema":{"type":"string","description":"State code (e.g. FL, NY, CO, VA)","title":"State"},"description":"State code (e.g. FL, NY, CO, VA)"},{"name":"include_non_operating","in":"query","required":false,"schema":{"type":"boolean","description":"Sellable-only counts by default; set true to include non-operating entities.","default":false,"title":"Include Non Operating"},"description":"Sellable-only counts by default; set true to include non-operating entities."},{"name":"include_existing","in":"query","required":false,"schema":{"type":"boolean","description":"Include existing businesses with a new filing: companies opening a location here, local owners who formed their company in another state, businesses back in business, established businesses under a new entity, moved, or with a new trade name. Default False — Just started only (a brand-new business), matching every file sold as new businesses. Naming a filing_kind in `filters` implies it.","default":false,"title":"Include Existing"},"description":"Include existing businesses with a new filing: companies opening a location here, local owners who formed their company in another state, businesses back in business, established businesses under a new entity, moved, or with a new trade name. Default False — Just started only (a brand-new business), matching every file sold as new businesses. Naming a filing_kind in `filters` implies it."},{"name":"include_registrations","in":"query","required":false,"schema":{"type":"boolean","description":"Deprecated alias of include_existing (kept one release so saved links resolve).","deprecated":true,"default":false,"title":"Include Registrations"},"description":"Deprecated alias of include_existing (kept one release so saved links resolve).","deprecated":true}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/leads/top-combinations":{"get":{"tags":["leads","leads"],"summary":"Top Combinations","description":"Top industry-name × metro combinations for the Inventory \"hottest\npockets\" leaderboard (e.g. \"roofing · Tampa\", \"dental · Denver\").\n\nThe combination is the unit a territory seller buys — a specific trade in a\nspecific metro. Dedicated, cached aggregation kept off the `/leads/summary`\nfast path. Each item carries a *compound* `filters` array\n`[{industry_name eq}, {msa_name eq}]` that Browse AND's together (Rule 12),\nso a row deep-links straight to its exact cohort.","operationId":"top_combinations_api_v1_leads_top_combinations_get","parameters":[{"name":"state","in":"query","required":true,"schema":{"type":"string","description":"State code (e.g. FL, NY, CO, VA)","title":"State"},"description":"State code (e.g. FL, NY, CO, VA)"},{"name":"include_non_operating","in":"query","required":false,"schema":{"type":"boolean","description":"Sellable-only counts by default; set true to include non-operating entities.","default":false,"title":"Include Non Operating"},"description":"Sellable-only counts by default; set true to include non-operating entities."},{"name":"include_existing","in":"query","required":false,"schema":{"type":"boolean","description":"Include existing businesses with a new filing: companies opening a location here, local owners who formed their company in another state, businesses back in business, established businesses under a new entity, moved, or with a new trade name. Default False — Just started only (a brand-new business), matching every file sold as new businesses. Naming a filing_kind in `filters` implies it.","default":false,"title":"Include Existing"},"description":"Include existing businesses with a new filing: companies opening a location here, local owners who formed their company in another state, businesses back in business, established businesses under a new entity, moved, or with a new trade name. Default False — Just started only (a brand-new business), matching every file sold as new businesses. Naming a filing_kind in `filters` implies it."},{"name":"include_registrations","in":"query","required":false,"schema":{"type":"boolean","description":"Deprecated alias of include_existing (kept one release so saved links resolve).","deprecated":true,"default":false,"title":"Include Registrations"},"description":"Deprecated alias of include_existing (kept one release so saved links resolve).","deprecated":true}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/leads/states":{"get":{"tags":["leads","leads"],"summary":"List States","description":"List all states with loaded lead data.\n\nReturns dynamically — no hardcoded state lists. When a new state is loaded\nvia the pipeline, it appears here automatically.","operationId":"list_states_api_v1_leads_states_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/v1/leads/summary":{"get":{"tags":["leads","leads"],"summary":"Leads Summary","description":"State-level aggregate stats: totals, contact rates, tier/sector distribution.\n\nAccepts optional filters to compute summary for any filtered subset,\nused by the pre-action context panel.","operationId":"leads_summary_api_v1_leads_summary_get","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"state","in":"query","required":true,"schema":{"type":"string","description":"State code (VA, CO, FL)","title":"State"},"description":"State code (VA, CO, FL)"},{"name":"filters","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"JSON-encoded filter array","title":"Filters"},"description":"JSON-encoded filter array"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["lists","lists"],"summary":"Inline Summary","description":"The same summary for an inline shape — one call per chip edit before a\nlist is ever saved (save happens after checkout, never before).","operationId":"inline_summary_api_v1_leads_summary_post","security":[{"APIKeyHeader":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SummaryRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/leads/coverage":{"get":{"tags":["leads","leads"],"summary":"Leads Coverage","description":"Per-day formation count for a state — or all states — across a date window.\n\nReturns `by_date` (zero-filled day-by-day count), `gap_groups` (consecutive\nzero-day ranges), `weekday_median` / `weekend_median` (baseline volumes for\nspotting partial pulls), and a `coverage_pct` summary. Caller can use this\nto decide whether the dataset is complete enough for their query — or to\nplan a backfill.\n\nOmit `state` (or pass `ALL`) to roll every live state together; the response\nthen carries `state_breakdown` (per-state split per day). Pass `industries=N`\nto attach `top_industries` — the N most-formed industry names per day. A day\nwith records but no classified industries comes back with an empty list\n(render as \"Not Yet Classified\").\n\nCounts read from `entity` so coverage reflects loaded data even if the\n`lead_browse` view hasn't been refreshed yet; industries read from\n`lead_browse`, which is populated by the classify stage.","operationId":"leads_coverage_api_v1_leads_coverage_get","parameters":[{"name":"state","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"State code (e.g. NY, CO, FL, VA). Omit (or ALL) to roll up every state.","title":"State"},"description":"State code (e.g. NY, CO, FL, VA). Omit (or ALL) to roll up every state."},{"name":"start_date","in":"query","required":true,"schema":{"type":"string","description":"Window start (YYYY-MM-DD), inclusive","title":"Start Date"},"description":"Window start (YYYY-MM-DD), inclusive"},{"name":"end_date","in":"query","required":true,"schema":{"type":"string","description":"Window end (YYYY-MM-DD), inclusive","title":"End Date"},"description":"Window end (YYYY-MM-DD), inclusive"},{"name":"industries","in":"query","required":false,"schema":{"type":"integer","maximum":20,"minimum":0,"description":"Attach the top-N industry_name values formed per day (0 = skip).","default":0,"title":"Industries"},"description":"Attach the top-N industry_name values formed per day (0 = skip)."},{"name":"commercial","in":"query","required":false,"schema":{"type":"boolean","description":"True (default) = curated commercial view (off-story hidden, demand-weighted, like the Inventory page). False = show everything (all classified industries, raw count).","default":true,"title":"Commercial"},"description":"True (default) = curated commercial view (off-story hidden, demand-weighted, like the Inventory page). False = show everything (all classified industries, raw count)."},{"name":"by","in":"query","required":false,"schema":{"type":"string","description":"What a day counts. 'formation' (default) = businesses formed that day (the calendar). 'loaded' = new businesses first loaded that UTC day — harvest delivery, the PM's patrol key.","default":"formation","title":"By"},"description":"What a day counts. 'formation' (default) = businesses formed that day (the calendar). 'loaded' = new businesses first loaded that UTC day — harvest delivery, the PM's patrol key."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/leads/data_quality":{"get":{"tags":["leads","leads"],"summary":"Leads Data Quality","description":"Per-state Data Quality scorecard over the customer-facing lead_browse view.\n\nMechanical conformance checks across four value dimensions — format (state,\nphone, email, zip), completeness (registered agent, address), standardization\n(canonical vocabulary), and consistency (names in CRM-ready Title Case, not\nALL-CAPS). Returns an overall 0–100 score, the per-dimension breakdown, and\nper-check pass rates with sample offenders.\n\n`residual_defects` and `checks_with_residual_defects` ride beside the\nheadline score: a small failure count (e.g. 159 defects over ~397K\napplicable rows) rounds away to a clean 100.0 at both the check and\nheadline level, so these two fields are how a reader tells \"zero defects\"\napart from \"100.0 that is hiding a known residual\" without digging into\n`checks[].failed` by hand.\n\nThe payload also carries the record-centric **coverage** dimension (the\n`coverage` block + `dimensions.coverage`): per pipeline stage, how many\nrecords that brain has never stamped — loaded-but-unprocessed inventory the\nvalue checks cannot see. Each coverage check ships `browse_filters` (a\n`missing_stage` filter) that opens the gap cohort on browse/export and\nscopes a surgical repair run on the pipeline trigger. Coverage does not\nmove the headline `score` (see stage_coverage.py for the scoring rules).\n\nThe `bad_emails` block counts every known-bad email we hold (ZeroBounce\ninvalid / spamtrap / abuse / do-not-mail, the email picker's own list):\n`primary_bad_contacts` (a bad email in the sellable slot — should be 0),\n`set_aside_bad_emails` (kept on purpose so we never pay to check them\nagain), `all_bad_contacts`, and `never_validated_contacts`. Reported\nbeside the score, never folded into it.\n\nThe `bad_phones` block is the phone-side mirror: `primary_unknown_type_on_fire`\n(an unresolved phone line type sold at full `reachability_tier='On Fire'`\nconfidence — should be 0, the one competitor-mined defect this check exists\nto catch), plus `primary_unknown_type_contacts` and\n`primary_not_confirmed_live_contacts` for context (some residual there is\nnormal — a real number with no vendor type/liveness signal).\n\nThis is the scoreboard the State GMs read each session and the State Quality\nBoard renders, so data-quality work has a number to move the way\nclassification does.","operationId":"leads_data_quality_api_v1_leads_data_quality_get","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"state","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"State code (e.g. CO, FL). Omit for all states, worst score first.","title":"State"},"description":"State code (e.g. CO, FL). Omit for all states, worst score first."},{"name":"sample_limit","in":"query","required":false,"schema":{"type":"integer","maximum":5000,"minimum":0,"description":"Max sample offenders per check. Default 8 is enough to eyeball a defect in a session. Raise toward the check's failed-count (see the `failed` field on each check) when the goal is remediation — e.g. collecting every failing lead_ref to drive a scoped, force-recomputed pipeline re-run via entity_id paste — not just a spot-check sample. The warmer already tallies offenders up to this ceiling for every state; a read only slices the cached list, so raising it changes the payload size, never the cost.","default":8,"title":"Sample Limit"},"description":"Max sample offenders per check. Default 8 is enough to eyeball a defect in a session. Raise toward the check's failed-count (see the `failed` field on each check) when the goal is remediation — e.g. collecting every failing lead_ref to drive a scoped, force-recomputed pipeline re-run via entity_id paste — not just a spot-check sample. The warmer already tallies offenders up to this ceiling for every state; a read only slices the cached list, so raising it changes the payload size, never the cost."},{"name":"fresh","in":"query","required":false,"schema":{"type":"boolean","description":"Ask the background warmer to recompute soon. This endpoint serves the in-process cache ONLY and never computes in the request path (the 2026-09-22 API OOM was a request-path recompute meeting a retrying caller); the response is still the last known card.","default":false,"title":"Fresh"},"description":"Ask the background warmer to recompute soon. This endpoint serves the in-process cache ONLY and never computes in the request path (the 2026-09-22 API OOM was a request-path recompute meeting a retrying caller); the response is still the last known card."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/leads/field_fill":{"get":{"tags":["leads","leads"],"summary":"Leads Field Fill","description":"Exact fill rate of every column in the delivered file, over the sellable book.\n\nOne row per delivered column in the file's own order: `filled` records carrying a\nvalue, `fill_pct` of the `total` sellable records (the cohort Browse returns by\ndefault), and the `basis` of the number — `counted` (exact, from stored values),\n`stamped at delivery` (written on every row by the file) or `not countable yet`\n(with the reason). Aggregate counts only; no records, no contact details.\nServed from a snapshot refreshed whenever the data changes (`computed_at`), never\ncomputed on a request.","operationId":"leads_field_fill_api_v1_leads_field_fill_get","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"state","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"State code (e.g. CO, FL). Omit for all live states together.","title":"State"},"description":"State code (e.g. CO, FL). Omit for all live states together."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/leads/fill_rates":{"get":{"tags":["leads","leads"],"summary":"Leads Fill Rates","description":"The Nutrition Label for the whole data set: per field, how many records have it filled.\n\nThe delivery file's Nutrition Label counts its own rows; this counts every record we\nhold, keyed by the column name a buyer sees. `fields[].pct` is filled / records;\n`fields[].source` says where it was counted (lead_browse column, entity_attribute, or\ncontact_attribute). `not_a_property` lists delivery-time names with nothing stored to\ncount; `not_measured` lists stored fields this endpoint does not count yet, with the\nreason — so an absence is never read as a zero.\n\nTwo numbers per field. `filled` / `pct` follow the delivery file's rule: a stored\nvalue that is not null and not blank (a placeholder such as `unclassified` ships in\nthe file, so it counts), except `has_phone` / `has_email`, which count TRUE only (a\nstored false means \"not found\"). `known` / `known_pct` is `filled` minus the placeholder\nvocabulary the filter grammar already treats as missing (`FIELD_SENTINELS`:\nunclassified, llm_unclassifiable, unknown, OTHER) — a real answer — and equals the\nfilter `exists` count. Stored keys that feed a delivery column (e.g. `status_canonical`)\nare also listed under their own name with `shipped:false` and `also_feeds`.\n\nCounts only — no record values, no contact data — so it is identical at both access\ntiers. Served from the in-process cache only (never computed on a request, the\n2026-09-22 OOM rule): `age_seconds` / `stale` date it, `202 computing` means this\nprocess has not finished its first sweep.","operationId":"leads_fill_rates_api_v1_leads_fill_rates_get","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"state","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"State code (e.g. CO). Omit for all states combined (ALL).","title":"State"},"description":"State code (e.g. CO). Omit for all states combined (ALL)."},{"name":"shipped_only","in":"query","required":false,"schema":{"type":"boolean","description":"Only the columns a delivery file carries. Default also lists every stored field the file holds back.","default":false,"title":"Shipped Only"},"description":"Only the columns a delivery file carries. Default also lists every stored field the file holds back."},{"name":"by_state","in":"query","required":false,"schema":{"type":"boolean","description":"Attach each field's fill percent in every state (`pct_by_state`).","default":false,"title":"By State"},"description":"Attach each field's fill percent in every state (`pct_by_state`)."},{"name":"fresh","in":"query","required":false,"schema":{"type":"boolean","description":"Ask the background warmer to recompute soon. Never computes in the request path; the response is the last snapshot.","default":false,"title":"Fresh"},"description":"Ask the background warmer to recompute soon. Never computes in the request path; the response is the last snapshot."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/leads/by-ref/{lead_ref}":{"get":{"tags":["leads","leads"],"summary":"Get a lead by GLID (one-call lookup)","description":"Full lead detail by GLID — the persistent human-readable reference\n(e.g. `GL-CO-00042`).\n\nUse this when you already know a lead's GLID (from a CRM, a Slack message,\na customer email, etc.) and want its full record in one call. Equivalent to\ncalling `POST /leads/browse` with `{\"filters\":[{\"field\":\"lead_ref\",\"op\":\"eq\",...}]}`\nthen `GET /leads/{entity_id}` — but one HTTP hop instead of two.\n\nGLIDs are case-insensitive; the canonical form is uppercase.\nReturns the same shape as `GET /leads/{entity_id}`. Contact fields are\nmasked under the commerce free/paid boundary; the response's\n`access_level` field signals \"full\" vs \"preview\".","operationId":"lead_detail_by_ref_api_v1_leads_by_ref__lead_ref__get","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"lead_ref","in":"path","required":true,"schema":{"type":"string","title":"Lead Ref"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/leads/{entity_id}":{"get":{"tags":["leads","leads"],"summary":"Lead Detail","description":"Full lead detail with all EAV attributes and provenance.\n\n`entity_id` is the internal UUID. To look up by GLID\n(e.g. `GL-CO-00042`), use `GET /leads/by-ref/{lead_ref}` instead.\n\nContact fields are masked under the commerce free/paid boundary; the\nresponse's `access_level` field signals \"full\" vs \"preview\".","operationId":"lead_detail_api_v1_leads__entity_id__get","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"entity_id","in":"path","required":true,"schema":{"type":"string","title":"Entity Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/leads/export":{"post":{"tags":["leads","leads"],"summary":"Export Leads","description":"Export selected leads as CSV or JSON, uploaded to S3 (or local tmp/ in dev).\n\nAccepts the admin key OR the read-only key — an export is the same\nfull-fidelity read the read-only key already has, materialized as a file.\nOutward dispatch (`to_email`) stays admin-only.\n\nReturns a presigned URL valid for 72 hours. Optionally emails the link\nvia SES if to_email is provided (admin key required).\n\nProvide entity_ids for specific leads, or set include_all_matching=True\n(optionally with state + filters) to export all matching leads. Omitting\nstate exports the matching cohort across every live state, same as an\n\"All States\" Browse.","operationId":"export_leads_api_v1_leads_export_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExportRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"APIKeyHeader":[]}]}},"/api/v1/schema/attributes":{"get":{"tags":["leads","schema"],"summary":"List Attributes","description":"List all filterable attributes with metadata.\n\nEach field carries its label, type, the ENFORCED operator set, `sortable`,\n`masked` (anonymous callers see a redacted value), and `allowed_values`\nwhere the vocabulary is enumerable. The default response is the bare list\nevery existing consumer iterates; `?include=grammar` returns\n{attributes, grammar} for agents that compose queries.","operationId":"list_attributes_api_v1_schema_attributes_get","parameters":[{"name":"include","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"`grammar` wraps the list as {attributes, grammar} — the grammar object describes the leaf shape, and/or/not groups, set predicates, operators per type, and sort keys.","title":"Include"},"description":"`grammar` wraps the list as {attributes, grammar} — the grammar object describes the leaf shape, and/or/not groups, set predicates, operators per type, and sort keys."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/schema/geo-words":{"get":{"tags":["leads","schema"],"summary":"Geo Words","description":"Neighborhood geography words for a state — every named neighborhood, Census\nDesignated Place, and alias the gazetteer knows, each as the filter chip it\nresolves to (`{field: 'neighborhood', op: 'eq', value: <canonical name>}`).\n\nFor the page grammar and the interpreter: a buyer's \"capitol hill\" or\n\"south austin\" matches a `word` here and becomes a `neighborhood` chip.\n`has_polygon` says whether records can carry the stamp; point-only names\nship `lat` / `lon` / `radius_m` so a radius predicate can stand in for the\nmissing polygon. Empty until the gazetteer is loaded for the state\n(docs/reference/NEIGHBORHOOD_SOURCES.md).","operationId":"geo_words_api_v1_schema_geo_words_get","parameters":[{"name":"state","in":"query","required":true,"schema":{"type":"string","description":"State code (e.g. CO, FL, TX)","title":"State"},"description":"State code (e.g. CO, FL, TX)"},{"name":"q","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Case-insensitive substring filter on the word","title":"Q"},"description":"Case-insensitive substring filter on the word"},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":5000,"minimum":1,"default":2000,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/schema/concepts":{"get":{"tags":["leads","schema"],"summary":"Explain Concept","description":"Map a buyer/agent term to this schema's ontology — or answer negatively but usefully.\n\nThe Ontology Bridge (R2): resolves the words an evaluating agent actually\nuses to the fields that serve them. `carried` names the fields and how to\nuse them; `partially_carried` adds per-state availability with the\nby-design reason; `not_carried` always names why and the nearest thing we\ndo hold. Ambiguous terms get a clarifying question, never a silent guess —\na confident mis-resolution ('registered agent' → decision-maker fields)\nis worse than no answer.","operationId":"explain_concept_api_v1_schema_concepts_get","parameters":[{"name":"term","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"A buyer's or agent's term in their own words ('vertical', 'direct dial', 'sole proprietor', 'registered agent'). Omit to list every curated concept.","title":"Term"},"description":"A buyer's or agent's term in their own words ('vertical', 'direct dial', 'sole proprietor', 'registered agent'). Omit to list every curated concept."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/schema/recipes":{"get":{"tags":["leads","schema"],"summary":"List Outcome Recipes","description":"The outcome-recipe bank — jobs-to-be-done answered in one call (ADR-034).\n\nEach recipe: the buyer phrasings it answers, the exact browse filters that\naccomplish the job, what each score means FOR THIS JOB, honest caveats\n(no score encodes intent, consent, or opt-in), and nearest-miss traps.\nPlus the vertical code tuples (plain word -> industry/NAICS/SIC/MCC/GMB\nas this data actually carries them). Recipes carry probe filters, never\ncounts - run the filter to get today's number.","operationId":"list_outcome_recipes_api_v1_schema_recipes_get","parameters":[{"name":"job","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter to recipes whose job or phrasings match this text (case-insensitive substring).","title":"Job"},"description":"Filter to recipes whose job or phrasings match this text (case-insensitive substring)."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/sic-naics/coverage":{"get":{"tags":["leads","schema"],"summary":"Sic Naics Coverage","description":"SIC/NAICS coverage stats — what % of entities have codes populated.\n\nOperational visibility for backfill progress and ongoing classifier\ncoverage. Per-granularity counts so we can see the always-2-digit\ninvariant in practice (2-digit should approach the populated total;\n4-digit and 6-digit may be lower due to ambiguous_deep rows where\ndeeper digits are intentionally null per ADR-008).\n\nReturns:\n    {\n      \"state\": \"CO\" | \"ALL\",\n      \"total\": 71744,\n      \"coverage\": {\n        \"sic_2_digit\": {\"count\": 12345, \"pct\": 17.2},\n        \"sic_4_digit\": {\"count\": 12000, \"pct\": 16.7},\n        \"naics_2_digit\": {\"count\": 12345, \"pct\": 17.2},\n        ...\n      }\n    }","operationId":"sic_naics_coverage_api_v1_sic_naics_coverage_get","parameters":[{"name":"state","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"State code (e.g. CO, FL, VA, NY). Omit for all-states aggregate.","title":"State"},"description":"State code (e.g. CO, FL, VA, NY). Omit for all-states aggregate."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/taxonomy":{"get":{"tags":["leads","schema"],"summary":"Get Taxonomy","description":"Industry taxonomy — sectors and industries for filter dropdowns.\n\nReturns the canonical sectors and industries from the classification taxonomy.\n`label` is the value stored in the DB (industry_sector / industry_name);\n`display_name` is the human-readable string for UI. Each industry includes\n`sector_label` so the UI can scope industry choices to a selected sector.","operationId":"get_taxonomy_api_v1_taxonomy_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/v1/sic-naics/labels":{"get":{"tags":["leads","schema"],"summary":"Get Sic Naics Labels","description":"SIC + NAICS code → human-readable label lookups.\n\nReturns the name of a code at every level we carry:\n  - SIC 2-digit major groups (~83 entries) and 3-digit industry groups\n    (~415, the 1987 SIC Manual's own titles)\n  - SIC 4-digit industries (~960 entries, from bpluly crosswalk + fallbacks)\n  - NAICS 2-digit sectors and 3/4/5-digit subsectors, industry groups and\n    industries (the Census Bureau's 2017 titles)\n  - NAICS 6-digit national industries (~990 entries)\n  - Google Business category display names and MCC descriptions\n\nSIC 677 sits on some records but is not a 1987 industry group, so it has\nno title — a code is never given a guessed name.\n\nCached for process lifetime. Frontend fetches once on page load and\njoins client-side to render meaningful filter chips, detail page rows,\nand CSV export headers.","operationId":"get_sic_naics_labels_api_v1_sic_naics_labels_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/v1/lists":{"post":{"tags":["lists","lists"],"summary":"Create List","description":"Save a shaped list. Anonymous allowed (rate-limited like browse); the\nresponse carries the one-time claim_token — the only time it is shown.","operationId":"create_list_api_v1_lists_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SavedListCreate"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"APIKeyHeader":[]}]}},"/api/v1/lists/starters":{"get":{"tags":["lists","lists"],"summary":"List Starters","description":"The starter shelf: every live state × business type we sell, each with\nthe summary's counts (`matching`, `sellable`, `verified_one`,\n`verified_both`), its display label, its from-price and the exact filters\nthe card opens with. Computed once and cached in-process (6 h; 5 min when\na state's count was partial) — never a live COUNT per page view.\n\nDeclared before `GET /lists/{list_id}` so the path is never read as a list id.","operationId":"list_starters_api_v1_lists_starters_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}},"security":[{"APIKeyHeader":[]}]}},"/api/v1/lists/shelf":{"get":{"tags":["lists","lists"],"summary":"List Shelf","description":"The time shelf: sellable counts per industry × live state for businesses\nfiled in the last 7 / 30 / 56 / 90 days and everything on file, each\nwindow's expected find upgrade per record, today's prices, and the window\nthe run rate of new records is read from. Built at the end of every pipeline\nrun and stored (backend/services/list_shelf.py); this reads the stored\nsnapshot, so a buyer's request never computes — a rolled date or a partial\ncount is rebuilt in the background.\n\nDeclared before `GET /lists/{list_id}` so the path is never read as a list id.","operationId":"list_shelf_api_v1_lists_shelf_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}},"security":[{"APIKeyHeader":[]}]}},"/api/v1/lists/{list_id}":{"get":{"tags":["lists","lists"],"summary":"Get List","operationId":"get_list_api_v1_lists__list_id__get","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"list_id","in":"path","required":true,"schema":{"type":"string","title":"List Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"patch":{"tags":["lists","lists"],"summary":"Patch List","description":"Rename. Authorized by the list's claim token or the owner. Until a\ncustomer session exists (wave two), the owner path is the admin key.","operationId":"patch_list_api_v1_lists__list_id__patch","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"list_id","in":"path","required":true,"schema":{"type":"string","title":"List Id"}},{"name":"X-Claim-Token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Claim-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SavedListPatch"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/lists/{list_id}/summary":{"get":{"tags":["lists","lists"],"summary":"List Summary Endpoint","description":"Counts + facets + prices for a saved list; add lane / cap for a quote.","operationId":"list_summary_endpoint_api_v1_lists__list_id__summary_get","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"list_id","in":"path","required":true,"schema":{"type":"string","title":"List Id"}},{"name":"lane","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"all | best | contact","title":"Lane"},"description":"all | best | contact"},{"name":"cap_type","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"count | budget","title":"Cap Type"},"description":"count | budget"},{"name":"cap_value","in":"query","required":false,"schema":{"anyOf":[{"type":"integer","minimum":0},{"type":"null"}],"description":"records for count, cents for budget","title":"Cap Value"},"description":"records for count, cents for budget"},{"name":"channel","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"phone | email — the one channel this buyer runs","title":"Channel"},"description":"phone | email — the one channel this buyer runs"},{"name":"offer_code","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"An offer code the buyer was given (ADR-058)","title":"Offer Code"},"description":"An offer code the buyer was given (ADR-058)"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/crosswalk":{"get":{"tags":["lists","lists"],"summary":"Crosswalk","description":"One classification code in, the other three systems out — with our industry, the filter for each, and a live count.\n\nWe carry NAICS, SIC, the Google Business category and the payment MCC on every\nrecord, tied together by our own taxonomy. Give any one (a code, or the words)\nand get the equivalents, the ready-to-use filter per system, and how many\nrecords are in it today. A code we do not carry widens through the crosswalk\n(to its parent group, then to the codes it ties to) and says so in `widened`.\nNo key needed.","operationId":"crosswalk_api_v1_crosswalk_get","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"q","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"A code or words: \"MCC 5812\", \"SIC 1711\", \"NAICS 238220\", \"google category plumber\", \"restaurants\".","title":"Q"},"description":"A code or words: \"MCC 5812\", \"SIC 1711\", \"NAICS 238220\", \"google category plumber\", \"restaurants\"."},{"name":"system","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"naics | sic | mcc | google_category — with `code`, instead of `q`.","title":"System"},"description":"naics | sic | mcc | google_category — with `code`, instead of `q`."},{"name":"code","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"The code in `system`. A SIC or NAICS prefix (17, 238) is a whole group.","title":"Code"},"description":"The code in `system`. A SIC or NAICS prefix (17, 238) is a whole group."},{"name":"states","in":"query","required":false,"schema":{"type":"string","description":"Comma-separated state codes for the live count; empty = every live state.","default":"","title":"States"},"description":"Comma-separated state codes for the live count; empty = every live state."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/counts":{"get":{"tags":["lists","lists"],"summary":"Counts By Url","description":"The summary as one GET — for agents and tools that can fetch a URL but cannot POST.\n\nSame numbers, same filter contract, same `group_by` as `POST /leads/summary`\n(this is a thin adapter over it); no key needed for counts.","operationId":"counts_by_url_api_v1_counts_get","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"states","in":"query","required":false,"schema":{"type":"string","description":"Comma-separated state codes; empty = every live state.","default":"","title":"States"},"description":"Comma-separated state codes; empty = every live state."},{"name":"filters","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"JSON-encoded filter array — the same contract as POST /leads/summary.","title":"Filters"},"description":"JSON-encoded filter array — the same contract as POST /leads/summary."},{"name":"group_by","in":"query","required":false,"schema":{"type":"string","description":"Comma-separated fields (max 2) to cross-tab by, e.g. property_classification,naics_2_digit.","default":"","title":"Group By"},"description":"Comma-separated fields (max 2) to cross-tab by, e.g. property_classification,naics_2_digit."},{"name":"include_existing","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"Include Existing"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/lists/interpret":{"post":{"tags":["lists","lists"],"summary":"Interpret List","description":"Translate one typed line into a list shape the page can open.","operationId":"interpret_list_api_v1_lists_interpret_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InterpretRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"APIKeyHeader":[]}]}},"/api/v1/crm/publish":{"post":{"tags":["crm"],"summary":"Publish Leads","description":"Publish selected leads to a connected CRM.\n\nProvide entity_ids for specific leads, or set include_all_matching=True\nwith filters to publish the whole filtered set — resolved server-side,\nsame contract as POST /leads/export. state is optional: omit it to push\nevery matching lead across all live states (e.g. an industry-only filter).\n\n`connection_id` is required — delivery runs through the engine (per-record\nledger, pacing, retries) against that connection. Returns immediately with\na durable job_id for polling. dry_run counts without sending.","operationId":"publish_leads_api_v1_crm_publish_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublishRequest"}}},"required":true},"responses":{"202":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublishResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"APIKeyHeader":[]}]}},"/api/v1/crm/status/{job_id}":{"get":{"tags":["crm","crm"],"summary":"Publish Status","description":"Check CRM publish job progress — durable, survives restarts.\n\nA job left `running` past the staleness window reports `interrupted`: the\nprocess died mid-push and its per-record ledger rows are intact. The\nengine's resume watchdog relaunches interrupted jobs automatically;\nre-pushing the same selection is also safe (delivered leads are skipped).","operationId":"publish_status_api_v1_crm_status__job_id__get","parameters":[{"name":"job_id","in":"path","required":true,"schema":{"type":"string","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/crm/field-map":{"get":{"tags":["crm","crm"],"summary":"Field Map","description":"Return HubSpot field mapping configuration.","operationId":"field_map_api_v1_crm_field_map_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/v1/crm/connections":{"get":{"tags":["crm"],"summary":"List Connections","description":"List CRM connections. Client secrets and access tokens are never returned.","operationId":"list_connections_api_v1_crm_connections_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ConnectionResponse"},"type":"array","title":"Response List Connections Api V1 Crm Connections Get"}}}}},"security":[{"APIKeyHeader":[]}]},"post":{"tags":["crm"],"summary":"Create Connection","description":"Register a partner CRM connection.\n\nTwo shapes, chosen by `credential_kind`:\n- **oauth** (Lawmatics): store the partner's app credentials and mint the\n  `authorize_url` they click (while logged in to their CRM) to grant access;\n  the callback endpoint below finishes the handshake.\n- **api_key** (Instantly): store the partner's pasted scoped key (encrypted)\n  and go straight to `connected` — no app to create, no callback. The\n  partner's only action is pasting the key.","operationId":"create_connection_api_v1_crm_connections_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConnectionCreateRequest"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConnectionResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"APIKeyHeader":[]}]}},"/api/v1/crm/connections/{connection_id}/repair-presentation":{"post":{"tags":["crm"],"summary":"Repair Presentation Route","description":"One-time person-first touch-up for already-delivered matters.\n\nRe-titles each ledgered matter to the person's name and fills its native\nbasics (partner feedback 2026-07-23: cards must show individuals, matching\nthe account's other pipelines). Idempotent; paced; per-record results.","operationId":"repair_presentation_route_api_v1_crm_connections__connection_id__repair_presentation_post","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"connection_id","in":"path","required":true,"schema":{"type":"string","title":"Connection Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/crm/connections/{connection_id}/seed-test":{"post":{"tags":["crm"],"summary":"Seed Test Connection","description":"Verify a live connection end to end with one synthetic seed lead.\n\nServer-side by design: access tokens are EncryptedText and never leave\nthe server, so the whole deliver → read-back → delete cycle runs here.\nDelivery goes through the real adapter (`ADAPTERS[provider].deliver_one`)\nbut writes NO CrmDelivery / CrmPublishJob rows — this is a probe, not a\ndelivery. Returns the exhaustive checklist ({check, expected, actual, ok}\nper field/tag/placement/link), `passed`, distilled `mismatches`, the\n`discoveries` map (candidate payload variants tried in-run, with the\nempirically working one named per construct), and the cleanup report —\ndeletion failures surface as `leftover_records`.","operationId":"seed_test_connection_api_v1_crm_connections__connection_id__seed_test_post","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"connection_id","in":"path","required":true,"schema":{"type":"string","title":"Connection Id"}}],"requestBody":{"content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/SeedTestRequest"},{"type":"null"}],"title":"Req"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/crm/connections/{connection_id}/delivered-records":{"get":{"tags":["crm"],"summary":"Inspect Delivered Records Route","description":"Read back what the CRM actually holds for records we already delivered.\n\nGround truth, not inference: for the connection's most recent delivered\nrecords (their Matter ids come from the crm_delivery ledger), read each\nMatter + its linked Contact + Company from the CRM with fields=all and\nreport exactly what's on them — native fields, custom-field values (by\nlabel), the channel/address collections, the tag. Strictly READ-ONLY (no\nwrites, no ledger rows). Admin-gated; paced under the rate limit.","operationId":"inspect_delivered_records_route_api_v1_crm_connections__connection_id__delivered_records_get","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"connection_id","in":"path","required":true,"schema":{"type":"string","title":"Connection Id"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","default":5,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/crm/connections/{connection_id}/delivery-summary":{"get":{"tags":["crm"],"summary":"Delivery Summary Route","description":"How many leads this connection has ever received — the delivery ledger,\naggregated. The question every partner conversation starts with.\n\nPure DB read, no partner API calls. `delivered_total` counts\nstatus='delivered' ledger rows — the exact never-twice set the engine\ndedups against, so it IS \"records this partner holds from us.\" Failed\nattempts are reported separately (they never block a retry and are not\npartner inventory). Weekly buckets + the recent publish jobs give the\npush history at a glance.","operationId":"delivery_summary_route_api_v1_crm_connections__connection_id__delivery_summary_get","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"connection_id","in":"path","required":true,"schema":{"type":"string","title":"Connection Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/crm/connections/{connection_id}/remove-delivered":{"post":{"tags":["crm"],"summary":"Remove Delivered Route","description":"Delete specific already-delivered leads from the partner CRM and drop\ntheir ledger rows — for records sent in error, off-target, or a removal\nrequest. Uses the connection's stored key server-side, so it needs DELETE\nscope on that key (a create-only key gets a 401, reported per-record, never\nsilent). Instantly only for now. Admin-gated. Dropping the ledger row makes\nthe record cleanly re-deliverable later if it becomes a wanted lead.","operationId":"remove_delivered_route_api_v1_crm_connections__connection_id__remove_delivered_post","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"connection_id","in":"path","required":true,"schema":{"type":"string","title":"Connection Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RemoveDeliveredRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/crm/oauth/callback":{"get":{"tags":["crm","crm"],"summary":"Oauth Callback","description":"Public OAuth redirect target — finishes the handshake, shows the partner a page.\n\nUnauthenticated by design: the partner's browser lands here from the CRM's\nauthorize screen. The `state` token (unique, unguessable, minted at\nregistration) is what ties the request to a known connection; anything\nthat doesn't match gets a plain-language error page and nothing else.","operationId":"oauth_callback_api_v1_crm_oauth_callback_get","parameters":[{"name":"state","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"State"}},{"name":"code","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Code"}},{"name":"error","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Error"}}],"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/subscriptions":{"get":{"tags":["subscriptions","subscriptions"],"summary":"List Subscriptions","operationId":"list_subscriptions_api_v1_subscriptions_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/SubscriptionResponse"},"type":"array","title":"Response List Subscriptions Api V1 Subscriptions Get"}}}}},"security":[{"APIKeyHeader":[]}]},"post":{"tags":["subscriptions","subscriptions"],"summary":"Create Subscription","description":"Set up a standing delivery for a client on any saved list, at any\nschedule, price shape and billing mode (admin). The response carries the\nmanage link to hand the client; `POST …/{id}/fire` runs it on demand.","operationId":"create_subscription_api_v1_subscriptions_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscriptionCreate"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscriptionResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"APIKeyHeader":[]}]}},"/api/v1/subscriptions/{subscription_id}":{"get":{"tags":["subscriptions","subscriptions"],"summary":"Get Subscription","operationId":"get_subscription_api_v1_subscriptions__subscription_id__get","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"subscription_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Subscription Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscriptionResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"patch":{"tags":["subscriptions","subscriptions"],"summary":"Update Subscription","operationId":"update_subscription_api_v1_subscriptions__subscription_id__patch","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"subscription_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Subscription Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscriptionUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscriptionResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/subscriptions/{subscription_id}/fire":{"post":{"tags":["subscriptions","subscriptions"],"summary":"Fire Subscription","description":"Fire a delivery now, due or not — the dry run before go-live and the\nfirst delivery on demand. Serves a one-off window; the schedule is untouched\nexcept that `next_delivery_at` moves past now.\n\nA real-size firing (thousands of records: selection, workbook, upload,\nemails) outlasts an HTTP request, so by default it runs in the background\nand the response says `started`; the row's `last_delivery` carries the\nresult within minutes. `?wait=true` runs it inline (tests, small dry runs).\nAn ended delivery never fires; a paused one does — that is the operator's\ndeliberate dry run.","operationId":"fire_subscription_api_v1_subscriptions__subscription_id__fire_post","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"subscription_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Subscription Id"}},{"name":"wait","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"Wait"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FireResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/subscriptions/receipts/import":{"post":{"tags":["subscriptions","subscriptions"],"summary":"Import Receipts","operationId":"import_receipts_api_v1_subscriptions_receipts_import_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReceiptImportRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReceiptImportResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"APIKeyHeader":[]}]}},"/api/v1/subscriptions/{subscription_id}/checkout":{"post":{"tags":["subscriptions","subscriptions"],"summary":"Create Subscription Checkout","description":"Create a subscription-mode Stripe Checkout Session for a standing order.\n\nThe purchase→subscription path (ADR-041): the operator creates the\nSubscription row first (existing CRUD — the frozen filter/cadence/stages\nthe client agreed to), then mints this recurring payment link to send the\nbuyer. The session threads ``subscription_id`` in metadata; on\n``checkout.session.completed`` the commerce webhook links the Stripe\nsubscription back to this row, stamps the ids, and flips\n``billing_status='active'``. Admin-only — same gate as the CRUD.","operationId":"create_subscription_checkout_api_v1_subscriptions__subscription_id__checkout_post","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"subscription_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Subscription Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscriptionCheckoutRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscriptionCheckoutResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/subscriptions/from-order":{"post":{"tags":["subscriptions","subscriptions"],"summary":"Subscription From Order","operationId":"subscription_from_order_api_v1_subscriptions_from_order_post","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"X-Claim-Token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Claim-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FromOrderRequest"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/subscriptions/from-list":{"post":{"tags":["subscriptions","subscriptions"],"summary":"Subscription From List","operationId":"subscription_from_list_api_v1_subscriptions_from_list_post","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"X-Claim-Token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Claim-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FromListRequest"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/subscriptions/manage/{token}":{"get":{"tags":["subscriptions","subscriptions"],"summary":"Manage Get","operationId":"manage_get_api_v1_subscriptions_manage__token__get","parameters":[{"name":"token","in":"path","required":true,"schema":{"type":"string","title":"Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"patch":{"tags":["subscriptions","subscriptions"],"summary":"Manage Update","operationId":"manage_update_api_v1_subscriptions_manage__token__patch","parameters":[{"name":"token","in":"path","required":true,"schema":{"type":"string","title":"Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ManageUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/subscriptions/manage/{token}/cancel":{"post":{"tags":["subscriptions","subscriptions"],"summary":"Manage Cancel","operationId":"manage_cancel_api_v1_subscriptions_manage__token__cancel_post","parameters":[{"name":"token","in":"path","required":true,"schema":{"type":"string","title":"Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/subscriptions/manage/{token}/results":{"post":{"tags":["subscriptions","subscriptions"],"summary":"Manage Upload Results","description":"Send back the delivered file (xlsx or csv) with the `outcome` column filled in.","operationId":"manage_upload_results_api_v1_subscriptions_manage__token__results_post","parameters":[{"name":"token","in":"path","required":true,"schema":{"type":"string","title":"Token"}}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_manage_upload_results_api_v1_subscriptions_manage__token__results_post"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"get":{"tags":["subscriptions","subscriptions"],"summary":"Manage Results","description":"Your results by state, tier and delivery week, with the denominator on every row.","operationId":"manage_results_api_v1_subscriptions_manage__token__results_get","parameters":[{"name":"token","in":"path","required":true,"schema":{"type":"string","title":"Token"}},{"name":"format","in":"query","required":false,"schema":{"enum":["json","markdown"],"type":"string","default":"json","title":"Format"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/enrichment/preview":{"post":{"tags":["enrichment","enrichment"],"summary":"Enrichment Preview","description":"Analyze selected leads for enrichment eligibility.\n\nReturns segment breakdown, contact coverage, eligible count, and cost estimate.\nUse this before committing to enrichment to understand the cost and value.\n\nStill consumed by the State GM agents (`get_enrichment_preview` tool) — read-only.","operationId":"enrichment_preview_api_v1_enrichment_preview_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnrichmentRequest"}}},"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/enrichment/build":{"post":{"tags":["enrichment","enrichment"],"summary":"Build Enrichment Batch Removed","description":"DEPRECATED — removed in favor of POST /api/v1/pipeline/trigger.\n\nThe old implementation built a Tracerfy batch and ran the enrichment pipeline\n(skip_trace → gapfill → validate → score → reload) as a local background thread\ninside the API container. That container is not provisioned to run paid\nenrichment stages, so the path failed in production (TX job 5ac78544:\n`skip_trace` \"exit code 1\" after ~90s).\n\nThe Browse selection bar and Lead Detail \"Send to Pipeline…\" actions now call\nPOST /api/v1/pipeline/trigger (PR #536), which runs stages as isolated ECS tasks\nwith a Run Manifest for per-entity COGS attribution. This endpoint returns 410\nGone; there are no remaining callers in the frontend or the agent layer.","operationId":"build_enrichment_batch_removed_api_v1_enrichment_build_post","responses":{"410":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}},"deprecated":true}},"/api/v1/monitoring/alerts":{"get":{"tags":["monitoring","monitoring"],"summary":"Monitoring Alerts","description":"Active threshold breaches and volume anomalies.\n\nReturns alerts where current metrics violate configured thresholds\n(e.g., phone fill below 45%) plus volume anomaly detection (>20% drop\nfrom 30-day baseline). Used by Anomaly Watch LIVE tile.","operationId":"monitoring_alerts_api_v1_monitoring_alerts_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/v1/monitoring/alerts/config":{"get":{"tags":["monitoring","monitoring"],"summary":"List Alert Configs","description":"List all alert threshold configurations.","operationId":"list_alert_configs_api_v1_monitoring_alerts_config_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}},"post":{"tags":["monitoring","monitoring"],"summary":"Upsert Alert Config","description":"Create or update an alert threshold configuration.","operationId":"upsert_alert_config_api_v1_monitoring_alerts_config_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlertConfigRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"APIKeyHeader":[]}]}},"/api/v1/monitoring/schedules":{"get":{"tags":["monitoring","monitoring"],"summary":"Get Schedule Board","description":"The Schedule Board's data: every registered rule + the live drift check.\n\nRegistry (the ledger Gib approves) always serves; the live EventBridge\ncomparison is fail-soft — without AWS read access the board still shows\nthe ledger, flagged `live_check: \"unavailable\"` instead of pretending.\n\n`overlap_issues()` (window-collision risk, 2026-09-03 PM finding) is a\npure function of the registry alone — no AWS call — so it runs OUTSIDE\nthe live-check try/except and is always present, even when\n`live_check: \"unavailable\"`.","operationId":"get_schedule_board_api_v1_monitoring_schedules_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/v1/events/stream":{"get":{"tags":["events","events"],"summary":"Event Stream","description":"SSE endpoint for live tile updates.\n\nThe browser connects once using EventSource. Events arrive when\ndata changes — tiles re-fetch only the affected data.\n\nFalls back gracefully: if SSE disconnects, the grid's 60-second\npolling catches up. SSE is an acceleration layer, not a dependency.","operationId":"event_stream_api_v1_events_stream_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/v1/events/status":{"get":{"tags":["events","events"],"summary":"Event Status","description":"Check how many SSE clients are connected.","operationId":"event_status_api_v1_events_status_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/v1/agents":{"get":{"tags":["agents","agents"],"summary":"List Agent Tiles","description":"List all agent tiles with their current narratives.\n\nLIVE tiles include cached narrative headlines. LAUNCH tiles include\ntheir greeting text. The grid frontend calls this on load and\nafter SSE events to refresh affected tiles.","operationId":"list_agent_tiles_api_v1_agents_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/v1/agents/{agent_id}/narrative":{"get":{"tags":["agents","agents"],"summary":"Get Tile Narrative","description":"Get the narrative for a LIVE agent tile.\n\nAlways calls generate() which uses hash-based caching internally —\nif data hasn't changed, returns the cached narrative; if data changed,\ngenerates a fresh one.","operationId":"get_tile_narrative_api_v1_agents__agent_id__narrative_get","parameters":[{"name":"agent_id","in":"path","required":true,"schema":{"type":"string","title":"Agent Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/agents/{agent_id}/chat":{"post":{"tags":["agents","agents"],"summary":"Agent Chat","description":"Handle a conversational turn with a LAUNCH agent.\n\nAccepts the operator's message and conversation history.\nRoutes to the appropriate agent service based on agent_id.\nReturns a natural-language response with optional follow-up chips.","operationId":"agent_chat_api_v1_agents__agent_id__chat_post","parameters":[{"name":"agent_id","in":"path","required":true,"schema":{"type":"string","title":"Agent Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChatRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/agents/{agent_id}/config":{"put":{"tags":["agents","agents"],"summary":"Update Tile Config","description":"Update tile settings (position, enabled, size).","operationId":"update_tile_config_api_v1_agents__agent_id__config_put","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"agent_id","in":"path","required":true,"schema":{"type":"string","title":"Agent Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TileConfigUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/services/summary":{"get":{"tags":["services","services"],"summary":"Formation Service Summary","description":"Formation service attribution counts by state — the SLA view.","operationId":"formation_service_summary_api_v1_services_summary_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/v1/services/registry":{"get":{"tags":["services","services"],"summary":"Formation Service Registry","description":"The full attribution registry — every RA name mapping with evidence.","operationId":"formation_service_registry_api_v1_services_registry_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/v1/services/coverage":{"get":{"tags":["services","services"],"summary":"Formation Service Coverage","description":"Attribution coverage — what % of formations can we identify by service.","operationId":"formation_service_coverage_api_v1_services_coverage_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/v1/services/{service}/entities":{"get":{"tags":["services","services"],"summary":"Formation Service Entities","description":"Drill-down: entities attributed to a formation service.","operationId":"formation_service_entities_api_v1_services__service__entities_get","parameters":[{"name":"service","in":"path","required":true,"schema":{"type":"string","title":"Service"}},{"name":"state","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"State"}},{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"default":1,"title":"Page"}},{"name":"page_size","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":25,"title":"Page Size"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/services/ra-names":{"get":{"tags":["services","services"],"summary":"Formation Service Ra Names","description":"All matched RA names with actual formation counts.","operationId":"formation_service_ra_names_api_v1_services_ra_names_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/v1/services/address-clusters":{"get":{"tags":["services","services"],"summary":"Formation Service Address Clusters","description":"RA address clustering — which physical addresses do formation services use?","operationId":"formation_service_address_clusters_api_v1_services_address_clusters_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/v1/admin/partner-access":{"post":{"tags":["admin"],"summary":"Create Partner Access","description":"Mint a 72-hour magic link that delivers the read-only dashboard key.\n\nAdmin-only (the page carries a live credential). Returns the presigned URL\nfor the admin to send from their own email/text — nothing is dispatched.","operationId":"create_partner_access_api_v1_admin_partner_access_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PartnerAccessRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PartnerAccessResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"APIKeyHeader":[]}]}},"/api/v1/admin/replay-tracerfy":{"post":{"tags":["admin"],"summary":"Replay Tracerfy Start","description":"Launch a replay job and return immediately.\n\nThe work runs in the background; the report lands in S3 at\n`s3://<bucket>/enrichment/_replay/tracerfy/reports/<report_id>.json`.\nPoll `GET /admin/replay-tracerfy/{report_id}` for completion.","operationId":"replay_tracerfy_start_api_v1_admin_replay_tracerfy_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReplayTracerfyRequest"}}},"required":true},"responses":{"202":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReplayTracerfyAccepted"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"APIKeyHeader":[]}]}},"/api/v1/admin/replay-tracerfy/{report_id}":{"get":{"tags":["admin"],"summary":"Replay Tracerfy Status","description":"Read the current state of a replay job from S3.","operationId":"replay_tracerfy_status_api_v1_admin_replay_tracerfy__report_id__get","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"report_id","in":"path","required":true,"schema":{"type":"string","title":"Report Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReplayTracerfyReport"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/llm-audit/summary":{"get":{"tags":["admin"],"summary":"Llm Audit Summary","description":"Aggregate repeat-spend view over the last `days` of LLM calls.\n\nRead-only, admin-key gated; runs on the read session (replica when one is\nconfigured). Out-of-range `days` is a 422, not a silent reinterpretation.","operationId":"llm_audit_summary_api_v1_admin_llm_audit_summary_get","security":[{"APIKeyHeader":[]}],"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/LlmAuditSummary"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/classification/coverage":{"get":{"tags":["classification"],"summary":"Get Coverage","description":"Coverage summary for the classification brain.\n\nReturns total / classified / unclassified counts, confidence-tier\ndistribution, and a top-K sample of unclassified entity names. The\nagent tokenizes the sample natively (no server-side tokenization).","operationId":"get_coverage_api_v1_classification_coverage_get","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"state","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Two-letter state code (CO, FL, VA, NY); omit for cross-state","title":"State"},"description":"Two-letter state code (CO, FL, VA, NY); omit for cross-state"},{"name":"sector","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"industry_sector to scope; omit for all sectors","title":"Sector"},"description":"industry_sector to scope; omit for all sectors"},{"name":"top_tokens","in":"query","required":false,"schema":{"type":"integer","maximum":200,"minimum":1,"description":"How many top unclassified entity names to return for token-mining","default":30,"title":"Top Tokens"},"description":"How many top unclassified entity names to return for token-mining"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CoverageResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/classification/fp-sample":{"get":{"tags":["classification"],"summary":"Get Fp Sample","description":"Random sample of N records currently classified into `sector` for\nfalse-positive audit.\n\nUses `ORDER BY random() LIMIT n` — fine at our scale (≤ ~1M rows per\nsector cross-state). If sample sizes climb past ~100, swap to\nTABLESAMPLE BERNOULLI which is constant-time. Random ordering rather\nthan recency on purpose — FP audit needs an unbiased sample so the\nagent isn't seeing only the most recent classification decisions.","operationId":"get_fp_sample_api_v1_classification_fp_sample_get","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"sector","in":"query","required":true,"schema":{"type":"string","description":"industry_sector to sample (required)","title":"Sector"},"description":"industry_sector to sample (required)"},{"name":"n","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":30,"title":"N"}},{"name":"state","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Optional state scope (CO/FL/VA/NY)","title":"State"},"description":"Optional state scope (CO/FL/VA/NY)"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FpSampleResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/classification/taxonomy-proposal":{"post":{"tags":["classification"],"summary":"Post Taxonomy Proposal","description":"Accept a structured taxonomy proposal from the agent and persist it\nas an AgentFinding (finding_type='revenue_opportunity', domain='data_quality').\n\nThe proposal action + target + evidence land in the finding's\nevidence JSONB so the existing approval queue (and the agent's\n`evaluate_peer_findings` skill) reads them with the same machinery\nit uses for every other finding type. Proposals are always created\n`pending` — no auto-approval path; Gib reviews on the standard\ncadence (Tenet #31 — blast radius must be visible before approval).","operationId":"post_taxonomy_proposal_api_v1_classification_taxonomy_proposal_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TaxonomyProposalRequest"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TaxonomyProposalResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"APIKeyHeader":[]}]}},"/api/v1/classification/blast-radius":{"post":{"tags":["classification"],"summary":"Post Blast Radius","description":"Blast-radius preflight for a proposed taxonomy diff.\n\nTenet #31 enforcement: every keyword / taxonomy proposal must ship\nwith three numbers (records newly classified, records rebucketed,\nrecords confidence-tier shifted). This endpoint produces those\nnumbers by loading the current FusionEngine, applying the proposed\ndiff in-memory, classifying a representative sample, and diffing\nagainst current labels.\n\nResponse shape mirrors `/api/v1/enrichment/preview` — same\n`total / eligible / by_segment / sample / cost_implication` skeleton\nso reviewers read both with the same mental model.\n\nScope discipline for v1:\n  - add_keyword is fully modelled.\n  - split / merge / add_sub return a partial response with\n    `requires_offline_review=true` and the sample populated —\n    enough to file a Tier-2 finding with legible-but-partial\n    numbers; full modelling lands when PR 1's taxonomy IP tables\n    are populated.","operationId":"post_blast_radius_api_v1_classification_blast_radius_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BlastRadiusRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BlastRadiusResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"APIKeyHeader":[]}]}},"/api/v1/config/public":{"get":{"tags":["config"],"summary":"Public Config","description":"Secret-free runtime config for the browser. No auth, no DB.","operationId":"public_config_api_v1_config_public_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicConfig"}}}}}}},"/api/v1/manifest":{"get":{"tags":["config"],"summary":"Every field, limit, price, state and live feature — one machine-readable page","description":"What the platform can do today: fields (with the doors that carry each), endpoints and\ntheir limits, live states, prices, which features are live, and the glossary.","operationId":"get_manifest_api_v1_manifest_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Get Manifest Api V1 Manifest Get"}}}}}}},"/api/v1/telemetry/agent-session":{"post":{"tags":["telemetry"],"summary":"Agent Session","description":"Record one `agent_session`. 204 always; records only with a valid surface.","operationId":"agent_session_api_v1_telemetry_agent_session_post","requestBody":{"content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/AgentSessionBeacon"},{"type":"null"}],"title":"Body"}}}},"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/privacy-request":{"post":{"tags":["privacy","privacy"],"summary":"Submit Privacy Request","description":"Accept a CCPA/CPRA privacy rights request and notify the operator.\n\nRate limited to prevent spam POSTs from generating notification-email\nfloods. Always 200 on an accepted submission — email delivery is\nbest-effort (see privacy_notify.send_privacy_request_email).","operationId":"submit_privacy_request_api_v1_privacy_request_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PrivacyRequestPayload"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PrivacyRequestResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/gm/llm-classify":{"post":{"tags":["gm","gm"],"summary":"Llm Classify","description":"Run the LLM second pass over the unclassified residue.\n\nThe classifier + TROOP prompt live under agents/ — the optional agent\nlayer, which the pipeline reaches only over HTTP (never by import).\nScopes to a manifest's entities when given, else the whole state. No-op\n(returns residue=0) unless enable_llm_classification + an OpenAI key are set.","operationId":"llm_classify_api_v1_gm_llm_classify_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LLMClassifyRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"APIKeyHeader":[]}]}},"/api/v1/gm/llm-classify-repair":{"post":{"tags":["gm","gm"],"summary":"Llm Classify Repair","description":"Restore classifications lost to the pre-guard downgrade path.\n\nOne-shot maintenance for the GL-FL-132667 incident shape: entities whose\nconfident (paid) LLM classification was overwritten with unknown /\n'llm_unclassifiable' while their method='llm_classify' SIC/NAICS rows\nsurvived. Reverse-maps the surviving codes through the taxonomy and\nrestores sector/industry/tier at conservative confidence — no LLM spend.\nUse dry_run=true to count the damage first.","operationId":"llm_classify_repair_api_v1_gm_llm_classify_repair_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LLMClassifyRepairRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"APIKeyHeader":[]}]}},"/api/v1/gm/llm-name":{"post":{"tags":["gm","gm"],"summary":"Llm Name","description":"Run the AI name pass over the low-confidence Name Intelligence residue.\n\nThe resolver + TROOP prompt live under agents/ — the optional agent\nlayer, which the pipeline reaches only over HTTP (never by import).\nScopes to a manifest's entities when given, else the whole state. No-op\n(residue=0) unless an OpenAI key is set (selecting the stage is the on-switch).","operationId":"llm_name_api_v1_gm_llm_name_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LLMNameRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"APIKeyHeader":[]}]}},"/api/v1/gm/llm-namesake":{"post":{"tags":["gm","gm"],"summary":"Llm Namesake","description":"Adjudicate the namesake-blend residue (mid-word / deep-interior\ncontainments the deterministic matcher refuses to score). Judge + prompt\nlive under agents/ — HTTP-only from the pipeline. Insert-only verdicts:\neach contact/entity pair is paid for once, ever. No-op without an OpenAI\nkey. Eval gate: the adjudicated 31-pair corpus fixture.","operationId":"llm_namesake_api_v1_gm_llm_namesake_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LLMNamesakeRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"APIKeyHeader":[]}]}},"/api/v1/gm/classification-provenance":{"get":{"tags":["gm","gm"],"summary":"Classification Provenance","description":"Read-only diagnostic: entities whose industry_sector was stamped by a\ngiven classification method — default 'llm_classify', the paid LLM second\npass. Built for vendor bake-offs: pull the exact records a prior LLM model\nalready classified, replay them through a candidate model, and measure\nagreement against what's on file — instead of eyeballing a fresh sample\nwith no reference answer. Modeled on agents/services/llm_distill.py's\n`_pull_llm_wins` query (same join, same method filter).\n\nCaveat: entity_attribute.method records WHICH STAGE produced a result\n('llm_classify' vs 'classification_service'), not which specific model\nversion was live when it ran — that isn't persisted per-row. This\nidentifies \"the LLM stage decided this\", not a pinned model ID.\n\nNo vendor spend, no writes — gated to ADMIN/READ_ONLY like every other\nfull-fidelity read (see backend/auth.py::require_export_key).","operationId":"classification_provenance_api_v1_gm_classification_provenance_get","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"state","in":"query","required":true,"schema":{"type":"string","description":"Two-letter state code","title":"State"},"description":"Two-letter state code"},{"name":"method","in":"query","required":false,"schema":{"type":"string","description":"entity_attribute.method to filter on (e.g. llm_classify, classification_service)","default":"llm_classify","title":"Method"},"description":"entity_attribute.method to filter on (e.g. llm_classify, classification_service)"},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":1000,"minimum":1,"default":500,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/gm/summary":{"get":{"tags":["gm","gm"],"summary":"State Summary","description":"State metrics dashboard for agent assessment.\n\nAggregates from the lead_browse materialized view: record count, fill rates,\nquality metrics, top industries, and last pipeline run.","operationId":"state_summary_api_v1_gm_summary_get","parameters":[{"name":"state","in":"query","required":true,"schema":{"type":"string","description":"Two-letter state code","title":"State"},"description":"Two-letter state code"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/gm/economics":{"get":{"tags":["gm","gm"],"summary":"State Economics","description":"Enrichment unit economics per state.\n\nReturns contact coverage, enrichment spend estimates, and vendor hit rates.\nServed from a short per-process TTL cache (see note above) — pass\n``fresh=true`` to force a recompute.","operationId":"state_economics_api_v1_gm_economics_get","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"state","in":"query","required":true,"schema":{"type":"string","description":"Two-letter state code","title":"State"},"description":"Two-letter state code"},{"name":"fresh","in":"query","required":false,"schema":{"type":"boolean","description":"Bypass the per-process TTL cache and recompute now. Leave off for routine reads — warm responses are what keep this endpoint inside agent tool budgets (mirrors data_quality_service's scorecard cache).","default":false,"title":"Fresh"},"description":"Bypass the per-process TTL cache and recompute now. Leave off for routine reads — warm responses are what keep this endpoint inside agent tool budgets (mirrors data_quality_service's scorecard cache)."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/gm/findings":{"get":{"tags":["gm","gm"],"summary":"List Findings","description":"List agent findings with optional filters.","operationId":"list_findings_api_v1_gm_findings_get","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"state","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"State"}},{"name":"status","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Status"}},{"name":"finding_type","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Finding Type"}},{"name":"priority","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Priority"}},{"name":"domain","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Domain"}},{"name":"memory_route","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by memory_route (episodic/semantic/procedural/working)","title":"Memory Route"},"description":"Filter by memory_route (episodic/semantic/procedural/working)"},{"name":"author_agent","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by evidence.author_agent. Surfaces findings that reference this agent's work — used by the four-layer briefing binder so a state GM sees EM's feedback on its own PRs at session start.","title":"Author Agent"},"description":"Filter by evidence.author_agent. Surfaces findings that reference this agent's work — used by the four-layer briefing binder so a state GM sees EM's feedback on its own PRs at session start."},{"name":"active_only","in":"query","required":false,"schema":{"type":"boolean","description":"Exclude superseded findings","default":false,"title":"Active Only"},"description":"Exclude superseded findings"},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":200,"minimum":1,"default":50,"title":"Limit"}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0,"default":0,"title":"Offset"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["gm","gm"],"summary":"Create Finding","description":"Create a finding. Called by the State GM agent via custom tool bridge.","operationId":"create_finding_api_v1_gm_findings_post","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FindingCreate"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/gm/actions":{"get":{"tags":["gm","gm"],"summary":"List Actions","description":"List actions with optional filters.","operationId":"list_actions_api_v1_gm_actions_get","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"status","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Status"}},{"name":"finding_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Finding Id"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":200,"default":50,"title":"Limit"}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","default":0,"title":"Offset"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["gm","gm"],"summary":"Create Action","description":"Propose an action. Called by the State GM agent.","operationId":"create_action_api_v1_gm_actions_post","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ActionCreate"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/gm/actions/{action_id}":{"patch":{"tags":["gm","gm"],"summary":"Update Action","description":"Approve or reject an action. Called by Gib via review CLI/API.","operationId":"update_action_api_v1_gm_actions__action_id__patch","parameters":[{"name":"action_id","in":"path","required":true,"schema":{"type":"string","title":"Action Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ActionUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/gm/schedules/{rule_name}/enable":{"post":{"tags":["gm","gm"],"summary":"Enable Schedule","description":"Enable one EventBridge rule — server-side half of Rule 6 v2.\n\nRefuses unless fresh evidence says `may_self_enable` is true: TIER_PM,\nevery pre-flight check green, not already enabled, and not `pinned` in\nthe registry (a human hold that survives even a green pre-flight). A rule\nis never enabled on a tier the CALLER supplies — only on the tier this\nhandler derives right now.\n\nDoes NOT touch `scripts/deploy/schedule_registry.yaml` — the registry is\ngit-tracked and updating it is a PR like any other registry change; the\nPM opens that PR itself in the same session (Rule 6 v2's \"records\nenabled: true in the registry the same session\"). This endpoint's job\nends at the live AWS state.","operationId":"enable_schedule_api_v1_gm_schedules__rule_name__enable_post","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"rule_name","in":"path","required":true,"schema":{"type":"string","title":"Rule Name"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/gm/schedules/{rule_name}/create":{"post":{"tags":["gm","gm"],"summary":"Create Schedule","description":"Create one registry-declared, free rule in EventBridge — DISABLED only (ADR-067).\n\nTakes a rule NAME and nothing else: the command, cron and target are all\nbuilt server-side from the registry entry, so a caller cannot supply or\nalter what will run. Eligibility is re-derived here on every call\n(`schedule_create.assess_creation`): registered, not pinned, not parked,\nnot the deliver layer, no vendor-paid stage, a real cron + command. The\nrule is written State=DISABLED; turning it on stays the separate,\npreflight-gated enable path. Idempotent: an identical live rule is a\nno-op, a live rule with a different command is refused.","operationId":"create_schedule_api_v1_gm_schedules__rule_name__create_post","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"rule_name","in":"path","required":true,"schema":{"type":"string","title":"Rule Name"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/gm/doc-registry":{"get":{"tags":["gm","gm"],"summary":"List Doc Registry","description":"List doc registry entries, newest first.\n\n`doc_path` is an exact match (same key the POST upserts on) — callers that\nlook up the Google Doc ID for a known file rely on this returning only that\nfile's row, never a newest-first fallback.","operationId":"list_doc_registry_api_v1_gm_doc_registry_get","parameters":[{"name":"doc_path","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Doc Path"}},{"name":"state","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"State"}},{"name":"doc_type","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Doc Type"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":50,"minimum":1,"default":10,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["gm","gm"],"summary":"Register Doc","description":"Register a Google Doc ID. Upserts by doc_path.","operationId":"register_doc_api_v1_gm_doc_registry_post","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DocRegistryCreate"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/gm/wiki":{"get":{"tags":["gm","gm"],"summary":"List Wiki Pages","description":"List wiki pages, optionally filtered by state and domain.","operationId":"list_wiki_pages_api_v1_gm_wiki_get","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"state","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"State"}},{"name":"domain","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Domain"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":50,"minimum":1,"default":20,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["gm","gm"],"summary":"Create Wiki Page","description":"Create a wiki page. Upserts by (state, domain, title).\n\nAdmin-gated: wiki pages are loaded verbatim into agent system prompts\n(Code Judgment onboarding, State GM briefings) — an unauthenticated write\nhere would be a prompt-injection path into the merge gate.","operationId":"create_wiki_page_api_v1_gm_wiki_post","security":[{"APIKeyHeader":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WikiPageCreate"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/gm/wiki/{wiki_page_id}":{"get":{"tags":["gm","gm"],"summary":"Get Wiki Page","description":"Get a specific wiki page by ID.","operationId":"get_wiki_page_api_v1_gm_wiki__wiki_page_id__get","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"wiki_page_id","in":"path","required":true,"schema":{"type":"string","title":"Wiki Page Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["gm","gm"],"summary":"Update Wiki Page","description":"Update a wiki page. Bumps version and updated_at.\n\nAdmin-gated for the same reason as POST /wiki: wiki content feeds agent\nsystem prompts, so writes require the admin key.","operationId":"update_wiki_page_api_v1_gm_wiki__wiki_page_id__put","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"wiki_page_id","in":"path","required":true,"schema":{"type":"string","title":"Wiki Page Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WikiPageUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/gm/experiment/propose":{"post":{"tags":["gm","gm"],"summary":"Propose Experiment Endpoint","description":"Validate + create a pending experiment + check the agent's budget.\n\nReturns 422 if cost exceeds remaining envelope or proposal is invalid.\nReturns 201 with experiment_id, cost_estimate_usd, remaining_envelope_after_usd.","operationId":"propose_experiment_endpoint_api_v1_gm_experiment_propose_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProposeExperimentRequest"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"APIKeyHeader":[]}]}},"/api/v1/gm/experiment/{experiment_id}/run":{"post":{"tags":["gm","gm"],"summary":"Run Experiment Endpoint","description":"Execute a pending experiment and record actual spend on the envelope.\n\nReturns the orchestrator's result + final spend. Long-running endpoint:\nreal vendor experiments may take minutes (Tracerfy polling). Agent\ncallers should expect this and have a generous timeout.","operationId":"run_experiment_endpoint_api_v1_gm_experiment__experiment_id__run_post","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"experiment_id","in":"path","required":true,"schema":{"type":"string","title":"Experiment Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RunExperimentRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/gm/experiment/corpus-preview":{"post":{"tags":["gm","gm"],"summary":"Corpus Preview Endpoint","description":"FREE preflight: materialize a corpus spec without running anything.\n\nReturns the item count, a small sample, and (for loaders that expose\nthem) selection stats — read the free data BEFORE spending vendor\ncredits (Tenet #7). Exactly the loader `run_experiment` would invoke,\nso what you preview is what a paid run would dip.","operationId":"corpus_preview_endpoint_api_v1_gm_experiment_corpus_preview_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CorpusPreviewRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"APIKeyHeader":[]}]}},"/api/v1/gm/experiment/{experiment_id}/reattribute":{"post":{"tags":["gm","gm"],"summary":"Reattribute Experiment Endpoint","description":"Re-fetch a completed Tracerfy queue and re-attribute the cells — free.\n\nRecovery for a run that billed spend but read the batch before the\nvendor finished (the 2026-08-09 premature-poll incident): the results\nstill sit on the vendor's queue endpoint; this replays attribution from\neach cell's stored submitted_attributes and updates output_artifact in\nplace. Idempotent. Admin-gated: it mutates experiment cells.","operationId":"reattribute_experiment_endpoint_api_v1_gm_experiment__experiment_id__reattribute_post","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"experiment_id","in":"path","required":true,"schema":{"type":"string","title":"Experiment Id"}}],"requestBody":{"content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/ReattributeRequest"},{"type":"null"}],"title":"Req"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/gm/experiment/{experiment_id}":{"get":{"tags":["gm","gm"],"summary":"Read Experiment Endpoint","description":"Read-only summary of an experiment + per-variant cell + match counts.\n\n`include_cells=true` attaches each variant's per-cell rows\n({corpus_item_key, output_artifact}) — the raw material for computing\na vendor experiment's verdict (fill rates per cohort, identity\nconfirmation against the submitted name) outside the harness.","operationId":"read_experiment_endpoint_api_v1_gm_experiment__experiment_id__get","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"experiment_id","in":"path","required":true,"schema":{"type":"string","title":"Experiment Id"}},{"name":"include_cells","in":"query","required":false,"schema":{"type":"boolean","description":"Attach per-cell output artifacts to each variant","default":false,"title":"Include Cells"},"description":"Attach per-cell output artifacts to each variant"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/gm/experiment/budget/{agent_id}":{"get":{"tags":["gm","gm"],"summary":"Read Experiment Budget Endpoint","description":"Return the agent's experiment-spend envelope for the current month.\n\nIdempotent — creates the row with the default $50 envelope if it\ndoesn't exist yet (so the agent can read its budget on first call\nof any new month without a separate setup step).","operationId":"read_experiment_budget_endpoint_api_v1_gm_experiment_budget__agent_id__get","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"agent_id","in":"path","required":true,"schema":{"type":"string","title":"Agent Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/gm/experiment/{experiment_id}/revert":{"post":{"tags":["gm","gm"],"summary":"Revert Experiment Endpoint","description":"Manually revert all vendor_config rows ever written by this experiment.\n\nIdempotent — running twice only flips rows that are still active.\nUsed when post-hoc evidence shows a shipped change was wrong; the\ncron-driven verify_recent_shipments path also calls the underlying\nhelper automatically when production metrics drop.","operationId":"revert_experiment_endpoint_api_v1_gm_experiment__experiment_id__revert_post","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"experiment_id","in":"path","required":true,"schema":{"type":"string","title":"Experiment Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/gm/experiment/verify-recent":{"post":{"tags":["gm","gm"],"summary":"Verify Recent Shipments Endpoint","description":"Cron entry point: re-check recently-shipped experiments against production.\n\nTriggered by EventBridge daily. For each vendor_config row written in\nthe last `lookback_days`, runs the per-vendor verifier (if registered),\nauto-reverts the row + files a deployment_verification finding when\nproduction metrics have dropped past `drop_threshold_pct`.\n\nReturns a per-row check list so the cron's emailed digest can render\n\"what was inspected, what held, what got reverted.\"","operationId":"verify_recent_shipments_endpoint_api_v1_gm_experiment_verify_recent_post","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"lookback_days","in":"query","required":false,"schema":{"type":"integer","maximum":30,"minimum":1,"default":7,"title":"Lookback Days"}},{"name":"drop_threshold_pct","in":"query","required":false,"schema":{"type":"number","maximum":1.0,"minimum":0.0,"default":0.5,"title":"Drop Threshold Pct"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/gm/experiment/variant/{variant_id}/ship":{"post":{"tags":["gm","gm"],"summary":"Ship Experiment Variant Endpoint","description":"Ship a winning variant by writing its diff to vendor_config.\n\nSprint 12 supports vendor_config artifacts only. The new row carries\nthe experiment_id; any prior active row for the same (vendor, key) is\nsuperseded (active=False, reverted_at stamped). PR 5 wires the\nauto-rollback path that flips active=False on experiment failure.","operationId":"ship_experiment_variant_endpoint_api_v1_gm_experiment_variant__variant_id__ship_post","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"variant_id","in":"path","required":true,"schema":{"type":"string","title":"Variant Id"}}],"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/gm/wake":{"post":{"tags":["gm"],"summary":"Wake Gm","description":"Wake the GM: process approval comments and launch a focused session.\n\nGib's workflow: comment \"approved\" on standup doc → hit this endpoint → agent\nprocesses approvals and executes approved work → Gib gets email with results.\n\nAn optional JSON body `{\"prompt\": \"...\"}` hands the session a custom prompt\n(via the GM_SESSION_PROMPT env var gm_session already reads). The bare wake\nstays unauthenticated — it only triggers the agent's own standing flow — but\na custom prompt is arbitrary instruction injection into a credentialed\nsession, so it requires the admin key.\n\nLaunches the session as an ECS task (same pattern as pipeline launcher).\nReturns immediately with task info — the session runs asynchronously.","operationId":"wake_gm_api_v1_gm_wake_post","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"state","in":"query","required":true,"schema":{"type":"string","description":"Two-letter state code","title":"State"},"description":"Two-letter state code"}],"requestBody":{"content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/WakeRequest"},{"type":"null"}],"title":"Body"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/gm/review-pr":{"post":{"tags":["gm"],"summary":"Review Pr Webhook","description":"GitHub webhook entry — launches Platform EM review on every non-draft PR.\n\nSubscribed events: `pull_request` with actions `opened`, `synchronize`,\n`reopened`, `ready_for_review`. Non-matching events return 200 with a\nno-op response so the webhook delivery stays healthy in GitHub's UI.\n\n`ready_for_review` (2026-09-05): a PR opened as a draft and later marked\nready never carried a reviewable delivery — its `opened` / `synchronize`\nevents all arrived with `draft: true` and were skipped, and GitHub sends\nno further `synchronize` until the next push. PRs #1169 and #1192 had\nto be woken by hand with `scripts/wake_em.py`. The draft skip below\nstill applies to every action, so draft pushes never burn a review.\n\nSecurity: HMAC-SHA256 signature required via `X-Hub-Signature-256`.\nConfigured by setting `GITHUB_WEBHOOK_SECRET` in Secrets Manager.\n\nFiltering (2026-04-27): no author filter. Per Gib's principle —\n*\"any pr where both reviewers are green, we should merge — why\nwouldn't we\"* — code quality is the gate, not author identity. Two\ngenuinely different model families (Platform EM Claude + Code\nJudgment Codex) agreeing IS the multi-eye guarantee. Draft PRs are\nskipped — that is the work-in-progress opt-out.","operationId":"review_pr_webhook_api_v1_gm_review_pr_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/v1/gm/wake-link/{state}":{"get":{"tags":["gm","gm"],"summary":"Get Wake Link","description":"Mint the canonical signed 'Done Reviewing' URL for a state.\n\nThe wake token is an HMAC keyed on THIS server's API_KEY — the same\nprocess that verifies it in `done_reviewing`. A session runner signing\nlocally with a drifted key produces a dead button that 403s on click\n(the 2026-07-18 PMM email). Email builders call this endpoint so sender\nand verifier always share one secret.","operationId":"get_wake_link_api_v1_gm_wake_link__state__get","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"state","in":"path","required":true,"schema":{"type":"string","title":"State"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/gm/wake-pr/{pr_number}":{"get":{"tags":["gm"],"summary":"Wake Platform Em Pr","description":"One-click per-PR re-review — launches Platform EM review_pr session.\n\nGib's workflow: daily email shows a PR row with \"Wake EM to re-review\"\nbutton → click → this endpoint validates the signed token → launches\nECS task that runs the full review_pr flow on that specific PR. Full\ncross-model path (Platform EM Claude + Code Judgment Codex) re-runs.","operationId":"wake_platform_em_pr_api_v1_gm_wake_pr__pr_number__get","parameters":[{"name":"pr_number","in":"path","required":true,"schema":{"type":"integer","title":"Pr Number"}},{"name":"token","in":"query","required":true,"schema":{"type":"string","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/gm/code-judgment":{"post":{"tags":["gm","gm"],"summary":"Code Judgment Endpoint","description":"Cross-model DoD verdict for a PR. Called by Platform EM before merge decision.\n\nRuns:\n  1. Mechanical DoD Checker (deterministic, ~50ms, no LLM)\n  2. Code Judgment Agent (OpenAI single-shot, ~3-8s, different model family from Platform EM)\n  3. Aggregator (combines verdicts into final decision per tier rules)\n\nReturns an AggregateVerdict as JSON. Platform EM interprets:\n  - decision=auto_merge_eligible → proceed with `gh pr merge`\n  - decision=advisory_pass       → comment only, advisory review\n  - decision=requires_human_ack  → Tier S; route to Google Doc product-level ack\n  - decision=block               → do not merge; block_reasons explain why\n  - decision=degraded            → judgment unavailable; handle per tier\n\nThe `tension_flags` field captures places where Code Judgment disagreed\nwith Platform EM or where judgment is genuinely ambiguous — these\nbecome Google Doc items for strategic review, not code review.","operationId":"code_judgment_endpoint_api_v1_gm_code_judgment_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CodeJudgmentRequest"}}},"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/gm/verify-deployments":{"post":{"tags":["gm","gm"],"summary":"Verify Deployments Endpoint","description":"Run T+24h and T+7d re-checks on every eligible deployment_verification finding.\n\nCalled by an EventBridge hourly rule (see\n`scripts/deploy/create_verify_deployment_schedule.sh`). Deterministic,\nno LLM, no agent session — just: find eligible findings, resolve the\ntarget metric, PATCH the observation, file an anomaly finding if the\nobservation regressed past the monitoring plan's threshold.\n\nThe returned summary lets EventBridge logs show the cycle's work and\ngives Platform EM's next session a quick signal via the findings\nstream (regression anomalies appear in `fetch_unread_signals_for_me`).\n\nSafe to call ad hoc for debugging — idempotent (already-observed\nfindings are excluded by the eligibility query).","operationId":"verify_deployments_endpoint_api_v1_gm_verify_deployments_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/v1/gm/decide":{"get":{"tags":["gm"],"summary":"Decide","description":"One-click answer to a 'call I need from you' in the daily EM email.\n\nRecords Gib's choice as a durable `decision_response` finding (auditable,\nand read by the EM's next session) and wakes the EM to execute the\ninstruction it proposed for that option. The button never mutates\nproduction directly — the EM carries out its own proposed instruction with\nGib's recorded click as the authorization, preserving the trust ladder.","operationId":"decide_api_v1_gm_decide_get","parameters":[{"name":"fid","in":"query","required":true,"schema":{"type":"string","description":"leadership_update finding id this decision belongs to","title":"Fid"},"description":"leadership_update finding id this decision belongs to"},{"name":"did","in":"query","required":true,"schema":{"type":"string","description":"decision id within that update","title":"Did"},"description":"decision id within that update"},{"name":"choice","in":"query","required":true,"schema":{"type":"string","description":"the chosen option value","title":"Choice"},"description":"the chosen option value"},{"name":"label","in":"query","required":false,"schema":{"type":"string","description":"human label of the chosen option, for the confirmation page","default":"","title":"Label"},"description":"human label of the chosen option, for the confirmation page"},{"name":"token","in":"query","required":true,"schema":{"type":"string","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/gm/done-reviewing/{state}":{"get":{"tags":["gm"],"summary":"Done Reviewing","description":"One-click 'Done Reviewing' — processes doc comments and launches wake session.\n\nGib's workflow: read evening standup doc → comment with direction → click this\nlink → agent wakes, processes comments, executes approved work overnight.","operationId":"done_reviewing_api_v1_gm_done_reviewing__state__get","parameters":[{"name":"state","in":"path","required":true,"schema":{"type":"string","title":"State"}},{"name":"token","in":"query","required":true,"schema":{"type":"string","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/gm/review/{action_id}":{"get":{"tags":["gm"],"summary":"Review Action Page","description":"Render the approve/reject page for an action. Linked from standup email.","operationId":"review_action_page_api_v1_gm_review__action_id__get","parameters":[{"name":"action_id","in":"path","required":true,"schema":{"type":"string","title":"Action Id"}},{"name":"token","in":"query","required":true,"schema":{"type":"string","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"}}}}}},"post":{"tags":["gm"],"summary":"Process Review","description":"Process approval/rejection from the review page form.","operationId":"process_review_api_v1_gm_review__action_id__post","parameters":[{"name":"action_id","in":"path","required":true,"schema":{"type":"string","title":"Action Id"}},{"name":"token","in":"query","required":true,"schema":{"type":"string","title":"Token"}}],"requestBody":{"content":{"application/x-www-form-urlencoded":{"schema":{"$ref":"#/components/schemas/Body_process_review_api_v1_gm_review__action_id__post"}}}},"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/commerce/products":{"get":{"tags":["commerce","commerce"],"summary":"List Products","description":"List active products in the catalog — what the frontend Products page renders.\n\nNo filtering / pagination today; the catalog is small (10 rows seeded).","operationId":"list_products_api_v1_commerce_products_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ProductCardResponse"},"type":"array","title":"Response List Products Api V1 Commerce Products Get"}}}}}}},"/api/v1/commerce/list-quote":{"post":{"tags":["commerce","commerce"],"summary":"Quote List Checkout","description":"The exact quote a list checkout would freeze — after every guard, before\nanything is written (no saved list, product, order, manifest or Stripe\nsession). What a buyer's page prints before Pay when it cannot derive the\nprice itself: a purchase that wants one contact (`contact`) charges today\nonly what carries it and holds the rest under a ceiling (ADR-052 amendment\n2026-10-16). Same refusals as the checkout, as 4xx with the quote.","operationId":"quote_list_checkout_api_v1_commerce_list_quote_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CheckoutRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"APIKeyHeader":[]}]}},"/api/v1/commerce/checkout":{"post":{"tags":["commerce","commerce"],"summary":"Create Checkout","description":"Start a Stripe Checkout Session — for a shelf product, or for a shaped list.\n\nReturns the hosted Checkout URL — the frontend redirects the buyer.\nA `commerce.order` row is created with status='pending' immediately;\nthe webhook flips it to 'paid' then 'delivered' as fulfillment completes.\nA list order (ADR-045) also freezes its Run Manifest here, before payment.\n\nRate limited per IP to prevent orphan-session abuse.","operationId":"create_checkout_api_v1_commerce_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"}}}}},"security":[{"APIKeyHeader":[]}]}},"/api/v1/commerce/webhook":{"post":{"tags":["commerce","commerce"],"summary":"Stripe Webhook","description":"Stripe webhook handler — verifies signature, marks the order paid, acks.\n\nFulfillment (cohort → workbook → S3 → emails) runs AFTER the 200 is sent,\nas a FastAPI BackgroundTask on the same worker (`_fulfill_paid_order`).\nStripe treats a slow response as a failure and redelivers, and this week's\nlive deliveries took 11.5–13.9 s — a fulfillment that runs inside the\nrequest is one slow S3 write away from building the same file twice and\nemailing the buyer twice (2026-09-05). The ack now carries only the\nmoney-side writes: the order is 'paid' before Stripe hears 200.\n\nIdempotent: a delivered order no-ops; a 'paid' order inside its\nfulfillment lease (`FULFILLMENT_LEASE`) is the same build still running\nand no-ops too; the pending→paid write is a conditional UPDATE so two\nconcurrent deliveries can't both claim it. Nothing the buyer sees changed:\nthe success page already polls `/orders/by-session` until 'delivered'.","operationId":"stripe_webhook_api_v1_commerce_webhook_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/v1/commerce/orders/by-session/{session_id}":{"get":{"tags":["commerce","commerce"],"summary":"Get Order By Session","description":"Buyer-facing order status. The success page polls this until delivered.\n\nLooked up by stripe_session_id (unguessable, only known to buyer + Stripe + us).\nNo auth needed — the session_id IS the bearer.","operationId":"get_order_by_session_api_v1_commerce_orders_by_session__session_id__get","parameters":[{"name":"session_id","in":"path","required":true,"schema":{"type":"string","title":"Session Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrderStatusResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/commerce/orders/by-session/{session_id}/add-other-way":{"post":{"tags":["commerce","commerce"],"summary":"Add Other Way","description":"Buy the way to reach this order did not (ADR-056).\n\nThe checkout session id is the bearer, exactly as it is for the receipt this\naction sits on — no auth, and nobody who does not already hold the order's\nlink can open a payment page against it.\n\nThis is a NEW purchase, not a second charge on the first one: it mints its\nown order, its own hosted Checkout Session and its own authorization. The\nfirst order's hold is settled and closed by the time an offer exists, and\nnothing on this path reads its PaymentIntent or its ceiling (ADR-016 — a\nmoney surface alerts, it never auto-mutates).","operationId":"add_other_way_api_v1_commerce_orders_by_session__session_id__add_other_way_post","parameters":[{"name":"session_id","in":"path","required":true,"schema":{"type":"string","title":"Session Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddOtherWayRequest"}}}},"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/commerce/orders/{order_id}/settle-check":{"post":{"tags":["commerce","commerce"],"summary":"Settle Check","description":"Operator: run the check-what-they-bought step for ONE order now (ADR-052)\ninstead of waiting for the scheduled sweep — resume a half-started order\n(read the hold, capture today's total, start or retry the check runs), then\nsettle it if its runs are done. Idempotent; the same code the sweep runs.","operationId":"settle_check_api_v1_commerce_orders__order_id__settle_check_post","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"order_id","in":"path","required":true,"schema":{"type":"string","title":"Order Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/commerce/orders/{order_id}/reorder":{"post":{"tags":["commerce","commerce"],"summary":"Reorder","description":"Buy what's new since this order (ADR-045 §9).\n\nA fresh list checkout from the parent order's shape plus `created_at >\norder.created_at` (our load time — the only key that also catches a\nlate-published filing), with the parent's manifest subtracted, so nothing\nalready delivered is quoted or charged again. Lane, cap, delivery and email\ninherit from the parent unless overridden. Same rate limit as checkout —\nthe order id is the bearer, as the session id is for the receipt.","operationId":"reorder_api_v1_commerce_orders__order_id__reorder_post","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"order_id","in":"path","required":true,"schema":{"type":"string","title":"Order Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReorderRequest"}}}},"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/commerce/orders/{order_id}/revoke":{"post":{"tags":["commerce","commerce"],"summary":"Revoke Order Downloads","description":"Kill switch — switch off every download link for an order (refund / abuse). Admin-only.\nSame path the dispute / refund webhooks take (`_revoke_exports`).","operationId":"revoke_order_downloads_api_v1_commerce_orders__order_id__revoke_post","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"order_id","in":"path","required":true,"schema":{"type":"string","title":"Order Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/backend__routers__commerce__RevokeRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/commerce/orders/{order_id}/unrevoke":{"post":{"tags":["commerce","commerce"],"summary":"Unrevoke Order Downloads","description":"Reverse a revoke — restore download access for an order. Admin-only.","operationId":"unrevoke_order_downloads_api_v1_commerce_orders__order_id__unrevoke_post","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"order_id","in":"path","required":true,"schema":{"type":"string","title":"Order Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/commerce/orders/{order_id}/downloads":{"get":{"tags":["commerce","commerce"],"summary":"Get Order Download Status","description":"Has this order's file actually been opened? Admin-only.\n\nReads commerce.download_log — the audit trail every durable download link\nalready writes on each attempt (ADR-026) but that had no read surface\nuntil now. Primary use: pre-meeting engagement telemetry for comp\ndeliveries (POC samples, design-partner files) — did the recipient open\nit before the review call, from what IP, how many times.","operationId":"get_order_download_status_api_v1_commerce_orders__order_id__downloads_get","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"order_id","in":"path","required":true,"schema":{"type":"string","title":"Order Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrderDownloadStatusResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/commerce/orders/{order_id}/resend-data":{"post":{"tags":["commerce","commerce"],"summary":"Resend Order Data","description":"Re-deliver an already-paid order's file — to the buyer OR a teammate. Admin-only.\n\nThe purchase belongs to the buyer's org, but the download link is a bearer:\nwhoever holds it can grab the file. This exposes that to the operator, keyed on\nthe order (which the Orders screen has) instead of possession of the link — so a\nbuyer who lost the email, or a colleague who needs the same file, gets it in one\nclick. This is the support answer to \"I paid but a teammate needs to download.\"\n\nNo new sale, no charge, no re-resolving the cohort: it re-emails the SAME durable\nlink to the SAME file, refreshes its 30-day window, and clears the download cap.\nThe token is NOT rotated — the buyer's existing link keeps working alongside the\nteammate's (both are the one bearer link; rotation is the leak-response reserved\nfor the self-serve path). A revoked order is refused: un-revoke first.\nSend-first-then-persist, so a Gmail refusal changes nothing.","operationId":"resend_order_data_api_v1_commerce_orders__order_id__resend_data_post","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"order_id","in":"path","required":true,"schema":{"type":"string","title":"Order Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResendDataRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/commerce/comp-list":{"post":{"tags":["commerce","commerce"],"summary":"Comp List","description":"Build the cohort's workbook and deliver it FREE through the comp door.\n\nAdmin-only. Resolves the cohort exactly as a sale would, builds the\ncustomer workbook through the one gated builder, uploads it, and writes the\nsame ledger rows POST /commerce/comp-deliver writes (customer find-or-create,\nhidden $0 product carrying the filter so \"Sell this again\" works, one Order\nwith status='comp', one Export with a durable token). Then emails the\nrecipient with evaluation wording. The Run Manifest records exactly what\nshipped (`order.run_manifest_id`), same as a paid order.\n\nNothing is written if the file can't be built: a gate refusal or an empty\ncohort returns 422 and leaves no order behind.","operationId":"comp_list_api_v1_commerce_comp_list_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CompListRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CompListResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"APIKeyHeader":[]}]}},"/api/v1/commerce/comp-deliver":{"post":{"tags":["commerce","commerce"],"summary":"Comp Deliver","description":"Deliver FREE files (POC samples, design-partner deliverables) via magic links.\n\nAdmin-only (same gate as revoke/resend — the read-only key is refused). The\nfiles must already be staged in the exports bucket; each key is HEAD-checked\nso a dead link can never be minted. Creates:\n\n  - the `commerce.customer` (find-or-create by email — the ledger continuity),\n  - a hidden $0 product (listed=False, like a \"Sell this list\" ad-hoc product),\n  - one Order with status='comp' — never 'pending'/'paid'/'delivered', so the\n    stuck-order money scan skips it and no ledger view can count it as revenue,\n  - one Export row per file with a durable download token (ADR-026 defaults:\n    5-download cap, 30-day window; both overridable here),\n\nthen emails the recipient their links with evaluation wording — no price, no\nreceipt language. Tenet #12 (Show Value Before Asking for Money) + #13\n(Eliminate Friction for the Buyer). The links come back in the response too,\nso a failed send never strands the delivery.","operationId":"comp_deliver_api_v1_commerce_comp_deliver_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CompDeliverRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CompDeliverResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"APIKeyHeader":[]}]}},"/api/v1/commerce/quote":{"post":{"tags":["commerce","commerce"],"summary":"Quote List","description":"Preview how many leads the cohort yields, before minting a link.","operationId":"quote_list_api_v1_commerce_quote_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/QuoteRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/QuoteResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"APIKeyHeader":[]}]}},"/api/v1/commerce/orders":{"get":{"tags":["commerce","commerce"],"summary":"List Orders","description":"Operator Orders screen — recent orders as a scannable ledger (admin-only).\n\nNewest first. Each row carries the frozen cohort filter so the UI can offer\n'Sell this again' by reopening that exact list.","operationId":"list_orders_api_v1_commerce_orders_get","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","default":50,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/OrderRow"},"title":"Response List Orders Api V1 Commerce Orders Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/commerce/orders/{order_id}/email-link":{"post":{"tags":["commerce","commerce"],"summary":"Email Payment Link","description":"Send the buyer the branded payment-link email From the operator inbox.\n\nOne click on the sell-result screen — the approved 'you're first' template\nwith the sale's count, price, and checkout button filled in. Same Gmail\npath as the receipts; the operator's address is the sender.","operationId":"email_payment_link_api_v1_commerce_orders__order_id__email_link_post","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"order_id","in":"path","required":true,"schema":{"type":"string","title":"Order Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailLinkRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/commerce/orders/{order_id}/cancel-options":{"get":{"tags":["commerce","commerce"],"summary":"Cancel Options","description":"What the Cancel dialog needs: the reasons, and the exact email each one sends\nto THIS order's buyer (subject + text), so the operator sees the words before clicking.","operationId":"cancel_options_api_v1_commerce_orders__order_id__cancel_options_get","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"order_id","in":"path","required":true,"schema":{"type":"string","title":"Order Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/commerce/orders/{order_id}/cancel":{"post":{"tags":["commerce","commerce"],"summary":"Cancel Order","description":"Withdraw a pending order (admin-only): switch its payment link off at Stripe,\nmark it canceled with the reason, and email the buyer a warm, reason-specific note.\n\nRefuses anything that isn't an unpaid pending order — a link Stripe shows as\npaid is a real sale and never gets canceled here. The email is best-effort\nafter the cancel is committed; `email_sent` says whether it went out.","operationId":"cancel_order_api_v1_commerce_orders__order_id__cancel_post","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"order_id","in":"path","required":true,"schema":{"type":"string","title":"Order Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CancelOrderRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/commerce/sell":{"post":{"tags":["commerce","commerce"],"summary":"Sell This List","description":"Mint a payment link for the exact filtered list (admin-only).\n\nCreates a hidden ad-hoc product (the sale's frozen filter + price), an order,\nand a Stripe Checkout Session — test-mode by default so the link is safe to\nclick before going live. Returns the hosted checkout URL to send the buyer.","operationId":"sell_this_list_api_v1_commerce_sell_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SellRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SellResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"APIKeyHeader":[]}]}},"/api/v1/commerce/sample-file":{"get":{"tags":["commerce","commerce"],"summary":"Sample File","description":"The exact file a buyer receives, built from ten synthetic records — open it before paying.\n\nSame builders the paid path uses (customer workbook / product CSV), so every\ntab, header, label, and gate a paid file carries is what the sample carries.\nEvery record is invented: `example.com` emails, 555-01xx phones, the cover\nsheet says so. Public, no key; cached per process; `format=xlsx|csv`.","operationId":"sample_file_api_v1_commerce_sample_file_get","parameters":[{"name":"format","in":"query","required":false,"schema":{"type":"string","default":"xlsx","title":"Format"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/commerce/connector-requests":{"post":{"tags":["commerce","commerce"],"summary":"Create Connector Request","description":"Record a request for a CRM connector we don't offer yet. Public, rate-limited.\n\nA demand signal and nothing else: no email is sent, nothing is fulfilled or\nbilled. `order_id`, when present, must name a real order — the ask came from\na paid list's delivery page, and the link is what lets an operator find both\nthe buyer and the list when the connector ships.","operationId":"create_connector_request_api_v1_commerce_connector_requests_post","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConnectorRequestIn"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConnectorRequestRow"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"get":{"tags":["commerce","commerce"],"summary":"List Connector Requests","description":"Operator ledger of connector asks, newest first (admin key). Which adapter to build next.","operationId":"list_connector_requests_api_v1_commerce_connector_requests_get","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","default":50,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ConnectorRequestRow"},"title":"Response List Connector Requests Api V1 Commerce Connector Requests Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/commerce/offers":{"post":{"tags":["commerce","commerce"],"summary":"Mint Offer","description":"Write down a price agreed in conversation. Returns the code to send the buyer.","operationId":"mint_offer_api_v1_commerce_offers_post","security":[{"APIKeyHeader":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OfferIn"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OfferRow"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"get":{"tags":["commerce","commerce"],"summary":"List Offers","description":"Every code, newest first, with what is left on each.","operationId":"list_offers_api_v1_commerce_offers_get","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"status","in":"query","required":false,"schema":{"type":"string","description":"all | live | expired | revoked | exhausted","default":"all","title":"Status"},"description":"all | live | expired | revoked | exhausted"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/OfferRow"},"title":"Response List Offers Api V1 Commerce Offers Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/commerce/offers/{code}":{"get":{"tags":["commerce","commerce"],"summary":"Get Offer","description":"One code and the orders that carry it — the case-study ledger.","operationId":"get_offer_api_v1_commerce_offers__code__get","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"code","in":"path","required":true,"schema":{"type":"string","title":"Code"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OfferDetail"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"patch":{"tags":["commerce","commerce"],"summary":"Edit Offer","description":"Extend, shorten, re-cap, bind or annotate a code. Null clears; absent keeps.","operationId":"edit_offer_api_v1_commerce_offers__code__patch","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"code","in":"path","required":true,"schema":{"type":"string","title":"Code"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OfferPatch"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OfferRow"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/commerce/offers/{code}/revoke":{"post":{"tags":["commerce","commerce"],"summary":"Revoke Offer","description":"Withdraw a code now. Orders already paid under it keep their price.","operationId":"revoke_offer_api_v1_commerce_offers__code__revoke_post","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"code","in":"path","required":true,"schema":{"type":"string","title":"Code"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OfferRow"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/commerce/offers/{code}/reinstate":{"post":{"tags":["commerce","commerce"],"summary":"Reinstate Offer","description":"Undo a revoke. Expiry and caps still apply.","operationId":"reinstate_offer_api_v1_commerce_offers__code__reinstate_post","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"code","in":"path","required":true,"schema":{"type":"string","title":"Code"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OfferRow"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/api-keys":{"post":{"tags":["admin","admin"],"summary":"Issue Key","operationId":"issue_key_api_v1_admin_api_keys_post","security":[{"APIKeyHeader":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/IssueKeyRequest"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Issue Key Api V1 Admin Api Keys Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"get":{"tags":["admin","admin"],"summary":"List Keys","operationId":"list_keys_api_v1_admin_api_keys_get","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"email","in":"query","required":true,"schema":{"type":"string","minLength":3,"maxLength":320,"title":"Email"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response List Keys Api V1 Admin Api Keys Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/api-keys/{key_id}/revoke":{"post":{"tags":["admin","admin"],"summary":"Revoke Key","operationId":"revoke_key_api_v1_admin_api_keys__key_id__revoke_post","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"key_id","in":"path","required":true,"schema":{"type":"string","title":"Key Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/backend__routers__admin_api_keys__RevokeRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Revoke Key Api V1 Admin Api Keys  Key Id  Revoke Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}}},"components":{"schemas":{"ActionCreate":{"properties":{"finding_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Finding Id"},"agent_id":{"type":"string","title":"Agent Id"},"action_type":{"type":"string","title":"Action Type"},"action_payload":{"additionalProperties":true,"type":"object","title":"Action Payload"},"requires_approval":{"type":"boolean","title":"Requires Approval","default":true},"cost_estimate":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Cost Estimate"},"work_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Work Type"}},"type":"object","required":["agent_id","action_type","action_payload"],"title":"ActionCreate"},"ActionUpdate":{"properties":{"status":{"type":"string","title":"Status"},"reviewer_notes":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Reviewer Notes"}},"type":"object","required":["status"],"title":"ActionUpdate"},"AddOtherWayRequest":{"properties":{"success_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Success Url"},"cancel_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Cancel Url"}},"type":"object","title":"AddOtherWayRequest"},"AgentSessionBeacon":{"properties":{"tools_listed":{"anyOf":[{"type":"integer","maximum":500.0,"minimum":0.0},{"type":"null"}],"title":"Tools Listed"},"page":{"anyOf":[{"type":"string","maxLength":64},{"type":"null"}],"title":"Page"},"protocol_version":{"anyOf":[{"type":"string","maxLength":16},{"type":"null"}],"title":"Protocol Version"}},"additionalProperties":false,"type":"object","title":"AgentSessionBeacon"},"AlertConfigRequest":{"properties":{"metric_name":{"type":"string","title":"Metric Name"},"threshold_value":{"type":"number","title":"Threshold Value"},"direction":{"type":"string","title":"Direction"},"state":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"State"}},"type":"object","required":["metric_name","threshold_value","direction"],"title":"AlertConfigRequest"},"AnalyticsConfig":{"properties":{"provider":{"type":"string","title":"Provider","default":"posthog"},"key":{"type":"string","title":"Key"},"host":{"type":"string","title":"Host"}},"type":"object","required":["key","host"],"title":"AnalyticsConfig"},"BlastRadiusRequest":{"properties":{"action":{"type":"string","title":"Action","description":"Diff type — one of ['add_keyword', 'add_sub', 'merge', 'split']. add_keyword is fully modelled; split / merge / add_sub return a partial response with requires_offline_review=true for v1."},"target":{"additionalProperties":true,"type":"object","title":"Target","description":"What the diff changes. For add_keyword: {keyword, tier, sector_label, formation_code (optional)}. Other actions accept arbitrary shape so the stub path can pass them through to the proposal."},"state":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"State","description":"Optional state scope (CO/FL/VA/NY); omit for cross-state preflight"}},"type":"object","required":["action","target"],"title":"BlastRadiusRequest"},"BlastRadiusResponse":{"properties":{"state":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"State"},"total":{"type":"integer","title":"Total"},"eligible":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Eligible"},"by_segment":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"By Segment"},"sample":{"items":{"$ref":"#/components/schemas/BlastRadiusSampleRecord"},"type":"array","title":"Sample"},"cost_implication":{"type":"string","title":"Cost Implication"},"runtime_warning":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Runtime Warning"},"diff_applied":{"additionalProperties":true,"type":"object","title":"Diff Applied"},"requires_offline_review":{"type":"boolean","title":"Requires Offline Review","default":false}},"type":"object","required":["state","total","eligible","by_segment","sample","cost_implication","diff_applied"],"title":"BlastRadiusResponse","description":"Response mirrors `/api/v1/enrichment/preview` so reviewers read both\nwith the same mental model — `total`, `eligible`, `by_segment`, `sample`,\n`cost_implication` map 1:1."},"BlastRadiusSampleRecord":{"properties":{"glid":{"type":"string","title":"Glid"},"name":{"type":"string","title":"Name"},"current":{"type":"string","title":"Current"},"proposed":{"type":"string","title":"Proposed"}},"type":"object","required":["glid","name","current","proposed"],"title":"BlastRadiusSampleRecord"},"Body_manage_upload_results_api_v1_subscriptions_manage__token__results_post":{"properties":{"file":{"type":"string","contentMediaType":"application/octet-stream","title":"File"}},"type":"object","required":["file"],"title":"Body_manage_upload_results_api_v1_subscriptions_manage__token__results_post"},"Body_process_review_api_v1_gm_review__action_id__post":{"properties":{"decision":{"type":"string","title":"Decision","default":"approved"},"notes":{"type":"string","title":"Notes","default":""}},"type":"object","title":"Body_process_review_api_v1_gm_review__action_id__post"},"Body_upload_bulk_file_api_v1_pipeline_upload_bulk_file_post":{"properties":{"state":{"type":"string","title":"State"},"file":{"type":"string","contentMediaType":"application/octet-stream","title":"File"}},"type":"object","required":["state","file"],"title":"Body_upload_bulk_file_api_v1_pipeline_upload_bulk_file_post"},"BulkUploadResponse":{"properties":{"input_file":{"type":"string","title":"Input File"},"filename":{"type":"string","title":"Filename"},"state":{"type":"string","title":"State"},"entity_count":{"type":"integer","title":"Entity Count"},"line_count":{"type":"integer","title":"Line Count"},"size_bytes":{"type":"integer","title":"Size Bytes"},"repaired_line_count":{"type":"integer","title":"Repaired Line Count","default":0}},"type":"object","required":["input_file","filename","state","entity_count","line_count","size_bytes"],"title":"BulkUploadResponse"},"CancelOrderRequest":{"properties":{"reason":{"type":"string","title":"Reason"},"note":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Note"},"send_email":{"type":"boolean","title":"Send Email","default":true},"to_email":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"To Email"}},"type":"object","required":["reason"],"title":"CancelOrderRequest"},"ChatRequest":{"properties":{"message":{"type":"string","title":"Message"},"context":{"additionalProperties":true,"type":"object","title":"Context","default":{}}},"type":"object","required":["message"],"title":"ChatRequest"},"CheckoutRequest":{"properties":{"product_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Product Id"},"success_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Success Url"},"cancel_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Cancel Url"},"customer_email":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Customer Email"},"list_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"List Id"},"states":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"States"},"filters":{"anyOf":[{"items":{"additionalProperties":true,"type":"object"},"type":"array"},{"type":"null"}],"title":"Filters"},"include_held":{"type":"boolean","title":"Include Held","default":false},"include_existing":{"type":"boolean","title":"Include Existing","default":false},"lane":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Lane"},"cap":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Cap"},"channel":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Channel"},"contact":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Contact"},"delivery":{"type":"string","title":"Delivery","default":"file"},"crm_connection_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Crm Connection Id"},"connector_crm_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Connector Crm Name"},"price_rule_version":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Price Rule Version"},"expected_total_cents":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Expected Total Cents"},"offer_code":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Offer Code"}},"type":"object","title":"CheckoutRequest","description":"Buy a shelf product (`product_id`) OR a shaped list (ADR-045) — never both.\n\nA list is either a saved one (`list_id`) or an inline shape (`states` +\n`filters`); the buyer picks a lane, an optional cap (the dial) and how the\nrecords arrive. `price_rule_version` / `expected_total_cents` are the quote\nthe buyer saw — when either has moved, the answer is a 409 carrying the\nfresh quote, never a silent different charge."},"CheckoutResponse":{"properties":{"session_id":{"type":"string","title":"Session Id"},"checkout_url":{"type":"string","title":"Checkout Url"},"order_id":{"type":"string","title":"Order Id"},"quote":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Quote"},"saved_list":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Saved List"}},"type":"object","required":["session_id","checkout_url","order_id"],"title":"CheckoutResponse"},"CodeJudgmentRequest":{"properties":{"pr_number":{"type":"integer","title":"Pr Number"},"title":{"type":"string","title":"Title"},"body":{"type":"string","title":"Body"},"author":{"type":"string","title":"Author"},"base_sha":{"type":"string","title":"Base Sha"},"head_sha":{"type":"string","title":"Head Sha"},"base_updated_at":{"type":"string","format":"date-time","title":"Base Updated At"},"files_changed":{"items":{"type":"string"},"type":"array","title":"Files Changed"},"additions":{"type":"integer","title":"Additions"},"deletions":{"type":"integer","title":"Deletions"},"commit_messages":{"items":{"type":"string"},"type":"array","title":"Commit Messages"},"ci_conclusion":{"type":"string","title":"Ci Conclusion"},"ci_checks":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Ci Checks"},"diff":{"type":"string","title":"Diff"},"matrix_confidence":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Matrix Confidence"},"platform_em_verdict":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Platform Em Verdict"},"labels":{"items":{"type":"string"},"type":"array","title":"Labels","default":[]},"behind_base_by":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Behind Base By"}},"type":"object","required":["pr_number","title","body","author","base_sha","head_sha","base_updated_at","files_changed","additions","deletions","commit_messages","ci_conclusion","ci_checks","diff"],"title":"CodeJudgmentRequest","description":"Payload Platform EM POSTs to /gm/code-judgment for merge-decision support.\n\nPlatform EM (Anthropic Managed Agent with gh auth) fetches PR data via\ngh CLI, then forwards it here. The endpoint runs the Mechanical Checker\n+ Code Judgment (GPT) in parallel, aggregates, returns a structured\nverdict. No GitHub API calls happen inside the endpoint — the API task\ndoes not need GITHUB_TOKEN."},"CompDeliverRequest":{"properties":{"buyer_email":{"type":"string","title":"Buyer Email"},"buyer_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Buyer Name"},"buyer_company":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Buyer Company"},"label":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Label"},"note":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Note"},"files":{"items":{"$ref":"#/components/schemas/CompFile"},"type":"array","title":"Files"},"expires_days":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Expires Days"},"download_limit":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Download Limit"}},"type":"object","required":["buyer_email","files"],"title":"CompDeliverRequest","description":"Operator comp delivery — free files through the paid-order door (admin-only).\n\nPOC samples and design-partner deliverables (immediate driver: the iPostal1\nevaluation workbooks) get the exact same delivery UX as a purchase: durable\nmagic link, download cap, 30-day window, revoke, per-attempt audit, and a row\nin the customer ledger — with no payment and no receipt language anywhere."},"CompDeliverResponse":{"properties":{"order_id":{"type":"string","title":"Order Id"},"customer_id":{"type":"string","title":"Customer Id"},"files":{"items":{"$ref":"#/components/schemas/CompDeliveredFile"},"type":"array","title":"Files"},"email_sent":{"type":"boolean","title":"Email Sent"}},"type":"object","required":["order_id","customer_id","files","email_sent"],"title":"CompDeliverResponse"},"CompDeliveredFile":{"properties":{"s3_key":{"type":"string","title":"S3 Key"},"label":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Label"},"download_url":{"type":"string","title":"Download Url"},"expires_at":{"type":"string","title":"Expires At"}},"type":"object","required":["s3_key","label","download_url","expires_at"],"title":"CompDeliveredFile"},"CompFile":{"properties":{"s3_key":{"type":"string","title":"S3 Key"},"label":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Label"},"record_count":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Record Count"}},"type":"object","required":["s3_key"],"title":"CompFile","description":"One already-staged object to hand over through the durable download door."},"CompListRequest":{"properties":{"label":{"type":"string","title":"Label"},"state":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"State"},"filters":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Filters","default":[]},"entity_ids":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Entity Ids"},"lead_count":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Lead Count"},"audience":{"type":"string","title":"Audience","default":"customer"},"buyer_email":{"type":"string","title":"Buyer Email"},"buyer_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Buyer Name"},"note":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Note"}},"type":"object","required":["label","buyer_email"],"title":"CompListRequest","description":"Operator \"Send free\" — the Sell modal's comp path.\n\nThe cohort on screen (filter bar or hand-picked rows, same 1/some/all\ncontract as Sell) becomes a workbook and goes out through the comp door:\nstatus='comp', hidden $0 product, durable 30-day link, evaluation wording,\nno Stripe session. Unlike POST /commerce/comp-deliver there is no staging\nstep — the file is built here from the cohort, so the operator never\ntouches an s3_key."},"CompListResponse":{"properties":{"order_id":{"type":"string","title":"Order Id"},"record_count":{"type":"integer","title":"Record Count"},"download_url":{"type":"string","title":"Download Url"},"expires_at":{"type":"string","title":"Expires At"},"email_sent":{"type":"boolean","title":"Email Sent"}},"type":"object","required":["order_id","record_count","download_url","expires_at","email_sent"],"title":"CompListResponse"},"ConnectionCreateRequest":{"properties":{"label":{"type":"string","title":"Label"},"provider":{"type":"string","title":"Provider","default":"lawmatics"},"credential_kind":{"type":"string","title":"Credential Kind","default":"oauth"},"client_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Client Id"},"client_secret":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Client Secret"},"redirect_uri":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Redirect Uri"},"api_key":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Api Key"},"campaign_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Campaign Id"}},"type":"object","required":["label"],"title":"ConnectionCreateRequest"},"ConnectionResponse":{"properties":{"connection_id":{"type":"string","title":"Connection Id"},"provider":{"type":"string","title":"Provider"},"label":{"type":"string","title":"Label"},"status":{"type":"string","title":"Status"},"credential_kind":{"type":"string","title":"Credential Kind"},"redirect_uri":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Redirect Uri"},"authorize_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorize Url"},"connected_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Connected At"}},"type":"object","required":["connection_id","provider","label","status","credential_kind"],"title":"ConnectionResponse"},"ConnectorRequestIn":{"properties":{"crm_name":{"type":"string","title":"Crm Name"},"email":{"type":"string","title":"Email"},"order_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Order Id"}},"type":"object","required":["crm_name","email"],"title":"ConnectorRequestIn","description":"A buyer names the CRM they want us to deliver into and where to reach them."},"ConnectorRequestRow":{"properties":{"id":{"type":"string","title":"Id"},"crm_name":{"type":"string","title":"Crm Name"},"email":{"type":"string","title":"Email"},"order_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Order Id"},"created_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Created At"}},"type":"object","required":["id","crm_name","email","order_id","created_at"],"title":"ConnectorRequestRow"},"CorpusPreviewRequest":{"properties":{"corpus_type":{"type":"string","title":"Corpus Type"},"corpus_spec":{"additionalProperties":true,"type":"object","title":"Corpus Spec"},"sample_size":{"type":"integer","title":"Sample Size","default":3}},"type":"object","required":["corpus_type","corpus_spec"],"title":"CorpusPreviewRequest"},"CoverageResponse":{"properties":{"state":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"State"},"sector":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Sector"},"total":{"type":"integer","title":"Total"},"classified":{"type":"integer","title":"Classified"},"unclassified":{"type":"integer","title":"Unclassified"},"classified_pct":{"type":"number","title":"Classified Pct"},"by_confidence_tier":{"additionalProperties":{"type":"integer"},"type":"object","title":"By Confidence Tier"},"sample_unclassified":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Sample Unclassified"}},"type":"object","required":["state","sector","total","classified","unclassified","classified_pct","by_confidence_tier","sample_unclassified"],"title":"CoverageResponse"},"CurrentShape":{"properties":{"states":{"items":{"type":"string"},"type":"array","title":"States"},"filters":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Filters"},"lane":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Lane"},"cap":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Cap"}},"type":"object","title":"CurrentShape"},"DocRegistryCreate":{"properties":{"doc_path":{"type":"string","title":"Doc Path"},"google_doc_id":{"type":"string","title":"Google Doc Id"},"state":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"State"},"doc_type":{"type":"string","title":"Doc Type","default":"standup"},"session_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Session Id"}},"type":"object","required":["doc_path","google_doc_id"],"title":"DocRegistryCreate"},"DownloadLogEntry":{"properties":{"outcome":{"type":"string","title":"Outcome"},"ip_address":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Ip Address"},"user_agent":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"User Agent"},"downloaded_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Downloaded At"}},"type":"object","required":["outcome","ip_address","user_agent","downloaded_at"],"title":"DownloadLogEntry","description":"One attempt against a download link — outcome + who/where (commerce.download_log)."},"EmailLinkRequest":{"properties":{"checkout_url":{"type":"string","title":"Checkout Url"},"lead_count":{"type":"integer","title":"Lead Count"},"to_email":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"To Email"}},"type":"object","required":["checkout_url","lead_count"],"title":"EmailLinkRequest","description":"Send the branded payment-link email for an order (operator click)."},"EnrichmentRequest":{"properties":{"state":{"type":"string","title":"State"},"entity_ids":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Entity Ids"},"include_all_matching":{"type":"boolean","title":"Include All Matching","default":false},"filters":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Filters","default":[]}},"type":"object","required":["state"],"title":"EnrichmentRequest"},"ExportDownloadStatus":{"properties":{"export_id":{"type":"string","title":"Export Id"},"label":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Label"},"download_count":{"type":"integer","title":"Download Count"},"download_limit":{"type":"integer","title":"Download Limit"},"download_expires_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Download Expires At"},"revoked_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Revoked At"},"attempts":{"items":{"$ref":"#/components/schemas/DownloadLogEntry"},"type":"array","title":"Attempts"}},"type":"object","required":["export_id","label","download_count","download_limit","download_expires_at","revoked_at","attempts"],"title":"ExportDownloadStatus","description":"One order's file, with its full access history — has it been opened?"},"ExportRequest":{"properties":{"state":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"State"},"entity_ids":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Entity Ids"},"include_all_matching":{"type":"boolean","title":"Include All Matching","default":false},"filters":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Filters","default":[]},"format":{"type":"string","enum":["csv","json","xlsx"],"title":"Format","default":"csv"},"to_email":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"To Email"},"include_non_operating":{"type":"boolean","title":"Include Non Operating","default":false},"include_existing":{"type":"boolean","title":"Include Existing","default":false},"include_registrations":{"type":"boolean","title":"Include Registrations","default":false},"audience":{"type":"string","enum":["customer","design_partner","data_partner"],"title":"Audience","default":"customer"},"licensed_to":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Licensed To"},"cohort_note":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Cohort Note"}},"type":"object","title":"ExportRequest"},"FindingCreate":{"properties":{"agent_id":{"type":"string","title":"Agent Id"},"state":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"State"},"finding_type":{"type":"string","title":"Finding Type"},"title":{"type":"string","title":"Title"},"description":{"type":"string","title":"Description"},"evidence":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Evidence"},"proposed_action":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Proposed Action"},"priority":{"type":"string","title":"Priority","default":"medium"},"session_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Session Id"},"work_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Work Type"},"domain":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Domain"},"memory_route":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Memory Route"},"hypothesis":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Hypothesis"},"target_metric":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Target Metric"},"baseline_value":{"anyOf":[{"additionalProperties":true,"type":"object"},{"items":{},"type":"array"},{"type":"number"},{"type":"integer"},{"type":"string"},{"type":"null"}],"title":"Baseline Value"},"observed_value_t24h":{"anyOf":[{"additionalProperties":true,"type":"object"},{"items":{},"type":"array"},{"type":"number"},{"type":"integer"},{"type":"string"},{"type":"null"}],"title":"Observed Value T24H"},"observed_value_t7d":{"anyOf":[{"additionalProperties":true,"type":"object"},{"items":{},"type":"array"},{"type":"number"},{"type":"integer"},{"type":"string"},{"type":"null"}],"title":"Observed Value T7D"}},"type":"object","required":["agent_id","finding_type","title","description"],"title":"FindingCreate"},"FireResponse":{"properties":{"subscription_id":{"type":"string","format":"uuid","title":"Subscription Id"},"outcome":{"type":"string","title":"Outcome"},"delivery":{"anyOf":[{"$ref":"#/components/schemas/LastDelivery"},{"type":"null"}]}},"type":"object","required":["subscription_id","outcome"],"title":"FireResponse"},"FpSampleRecord":{"properties":{"lead_ref":{"type":"string","title":"Lead Ref"},"state":{"type":"string","title":"State"},"entity_name":{"type":"string","title":"Entity Name"},"entity_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Entity Type"},"industry_sector":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Industry Sector"},"industry_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Industry Name"},"industry_confidence_tier":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Industry Confidence Tier"}},"type":"object","required":["lead_ref","state","entity_name","entity_type","industry_sector","industry_name","industry_confidence_tier"],"title":"FpSampleRecord"},"FpSampleResponse":{"properties":{"sector":{"type":"string","title":"Sector"},"n_requested":{"type":"integer","title":"N Requested"},"n_returned":{"type":"integer","title":"N Returned"},"records":{"items":{"$ref":"#/components/schemas/FpSampleRecord"},"type":"array","title":"Records"}},"type":"object","required":["sector","n_requested","n_returned","records"],"title":"FpSampleResponse"},"FromListRequest":{"properties":{"list_id":{"type":"string","title":"List Id"},"email":{"type":"string","title":"Email"},"claim_token":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Claim Token"},"cadence":{"type":"string","enum":["daily","weekly","monthly","quarterly"],"title":"Cadence","default":"monthly"},"cap_cents":{"type":"integer","title":"Cap Cents"},"lane":{"type":"string","enum":["all","best","contact"],"title":"Lane","default":"best"},"delivery":{"type":"string","enum":["file","crm"],"title":"Delivery","default":"file"},"crm_connection_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Crm Connection Id"},"run_days":{"anyOf":[{"type":"integer","maximum":366.0,"minimum":1.0},{"type":"null"}],"title":"Run Days"},"contact":{"type":"string","enum":["any","email","phone","both"],"title":"Contact","default":"any"},"success_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Success Url"},"cancel_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Cancel Url"},"test_mode":{"type":"boolean","title":"Test Mode","default":false}},"additionalProperties":false,"type":"object","required":["list_id","email","cap_cents"],"title":"FromListRequest","description":"Get new matches on a saved list the buyer has not bought. The first\ndelivery is new matches from creation on — never the list as it stands."},"FromOrderRequest":{"properties":{"order_id":{"type":"string","title":"Order Id"},"cadence":{"type":"string","enum":["daily","weekly","monthly","quarterly"],"title":"Cadence","default":"monthly"},"cap_cents":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Cap Cents"},"lane":{"anyOf":[{"type":"string","enum":["all","best","contact"]},{"type":"null"}],"title":"Lane"},"run_days":{"anyOf":[{"type":"integer","maximum":366.0,"minimum":1.0},{"type":"null"}],"title":"Run Days"},"contact":{"type":"string","enum":["any","email","phone","both"],"title":"Contact","default":"any"},"session_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Session Id"},"success_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Success Url"},"cancel_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Cancel Url"},"test_mode":{"type":"boolean","title":"Test Mode","default":false}},"additionalProperties":false,"type":"object","required":["order_id"],"title":"FromOrderRequest","description":"Get new matches on a paid list order. `session_id` (the order's Stripe\nCheckout session, as the success page holds it) or the list's X-Claim-Token\nheader is the bearer — the same two secrets the receipt already trusts."},"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"InterpretRequest":{"properties":{"text":{"type":"string","maxLength":500,"minLength":1,"title":"Text","description":"What the buyer typed"},"state":{"anyOf":[{"type":"string","maxLength":2},{"type":"null"}],"title":"State","description":"Optional state hint (two-letter code)"},"current":{"anyOf":[{"$ref":"#/components/schemas/CurrentShape"},{"type":"null"}],"description":"The buyer's current shape, merged into the answer"}},"additionalProperties":false,"type":"object","required":["text"],"title":"InterpretRequest"},"IssueKeyRequest":{"properties":{"email":{"type":"string","maxLength":320,"minLength":3,"title":"Email"},"declared_use":{"type":"string","maxLength":64,"title":"Declared Use","description":"One of: b2b_sales_outreach, b2b_marketing, crm_enrichment, market_research, platform_integration"},"mode":{"type":"string","maxLength":8,"title":"Mode","default":"test"},"label":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}],"title":"Label"},"company":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}],"title":"Company"},"scopes":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Scopes","description":"Default: every scope."},"rate_limit_per_min":{"anyOf":[{"type":"integer","maximum":10000.0,"exclusiveMinimum":0.0},{"type":"null"}],"title":"Rate Limit Per Min"},"expires_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Expires At"}},"additionalProperties":false,"type":"object","required":["email","declared_use"],"title":"IssueKeyRequest"},"LLMClassifyRepairRequest":{"properties":{"state":{"type":"string","title":"State"},"dry_run":{"type":"boolean","title":"Dry Run","default":false}},"type":"object","required":["state"],"title":"LLMClassifyRepairRequest"},"LLMClassifyRequest":{"properties":{"state":{"type":"string","title":"State"},"manifest_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Manifest Id"},"dry_run":{"type":"boolean","title":"Dry Run","default":false},"max_calls":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Max Calls"}},"type":"object","required":["state"],"title":"LLMClassifyRequest"},"LLMNameRequest":{"properties":{"state":{"type":"string","title":"State"},"manifest_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Manifest Id"},"dry_run":{"type":"boolean","title":"Dry Run","default":false},"max_calls":{"type":"integer","title":"Max Calls","default":150}},"type":"object","required":["state"],"title":"LLMNameRequest"},"LLMNamesakeRequest":{"properties":{"state":{"type":"string","title":"State"},"manifest_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Manifest Id"},"dry_run":{"type":"boolean","title":"Dry Run","default":false},"max_calls":{"type":"integer","title":"Max Calls","default":100}},"type":"object","required":["state"],"title":"LLMNamesakeRequest"},"LastDelivery":{"properties":{"delivery_id":{"type":"string","format":"uuid","title":"Delivery Id"},"status":{"type":"string","title":"Status"},"fired_at":{"type":"string","format":"date-time","title":"Fired At"},"delivered_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Delivered At"},"window_key":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Window Key"},"record_count":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Record Count"},"waiting_count":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Waiting Count"},"total_cents":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Total Cents"},"retail_cents":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Retail Cents"},"cost_cents":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Cost Cents"},"order_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Order Id"},"error":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Error"}},"type":"object","required":["delivery_id","status","fired_at"],"title":"LastDelivery"},"LlmAuditAgentSummary":{"properties":{"agent_id":{"type":"string","title":"Agent Id"},"calls":{"type":"integer","title":"Calls"},"unique_prompts":{"type":"integer","title":"Unique Prompts"},"repeat_calls":{"type":"integer","title":"Repeat Calls","description":"calls - unique_prompts: the re-paid work a harvest store would answer for free"},"repeat_rate":{"type":"number","title":"Repeat Rate"},"input_tokens":{"type":"integer","title":"Input Tokens"},"output_tokens":{"type":"integer","title":"Output Tokens"},"errors":{"type":"integer","title":"Errors"}},"type":"object","required":["agent_id","calls","unique_prompts","repeat_calls","repeat_rate","input_tokens","output_tokens","errors"],"title":"LlmAuditAgentSummary"},"LlmAuditSummary":{"properties":{"window_days":{"type":"integer","title":"Window Days"},"total_calls":{"type":"integer","title":"Total Calls"},"unique_prompts":{"type":"integer","title":"Unique Prompts","description":"Distinct prompt hashes across ALL agents (a true global distinct, not a per-agent sum)"},"repeat_calls":{"type":"integer","title":"Repeat Calls"},"repeat_rate":{"type":"number","title":"Repeat Rate"},"agents":{"items":{"$ref":"#/components/schemas/LlmAuditAgentSummary"},"type":"array","title":"Agents"}},"type":"object","required":["window_days","total_calls","unique_prompts","repeat_calls","repeat_rate","agents"],"title":"LlmAuditSummary"},"ManageUpdate":{"properties":{"cadence":{"anyOf":[{"type":"string","enum":["daily","weekly","monthly","quarterly"]},{"type":"null"}],"title":"Cadence"},"schedule":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Schedule"},"cap_cents":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Cap Cents"},"status":{"anyOf":[{"type":"string","enum":["active","paused"]},{"type":"null"}],"title":"Status"}},"additionalProperties":false,"type":"object","title":"ManageUpdate"},"MultiStateLeg":{"properties":{"state":{"type":"string","title":"State"},"matched":{"type":"integer","title":"Matched","description":"Records the selection resolved to in this state."},"status":{"type":"string","title":"Status","description":"`started` (a job is running) · `queued` (accepted, waiting for a worker — starts on its own) · `blocked` (another run holds this state's lock — re-run when it clears) · `unavailable` (records but no pipeline config) · `skipped` (nothing runnable) · `error` (launch failed, nothing ran)."},"detail":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Detail"},"job_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Job Id"},"status_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Status Url"},"task_arn":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Task Arn"}},"type":"object","required":["state","matched","status"],"title":"MultiStateLeg","description":"One state's leg of a fan-out — what it matched and what happened to it."},"MultiStatePreviewLeg":{"properties":{"state":{"type":"string","title":"State"},"matched":{"type":"integer","title":"Matched"},"will_run":{"type":"integer","title":"Will Run","description":"`matched`, or the per-state `limit` if that is smaller."},"status":{"type":"string","title":"Status"},"detail":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Detail"}},"type":"object","required":["state","matched","will_run","status"],"title":"MultiStatePreviewLeg","description":"`status`: `ready` · `blocked` (state lock held) · `unavailable` (no config)."},"MultiStatePreviewResponse":{"properties":{"total_matched":{"type":"integer","title":"Total Matched"},"total_will_run":{"type":"integer","title":"Total Will Run"},"states_ready":{"type":"integer","title":"States Ready"},"legs":{"items":{"$ref":"#/components/schemas/MultiStatePreviewLeg"},"type":"array","title":"Legs"},"capacity_note":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Capacity Note"}},"type":"object","required":["total_matched","total_will_run","states_ready","legs"],"title":"MultiStatePreviewResponse"},"MultiStateScopeRequest":{"properties":{"states":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"States","description":"Restrict the fan-out to these states. Omit to run every state the selection touches. It narrows, never widens: a state named here that the selection does not touch is simply absent from the result.","examples":[["CO","FL"]]},"limit":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Limit","description":"PER-STATE cap, not a total — `limit=100` across 5 states runs up to 500 records. One shared budget would have to pick which state gets starved; capping each leg is the predictable reading of 'take 100 from each'.","examples":[100]},"entity_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Entity Id","description":"Comma/space/newline-separated UUIDs or GLIDs that may span states. Grouped by state, one run per state. Mutually exclusive with `filters`.","examples":["GL-CO-00042, GL-FL-00099"]},"filters":{"anyOf":[{"items":{"additionalProperties":true,"type":"object"},"type":"array"},{"type":"null"}],"title":"Filters","description":"Filter expression, same shape as POST /api/v1/leads/browse, WITHOUT a state clause — the fan-out supplies each leg's own. Mutually exclusive with `entity_id`.","examples":[[{"field":"reachability_tier","op":"eq","value":"On Fire"}]]},"include_non_operating":{"type":"boolean","title":"Include Non Operating","description":"Only meaningful with `filters`. Mirrors Browse's own default so the per-state counts match the number on the button the operator pressed — see `TriggerRequest.include_non_operating`.","default":false},"include_existing":{"type":"boolean","title":"Include Existing","description":"Only meaningful with `filters`. See `TriggerRequest.include_existing`.","default":false},"include_registrations":{"type":"boolean","title":"Include Registrations","description":"Deprecated alias of include_existing (kept one release so saved requests resolve).","default":false,"deprecated":true}},"additionalProperties":false,"type":"object","title":"MultiStateScopeRequest","description":"The scope half of a fan-out: which records, across which states.\n\nShared by the preview and the trigger so the states and counts an operator\napproves are resolved by exactly one piece of code. Deliberately carries NO\nstage list — which states a selection touches, and how many records it\nmatches in each, does not depend on what you intend to run on them."},"MultiStateTriggerRequest":{"properties":{"states":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"States","description":"Restrict the fan-out to these states. Omit to run every state the selection touches. It narrows, never widens: a state named here that the selection does not touch is simply absent from the result.","examples":[["CO","FL"]]},"limit":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Limit","description":"PER-STATE cap, not a total — `limit=100` across 5 states runs up to 500 records. One shared budget would have to pick which state gets starved; capping each leg is the predictable reading of 'take 100 from each'.","examples":[100]},"entity_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Entity Id","description":"Comma/space/newline-separated UUIDs or GLIDs that may span states. Grouped by state, one run per state. Mutually exclusive with `filters`.","examples":["GL-CO-00042, GL-FL-00099"]},"filters":{"anyOf":[{"items":{"additionalProperties":true,"type":"object"},"type":"array"},{"type":"null"}],"title":"Filters","description":"Filter expression, same shape as POST /api/v1/leads/browse, WITHOUT a state clause — the fan-out supplies each leg's own. Mutually exclusive with `entity_id`.","examples":[[{"field":"reachability_tier","op":"eq","value":"On Fire"}]]},"include_non_operating":{"type":"boolean","title":"Include Non Operating","description":"Only meaningful with `filters`. Mirrors Browse's own default so the per-state counts match the number on the button the operator pressed — see `TriggerRequest.include_non_operating`.","default":false},"include_existing":{"type":"boolean","title":"Include Existing","description":"Only meaningful with `filters`. See `TriggerRequest.include_existing`.","default":false},"include_registrations":{"type":"boolean","title":"Include Registrations","description":"Deprecated alias of include_existing (kept one release so saved requests resolve).","default":false,"deprecated":true},"stages":{"anyOf":[{"type":"string"},{"items":{"type":"string"},"type":"array"}],"title":"Stages","description":"Pipeline stages to run in EVERY state leg. Same vocabulary as POST /trigger. `pull` is refused here — and because `all` contains `pull`, the default is refused too: a fan-out must name the stages it is running.","default":"all","examples":["score","enrich"]},"gapfill_force":{"type":"boolean","title":"Gapfill Force","description":"Forced paid re-dip, applied to every leg. Same rules as POST /trigger.","default":false},"force_recompute":{"type":"boolean","title":"Force Recompute","description":"Force free stages to recompute in every leg. Same rules as POST /trigger.","default":false}},"additionalProperties":false,"type":"object","title":"MultiStateTriggerRequest","description":"Run one scoped pipeline job per state for a selection that spans states.\n\nScope fields are inherited, so what the preview resolved is what this runs.\nEach state gets its own ordinary scoped run — own Job, own Run Manifest,\nown COGS attribution — launched in parallel.","examples":[{"summary":"Enrich an all-states Browse selection","value":{"filters":[{"field":"has_email","op":"eq","value":false}],"stages":["skip_trace","gapfill","validate"]}}]},"MultiStateTriggerResponse":{"properties":{"started":{"type":"integer","title":"Started"},"skipped":{"type":"integer","title":"Skipped"},"stages":{"items":{"type":"string"},"type":"array","title":"Stages","description":"The expanded stage list every started leg is running."},"legs":{"items":{"$ref":"#/components/schemas/MultiStateLeg"},"type":"array","title":"Legs"},"capacity_note":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Capacity Note"}},"type":"object","required":["started","skipped","stages","legs"],"title":"MultiStateTriggerResponse"},"OfferDetail":{"properties":{"code":{"type":"string","title":"Code"},"unit_cents":{"type":"integer","title":"Unit Cents"},"status":{"type":"string","title":"Status"},"rule":{"type":"string","title":"Rule"},"cap_records":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Cap Records"},"cap_cents":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Cap Cents"},"remaining_records":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Remaining Records"},"remaining_cents":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Remaining Cents"},"redeemed_records":{"type":"integer","title":"Redeemed Records"},"redeemed_cents":{"type":"integer","title":"Redeemed Cents"},"bound_email":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Bound Email"},"expires_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Expires At"},"revoked_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Revoked At"},"note":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Note"},"created_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Created At"},"orders":{"type":"integer","title":"Orders"},"order_rows":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Order Rows"}},"type":"object","required":["code","unit_cents","status","rule","cap_records","cap_cents","remaining_records","remaining_cents","redeemed_records","redeemed_cents","bound_email","expires_at","revoked_at","note","created_at","orders","order_rows"],"title":"OfferDetail"},"OfferIn":{"properties":{"code":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Code","description":"Leave blank to mint one like GL-7K3Q9M"},"unit_cents":{"type":"integer","minimum":1.0,"title":"Unit Cents","description":"The agreed price per record, in cents — a ceiling on every grade"},"cap_records":{"anyOf":[{"type":"integer","minimum":1.0},{"type":"null"}],"title":"Cap Records"},"cap_cents":{"anyOf":[{"type":"integer","minimum":1.0},{"type":"null"}],"title":"Cap Cents"},"bound_email":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Bound Email","description":"Only this buyer may use the code"},"expires_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Expires At"},"expires_in_days":{"anyOf":[{"type":"integer","minimum":1.0},{"type":"null"}],"title":"Expires In Days"},"note":{"anyOf":[{"type":"string","maxLength":500},{"type":"null"}],"title":"Note","description":"Who and why — 'case study, Acme Web Design'"}},"additionalProperties":false,"type":"object","required":["unit_cents"],"title":"OfferIn","description":"Mint. `unit_cents` is the ceiling every grade bills under (min with list).\nGive `expires_at` or `expires_in_days`, not both; neither = open-ended."},"OfferPatch":{"properties":{"cap_records":{"anyOf":[{"type":"integer","minimum":1.0},{"type":"null"}],"title":"Cap Records"},"cap_cents":{"anyOf":[{"type":"integer","minimum":1.0},{"type":"null"}],"title":"Cap Cents"},"bound_email":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Bound Email"},"expires_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Expires At"},"expires_in_days":{"anyOf":[{"type":"integer","minimum":1.0},{"type":"null"}],"title":"Expires In Days"},"note":{"anyOf":[{"type":"string","maxLength":500},{"type":"null"}],"title":"Note"}},"additionalProperties":false,"type":"object","title":"OfferPatch","description":"Change the terms. A field sent as null CLEARS it (an uncapped, open-ended\nor unbound code); a field left out is untouched. `unit_cents` is not\neditable — a different price is a different deal, so mint a new code."},"OfferRow":{"properties":{"code":{"type":"string","title":"Code"},"unit_cents":{"type":"integer","title":"Unit Cents"},"status":{"type":"string","title":"Status"},"rule":{"type":"string","title":"Rule"},"cap_records":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Cap Records"},"cap_cents":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Cap Cents"},"remaining_records":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Remaining Records"},"remaining_cents":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Remaining Cents"},"redeemed_records":{"type":"integer","title":"Redeemed Records"},"redeemed_cents":{"type":"integer","title":"Redeemed Cents"},"bound_email":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Bound Email"},"expires_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Expires At"},"revoked_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Revoked At"},"note":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Note"},"created_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Created At"},"orders":{"type":"integer","title":"Orders"}},"type":"object","required":["code","unit_cents","status","rule","cap_records","cap_cents","remaining_records","remaining_cents","redeemed_records","redeemed_cents","bound_email","expires_at","revoked_at","note","created_at","orders"],"title":"OfferRow"},"OrderDownloadStatusResponse":{"properties":{"order_id":{"type":"string","title":"Order Id"},"buyer_email":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Buyer Email"},"exports":{"items":{"$ref":"#/components/schemas/ExportDownloadStatus"},"type":"array","title":"Exports"}},"type":"object","required":["order_id","buyer_email","exports"],"title":"OrderDownloadStatusResponse"},"OrderRow":{"properties":{"order_id":{"type":"string","title":"Order Id"},"created_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Created At"},"buyer_email":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Buyer Email"},"product_name":{"type":"string","title":"Product Name"},"price_cents":{"type":"integer","title":"Price Cents"},"billing":{"type":"string","title":"Billing"},"status":{"type":"string","title":"Status"},"delivery_method":{"type":"string","title":"Delivery Method"},"record_count":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Record Count"},"state":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"State"},"filters":{"anyOf":[{"items":{"additionalProperties":true,"type":"object"},"type":"array"},{"type":"null"}],"title":"Filters"},"download_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Download Url"},"surface":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Surface"},"cancel_reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Cancel Reason"},"cancel_email_sent":{"type":"boolean","title":"Cancel Email Sent","default":false}},"type":"object","required":["order_id","created_at","buyer_email","product_name","price_cents","billing","status","delivery_method","record_count","state","filters","download_url"],"title":"OrderRow","description":"One row on the operator Orders screen — the on-screen ledger."},"OrderStatusResponse":{"properties":{"order_id":{"type":"string","title":"Order Id"},"status":{"type":"string","title":"Status"},"product_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Product Name"},"download_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Download Url"},"download_expires_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Download Expires At"},"record_count":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Record Count"},"delivery_method":{"type":"string","title":"Delivery Method","default":"file"},"crm_provider":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Crm Provider"},"crm_status":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Crm Status"},"crm_delivered":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Crm Delivered"},"crm_duplicates":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Crm Duplicates"},"crm_failed":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Crm Failed"},"lane":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Lane"},"cap":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Cap"},"channel":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Channel"},"lines":{"anyOf":[{"items":{"additionalProperties":true,"type":"object"},"type":"array"},{"type":"null"}],"title":"Lines"},"total_cents":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Total Cents"},"price_rule_version":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Price Rule Version"},"offer":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Offer"},"delivered":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Delivered"},"saved_list":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Saved List"},"connector_crm_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Connector Crm Name"},"attestation_accepted_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Attestation Accepted At"},"reorder_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Reorder Url"},"guarantee":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Guarantee"},"superseded_download_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Superseded Download Url"},"check":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Check"},"upsell":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Upsell"}},"type":"object","required":["order_id","status","product_name","download_url","download_expires_at","record_count"],"title":"OrderStatusResponse"},"PartnerAccessRequest":{"properties":{"partner_name":{"type":"string","maxLength":80,"minLength":1,"title":"Partner Name","description":"Shown on the welcome page greeting"}},"type":"object","required":["partner_name"],"title":"PartnerAccessRequest"},"PartnerAccessResponse":{"properties":{"url":{"type":"string","title":"Url"},"expires_at":{"type":"string","title":"Expires At"},"partner_name":{"type":"string","title":"Partner Name"}},"type":"object","required":["url","expires_at","partner_name"],"title":"PartnerAccessResponse"},"PrivacyRequestPayload":{"properties":{"request_type":{"type":"string","title":"Request Type"},"know_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Know Type"},"requestor_type":{"type":"string","title":"Requestor Type"},"full_name":{"type":"string","title":"Full Name"},"email":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Email"},"phone":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Phone"},"mailing_address":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Mailing Address"},"notes":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Notes"},"gpc_signal_detected":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Gpc Signal Detected"}},"type":"object","required":["request_type","requestor_type","full_name"],"title":"PrivacyRequestPayload"},"PrivacyRequestResponse":{"properties":{"status":{"type":"string","title":"Status"}},"type":"object","required":["status"],"title":"PrivacyRequestResponse"},"ProductCardResponse":{"properties":{"product_id":{"type":"string","title":"Product Id"},"name":{"type":"string","title":"Name"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"state":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"State"},"period":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Period"},"lead_count":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Lead Count"},"price_cents":{"type":"integer","title":"Price Cents"},"stripe_price_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Stripe Price Id"}},"type":"object","required":["product_id","name","description","state","period","lead_count","price_cents","stripe_price_id"],"title":"ProductCardResponse"},"ProposeExperimentRequest":{"properties":{"agent_id":{"type":"string","title":"Agent Id"},"name":{"type":"string","title":"Name"},"hypothesis":{"type":"string","title":"Hypothesis"},"target_artifact":{"type":"string","title":"Target Artifact"},"target_artifact_ref":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Target Artifact Ref"},"corpus_type":{"type":"string","title":"Corpus Type"},"corpus_spec":{"additionalProperties":true,"type":"object","title":"Corpus Spec"},"variants":{"items":{"$ref":"#/components/schemas/VariantSpecRequest"},"type":"array","title":"Variants"},"item_count_estimate":{"type":"integer","title":"Item Count Estimate"}},"type":"object","required":["agent_id","name","hypothesis","target_artifact","corpus_type","corpus_spec","variants","item_count_estimate"],"title":"ProposeExperimentRequest"},"PublicConfig":{"properties":{"analytics":{"anyOf":[{"$ref":"#/components/schemas/AnalyticsConfig"},{"type":"null"}]},"git_sha":{"type":"string","title":"Git Sha"},"environment":{"type":"string","title":"Environment"}},"type":"object","required":["analytics","git_sha","environment"],"title":"PublicConfig"},"PublishRequest":{"properties":{"state":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"State"},"entity_ids":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Entity Ids"},"include_all_matching":{"type":"boolean","title":"Include All Matching","default":false},"filters":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Filters","default":[]},"include_non_operating":{"type":"boolean","title":"Include Non Operating","default":false},"include_existing":{"type":"boolean","title":"Include Existing","default":false},"include_registrations":{"type":"boolean","title":"Include Registrations","default":false},"dry_run":{"type":"boolean","title":"Dry Run","default":false},"connection_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Connection Id"}},"type":"object","title":"PublishRequest"},"PublishResponse":{"properties":{"job_id":{"type":"string","title":"Job Id"},"status":{"type":"string","title":"Status"},"status_url":{"type":"string","title":"Status Url"}},"type":"object","required":["job_id","status","status_url"],"title":"PublishResponse"},"QuoteRequest":{"properties":{"state":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"State"},"filters":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Filters","default":[]},"entity_ids":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Entity Ids"}},"type":"object","title":"QuoteRequest","description":"Operator preview: how many leads the current Browse cohort yields."},"QuoteResponse":{"properties":{"matched_count":{"type":"integer","title":"Matched Count"}},"type":"object","required":["matched_count"],"title":"QuoteResponse"},"ReattributeRequest":{"properties":{"queue_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Queue Id"}},"type":"object","title":"ReattributeRequest"},"ReceiptImportRequest":{"properties":{"customer_email":{"type":"string","title":"Customer Email"},"lead_refs":{"items":{"type":"string"},"type":"array","title":"Lead Refs","default":[]},"entity_ids":{"items":{"type":"string","format":"uuid"},"type":"array","title":"Entity Ids","default":[]},"manifest_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Manifest Id"},"note":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Note"}},"additionalProperties":false,"type":"object","required":["customer_email"],"title":"ReceiptImportRequest","description":"Records a customer already received OUTSIDE this system — a file sent by\nhand, a POC workbook — so a standing delivery never sends them again."},"ReceiptImportResponse":{"properties":{"customer_id":{"type":"string","format":"uuid","title":"Customer Id"},"resolved":{"type":"integer","title":"Resolved"},"added":{"type":"integer","title":"Added"},"total_received":{"type":"integer","title":"Total Received"},"unknown_refs":{"items":{"type":"string"},"type":"array","title":"Unknown Refs","default":[]}},"type":"object","required":["customer_id","resolved","added","total_received"],"title":"ReceiptImportResponse"},"RecomputeSignalsRequest":{"properties":{"service":{"type":"string","title":"Service"},"state":{"type":"string","title":"State"},"entity_ids":{"items":{"type":"string"},"type":"array","title":"Entity Ids"},"force":{"type":"boolean","title":"Force","default":true},"dry_run":{"type":"boolean","title":"Dry Run","default":false}},"additionalProperties":false,"type":"object","required":["service","state","entity_ids"],"title":"RecomputeSignalsRequest","description":"ADR-004 Phase 3 request shape.\n\n`service` selects the IP service(s) to recompute. `entity_ids` is\n**required** — this endpoint is for targeted recomputes only. Whole-state\nrecomputes go through the pipeline trigger endpoint with filters, or\nthrough the CLI (`python -m backend.services.ra_intelligence_service\n--state CO --force-recompute`).\n\nNo hard count cap. If an ALB/proxy timeout hits mid-request, the\nservice's session rollback-on-exception (ra_intelligence_service.py and\ncontact_relevance.py `except/rollback` blocks) guarantees no partial\nwrites — the caller just sees a 504 and can retry with a smaller batch.\nAPI worker saturation (if it ever becomes a real problem) is a\nrate-limiting concern, not a per-request bound."},"RecomputeSignalsResponse":{"properties":{"service":{"type":"string","title":"Service"},"state":{"type":"string","title":"State"},"ra_intelligence":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Ra Intelligence"},"contact_relevance":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Contact Relevance"},"classify":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Classify"},"dry_run":{"type":"boolean","title":"Dry Run"}},"type":"object","required":["service","state","dry_run"],"title":"RecomputeSignalsResponse"},"RemoveDeliveredRequest":{"properties":{"entity_ids":{"items":{"type":"string"},"type":"array","title":"Entity Ids"}},"type":"object","required":["entity_ids"],"title":"RemoveDeliveredRequest"},"ReorderRequest":{"properties":{"lane":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Lane"},"cap":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Cap"},"channel":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Channel"},"delivery":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Delivery"},"crm_connection_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Crm Connection Id"},"connector_crm_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Connector Crm Name"},"customer_email":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Customer Email"},"success_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Success Url"},"cancel_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Cancel Url"},"price_rule_version":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Price Rule Version"},"expected_total_cents":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Expected Total Cents"},"offer_code":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Offer Code"}},"type":"object","title":"ReorderRequest","description":"'Buy what's new since this order' — every field inherits from the parent order when omitted."},"ReplayTracerfyAccepted":{"properties":{"report_id":{"type":"string","title":"Report Id"},"status_url":{"type":"string","title":"Status Url"},"state":{"type":"string","title":"State","default":"running"}},"type":"object","required":["report_id","status_url"],"title":"ReplayTracerfyAccepted"},"ReplayTracerfyReport":{"properties":{"report_id":{"type":"string","title":"Report Id"},"state":{"type":"string","title":"State"},"started_at":{"type":"string","title":"Started At"},"completed_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Completed At"},"error":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Error"},"aggregate":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Aggregate"},"per_queue":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Per Queue"},"state_coverage":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"State Coverage"},"matcher_stats":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Matcher Stats"}},"type":"object","required":["report_id","state","started_at"],"title":"ReplayTracerfyReport"},"ReplayTracerfyRequest":{"properties":{"queue_ids":{"items":{"type":"integer"},"type":"array","maxItems":200,"minItems":1,"title":"Queue Ids"},"states":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"States","description":"States to load into the matcher index. Defaults to all live states (the pipeline.config registry)."},"dry_run":{"type":"boolean","title":"Dry Run","description":"When True, parse + match but don't commit any writes","default":false}},"type":"object","required":["queue_ids"],"title":"ReplayTracerfyRequest"},"ResendDataRequest":{"properties":{"to_email":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"To Email"}},"type":"object","title":"ResendDataRequest","description":"Operator re-delivery of an already-paid order's file (no new sale, no charge).\n\n`to_email` re-addresses the delivery to a teammate at the buyer's org; omit it to\nre-send to the buyer on file. Same durable bearer link, same file — the resend\njust refreshes the 30-day window and clears the download cap so whoever receives\nit grabs the file cleanly."},"RunExperimentRequest":{"properties":{"agent_id":{"type":"string","title":"Agent Id"},"budget_usd":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Budget Usd"},"auto_ship":{"type":"boolean","title":"Auto Ship","default":true}},"type":"object","required":["agent_id"],"title":"RunExperimentRequest"},"SavedListCreate":{"properties":{"states":{"items":{"type":"string"},"type":"array","title":"States","description":"State codes; empty = every live state"},"filters":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Filters","description":"Browse filter contract [{field, op, value}] with groups"},"sort":{"anyOf":[{"items":{"additionalProperties":true,"type":"object"},"type":"array"},{"type":"null"}],"title":"Sort","description":"[{field, dir}]"},"name":{"anyOf":[{"type":"string","maxLength":120},{"type":"null"}],"title":"Name"},"include_held":{"type":"boolean","title":"Include Held","default":false},"include_existing":{"type":"boolean","title":"Include Existing","default":false}},"additionalProperties":false,"type":"object","title":"SavedListCreate"},"SavedListPatch":{"properties":{"name":{"anyOf":[{"type":"string","maxLength":120},{"type":"null"}],"title":"Name"}},"additionalProperties":false,"type":"object","title":"SavedListPatch"},"SeedTestRequest":{"properties":{"run_suffix":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Run Suffix"},"campaign_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Campaign Name"}},"type":"object","title":"SeedTestRequest"},"SellRequest":{"properties":{"label":{"type":"string","title":"Label"},"state":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"State"},"filters":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Filters","default":[]},"entity_ids":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Entity Ids"},"price_cents":{"type":"integer","title":"Price Cents"},"lead_count":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Lead Count"},"delivery_method":{"type":"string","title":"Delivery Method","default":"file"},"audience":{"type":"string","title":"Audience","default":"customer"},"crm_connection_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Crm Connection Id"},"billing":{"type":"string","title":"Billing","default":"one_time"},"buyer_email":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Buyer Email"},"test_mode":{"type":"boolean","title":"Test Mode","default":false},"success_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Success Url"},"cancel_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Cancel Url"}},"type":"object","required":["label","price_cents"],"title":"SellRequest","description":"Operator 'Sell this list' — mint a payment link for the exact filtered cohort.\n\nAdmin-only. Creates a hidden ad-hoc product carrying this sale's frozen filter\n+ price, then a live Stripe Checkout Session whose link the operator sends to\nthe buyer. On payment the webhook delivers by delivery_method."},"SellResponse":{"properties":{"order_id":{"type":"string","title":"Order Id"},"product_id":{"type":"string","title":"Product Id"},"session_id":{"type":"string","title":"Session Id"},"checkout_url":{"type":"string","title":"Checkout Url"},"matched_count":{"type":"integer","title":"Matched Count"},"test_mode":{"type":"boolean","title":"Test Mode"}},"type":"object","required":["order_id","product_id","session_id","checkout_url","matched_count","test_mode"],"title":"SellResponse"},"SubscriptionCheckoutRequest":{"properties":{"price_cents":{"type":"integer","title":"Price Cents"},"billing_interval":{"type":"string","enum":["day","week","month","year"],"title":"Billing Interval","default":"month"},"buyer_email":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Buyer Email"},"test_mode":{"type":"boolean","title":"Test Mode","default":false},"success_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Success Url"},"cancel_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Cancel Url"}},"additionalProperties":false,"type":"object","required":["price_cents"],"title":"SubscriptionCheckoutRequest","description":"Mint the recurring payment link that funds a standing order (ADR-041)."},"SubscriptionCheckoutResponse":{"properties":{"subscription_id":{"type":"string","format":"uuid","title":"Subscription Id"},"session_id":{"type":"string","title":"Session Id"},"checkout_url":{"type":"string","title":"Checkout Url"}},"type":"object","required":["subscription_id","session_id","checkout_url"],"title":"SubscriptionCheckoutResponse"},"SubscriptionCreate":{"properties":{"saved_list_id":{"type":"string","title":"Saved List Id"},"buyer_email":{"type":"string","title":"Buyer Email"},"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name"},"schedule":{"additionalProperties":true,"type":"object","title":"Schedule","default":{"cadence":"daily"}},"pricing":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Pricing"},"billing_mode":{"type":"string","enum":["card","invoice","none"],"title":"Billing Mode","default":"card"},"offer_code":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Offer Code"},"cap":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Cap"},"lane":{"type":"string","enum":["all","best","contact"],"title":"Lane","default":"best"},"delivery_method":{"type":"string","enum":["file","crm"],"title":"Delivery Method","default":"file"},"connection_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Connection Id"},"start":{"type":"string","enum":["new","backlog"],"title":"Start","default":"new"},"status":{"anyOf":[{"type":"string","enum":["active","paused"]},{"type":"null"}],"title":"Status"},"customer_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Customer Id"},"attestation_version":{"type":"string","title":"Attestation Version","default":"v1-with-contacts"},"max_age_days":{"anyOf":[{"type":"integer","maximum":3650.0,"minimum":1.0},{"type":"null"}],"title":"Max Age Days"},"notify_empty":{"type":"boolean","title":"Notify Empty","default":true},"recipients":{"items":{"type":"string"},"type":"array","title":"Recipients","default":[]}},"additionalProperties":false,"type":"object","required":["saved_list_id","buyer_email"],"title":"SubscriptionCreate","description":"A standing delivery on a saved list (admin). Every field but the list and\nthe buyer is a setting with a safe default: list price, card billing, a\nfile link, every morning at 7:00 in the buyer's zone, new filings only."},"SubscriptionResponse":{"properties":{"subscription_id":{"type":"string","format":"uuid","title":"Subscription Id"},"name":{"type":"string","title":"Name"},"status":{"type":"string","title":"Status"},"buyer_email":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Buyer Email"},"customer_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Customer Id"},"saved_list_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Saved List Id"},"schedule":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Schedule"},"schedule_words":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Schedule Words"},"pricing":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Pricing"},"billing_mode":{"type":"string","title":"Billing Mode","default":"card"},"billing_status":{"type":"string","title":"Billing Status","default":"none"},"offer_code":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Offer Code"},"credits_remaining_cents":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Credits Remaining Cents"},"unbilled_cents":{"type":"integer","title":"Unbilled Cents","default":0},"cap":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Cap"},"lane":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Lane"},"delivery_method":{"type":"string","title":"Delivery Method","default":"crm"},"connection_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Connection Id"},"floor_created_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Floor Created At"},"max_age_days":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Max Age Days"},"notify_empty":{"type":"boolean","title":"Notify Empty","default":true},"recipients":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Recipients"},"next_delivery_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Next Delivery At"},"last_run_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Last Run At"},"last_error":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Last Error"},"retry_after":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Retry After"},"manage_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Manage Url"},"created_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Created At"},"stripe_subscription_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Stripe Subscription Id"},"stripe_customer_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Stripe Customer Id"},"stripe_price_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Stripe Price Id"},"current_period_end":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Current Period End"},"last_delivery":{"anyOf":[{"$ref":"#/components/schemas/LastDelivery"},{"type":"null"}]},"health":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Health"},"cadence":{"type":"string","title":"Cadence"},"cap_cents_per_delivery":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Cap Cents Per Delivery"},"high_water_mark":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"High Water Mark"}},"type":"object","required":["subscription_id","name","status","customer_id","connection_id","last_run_at","created_at","cadence"],"title":"SubscriptionResponse"},"SubscriptionUpdate":{"properties":{"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name"},"schedule":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Schedule"},"pricing":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Pricing"},"billing_mode":{"anyOf":[{"type":"string","enum":["card","invoice","none"]},{"type":"null"}],"title":"Billing Mode"},"offer_code":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Offer Code"},"cap":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Cap"},"lane":{"anyOf":[{"type":"string","enum":["all","best","contact"]},{"type":"null"}],"title":"Lane"},"delivery_method":{"anyOf":[{"type":"string","enum":["file","crm"]},{"type":"null"}],"title":"Delivery Method"},"connection_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Connection Id"},"buyer_email":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Buyer Email"},"floor_created_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Floor Created At"},"status":{"anyOf":[{"type":"string","enum":["active","paused","canceled"]},{"type":"null"}],"title":"Status"},"customer_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Customer Id"},"billing_status":{"anyOf":[{"type":"string","enum":["none","active","past_due","canceled"]},{"type":"null"}],"title":"Billing Status"},"max_age_days":{"anyOf":[{"type":"integer","maximum":3650.0,"minimum":1.0},{"type":"null"}],"title":"Max Age Days"},"notify_empty":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Notify Empty"},"recipients":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Recipients"}},"additionalProperties":false,"type":"object","title":"SubscriptionUpdate"},"SummaryRequest":{"properties":{"states":{"items":{"type":"string"},"type":"array","title":"States"},"filters":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Filters"},"include_held":{"type":"boolean","title":"Include Held","default":false},"include_existing":{"type":"boolean","title":"Include Existing","description":"Widen past the Just-started default to existing businesses with a new filing (Browse's checkbox).","default":false},"lane":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Lane","description":"all | best | contact"},"cap":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Cap","description":"{\"type\": \"count\"|\"budget\", \"value\": int}"},"offer_code":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Offer Code"},"channel":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Channel","description":"phone | email — the one channel this buyer runs"},"group_by":{"items":{"type":"string"},"type":"array","title":"Group By","description":"Up to two fields to cross-tab the count by (e.g. [\"property_classification\", \"naics_2_digit\"]); adds a `groups` block with the four counts per group. Groupable fields are listed in the 422 for an unknown one."}},"additionalProperties":false,"type":"object","title":"SummaryRequest"},"TaxonomyProposalRequest":{"properties":{"agent_id":{"type":"string","title":"Agent Id","description":"Agent that authored the proposal"},"action":{"type":"string","title":"Action","description":"One of: ['add_keyword', 'add_sub', 'merge', 'split']"},"target":{"additionalProperties":true,"type":"object","title":"Target","description":"What the proposal is changing. Shape depends on action: {industry_id} for merge, {sector, name} for split/add_sub, {keyword, industry_id_or_industry_sub_id, tier} for add_keyword."},"evidence":{"additionalProperties":true,"type":"object","title":"Evidence","description":"Supporting data: corpus_frequency, sample_records, blast_radius (records newly classified / rebucketed / confidence-tier shifted), source_findings."},"title":{"type":"string","title":"Title","description":"One-line summary for the findings table"},"description":{"type":"string","title":"Description","description":"Full proposal narrative"},"state":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"State"},"session_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Session Id"}},"type":"object","required":["agent_id","action","target","evidence","title","description"],"title":"TaxonomyProposalRequest"},"TaxonomyProposalResponse":{"properties":{"finding_id":{"type":"string","title":"Finding Id"},"status":{"type":"string","title":"Status"}},"type":"object","required":["finding_id","status"],"title":"TaxonomyProposalResponse"},"TileConfigUpdate":{"properties":{"position":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Position"},"enabled":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Enabled"},"size":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Size"}},"type":"object","title":"TileConfigUpdate"},"TriggerRequest":{"properties":{"state":{"type":"string","title":"State","description":"Two-letter US state code (e.g. 'CO', 'FL', 'VA', 'NY'). Must be a live state.","examples":["CO"]},"stages":{"anyOf":[{"type":"string"},{"items":{"type":"string"},"type":"array"}],"title":"Stages","description":"Pipeline stages to run. Either 'all', a single stage name, a comma-separated list, or an array. Shortcut: 'enrich' = skip_trace + gapfill + validate. See GET /api/v1/pipeline/stages for the canonical stage order.","default":"all","examples":["score","enrich","pull,reload,normalize_addresses"]},"limit":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Limit","description":"Cap the number of records this run touches. Applied at scope-resolution time, so all stages operate on the same set.","examples":[100]},"batch_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Batch Id","description":"Run the pipeline on every entity in this batch (UUID). Mutually exclusive with `entity_id` and `filters`.","examples":["a1b2c3d4-e5f6-7890-abcd-ef1234567890"]},"entity_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Entity Id","description":"Scope the run to one or more specific records. Accepts a UUID, a GLID (e.g. 'GL-CO-00042'), or a comma/space/newline-separated list of either. Single ID → runs on that one record; multiple → resolves all, stamps a Batch, runs the pipeline scoped to that Batch. Mutually exclusive with `batch_id` and `filters`.","examples":["GL-CO-00042","GL-CO-00042, GL-CO-00043, GL-FL-00099"]},"filters":{"anyOf":[{"items":{"additionalProperties":true,"type":"object"},"type":"array"},{"type":"null"}],"title":"Filters","description":"Scope the run to records matching a filter expression. Same shape as POST /api/v1/leads/browse: [{field, op, value}]. Discover available fields and operators via GET /api/v1/schema/attributes. Mutually exclusive with `batch_id` and `entity_id`.","examples":[[{"field":"reachability_tier","op":"eq","value":"On Fire"}]]},"manifest_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Manifest Id","description":"Run the pipeline on the exact entity set of a previous run (UUID of a `run_manifest`). The natural recovery gesture after a failed or partial run: get the manifest id from GET /jobs/{id}/results and re-run any stages on precisely those entities. Mutually exclusive with `batch_id`, `entity_id`, and `filters`.","examples":["a1b2c3d4-e5f6-7890-abcd-ef1234567890"]},"start_date":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Start Date","description":"YYYY-MM-DD. For the PULL stage, the earliest filing date to fetch from the Secretary of State.","examples":["2026-05-01"]},"end_date":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"End Date","description":"YYYY-MM-DD. For the PULL stage, the latest filing date to fetch from the Secretary of State.","examples":["2026-05-18"]},"input_file":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Input File","description":"Source file for the PULL stage, for states whose feed is a portal download rather than an API (currently TX). Use the reference returned by POST /api/v1/pipeline/upload-bulk-file (an s3:// URI in production). Only valid when the run includes the `pull` stage.","examples":["s3://formation-gtm-artifacts-123-production/bulk-uploads/TX/CW060626_ab12cd34.txt"]},"pull_mode":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Pull Mode","description":"Alternate pull mode for harvest sweeps (trade_names, sole_props). trade_names stamps DBA attributes on existing entities (update-only, stages pull,reload only); sole_props mints the sole-proprietor inventory class (create-mode load + free brains); fact_backfill (FL) fills missing filing facts — the federal tax ID — on existing entities without moving batch, pulled date, name, status or filing event (stages pull,reload). Paid stages are always refused for harvest modes. Only valid for states with the mode's feed configured.","examples":["trade_names"]},"gapfill_force":{"type":"boolean","title":"Gapfill Force","description":"Gap-fill re-dips EVERY scoped record regardless of existing channels or prior Enformion delivery — a deliberate paid re-spend for vendor-quality evaluation. Requires the run to include the `gapfill` stage AND an explicit scope (`entity_id`, `batch_id`, `manifest_id`, or `filters`); refused on an unscoped whole-state run. Filer exclusion and 'hold' routing still apply.","default":false},"include_non_operating":{"type":"boolean","title":"Include Non Operating","description":"Only meaningful with `filters`. Browse hides non-operating entities (`enrichment_strategy = 'hold'` — shell LLCs, single-asset holdings) by default, so a filter set copied out of Browse resolves here the same way and the manifest matches the count the operator saw. Set true to include them, exactly as the Browse toggle does. An explicit `enrichment_strategy` or `lead_ref` filter bypasses the default either way.","default":false},"include_existing":{"type":"boolean","title":"Include Existing","description":"Only meaningful with `filters`. Browse holds Just started only — a brand-new business — and hides every existing business with a new filing (opening a location here, formed in another state, back in business, a new entity, moved, a new trade name), so a filter set copied out of Browse resolves here the same way. Set true to include them, exactly as the Browse checkbox does. An explicit `filing_kind`, `business_origin` or `lead_ref` filter bypasses the default either way.","default":false},"include_registrations":{"type":"boolean","title":"Include Registrations","description":"Deprecated alias of include_existing (kept one release so saved requests resolve).","default":false,"deprecated":true},"force_recompute":{"type":"boolean","title":"Force Recompute","description":"Only meaningful with `filters` scoping more than one record — `entity_id` and a single-match `filters` already always recompute (an operator who names records wants them re-answered). Bulk `filters` runs default to skip-if-current as the whole-sweep cost guard; set this to override that guard and force every SELECTED free stage to recompute even if its version is already current. Paid/metered stages (skip_trace, gapfill, validate) are exempt regardless — they own their own spend gates. The unblock for a backlog that was filter-scoped-processed under a stale ruleset and needs to re-run against today's classify rules without pasting thousands of individual entity_id values.","default":false},"days_back":{"anyOf":[{"type":"integer","minimum":1.0},{"type":"null"}],"title":"Days Back","description":"For the PULL stage: rolling window of N calendar days ago through today (the flag the sweep schedules use). Mutually exclusive with `start_date`/`end_date`.","examples":[10]},"options":{"anyOf":[{"additionalProperties":{"type":"boolean"},"type":"object"},{"type":"null"}],"title":"Options","description":"Per-run switches, flipped on THIS task only (a canary never needs a redeploy): `events_apply` — The events stage projects status / name / prior-entity onto records (ADR-061). On by default; false runs it dark. `linkage_stamp` — The family stage writes clusters into the container (ADR-060). On by default; false runs it dark. `founder_history_stamp` — The family stage also answers 'has this owner run a company before' against the state's whole book and stamps it on the record (Entrepreneur Layer, dark: no customer surface shows it). OFF by default until a production canary measures its runtime (it reads the whole state book); true runs it for one run. Booleans only. An unknown key is refused (422); a switch whose stage is not in the run is refused (400). Carried as the task's environment, so the run still goes through this endpoint and its manifest — never a raw task launch.","examples":[{"events_apply":true}]}},"additionalProperties":false,"type":"object","required":["state"],"title":"TriggerRequest","description":"Submit a pipeline run, optionally scoped to one record, a set of records,\na batch, or a filter expression. See `GET /api/v1/schema/attributes` for the\nfull list of fields that can appear in `filters`.","examples":[{"summary":"Run scoring on a single record by GLID","value":{"entity_id":"GL-CO-00042","stages":"score","state":"CO"}},{"summary":"Run enrichment on a paste of GLIDs","value":{"entity_id":"GL-CO-00042, GL-CO-00043, GL-CO-00044","stages":"enrich","state":"CO"}},{"summary":"Run scoring on every On-Fire lead missing a phone","value":{"filters":[{"field":"reachability_tier","op":"eq","value":"On Fire"},{"field":"has_phone","op":"eq","value":false}],"stages":"score","state":"VA"}}]},"TriggerResponse":{"properties":{"job_id":{"type":"string","title":"Job Id"},"status":{"type":"string","title":"Status"},"status_url":{"type":"string","title":"Status Url"},"task_arn":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Task Arn"}},"type":"object","required":["job_id","status","status_url"],"title":"TriggerResponse"},"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"},"VariantSpecRequest":{"properties":{"label":{"type":"string","title":"Label"},"description":{"type":"string","title":"Description"},"diff":{"additionalProperties":true,"type":"object","title":"Diff"}},"type":"object","required":["label","description","diff"],"title":"VariantSpecRequest"},"WakeRequest":{"properties":{"prompt":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Prompt"}},"type":"object","title":"WakeRequest","description":"Optional body for POST /wake. `prompt` becomes GM_SESSION_PROMPT on the\nsession task, overriding the agent's default session-type prompt."},"WikiPageCreate":{"properties":{"state":{"type":"string","title":"State"},"domain":{"type":"string","title":"Domain"},"title":{"type":"string","title":"Title"},"content_md":{"type":"string","title":"Content Md"},"source_finding_ids":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Source Finding Ids"},"contributors":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Contributors"}},"type":"object","required":["state","domain","title","content_md"],"title":"WikiPageCreate"},"WikiPageUpdate":{"properties":{"content_md":{"type":"string","title":"Content Md"},"source_finding_ids":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Source Finding Ids"}},"type":"object","required":["content_md"],"title":"WikiPageUpdate"},"backend__routers__admin_api_keys__RevokeRequest":{"properties":{"reason":{"type":"string","maxLength":500,"minLength":1,"title":"Reason"}},"additionalProperties":false,"type":"object","required":["reason"],"title":"RevokeRequest"},"backend__routers__commerce__RevokeRequest":{"properties":{"reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Reason"}},"type":"object","title":"RevokeRequest"}},"securitySchemes":{"APIKeyHeader":{"type":"apiKey","in":"header","name":"X-API-Key"}}}}