{"openapi":"3.1.0","info":{"title":"Tru8 Evidence Research API","description":"\nStructured evidence research for AI agents and developers.\n\nTru8 extracts claims from text or URLs, retrieves evidence from web search and specialist\nproviders (government data, academic databases, news, official records),\ndecomposes claims into verifiable elements, and maps evidence to elements\nwith relationship labels (**supports** / **challenges** / **context**).\n\nEvery source is classified by **tier** (primary, reporting, commentary) and\n**type** (data, official, news, analysis, opinion, academic). No hidden\ncuration — every exclusion has a receipt.\n\n## Authentication\n\n**API key** (recommended for agents and scripts):\n```\nX-API-Key: tru8_sk_your_key_here\n```\n\n**JWT** (dashboard sessions):\n```\nAuthorization: Bearer <clerk_jwt>\n```\n\nCreate and manage API keys at `POST /api/v1/api-keys` (requires JWT auth).\n\n**Security:** Store API keys in environment variables or a secrets manager.\nNever hardcode keys in source code, logs, or client-side bundles.\nIf a key is compromised, revoke it immediately via `DELETE /api/v1/api-keys/{id}`.\n\n## Workflows\n\n### Agents — submit, then poll\n```\nPOST /api/v1/agent/check?async=true   → 202 {checkId, pollUrl}\nGET  /api/v1/agent/result/{checkId}   → status until completed, then the result\n```\nAPI keys use the metered `/agent/*` endpoints. Poll every few seconds rather\nthan holding one connection: the edge closes a connection that stays silent\nfor ~125 s.\n\n### Synchronous — signed-in Console users\n```\nPOST /api/v1/checks/run\n```\nSingle HTTP call. Blocks until complete (60-120s, longer for URLs) and sends\nnothing until then, so a slow run can outlast the edge's ~125 s idle limit.\nURL inputs auto-select claims (top-ranked, up to 5).\n\n### Streaming — for dashboards\n1. **Submit** via `POST /api/v1/checks/stream` — returns SSE progress events\n2. **Monitor** via `GET /api/v1/checks/{id}/progress` (SSE) or poll `GET /api/v1/checks/{id}`\n3. **Select claims** (article mode): `PATCH /api/v1/checks/{id}/select-claims`\n\n### Agent Commerce — tiered access\nFor cost-sensitive agent workflows, use the `/agent/` endpoints:\n\n| Tier | Endpoint | Time | Cost | Description |\n|------|----------|------|------|-------------|\n| Lookup | `POST /agent/lookup` | Instant | £0.02 | Cached result lookup |\n| Consensus | via `/agent/check` | Instant | £0.03 | Cross-user consensus (k≥3) |\n| Quick | `POST /agent/quick` | ~15s | £0.07 | Reduced pipeline, heuristic classification |\n| Full | `POST /agent/full` | ~90s | £0.15 | Complete pipeline, web + specialist APIs |\n| Smart | `POST /agent/check` | Varies | Varies | Automatic fallback: lookup → consensus → quick → full |\n\nPayment via prepaid credits, Skyfire JWT, or x402 (USDC/SIWE).\n\n## Response Structure\n\nEvery completed check returns:\n- **claims[]** — extracted claims with type and position\n- **claims[].claimMap** — elements, evidence refs, orientation line\n- **claims[].evidence[]** — sources with URL, snippet, tier, type, relevance\n- **_meta** (agent endpoints) — tier executed, cost, landscape metrics\n- **_manifest** (agent endpoints) — HMAC-signed manifest; verify the signed fields haven't changed since signing via `GET /verify/{id}`\n\n## Rate Limits\n\n| Endpoint | Limit |\n|----------|-------|\n| Default | 60 requests/minute |\n| Check creation | 10/minute |\n| Lookup | 30/minute |\n| Credits balance | 60/minute |\n","version":"1.0.0"},"paths":{"/api/v1/health/":{"get":{"tags":["health"],"summary":"Health Check","description":"Liveness, plus WHICH COMMIT is answering.\n\n`version` is a static string and always has been; it says nothing about the\ndeployed code. The commit fields are the ones that let you tell \"the fix is\nnot deployed\" from \"the fix is deployed and did not fire\" — a distinction\nthat cost 30p and an hour on 2026-08-05 for want of exactly this.\n`commit_source` is reported so a caller can see whether the value came from\nthe platform or from a local working tree; `unknown` means we could not\nestablish it, and is never filled with a placeholder.","operationId":"health_check_api_v1_health__get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/v1/health/ready":{"get":{"tags":["health"],"summary":"Readiness Check","operationId":"readiness_check_api_v1_health_ready_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/v1/health/cache-metrics":{"get":{"tags":["health"],"summary":"Get Cache Metrics","description":"Get API cache hit/miss statistics.\n\nWeek 4 - Government API Integration: Monitor cache performance to ensure 60%+ hit rate target.\n\nArgs:\n    api_name: Optional - filter metrics for specific API adapter\n\nReturns:\n    Cache metrics including hit rate percentage","operationId":"get_cache_metrics_api_v1_health_cache_metrics_get","parameters":[{"name":"api_name","in":"query","required":false,"schema":{"type":"string","description":"Optional: Get metrics for specific API","title":"Api Name"},"description":"Optional: Get metrics for specific API"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/health/circuit-breakers":{"get":{"tags":["health"],"summary":"Get Circuit Breakers","description":"Get circuit breaker states for API adapters.\n\nWeek 4 - Government API Integration: Monitor API health and circuit breaker status.\n\nArgs:\n    api_name: Optional - filter for specific API adapter\n\nReturns:\n    Circuit breaker states","operationId":"get_circuit_breakers_api_v1_health_circuit_breakers_get","parameters":[{"name":"api_name","in":"query","required":false,"schema":{"type":"string","description":"Optional: Get state for specific API","title":"Api Name"},"description":"Optional: Get state for specific API"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/health/email-config":{"get":{"tags":["health"],"summary":"Check Email Config","description":"Diagnostic endpoint to check email notification configuration.","operationId":"check_email_config_api_v1_health_email_config_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/v1/auth/me":{"get":{"tags":["auth"],"summary":"Get Me","description":"Get current user profile with credits","operationId":"get_me_api_v1_auth_me_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/auth/refresh":{"post":{"tags":["auth"],"summary":"Refresh Token","description":"Validate and return user info (token refresh)","operationId":"refresh_token_api_v1_auth_refresh_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/users/profile":{"get":{"tags":["users"],"summary":"Get Profile","description":"Get user profile with usage stats","operationId":"get_profile_api_v1_users_profile_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}},"security":[{"HTTPBearer":[]}]},"patch":{"tags":["users"],"summary":"Update Profile","description":"Update user profile (name, etc.)","operationId":"update_profile_api_v1_users_profile_patch","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProfileUpdateRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/users/stats":{"get":{"tags":["users"],"summary":"Get User Stats","description":"Get aggregated user statistics for dashboard insights","operationId":"get_user_stats_api_v1_users_stats_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/users/usage":{"get":{"tags":["users"],"summary":"Get Usage","description":"Get detailed usage statistics","operationId":"get_usage_api_v1_users_usage_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/users/agent-credits":{"get":{"tags":["users"],"summary":"Get Agent Credit Balance","description":"Prepaid agent API credit balance for the logged-in dashboard user.","operationId":"get_agent_credit_balance_api_v1_users_agent_credits_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/users/agent-credits/purchase":{"post":{"tags":["users"],"summary":"Purchase Agent Credits","description":"Stripe Checkout for an agent credit pack, from the dashboard.\n\nSame packs, price IDs and webhook fulfilment as POST /agent/credits/purchase;\nonly the auth (Clerk) and the success/cancel redirects (settings Developer\ntab) differ.","operationId":"purchase_agent_credits_api_v1_users_agent_credits_purchase_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentCreditPurchaseRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/users/signup-source":{"post":{"tags":["users"],"summary":"Record Signup Source","description":"Record WHY this account was created — the ?src= tag the visitor arrived\nwith (audit/OUTREACH.md). Write-once and time-boxed:\n\n- the tag only lands while ``signup_source`` is NULL (conditional UPDATE,\n  the same exactly-once shape as the lifecycle-email markers), and\n- only within the attribution window after account creation, so an old\n  account cannot be re-attributed by a later tagged visit.\n\nRefusals are 200s with ``recorded: false`` — a rejected tag simply leaves\nthe user UNKNOWN, and the frontend must not retry forever on an error.","operationId":"record_signup_source_api_v1_users_signup_source_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SignupSourceRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/users/heard-about":{"post":{"tags":["users"],"summary":"Record Heard About","description":"Record the self-reported \"How did you hear about us?\" (2026-10-01).\n\nWrite-once, like signup-source: a conditional UPDATE lands only while\n``heard_about`` is NULL, and \"skipped\" counts as an answer so the question\nis never asked twice. Refusals are 200s with ``recorded: false``.","operationId":"record_heard_about_api_v1_users_heard_about_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HeardAboutRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/users/push-token":{"post":{"tags":["users"],"summary":"Register Push Token","description":"Register a push token for the current user","operationId":"register_push_token_api_v1_users_push_token_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PushTokenRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]},"delete":{"tags":["users"],"summary":"Unregister Push Token","description":"Unregister push token for the current user","operationId":"unregister_push_token_api_v1_users_push_token_delete","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/users/notification-preferences":{"get":{"tags":["users"],"summary":"Get Notification Preferences","description":"Get user's push notification preferences","operationId":"get_notification_preferences_api_v1_users_notification_preferences_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}},"security":[{"HTTPBearer":[]}]},"put":{"tags":["users"],"summary":"Update Notification Preferences","description":"Update user's push notification preferences","operationId":"update_notification_preferences_api_v1_users_notification_preferences_put","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotificationPreferencesRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/users/me":{"delete":{"tags":["users"],"summary":"Delete User Account","description":"Delete user account and all associated data\n\nThis endpoint:\n- Deletes all checks, claims, and evidence (via CASCADE)\n- Cancels active Stripe subscriptions\n- Deletes all subscription records\n- Deletes the user record\n\nThis action is permanent and cannot be undone.\nFrontend must also delete the Clerk user separately.","operationId":"delete_user_account_api_v1_users_me_delete","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/users/email-preferences":{"get":{"tags":["users"],"summary":"Get Email Preferences","description":"Get user's email notification preferences","operationId":"get_email_preferences_api_v1_users_email_preferences_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}},"security":[{"HTTPBearer":[]}]},"put":{"tags":["users"],"summary":"Update Email Preferences","description":"Update user's email notification preferences","operationId":"update_email_preferences_api_v1_users_email_preferences_put","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailPreferencesRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/users/export":{"get":{"tags":["users"],"summary":"Export User Data","description":"Export all user data (GDPR Article 20 - Right to data portability).\n\nReturns a JSON file containing:\n- User profile information\n- All fact-checks performed\n- All claims extracted\n- All evidence gathered\n- Subscription history\n- Notification preferences\n\nRate limited to 3 requests per hour to prevent abuse.","operationId":"export_user_data_api_v1_users_export_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/checks/upload":{"post":{"tags":["checks"],"summary":"Upload File","description":"Upload a file for fact-checking (images only)","operationId":"upload_file_api_v1_checks_upload_post","requestBody":{"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_upload_file_api_v1_checks_upload_post"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/checks/stream":{"post":{"tags":["checks"],"summary":"Submit content for evidence research (SSE stream)","description":"Submit a URL or text for evidence research. Returns an SSE stream of\npipeline progress events.\n\n**Input types:** `url` (article analysis), `text` (direct claim or question).\n\nDeep Research pipeline: extract claims → retrieve evidence → decompose\ninto elements → map evidence with relationship labels (typically 60-120s).\n\n**SSE events emitted:**\n- `progress` — stage name, percentage, time estimate\n- `awaiting_selection` — article mode: claims extracted, awaiting user selection\n- `completed` — pipeline finished, check ID in payload\n- `error` — pipeline failed\n\nFor URL inputs with multiple claims, the pipeline pauses after extraction.\nCall `PATCH /checks/{id}/select-claims` to resume with chosen claims.\n\n**Rate limit:** 10/minute","operationId":"create_check_streaming_api_v1_checks_stream_post","parameters":[{"name":"token","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateCheckRequest"}}}},"responses":{"200":{"description":"Server-Sent Events stream of pipeline progress. Content-Type: text/event-stream","content":{"application/json":{"schema":{}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"402":{"description":"Monthly credit limit reached","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreditLimitError"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/checks/run":{"post":{"tags":["checks"],"summary":"Synchronous evidence research","description":"Synchronous evidence research — single HTTP call, blocks until complete.\n\nRecommended for agents and scripts. Submit a claim or URL, wait 60-120s,\nreceive the full result with claims, elements, evidence, and analytics.\nNo SSE, no polling, no claim selection required.\n\nFor URL/article inputs, claims are auto-selected (top-ranked, up to 5).\n\nSends nothing until the run finishes, and the edge closes a connection\nsilent for ~125 s, so a slow run (URL inputs especially) can be cut off\nwhile it completes. Agents: use `/agent/check?async=true` and poll.\n\n**Rate limit:** 10/minute","operationId":"create_check_sync_api_v1_checks_run_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateCheckRequest"}}},"required":true},"responses":{"200":{"description":"Complete evidence landscape with claims, elements, and evidence","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CheckResponse"}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"402":{"description":"Monthly credit limit reached","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreditLimitError"}}}},"504":{"description":"Pipeline timed out (>180s)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TimeoutErrorResponse"}}}},"502":{"description":"Pipeline error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PipelineErrorResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/checks":{"get":{"tags":["checks"],"summary":"List checks","description":"List the authenticated user's checks, newest first.\n\nReturns check metadata (ID, status, input type, claim count, timestamps)\nwith a preview of the first claim. Use `GET /checks/{id}` for full\nclaim and evidence data.","operationId":"get_checks_api_v1_checks_get","parameters":[{"name":"skip","in":"query","required":false,"schema":{"type":"integer","default":0,"title":"Skip"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","default":20,"title":"Limit"}}],"responses":{"200":{"description":"Paginated list of checks, newest first","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CheckListResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/checks/{check_id}":{"get":{"tags":["checks"],"summary":"Get check with full evidence","description":"Retrieve a completed check with all claims, elements, evidence, and claim maps.\n\n**Response includes:**\n- `claims[]` — extracted claims with type, position, element count\n- `claims[].claimMap` — elements, evidence refs, orientation line\n- `claims[].evidence[]` — sources with URL, snippet, tier, type, relevance\n- Check metadata: status, input URL, processing time, stage timings\n\n**Query params:**\n- `computed=true` — append `_computed` block with pre-computed analytics\n  (tier/type distributions, corroboration groups, diagnostic values, timeline,\n  element state summaries, per-claim dispositions). Designed for agent consumers\n  who need structured analytics without client-side computation.\n\nReturns 404 if the check doesn't exist or doesn't belong to the authenticated user.","operationId":"get_check_api_v1_checks__check_id__get","parameters":[{"name":"check_id","in":"path","required":true,"schema":{"type":"string","title":"Check Id"}},{"name":"computed","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"Computed"}}],"responses":{"200":{"description":"Full check with claims, evidence, and claim maps","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CheckResponse"}}}},"404":{"description":"Check not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/checks/{check_id}/select-claims":{"patch":{"tags":["checks"],"summary":"Select claims for analysis","description":"Select claims for full analysis (article mode only).\n\nWhen a URL/article check pauses with status `waiting_for_selection`,\ncall this endpoint with the positions of claims to investigate.\nTriggers Phase 2: evidence retrieval, decomposition, and mapping.\n\n**Request body:** `{\"selected_positions\": [0, 2, 4]}`\n\nMax 5 claims per check. The check resumes streaming progress via\n`GET /checks/{id}/progress`.","operationId":"select_claims_api_v1_checks__check_id__select_claims_patch","parameters":[{"name":"check_id","in":"path","required":true,"schema":{"type":"string","title":"Check Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SelectClaimsRequest"}}}},"responses":{"200":{"description":"Selection accepted — Phase 2 pipeline resumed via SSE","content":{"application/json":{"schema":{}}}},"400":{"description":"Invalid selection or too many claims","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Check not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Check is not in waiting_for_selection state","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/checks/{check_id}/claims/{claim_id}/elements/{element_id}/bounty":{"patch":{"tags":["checks"],"summary":"Update element bounty text","description":"Update bounty text on a specific claim element (Seeker feature).\n\nBounty text signals what evidence would help resolve an unresolved element.\nSet to null to clear.","operationId":"update_bounty_text_api_v1_checks__check_id__claims__claim_id__elements__element_id__bounty_patch","parameters":[{"name":"check_id","in":"path","required":true,"schema":{"type":"string","title":"Check Id"}},{"name":"claim_id","in":"path","required":true,"schema":{"type":"string","title":"Claim Id"}},{"name":"element_id","in":"path","required":true,"schema":{"type":"string","title":"Element Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateBountyRequest"}}}},"responses":{"200":{"description":"Bounty text updated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BountyUpdateResponse"}}}},"400":{"description":"Text exceeds 200 character limit","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Check, claim, or element not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Check is not completed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/checks/{check_id}/claims/{claim_id}/research-gaps":{"post":{"tags":["checks"],"summary":"Research all gap elements as one operation","operationId":"start_gap_research_api_v1_checks__check_id__claims__claim_id__research_gaps_post","parameters":[{"name":"check_id","in":"path","required":true,"schema":{"type":"string","title":"Check Id"}},{"name":"claim_id","in":"path","required":true,"schema":{"type":"string","title":"Claim Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/checks/{check_id}/claims/{claim_id}/research-thin":{"post":{"tags":["checks"],"summary":"Strengthen thin elements as one operation","operationId":"start_thin_research_api_v1_checks__check_id__claims__claim_id__research_thin_post","parameters":[{"name":"check_id","in":"path","required":true,"schema":{"type":"string","title":"Check Id"}},{"name":"claim_id","in":"path","required":true,"schema":{"type":"string","title":"Claim Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/checks/{check_id}/claims/{claim_id}/elements/{element_id}/research":{"post":{"tags":["checks"],"summary":"Research an element","operationId":"start_element_research_api_v1_checks__check_id__claims__claim_id__elements__element_id__research_post","parameters":[{"name":"check_id","in":"path","required":true,"schema":{"type":"string","title":"Check Id"}},{"name":"claim_id","in":"path","required":true,"schema":{"type":"string","title":"Claim Id"}},{"name":"element_id","in":"path","required":true,"schema":{"type":"string","title":"Element Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/checks/{check_id}/claims/{claim_id}/elements/{element_id}/research/status":{"get":{"tags":["checks"],"summary":"Get durable research status","operationId":"get_element_research_status_api_v1_checks__check_id__claims__claim_id__elements__element_id__research_status_get","parameters":[{"name":"check_id","in":"path","required":true,"schema":{"type":"string","title":"Check Id"}},{"name":"claim_id","in":"path","required":true,"schema":{"type":"string","title":"Claim Id"}},{"name":"element_id","in":"path","required":true,"schema":{"type":"string","title":"Element Id"}},{"name":"operation_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Operation Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/checks/{check_id}/revisions":{"get":{"tags":["checks"],"summary":"List retained report revisions","operationId":"list_report_revisions_api_v1_checks__check_id__revisions_get","parameters":[{"name":"check_id","in":"path","required":true,"schema":{"type":"string","title":"Check Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/checks/{check_id}/revisions/{revision_id}":{"get":{"tags":["checks"],"summary":"Read a retained report revision","operationId":"get_report_revision_api_v1_checks__check_id__revisions__revision_id__get","parameters":[{"name":"check_id","in":"path","required":true,"schema":{"type":"string","title":"Check Id"}},{"name":"revision_id","in":"path","required":true,"schema":{"type":"string","title":"Revision Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/checks/{check_id}/claims/{claim_id}/explore":{"get":{"tags":["checks"],"summary":"Get related claims for Seeker explore mode","description":"Surface related claims investigated by other users.\n\nUsed by the Seeker view when no evidence gaps remain. Returns normalised\nclaim text + element descriptions from related checks. Privacy-safe:\nno user IDs, no check IDs, no individual evidence items.\n\nRelatedness is determined by shared key_entities (preferred) with\nsubject_context fallback.","operationId":"get_explore_data_api_v1_checks__check_id__claims__claim_id__explore_get","parameters":[{"name":"check_id","in":"path","required":true,"schema":{"type":"string","title":"Check Id"}},{"name":"claim_id","in":"path","required":true,"schema":{"type":"string","title":"Claim Id"}}],"responses":{"200":{"description":"Related claims from other users","content":{"application/json":{"schema":{}}}},"404":{"description":"Check or claim not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/checks/{check_id}/sse-token":{"post":{"tags":["checks"],"summary":"Generate short-lived SSE stream token","description":"Generate a short-lived, check-scoped token for SSE progress streaming.\n\nUse this token as `?token=<token>` in the `GET /progress` EventSource URL\ninstead of passing the full JWT in the query string.\n\nToken is valid for 5 minutes and scoped to the specified check ID.","operationId":"create_sse_token_api_v1_checks__check_id__sse_token_post","parameters":[{"name":"check_id","in":"path","required":true,"schema":{"type":"string","title":"Check Id"}}],"responses":{"200":{"description":"SSE stream token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SSETokenResponse"}}}},"404":{"description":"Check not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/checks/{check_id}/progress":{"get":{"tags":["checks"],"summary":"Stream pipeline progress (SSE)","description":"Stream real-time pipeline progress via Server-Sent Events.\n\n**SSE events:** `progress` (stage/percent), `awaiting_selection`,\n`completed`, `error`. Connection auto-closes on completion or after 5 min timeout.\n\n**Auth:** Accepts `X-API-Key` header or `?token=<jwt>` query param\n(EventSource can't set headers).","operationId":"stream_check_progress_api_v1_checks__check_id__progress_get","parameters":[{"name":"check_id","in":"path","required":true,"schema":{"type":"string","title":"Check Id"}},{"name":"token","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"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/checks/{check_id}/export/pdf":{"get":{"tags":["checks"],"summary":"Export check as PDF","description":"Export fact-check as PDF report","operationId":"export_check_pdf_api_v1_checks__check_id__export_pdf_get","parameters":[{"name":"check_id","in":"path","required":true,"schema":{"type":"string","title":"Check Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/checks/public/{check_id}/export/pdf":{"get":{"tags":["checks"],"summary":"Export public check as PDF (no auth)","description":"Export a completed check as PDF. Public, no auth.\n\nMirrors GET /public/{check_id}: any completed check is publicly viewable by\nid (no user verification). The PDF template never renders the raw input\nprompt (F-SEC-06).","operationId":"export_public_check_pdf_api_v1_checks_public__check_id__export_pdf_get","parameters":[{"name":"check_id","in":"path","required":true,"schema":{"type":"string","title":"Check Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/checks/{check_id}/sources":{"get":{"tags":["checks"],"summary":"Get all reviewed sources","description":"Get all sources reviewed during evidence research (Pro feature).\n\nReturns every source the pipeline considered, including those excluded\nby filtering. Each excluded source shows which pipeline stage removed it\nand why — full transparency into the curation process.\n\n**Query params:**\n- `include_filtered` — include filtered-out sources (default: true)\n- `sort_by` — sort order: 'relevance' or 'date'","operationId":"get_check_sources_api_v1_checks__check_id__sources_get","parameters":[{"name":"check_id","in":"path","required":true,"schema":{"type":"string","title":"Check Id"}},{"name":"include_filtered","in":"query","required":false,"schema":{"type":"boolean","default":true,"title":"Include Filtered"}},{"name":"sort_by","in":"query","required":false,"schema":{"type":"string","default":"relevance","title":"Sort By"}}],"responses":{"200":{"description":"All sources reviewed with filter breakdown (Pro feature)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SourcesResponse"}}}},"403":{"description":"Pro subscription required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Check not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/checks/{check_id}/videos":{"get":{"tags":["checks"],"summary":"Get video recommendations","description":"Get YouTube video recommendations for a check or specific claim.\n\nVideos are retrieved during the pipeline from YouTube Data API and\nclassified with tier/type labels.\n\n**Query params:**\n- `claim_id` — filter to videos for a specific claim","operationId":"get_check_videos_api_v1_checks__check_id__videos_get","parameters":[{"name":"check_id","in":"path","required":true,"schema":{"type":"string","title":"Check Id"}},{"name":"claim_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Claim Id"}}],"responses":{"200":{"description":"Video recommendations","content":{"application/json":{"schema":{"$ref":"#/components/schemas/VideosResponse"}}}},"404":{"description":"Check not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Not authorised","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/checks/{check_id}/videos/recover":{"post":{"tags":["checks"],"summary":"Recover missing video recommendations","description":"Owner-only, idempotent on-demand recovery for videos that the\nfire-and-forget generation task lost (e.g. an API restart during its short\nwindow). Returns existing videos untouched if any exist; otherwise\ngenerates them durably (awaited, in-request, so it survives) for a\ncompleted check and returns them.","operationId":"recover_check_videos_api_v1_checks__check_id__videos_recover_post","parameters":[{"name":"check_id","in":"path","required":true,"schema":{"type":"string","title":"Check Id"}}],"responses":{"200":{"description":"Video recommendations","content":{"application/json":{"schema":{"$ref":"#/components/schemas/VideosResponse"}}}},"404":{"description":"Check not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Not authorised","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/checks/public/{check_id}":{"get":{"tags":["checks"],"summary":"Get public check data (no auth)","description":"Get public check data. No authentication required.\n\n**Query params:**\n- `detailed=false` (default) — minimal data for OG card generation\n- `detailed=true` — full check data for the public report page,\n  including claims, evidence, and video recommendations\n\nOnly returns completed checks.","operationId":"get_public_check_api_v1_checks_public__check_id__get","parameters":[{"name":"check_id","in":"path","required":true,"schema":{"type":"string","title":"Check Id"}},{"name":"detailed","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"Detailed"}}],"responses":{"200":{"description":"Public check data (minimal or detailed)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicCheckMinimal"}}}},"404":{"description":"Check not found or not completed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/checks/public/{check_id}/videos":{"get":{"tags":["checks"],"summary":"Get video recommendations (public, no auth)","description":"Public video recommendations for a check.\n\nMirrors the authenticated `/{check_id}/videos` endpoint without the\nownership gate — public reports already expose the full check (claims,\nevidence, videos) by id, and videos are public YouTube links (no PII).\nLets the public report re-poll for videos that the fire-and-forget task\nwrites ~1s after the check completes (after the cached page first renders).","operationId":"get_public_check_videos_api_v1_checks_public__check_id__videos_get","parameters":[{"name":"check_id","in":"path","required":true,"schema":{"type":"string","title":"Check Id"}},{"name":"claim_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Claim Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/checks/{check_id}/sources/export":{"get":{"tags":["checks"],"summary":"Export sources as CSV/BibTeX/APA","description":"Export sources as CSV, BibTeX, or APA format (Pro feature).\n\nQuery params:\n- format: Export format - csv, bibtex, or apa\n- include_filtered: Include filtered sources (default: false)","operationId":"export_check_sources_api_v1_checks__check_id__sources_export_get","parameters":[{"name":"check_id","in":"path","required":true,"schema":{"type":"string","title":"Check Id"}},{"name":"format","in":"query","required":false,"schema":{"type":"string","default":"csv","title":"Format"}},{"name":"include_filtered","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"Include Filtered"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/checks/{check_id}/claims/{claim_id}/comparisons":{"post":{"tags":["comparisons"],"summary":"Compare two sources on this claim (dashboard only)","operationId":"create_comparison_api_v1_checks__check_id__claims__claim_id__comparisons_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"check_id","in":"path","required":true,"schema":{"type":"string","title":"Check Id"}},{"name":"claim_id","in":"path","required":true,"schema":{"type":"string","title":"Claim Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateComparisonRequest"}}}},"responses":{"200":{"description":"Comparison (fresh or cached)","content":{"application/json":{"schema":{}}}},"404":{"description":"Check or claim not found"},"409":{"description":"Comparison budget exhausted"},"422":{"description":"Invalid pair"},"502":{"description":"Fetch or model failure — not charged"}}},"get":{"tags":["comparisons"],"summary":"List comparisons for a claim (dashboard)","operationId":"list_comparisons_api_v1_checks__check_id__claims__claim_id__comparisons_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"check_id","in":"path","required":true,"schema":{"type":"string","title":"Check Id"}},{"name":"claim_id","in":"path","required":true,"schema":{"type":"string","title":"Claim Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/checks/public/{check_id}/claims/{claim_id}/comparisons":{"get":{"tags":["comparisons"],"summary":"List comparisons for a claim (public report, read-only)","description":"The /r/ page: stored comparisons only, completed checks only, no\nauth, no budget, no create.","operationId":"list_comparisons_public_api_v1_checks_public__check_id__claims__claim_id__comparisons_get","parameters":[{"name":"check_id","in":"path","required":true,"schema":{"type":"string","title":"Check Id"}},{"name":"claim_id","in":"path","required":true,"schema":{"type":"string","title":"Claim Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/payments/create-checkout-session":{"post":{"tags":["payments"],"summary":"Create Checkout Session","description":"Create a Stripe Checkout session for subscription upgrade","operationId":"create_checkout_session_api_v1_payments_create_checkout_session_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateCheckoutRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/payments/webhook":{"post":{"tags":["payments"],"summary":"Stripe Webhook","description":"Handle Stripe webhook events","operationId":"stripe_webhook_api_v1_payments_webhook_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/v1/payments/subscription-status":{"get":{"tags":["payments"],"summary":"Get Subscription Status","description":"Get current user's subscription status","operationId":"get_subscription_status_api_v1_payments_subscription_status_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/payments/cancel-subscription":{"post":{"tags":["payments"],"summary":"Cancel Subscription","description":"Cancel user's subscription","operationId":"cancel_subscription_api_v1_payments_cancel_subscription_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/payments/create-portal-session":{"post":{"tags":["payments"],"summary":"Create Billing Portal Session","description":"Create a Stripe billing portal session\n\nAllows users to:\n- View billing history\n- Download invoices\n- Update payment method\n- Cancel subscription","operationId":"create_billing_portal_session_api_v1_payments_create_portal_session_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/payments/reactivate-subscription":{"post":{"tags":["payments"],"summary":"Reactivate Subscription","description":"Reactivate a subscription that was scheduled for cancellation\n\nRemoves the cancel_at_period_end flag from the Stripe subscription,\nallowing it to continue renewing after the current period ends.","operationId":"reactivate_subscription_api_v1_payments_reactivate_subscription_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/feedback":{"post":{"tags":["feedback"],"summary":"Submit Feedback","description":"Submit user feedback during beta testing period.\nSends email notification to admin with feedback details.","operationId":"submit_feedback_api_v1_feedback_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FeedbackRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FeedbackResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/waitlist":{"post":{"tags":["feedback"],"summary":"Join Waitlist","description":"Public endpoint for Pro subscription waitlist signup.\nDoes not require authentication - anyone can join the waitlist.","operationId":"join_waitlist_api_v1_waitlist_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WaitlistRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FeedbackResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/api-keys":{"get":{"tags":["api-keys"],"summary":"List Api Keys","description":"List all API keys for the current user. Raw keys are never returned.","operationId":"list_api_keys_api_v1_api_keys_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/APIKeyListResponse"}}}}},"security":[{"HTTPBearer":[]}]},"post":{"tags":["api-keys"],"summary":"Create Api Key","description":"Create a new API key. The raw key is returned in the response body\nexactly once — store it securely. It cannot be retrieved later.","operationId":"create_api_key_api_v1_api_keys_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateAPIKeyRequest"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/APIKeyCreatedResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/api-keys/{key_id}":{"delete":{"tags":["api-keys"],"summary":"Revoke Api Key","description":"Revoke an API key. The key immediately stops working.","operationId":"revoke_api_key_api_v1_api_keys__key_id__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"key_id","in":"path","required":true,"schema":{"type":"string","title":"Key Id"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/webhooks":{"get":{"tags":["webhooks"],"summary":"List Webhooks","description":"List all webhooks. Secrets are never returned after creation.","operationId":"list_webhooks_api_v1_webhooks_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookListResponse"}}}}}},"post":{"tags":["webhooks"],"summary":"Create Webhook","description":"Register a webhook URL. The signing secret is returned once — store it\nto verify `X-Tru8-Signature` headers on incoming payloads.","operationId":"create_webhook_api_v1_webhooks_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateWebhookRequest"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookCreatedResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/webhooks/{webhook_id}":{"delete":{"tags":["webhooks"],"summary":"Delete Webhook","description":"Delete a webhook. It immediately stops receiving events.","operationId":"delete_webhook_api_v1_webhooks__webhook_id__delete","parameters":[{"name":"webhook_id","in":"path","required":true,"schema":{"type":"string","title":"Webhook Id"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/agent/check":{"post":{"tags":["agent"],"summary":"Smart evidence research with automatic tier fallback","description":"Smart endpoint with automatic tier fallback — recommended for most agent use cases.\n\nTries cached lookup first (instant, £0.02). On cache miss, escalates through\nconsensus → quick → full up to the tier specified by `max_tier`.\nYou're only charged for the tier actually executed.\n\n**Fallback chain:** lookup → consensus → quick → full\n\nSet `?async=true` to get a 202 with a `pollUrl` when the pipeline has to\nrun, instead of one silent connection for the whole run (proxies close a\nconnection idle for ~125 s). Cache and consensus hits still answer at once.\n\n**Response headers:** `X-Check-Id`, `X-Tru8-Tx-Id`\n\n**Rate limit:** 10/minute","operationId":"agent_smart_check_api_v1_agent_check_post","parameters":[{"name":"async","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"Async"}},{"name":"Idempotency-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Idempotency-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SmartCheckRequest"}}}},"responses":{"200":{"description":"Evidence landscape returned (check `_meta.executedTier` for which tier was used, `hit` for cache status)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentCheckResponse"}}}},"202":{"description":"Accepted with `?async=true`: {checkId, status, tier, chargedPence, txId, pollUrl}. Poll `pollUrl` (GET /agent/result/{checkId})."},"402":{"description":"Insufficient credits or payment required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"504":{"description":"Pipeline timed out — no charge applied","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TimeoutErrorResponse"}}}},"502":{"description":"Pipeline error — charge refunded if applicable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PipelineErrorResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/agent/lookup":{"post":{"tags":["agent"],"summary":"Instant cached lookup","description":"Instant cached analysis — £0.02 per hit, no charge on miss.\n\nSearches for a previous analysis of this claim (scoped to your account).\nReturns 200 in both cases — check the `hit` field to distinguish.\n\n**Cache hit:** Full evidence landscape with `hit: true`.\n**Cache miss:** `{hit: false, nextSuggestedTier, upgradeCostPence}`.\n\n**Response headers (hit only):** `X-Check-Id`, `X-Tru8-Tx-Id`\n\n**Rate limit:** 30/minute","operationId":"agent_lookup_api_v1_agent_lookup_post","parameters":[{"name":"Idempotency-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Idempotency-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentClaimRequest"}}}},"responses":{"200":{"description":"Cache hit (full response with `hit: true`) or cache miss (structured miss with `hit: false`). Both return 200.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentCheckResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/agent/result/{check_id}":{"get":{"tags":["agent"],"summary":"Retrieve a completed check result (no charge)","description":"Retrieve a completed check result without re-paying.\n\nUse this for lost responses, retries, and client reconnection.\nOnly returns checks that belong to the authenticated agent.\n\n**Rate limit:** 30/minute","operationId":"get_agent_result_api_v1_agent_result__check_id__get","parameters":[{"name":"check_id","in":"path","required":true,"schema":{"type":"string","title":"Check Id"}},{"name":"compact","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"Compact"}}],"responses":{"200":{"description":"Full evidence landscape when completed; otherwise {checkId, status, hit: false} while the pipeline runs","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentCheckResponse"}}}},"404":{"description":"Check not found or not owned by this agent","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/agent/quick":{"post":{"tags":["agent"],"summary":"Quick evidence research (~15s)","description":"Reduced pipeline — fewer sources, heuristic classification. ~15 seconds, £0.07.\n\nSkips: fact-check lookup, government/academic API adapters, LLM relevance\nscoring, coverage recovery, and query answering. Uses heuristic tier/type\nclassification instead of LLM.\n\nCheck `_meta.limitations` in the response for the full list of skipped stages.\n\nSet `?async=true` to receive a 202 Accepted immediately and poll\n`/agent/result/{checkId}` for the completed result.\n\n**Response headers:** `X-Check-Id`, `X-Tru8-Tx-Id`\n\n**Rate limit:** 10/minute","operationId":"agent_quick_api_v1_agent_quick_post","parameters":[{"name":"async","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"Async"}},{"name":"Idempotency-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Idempotency-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentClaimRequest"}}}},"responses":{"200":{"description":"Evidence landscape (quick tier)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentCheckResponse"}}}},"202":{"description":"Accepted with `?async=true`: {checkId, status, tier, chargedPence, txId, pollUrl}. Poll `pollUrl` (GET /agent/result/{checkId})."},"402":{"description":"Insufficient credits or payment required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"504":{"description":"Pipeline timed out — no charge applied","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TimeoutErrorResponse"}}}},"502":{"description":"Pipeline error — charge refunded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PipelineErrorResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/agent/full":{"post":{"tags":["agent"],"summary":"Full evidence research (~60-90s)","description":"Complete evidence research pipeline — web + specialist APIs, all stages. ~50-70 seconds, £0.15.\n\nRuns the full pipeline: fact-check lookup, web search and specialist providers (government,\nacademic, news, data APIs), LLM classification, coverage recovery, and\nquery answering.\n\nPrefer `?async=true`: a 202 Accepted arrives immediately and you poll\n`/agent/result/{checkId}` for the completed result. A synchronous call holds\none silent connection for the whole run, and proxies close a connection\nidle for ~125 s.\n\n**Response headers:** `X-Check-Id`, `X-Tru8-Tx-Id`\n\n**Rate limit:** 5/minute","operationId":"agent_full_api_v1_agent_full_post","parameters":[{"name":"async","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"Async"}},{"name":"Idempotency-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Idempotency-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentClaimRequest"}}}},"responses":{"200":{"description":"Complete evidence landscape (full tier)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentCheckResponse"}}}},"202":{"description":"Accepted with `?async=true`: {checkId, status, tier, chargedPence, txId, pollUrl}. Poll `pollUrl` (GET /agent/result/{checkId})."},"402":{"description":"Insufficient credits or payment required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"504":{"description":"Pipeline timed out — no charge applied","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TimeoutErrorResponse"}}}},"502":{"description":"Pipeline error — charge refunded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PipelineErrorResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/agent/credits/balance":{"get":{"tags":["agent"],"summary":"Check prepaid credit balance","description":"Return the agent's prepaid credit balance in pence and GBP.\n\n**Rate limit:** 60/minute","operationId":"get_credit_balance_api_v1_agent_credits_balance_get","responses":{"200":{"description":"Current credit balance","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreditBalanceResponse"}}}}}}},"/api/v1/agent/credits/purchase":{"post":{"tags":["agent"],"summary":"Purchase credit pack via Stripe","description":"Create a Stripe Checkout session for a one-time credit pack purchase.\n\nReturns a redirect URL — send the user or agent operator to this URL\nto complete payment. Credits are added to the account automatically\nafter successful payment.\n\n**Available packs:** 20 or 100 (in GBP).\n\n**Rate limit:** 10/minute","operationId":"purchase_credits_api_v1_agent_credits_purchase_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreditPurchaseRequest"}}},"required":true},"responses":{"200":{"description":"Stripe Checkout session URL","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CheckoutSessionResponse"}}}},"400":{"description":"Invalid pack size","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Credit packs not yet configured","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/agent/stats":{"get":{"tags":["agent"],"summary":"Get agent usage statistics","description":"Aggregated usage statistics — broken down by pipeline tier and payment provider.\n\n**Rate limit:** 30/minute","operationId":"get_agent_stats_api_v1_agent_stats_get","responses":{"200":{"description":"Aggregated usage statistics","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentStatsResponse"}}}}}}},"/api/v1/agent/health":{"get":{"tags":["agent"],"summary":"Agent API health check","description":"Check agent API availability and dependency health. No auth required.\n\n**Rate limit:** 60/minute","operationId":"agent_health_api_v1_agent_health_get","responses":{"200":{"description":"API and dependency status","content":{"application/json":{"schema":{}}}}}}},"/api/v1/agent/tiers":{"get":{"tags":["agent"],"summary":"List available agent tiers and pricing","description":"Return agent tier names, pricing (pence), and estimated latency. No auth required.\n\n**Rate limit:** 60/minute","operationId":"agent_tiers_api_v1_agent_tiers_get","responses":{"200":{"description":"Tier pricing and estimated latency","content":{"application/json":{"schema":{}}}}}}},"/api/v1/agent/me":{"get":{"tags":["agent"],"summary":"Get authenticated agent identity","description":"Return the authenticated agent's identity and credit balance. Requires auth.\n\n**Rate limit:** 60/minute","operationId":"agent_me_api_v1_agent_me_get","responses":{"200":{"description":"Agent identity and credit balance","content":{"application/json":{"schema":{}}}}}}},"/api/v1/agent/batch":{"post":{"tags":["agent"],"summary":"Submit multiple claims for concurrent processing","description":"Submit up to 10 claims for concurrent background processing.\n\nAll claims run at the same tier (quick or full). Each claim creates its own\ncheck and transaction. The total cost is deducted upfront — if the balance\nis insufficient, no claims are submitted.\n\nReturns 202 with check IDs and poll URLs for each claim.\n\n**Rate limit:** 5/minute","operationId":"agent_batch_api_v1_agent_batch_post","parameters":[{"name":"Idempotency-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Idempotency-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BatchRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"202":{"description":"All claims accepted for processing"},"400":{"description":"Invalid tier or empty claims list","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"402":{"description":"Insufficient credits for batch","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/verify/{check_id}/revisions/{revision_id}":{"get":{"tags":["verify"],"summary":"Verify a retained report revision","operationId":"verify_report_revision_verify__check_id__revisions__revision_id__get","parameters":[{"name":"check_id","in":"path","required":true,"schema":{"type":"string","title":"Check Id"}},{"name":"revision_id","in":"path","required":true,"schema":{"type":"string","title":"Revision Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/verify/{check_id}":{"get":{"tags":["verify"],"summary":"Verify check manifest integrity","description":"Verify the signed manifest for a completed check.\n\nConfirms the signed fields haven't changed since signing.\n\n**Public endpoint** — no authentication required.\n\nTwo-step verification:\n1. **Signature authenticity** — proves the manifest wasn't forged\n2. **Data integrity** — proves the database wasn't mutated since signing\n\nReturns `{valid: true, ...}` on success, or `{valid: false, reason: \"...\"}` on failure.\n\n**Rate limit:** 60/minute per IP","operationId":"verify_check_verify__check_id__get","parameters":[{"name":"check_id","in":"path","required":true,"schema":{"type":"string","title":"Check Id"}}],"responses":{"200":{"description":"Verification result — check `valid` field","content":{"application/json":{"schema":{"$ref":"#/components/schemas/VerifySuccessResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/":{"get":{"summary":"Root","operationId":"root__get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}}},"components":{"schemas":{"APIKeyCreatedResponse":{"properties":{"id":{"type":"string","title":"Id","description":"API key database ID"},"key":{"type":"string","title":"Key","description":"Full API key (shown once). Format: tru8_sk_<32 hex chars>. Store securely — it cannot be retrieved later."},"key_prefix":{"type":"string","title":"Key Prefix","description":"Key prefix for identification (e.g. tru8_sk_a1b2)"},"name":{"type":"string","title":"Name","description":"Label for this key"},"created_at":{"type":"string","format":"date-time","title":"Created At","description":"Creation timestamp"}},"type":"object","required":["id","key","key_prefix","name","created_at"],"title":"APIKeyCreatedResponse","description":"Returned once at creation. The raw `key` is never shown again — store it securely."},"APIKeyListItem":{"properties":{"id":{"type":"string","title":"Id","description":"API key database ID"},"key_prefix":{"type":"string","title":"Key Prefix","description":"Key prefix for identification"},"name":{"type":"string","title":"Name","description":"Label for this key"},"is_active":{"type":"boolean","title":"Is Active","description":"Whether the key is currently active"},"last_used_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Last Used At","description":"Last time this key was used for authentication"},"usage_count":{"type":"integer","title":"Usage Count","description":"Total number of requests made with this key"},"created_at":{"type":"string","format":"date-time","title":"Created At","description":"Creation timestamp"}},"type":"object","required":["id","key_prefix","name","is_active","usage_count","created_at"],"title":"APIKeyListItem","description":"API key summary (raw key is never returned after creation)."},"APIKeyListResponse":{"properties":{"keys":{"items":{"$ref":"#/components/schemas/APIKeyListItem"},"type":"array","title":"Keys","description":"API keys, newest first. Raw keys are never included."}},"type":"object","required":["keys"],"title":"APIKeyListResponse","description":"All API keys for the authenticated user."},"AgentCheckResponse":{"properties":{"id":{"type":"string","title":"Id","description":"Check ID (UUID)"},"status":{"$ref":"#/components/schemas/CheckStatus","description":"Check status: completed"},"claims":{"items":{"$ref":"#/components/schemas/ClaimDetail"},"type":"array","title":"Claims","description":"Claims with full evidence, elements, and orientation"},"hit":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Hit","description":"Cache hit indicator (true = served from cache, absent = fresh pipeline run)"},"meta":{"$ref":"#/components/schemas/AgentMeta","title":"_meta","description":"(JSON key: `_meta`) Tier executed, cost, limitations, and landscape metrics"},"manifest":{"anyOf":[{"$ref":"#/components/schemas/AgentManifest"},{"type":"null"}],"title":"_manifest","description":"(JSON key: `_manifest`) HMAC-signed manifest. Agents can verify the signed fields haven't changed since signing."},"computed":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"_computed","description":"(JSON key: `_computed`) Pre-computed analytics: tier/type distributions, corroboration groups, diagnostic values, timeline, element state summaries"}},"type":"object","required":["id","status","claims","meta"],"title":"AgentCheckResponse","description":"Full agent response with evidence landscape, metadata, and signed manifest.\n\nReturned by /agent/check, /agent/quick, /agent/full, and /agent/lookup (on cache hit).\n\n**Note:** In the actual JSON response, the metadata fields are prefixed with\nunderscores: `_meta`, `_manifest`, `_computed`. The schema below shows them\nwithout the prefix for documentation purposes."},"AgentClaimRequest":{"properties":{"claim":{"type":"string","maxLength":10000,"title":"Claim","description":"The claim text to analyse, or a URL to extract claims from"},"input_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Input Type","description":"Input type: 'text' or 'url'. Auto-detected from the claim field if omitted."},"compact":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Compact","description":"If true, returns claims and claim maps only — no evidence arrays. Reduces payload size for agents that only need orientation.","default":false}},"type":"object","required":["claim"],"title":"AgentClaimRequest","description":"Submit a claim or URL for evidence research."},"AgentCreditPurchaseRequest":{"properties":{"pack":{"type":"string","title":"Pack"}},"type":"object","required":["pack"],"title":"AgentCreditPurchaseRequest"},"AgentManifest":{"properties":{"checkId":{"type":"string","title":"Checkid","description":"Check ID this manifest covers"},"landscapeHash":{"type":"string","title":"Landscapehash","description":"SHA-256 hash of the canonical evidence landscape"},"signedAt":{"type":"string","title":"Signedat","description":"Signing timestamp (ISO 8601)"},"signature":{"type":"string","title":"Signature","description":"HMAC-SHA256 signature (hex)"},"kid":{"type":"string","title":"Kid","description":"Key ID used for signing"},"verifyUrl":{"type":"string","title":"Verifyurl","description":"Relative URL for public verification: /verify/{checkId}"}},"type":"object","required":["checkId","landscapeHash","signedAt","signature","kid","verifyUrl"],"title":"AgentManifest","description":"HMAC-signed manifest. Verify the signed fields haven't changed since signing via GET /verify/{checkId}."},"AgentMeta":{"properties":{"executedTier":{"$ref":"#/components/schemas/PipelineTier","description":"Pipeline tier that was executed: lookup, consensus, quick, or full"},"chargedPence":{"type":"integer","title":"Chargedpence","description":"Amount charged in pence GBP (0 for free retrievals)"},"limitations":{"items":{"type":"string"},"type":"array","title":"Limitations","description":"Pipeline stages skipped in quick mode (empty for full tier). Values: heuristic_classification, no_factcheck_lookup, no_api_sources, no_llm_relevance_scoring, no_coverage_recovery, no_query_answering"},"landscape":{"$ref":"#/components/schemas/LandscapeMetrics","description":"Structured evidence landscape metrics for programmatic analysis"},"cachedFrom":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Cachedfrom","description":"ISO 8601 timestamp of the cached result (present only on lookup hits)"}},"type":"object","required":["executedTier","chargedPence","limitations","landscape"],"title":"AgentMeta","description":"Agent response metadata — tier, cost, and landscape summary."},"AgentStatsResponse":{"properties":{"byTier":{"additionalProperties":{"$ref":"#/components/schemas/TierStats"},"type":"object","title":"Bytier","description":"Transaction counts and spend broken down by pipeline tier"},"byProvider":{"additionalProperties":{"$ref":"#/components/schemas/ProviderStats"},"type":"object","title":"Byprovider","description":"Transaction counts broken down by payment provider (credit, skyfire, x402)"},"totalAgentChecks":{"type":"integer","title":"Totalagentchecks","description":"Total checks initiated via agent endpoints"}},"type":"object","required":["byTier","byProvider","totalAgentChecks"],"title":"AgentStatsResponse","description":"Aggregated agent usage statistics.","example":{"byProvider":{"credit":{"count":200},"skyfire":{"count":7}},"byTier":{"full":{"count":12,"totalPence":180},"lookup":{"count":150,"totalPence":300},"quick":{"count":45,"totalPence":315}},"totalAgentChecks":207}},"BatchClaimItem":{"properties":{"claim":{"type":"string","maxLength":10000,"title":"Claim","description":"The claim text to analyse, or a URL"},"input_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Input Type","description":"'text' or 'url'. Auto-detected if omitted."}},"type":"object","required":["claim"],"title":"BatchClaimItem","description":"A single claim within a batch request."},"BatchRequest":{"properties":{"claims":{"items":{"$ref":"#/components/schemas/BatchClaimItem"},"type":"array","maxItems":10,"minItems":1,"title":"Claims","description":"List of claims to process (max 10)"},"tier":{"type":"string","title":"Tier","description":"Pipeline tier for all claims: 'quick' or 'full'.","default":"quick"},"compact":{"type":"boolean","title":"Compact","description":"If true, compact responses for all claims.","default":false}},"type":"object","required":["claims"],"title":"BatchRequest","description":"Submit multiple claims for concurrent processing."},"Body_upload_file_api_v1_checks_upload_post":{"properties":{"file":{"type":"string","format":"binary","title":"File"}},"type":"object","required":["file"],"title":"Body_upload_file_api_v1_checks_upload_post"},"BountyUpdateResponse":{"properties":{"status":{"type":"string","title":"Status","description":"Operation status","default":"success"},"bountyText":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Bountytext","description":"Updated bounty text (null if cleared)"}},"type":"object","title":"BountyUpdateResponse","description":"Response after updating element bounty text."},"CheckListItem":{"properties":{"id":{"type":"string","title":"Id","description":"Check ID (UUID)"},"inputType":{"$ref":"#/components/schemas/InputType","description":"Input type: url, text, image, or video"},"inputUrl":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Inputurl","description":"Source URL"},"status":{"$ref":"#/components/schemas/CheckStatus","description":"Pipeline status"},"creditsUsed":{"type":"integer","title":"Creditsused","description":"Credits consumed"},"processingTimeMs":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Processingtimems","description":"Processing time in milliseconds"},"createdAt":{"type":"string","title":"Createdat","description":"Creation timestamp (ISO 8601)"},"completedAt":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Completedat","description":"Completion timestamp (ISO 8601)"},"claimsCount":{"type":"integer","title":"Claimscount","description":"Total number of claims extracted"},"claims":{"items":{"$ref":"#/components/schemas/ClaimSummary"},"type":"array","title":"Claims","description":"First claim summary for preview"},"entryMode":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Entrymode","description":"article or direct"},"selectedClaimsCount":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Selectedclaimscount","description":"Claims selected for analysis"},"articleDomain":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Articledomain","description":"Primary domain classification"}},"type":"object","required":["id","inputType","status","creditsUsed","createdAt","claimsCount","claims"],"title":"CheckListItem","description":"Check summary for list endpoints."},"CheckListResponse":{"properties":{"checks":{"items":{"$ref":"#/components/schemas/CheckListItem"},"type":"array","title":"Checks","description":"Check summaries, newest first"},"total":{"type":"integer","title":"Total","description":"Total number of checks returned"}},"type":"object","required":["checks","total"],"title":"CheckListResponse","description":"Paginated list of the user's checks.","example":{"checks":[{"articleDomain":"economics","claims":[{"claimType":"empirical","elementCount":2,"id":"claim_1","orientation":"Evidence broadly supports this claim.","position":0,"text":"UK GDP grew by 0.6% in Q3 2025"}],"claimsCount":3,"completedAt":"2026-03-10T14:31:25Z","createdAt":"2026-03-10T14:30:00Z","creditsUsed":1,"entryMode":"article","id":"abc-123","inputType":"url","inputUrl":"https://example.com/article","processingTimeMs":85000,"selectedClaimsCount":3,"status":"completed"}],"total":1}},"CheckResponse":{"properties":{"id":{"type":"string","title":"Id","description":"Check ID (UUID)"},"inputType":{"$ref":"#/components/schemas/InputType","description":"Input type: url, text, image, or video"},"inputContent":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Inputcontent","description":"Original input data"},"inputUrl":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Inputurl","description":"Source URL (if url input type)"},"status":{"$ref":"#/components/schemas/CheckStatus","description":"Pipeline status: processing, waiting_for_selection, completed, or failed"},"creditsUsed":{"type":"integer","title":"Creditsused","description":"Credits consumed by this check"},"processingTimeMs":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Processingtimems","description":"Total pipeline processing time in milliseconds"},"errorMessage":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Errormessage","description":"Error details (only present on failed checks)"},"entryMode":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Entrymode","description":"How the check was initiated: article or direct"},"selectedClaimsCount":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Selectedclaimscount","description":"Number of claims selected for analysis"},"articleDomain":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Articledomain","description":"Primary domain classification of the article"},"articleSecondaryDomains":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Articlesecondarydomains","description":"Secondary domain classifications"},"articleJurisdiction":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Articlejurisdiction","description":"Detected jurisdiction for adapter routing (UK, US, or global)"},"articleClassificationSource":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Articleclassificationsource","description":"How the article domain was classified"},"userQuery":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Userquery","description":"User's Search Clarity question (if provided)"},"queryResponse":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Queryresponse","description":"Search Clarity answer"},"queryConfidence":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Queryconfidence","description":"Search Clarity confidence score"},"querySources":{"anyOf":[{"items":{"additionalProperties":true,"type":"object"},"type":"array"},{"type":"null"}],"title":"Querysources","description":"Sources used for Search Clarity answer"},"queryRelatedClaims":{"anyOf":[{"items":{"additionalProperties":true,"type":"object"},"type":"array"},{"type":"null"}],"title":"Queryrelatedclaims","description":"Claims related to the Search Clarity question"},"claims":{"items":{"$ref":"#/components/schemas/ClaimDetail"},"type":"array","title":"Claims","description":"Extracted claims with full evidence landscapes"},"createdAt":{"type":"string","title":"Createdat","description":"Check creation timestamp (ISO 8601)"},"completedAt":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Completedat","description":"Check completion timestamp (ISO 8601)"},"currentStage":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Currentstage","description":"Current pipeline stage (only during processing): ingest, extract, retrieve, classify, map, etc."},"progress":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Progress","description":"Pipeline progress percentage (0-100)"},"progressMessage":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Progressmessage","description":"Human-readable progress message"}},"type":"object","required":["id","inputType","status","creditsUsed","claims","createdAt"],"title":"CheckResponse","description":"Full check response with claims, evidence, and metadata."},"CheckStatus":{"type":"string","enum":["processing","waiting_for_selection","completed","failed"],"title":"CheckStatus","description":"Pipeline status values."},"CheckoutSessionResponse":{"properties":{"sessionId":{"type":"string","title":"Sessionid","description":"Stripe Checkout session ID"},"url":{"type":"string","title":"Url","description":"Redirect URL — send the user here to complete payment"}},"type":"object","required":["sessionId","url"],"title":"CheckoutSessionResponse","description":"Stripe Checkout session for credit pack purchase."},"ClaimDetail":{"properties":{"id":{"type":"string","title":"Id","description":"Claim database ID"},"text":{"type":"string","title":"Text","description":"Original claim text as extracted"},"position":{"type":"integer","title":"Position","description":"Claim position within the check (0-indexed)"},"claimMap":{"anyOf":[{"$ref":"#/components/schemas/ClaimMapSchema"},{"type":"null"}],"description":"Structured analysis: elements, evidence mapping, orientation. Present only after Phase 2 completes."},"claimType":{"anyOf":[{"$ref":"#/components/schemas/ClaimTypeEnum"},{"type":"null"}],"description":"Claim classification: empirical, definitional, causal_interpretive, predictive, or normative_flagged"},"isSelected":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Isselected","description":"Whether this claim was selected for full analysis (article mode)"},"significanceRank":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Significancerank","description":"Significance ranking within the article (lower = more significant)"},"subjectContext":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Subjectcontext","description":"Subject area context for the claim"},"keyEntities":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Keyentities","description":"Key named entities mentioned in the claim"},"sourceTitle":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Sourcetitle","description":"Title of the source article (URL inputs)"},"sourceUrl":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Sourceurl","description":"URL of the source article"},"sourcesReviewedCount":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Sourcesreviewedcount","description":"Number of raw sources reviewed for this claim before filtering"},"evidence":{"items":{"$ref":"#/components/schemas/EvidenceItem"},"type":"array","title":"Evidence","description":"Evidence items organised by the pipeline — classified, mapped, and receipted"}},"type":"object","required":["id","text","position"],"title":"ClaimDetail","description":"A claim extracted from the input, with its evidence landscape."},"ClaimElement":{"properties":{"elementId":{"type":"string","title":"Elementid","description":"Unique element identifier"},"description":{"type":"string","title":"Description","description":"The verifiable sub-question this element investigates"},"state":{"$ref":"#/components/schemas/ElementState","description":"Evidence state: supported (evidence agrees), disputed (evidence conflicts), or unresolved (insufficient evidence)"},"evidenceRefs":{"items":{"$ref":"#/components/schemas/EvidenceRef"},"type":"array","title":"Evidencerefs","description":"Evidence items mapped to this element with relationship labels"},"uncertaintyNote":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Uncertaintynote","description":"Note on limitations or ambiguity in the evidence"},"bountyText":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Bountytext","description":"User-authored note requesting specific evidence for this element (Seeker feature)"},"basis":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Basis","description":"Metadata breakdown: evidence count, tier/relationship/classification/content_basis distributions"}},"type":"object","required":["elementId","description","state","evidenceRefs"],"title":"ClaimElement","description":"A verifiable sub-question decomposed from the parent claim."},"ClaimMapSchema":{"properties":{"normalisedClaim":{"type":"string","title":"Normalisedclaim","description":"The claim restated in neutral, verifiable language"},"claimType":{"anyOf":[{"$ref":"#/components/schemas/ClaimTypeEnum"},{"type":"null"}],"description":"Claim classification: empirical, definitional, causal_interpretive, predictive, or normative_flagged"},"elements":{"items":{"$ref":"#/components/schemas/ClaimElement"},"type":"array","title":"Elements","description":"1-5 verifiable sub-questions decomposed from the claim"},"orientation":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Orientation","description":"Evidence-centred summary derived mechanically from element states (no LLM). Describes what the evidence landscape shows, not a verdict."},"orientationBasis":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Orientationbasis","description":"Mechanical derivation data: element state counts and the rule that produced the orientation line"},"metadata":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Metadata","description":"Claim map metadata (input hash, model version)"}},"type":"object","required":["normalisedClaim","elements"],"title":"ClaimMapSchema","description":"Structured analysis of a single claim — elements, evidence mapping, and orientation.","example":{"claimType":"empirical","elements":[{"description":"Did UK GDP grow in Q3 2025?","elementId":"e1","evidenceRefs":[{"evidenceId":"a1b2c3d4","relationship":"supports","snippet":"GDP grew by 0.6% in Q3 2025..."}],"state":"supported"}],"normalisedClaim":"UK GDP grew in Q3 2025","orientation":"Evidence broadly supports this claim. 2 of 2 elements are supported by primary and reporting sources.","orientationBasis":{"disputed":0,"rule":"all_supported","supported":2,"unresolved":0}}},"ClaimSummary":{"properties":{"id":{"type":"string","title":"Id","description":"Claim database ID"},"text":{"type":"string","title":"Text","description":"Original claim text"},"position":{"type":"integer","title":"Position","description":"Claim position (0-indexed)"},"claimType":{"anyOf":[{"$ref":"#/components/schemas/ClaimTypeEnum"},{"type":"null"}],"description":"Claim classification"},"elementCount":{"type":"integer","title":"Elementcount","description":"Number of elements decomposed from this claim"},"orientation":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Orientation","description":"Evidence orientation summary line"}},"type":"object","required":["id","text","position","elementCount"],"title":"ClaimSummary","description":"Abbreviated claim data for list views."},"ClaimTypeEnum":{"type":"string","enum":["empirical","definitional","causal_interpretive","predictive","normative_flagged"],"title":"ClaimTypeEnum","description":"Claim type classification."},"ClassificationMethod":{"type":"string","enum":["llm","heuristic","api_metadata"],"title":"ClassificationMethod","description":"How the evidence was classified."},"ContentBasis":{"type":"string","enum":["full","snippet","api","pdf"],"title":"ContentBasis","description":"How the evidence content was obtained."},"CreateAPIKeyRequest":{"properties":{"name":{"type":"string","maxLength":100,"minLength":1,"title":"Name","description":"Label for this key"}},"type":"object","required":["name"],"title":"CreateAPIKeyRequest"},"CreateCheckRequest":{"properties":{"input_type":{"type":"string","title":"Input Type","description":"Input type: 'url' (article analysis), 'text' (direct claim), 'image' (OCR), or 'video' (transcript)"},"content":{"anyOf":[{"type":"string","maxLength":10000},{"type":"null"}],"title":"Content","description":"Claim text (required when input_type is 'text'). Supports both statements and questions. Capped at 10,000 chars to prevent DoS via oversized inputs."},"url":{"anyOf":[{"type":"string","maxLength":2048},{"type":"null"}],"title":"Url","description":"URL to analyse (required when input_type is 'url' or 'video'). HTTPS prefix is added automatically if omitted."},"file_path":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"File Path","description":"Server path for uploaded images (use POST /upload first)"},"user_query":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"User Query","description":"Optional Search Clarity question (max 200 chars). When provided, the pipeline generates a focused answer alongside the evidence landscape."},"frozen_evidence":{"anyOf":[{"additionalProperties":{"items":{"additionalProperties":true,"type":"object"},"type":"array"},"type":"object"},{"type":"null"}],"title":"Frozen Evidence","description":"Pre-supplied evidence for replay testing (internal use only)"}},"type":"object","required":["input_type"],"title":"CreateCheckRequest","description":"Submit content for evidence research."},"CreateCheckoutRequest":{"properties":{"price_id":{"type":"string","title":"Price Id"},"plan":{"type":"string","title":"Plan"}},"type":"object","required":["price_id","plan"],"title":"CreateCheckoutRequest"},"CreateComparisonRequest":{"properties":{"evidenceA":{"type":"string","maxLength":64,"minLength":1,"title":"Evidencea"},"evidenceB":{"type":"string","maxLength":64,"minLength":1,"title":"Evidenceb"}},"type":"object","required":["evidenceA","evidenceB"],"title":"CreateComparisonRequest"},"CreateWebhookRequest":{"properties":{"url":{"type":"string","maxLength":2048,"title":"Url","description":"HTTPS URL to receive events"},"events":{"items":{"type":"string"},"type":"array","minItems":1,"title":"Events","description":"Events to subscribe to"},"description":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}],"title":"Description","description":"Label for this webhook"}},"type":"object","required":["url","events"],"title":"CreateWebhookRequest"},"CreditBalanceResponse":{"properties":{"balancePence":{"type":"integer","title":"Balancepence","description":"Current credit balance in pence (GBP)"},"balanceGbp":{"type":"string","title":"Balancegbp","description":"Current credit balance formatted as GBP string (e.g. '5.00')"}},"type":"object","required":["balancePence","balanceGbp"],"title":"CreditBalanceResponse","description":"Agent prepaid credit balance.","example":{"balanceGbp":"5.00","balancePence":500}},"CreditLimitError":{"properties":{"detail":{"type":"string","title":"Detail","description":"Error message with usage count and limit"}},"type":"object","required":["detail"],"title":"CreditLimitError","description":"Credit limit exceeded error (402).","example":{"detail":"Monthly limit reached (10/10 checks used). Please upgrade your plan for more checks."}},"CreditPurchaseRequest":{"properties":{"pack":{"type":"string","title":"Pack","description":"Credit pack size: '20' (£3.00) or '100' (£15.00)"}},"type":"object","required":["pack"],"title":"CreditPurchaseRequest","description":"Purchase a prepaid credit pack via Stripe Checkout."},"ElementState":{"type":"string","enum":["supported","disputed","unresolved"],"title":"ElementState","description":"Evidence state for a claim element."},"EmailPreferencesRequest":{"properties":{"email_notifications_enabled":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Email Notifications Enabled"},"email_check_completion":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Email Check Completion"},"email_check_failure":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Email Check Failure"},"email_weekly_digest":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Email Weekly Digest"},"email_marketing":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Email Marketing"},"email_lifecycle":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Email Lifecycle"}},"type":"object","title":"EmailPreferencesRequest"},"ErrorResponse":{"properties":{"detail":{"type":"string","title":"Detail","description":"Human-readable error message"}},"type":"object","required":["detail"],"title":"ErrorResponse","description":"Standard error response body.","example":{"detail":"Check not found"}},"EvidenceItem":{"properties":{"id":{"type":"string","title":"Id","description":"Internal database ID"},"evidenceId":{"type":"string","title":"Evidenceid","description":"Stable evidence identifier (URL hash)"},"source":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Source","description":"Human-readable source name (e.g. 'BBC News', 'WHO')"},"url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Url","description":"Source URL"},"title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Title","description":"Article or document title"},"snippet":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Snippet","description":"Relevant excerpt from the source (up to 1,000 characters)"},"publishedDate":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Publisheddate","description":"Publication date in ISO 8601 format"},"relevanceScore":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Relevancescore","description":"Topical relevance score (1-5 scale). Measures how on-topic the source is, not source authority."},"tier":{"anyOf":[{"$ref":"#/components/schemas/EvidenceTier"},{"type":"null"}],"description":"Source tier: primary (original data/documents), reporting (news coverage), or commentary (opinion/analysis)"},"evidenceType":{"anyOf":[{"$ref":"#/components/schemas/EvidenceType"},{"type":"null"}],"description":"Content type: data, official, news, analysis, opinion, or academic"},"receiptStatus":{"anyOf":[{"$ref":"#/components/schemas/ReceiptStatus"},{"type":"null"}],"description":"Pipeline receipt: found → extracted → classified → shown (or excluded). Every exclusion has a receipt."},"corroborationGroupId":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Corroborationgroupid","description":"Group ID linking corroborating sources"},"corroboratingEvidenceIds":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Corroboratingevidenceids","description":"IDs of sources that corroborate this evidence"},"isFactcheck":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Isfactcheck","description":"Whether this is from a fact-checking organisation"},"externalSourceProvider":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Externalsourceprovider","description":"API provider that supplied this evidence (e.g. 'semantic_scholar', 'pubmed')"},"sourceType":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Sourcetype","description":"Retrieval method: web_search or api"},"archivedUrl":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Archivedurl","description":"Wayback Machine archived URL (auto-archived for permanence)"},"llmRelevanceScore":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Llmrelevancescore","description":"Raw LLM relevance score before normalisation"},"classificationMethod":{"anyOf":[{"$ref":"#/components/schemas/ClassificationMethod"},{"type":"null"}],"description":"How tier/type was assigned: llm, heuristic, or api_metadata"},"textProvenance":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Textprovenance","description":"Retained extraction excerpts; not verified relationship citations"},"contentBasis":{"anyOf":[{"$ref":"#/components/schemas/ContentBasis"},{"type":"null"}],"description":"How the content was obtained: full (page fetch), snippet (search result), api (structured API), pdf"}},"type":"object","required":["id","evidenceId"],"title":"EvidenceItem","description":"A single piece of evidence with source metadata and classification.","example":{"classificationMethod":"heuristic","contentBasis":"api","evidenceId":"a1b2c3d4","evidenceType":"data","id":"ev_abc123","publishedDate":"2025-11-15T00:00:00","receiptStatus":"shown","relevanceScore":4.2,"snippet":"GDP grew by 0.6% in Q3 2025, following growth of 0.5% in Q2...","source":"Office for National Statistics","tier":"primary","title":"UK GDP quarterly estimate","url":"https://www.ons.gov.uk/economy/data"}},"EvidenceRef":{"properties":{"evidenceId":{"type":"string","title":"Evidenceid","description":"ID of the referenced evidence item"},"relationship":{"$ref":"#/components/schemas/EvidenceRelationship","description":"How this evidence relates to the element: supports, challenges, or context"},"snippet":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Snippet","description":"Key excerpt used for this mapping"}},"type":"object","required":["evidenceId","relationship"],"title":"EvidenceRef","description":"Reference linking evidence to a claim element."},"EvidenceRelationship":{"type":"string","enum":["supports","challenges","context"],"title":"EvidenceRelationship","description":"How a piece of evidence relates to an element."},"EvidenceTier":{"type":"string","enum":["primary","reporting","commentary"],"title":"EvidenceTier","description":"Source tier classification — structural role of the source."},"EvidenceType":{"type":"string","enum":["data","official","news","analysis","opinion","academic"],"title":"EvidenceType","description":"Source type classification — content category."},"FeedbackRequest":{"properties":{"type":{"type":"string","title":"Type"},"message":{"type":"string","title":"Message"},"checkId":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Checkid"},"claimPosition":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Claimposition"},"claimText":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Claimtext"},"pageUrl":{"type":"string","title":"Pageurl"},"userEmail":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Useremail"}},"type":"object","required":["type","message","pageUrl"],"title":"FeedbackRequest"},"FeedbackResponse":{"properties":{"success":{"type":"boolean","title":"Success"},"message":{"type":"string","title":"Message"}},"type":"object","required":["success","message"],"title":"FeedbackResponse"},"Freshness":{"properties":{"freshestDaysAgo":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Freshestdaysago","description":"Days since the most recent dated evidence item"},"dateSpanDays":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Datespandays","description":"Time span in days between oldest and newest dated evidence"},"undatedCount":{"type":"integer","title":"Undatedcount","description":"Number of evidence items without a publication date"}},"type":"object","required":["undatedCount"],"title":"Freshness","description":"Evidence freshness metrics."},"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"HeardAboutRequest":{"properties":{"answer":{"type":"string","title":"Answer"},"detail":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Detail"}},"type":"object","required":["answer"],"title":"HeardAboutRequest"},"InputType":{"type":"string","enum":["url","text","image","video"],"title":"InputType","description":"Supported input types for evidence research."},"LandscapeGap":{"properties":{"elementId":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Elementid","description":"Element ID (if element-level gap)"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description","description":"Element description (if element-level gap)"},"claimPosition":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Claimposition","description":"Parent claim position"},"reason":{"type":"string","title":"Reason","description":"Gap type: no_evidence, unresolved, no_primary_sources, or no_academic_sources"},"evidenceCount":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Evidencecount","description":"Evidence count for unresolved elements"}},"type":"object","required":["reason"],"title":"LandscapeGap","description":"An identified gap in the evidence landscape."},"LandscapeMetrics":{"properties":{"elementCount":{"type":"integer","title":"Elementcount","description":"Total number of verifiable elements across all claims"},"elementStates":{"additionalProperties":{"type":"integer"},"propertyNames":{"$ref":"#/components/schemas/ElementState"},"type":"object","title":"Elementstates","description":"Count of elements in each state: supported, disputed, unresolved"},"evidenceDensity":{"type":"integer","title":"Evidencedensity","description":"Total evidence items across all claims"},"sourcesConsidered":{"type":"integer","title":"Sourcesconsidered","description":"Total sources reviewed (same as evidenceDensity for organised sources)"},"sourceDiversity":{"$ref":"#/components/schemas/SourceDiversity","description":"Source diversity breakdown: tier spread, unique domains, type coverage"},"freshness":{"$ref":"#/components/schemas/Freshness","description":"Evidence freshness: recency, date span, undated count"},"gaps":{"items":{"$ref":"#/components/schemas/LandscapeGap"},"type":"array","title":"Gaps","description":"Identified gaps in the evidence landscape (elements without evidence, missing source types)"},"providerStatus":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Providerstatus","description":"Aggregated provider status: which search/API providers succeeded, failed, or timed out during retrieval"}},"type":"object","required":["elementCount","elementStates","evidenceDensity","sourcesConsidered","sourceDiversity","freshness","gaps"],"title":"LandscapeMetrics","description":"Structured summary of the evidence landscape — designed for programmatic consumption.","example":{"elementCount":5,"elementStates":{"disputed":1,"supported":3,"unresolved":1},"evidenceDensity":13,"freshness":{"dateSpanDays":180,"freshestDaysAgo":2,"undatedCount":1},"gaps":[{"claimPosition":0,"description":"Is the trend accelerating?","elementId":"e3","evidenceCount":2,"reason":"unresolved"}],"sourceDiversity":{"tierSpread":{"commentary":3,"primary":4,"reporting":6},"typeCoverage":4,"uniqueDomains":9},"sourcesConsidered":13}},"NotificationPreferencesRequest":{"properties":{"notifications":{"type":"boolean","title":"Notifications"}},"type":"object","required":["notifications"],"title":"NotificationPreferencesRequest"},"PipelineErrorResponse":{"properties":{"detail":{"type":"string","title":"Detail","description":"Pipeline error description"}},"type":"object","required":["detail"],"title":"PipelineErrorResponse","description":"Pipeline failure error (502).","example":{"detail":"Pipeline error: content extraction failed"}},"PipelineTier":{"type":"string","enum":["lookup","consensus","quick","full"],"title":"PipelineTier","description":"Agent pipeline tiers — determines depth and cost."},"ProfileUpdateRequest":{"properties":{"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name"}},"type":"object","title":"ProfileUpdateRequest"},"ProviderStats":{"properties":{"count":{"type":"integer","title":"Count","description":"Number of completed transactions"}},"type":"object","required":["count"],"title":"ProviderStats","description":"Usage statistics for a single payment provider."},"PublicCheckMinimal":{"properties":{"id":{"type":"string","title":"Id","description":"Check ID"},"title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Title","description":"Derived title for display"},"sourceUrl":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Sourceurl","description":"Source URL"},"sourceDomain":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Sourcedomain","description":"Source domain name"},"claimsCount":{"type":"integer","title":"Claimscount","description":"Number of claims"},"sourcesCount":{"type":"integer","title":"Sourcescount","description":"Number of organised sources"},"totalSearchResults":{"type":"integer","title":"Totalsearchresults","description":"Total search results reviewed"},"evidenceCount":{"type":"integer","title":"Evidencecount","description":"Total evidence items"},"entryMode":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Entrymode","description":"article or direct"},"selectedClaimsCount":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Selectedclaimscount","description":"Number of selected claims"},"topSources":{"items":{"type":"string"},"type":"array","title":"Topsources","description":"Up to 5 prominent source names"}},"type":"object","required":["id","claimsCount","sourcesCount","totalSearchResults","evidenceCount","topSources"],"title":"PublicCheckMinimal","description":"Minimal public check data for OG card generation (no auth required)."},"PushTokenRequest":{"properties":{"push_token":{"type":"string","title":"Push Token"},"platform":{"type":"string","title":"Platform"},"device_id":{"type":"string","title":"Device Id"}},"type":"object","required":["push_token","platform","device_id"],"title":"PushTokenRequest"},"ReceiptStatus":{"type":"string","enum":["found","extracted","classified","excluded","shown"],"title":"ReceiptStatus","description":"Pipeline receipt status — tracks evidence through the pipeline."},"SSETokenResponse":{"properties":{"token":{"type":"string","title":"Token","description":"Check-scoped token (valid 5 minutes). Pass as ?token= in the EventSource URL."},"expiresIn":{"type":"integer","title":"Expiresin","description":"Token lifetime in seconds"},"streamUrl":{"type":"string","title":"Streamurl","description":"Full SSE endpoint URL with token appended"}},"type":"object","required":["token","expiresIn","streamUrl"],"title":"SSETokenResponse","description":"Short-lived token for SSE progress streaming."},"SelectClaimsRequest":{"properties":{"selected_positions":{"items":{"type":"integer"},"type":"array","maxItems":5,"title":"Selected Positions","description":"Claim positions to select for analysis (0-indexed). Maximum 5 claims per check."}},"type":"object","required":["selected_positions"],"title":"SelectClaimsRequest","description":"Select claims for full evidence analysis (article mode)."},"SignupSourceRequest":{"properties":{"source":{"type":"string","title":"Source"}},"type":"object","required":["source"],"title":"SignupSourceRequest"},"SmartCheckRequest":{"properties":{"claim":{"type":"string","maxLength":10000,"title":"Claim","description":"The claim text to analyse, or a URL to extract claims from"},"input_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Input Type","description":"Input type: 'text' or 'url'. Auto-detected from the claim field if omitted."},"max_tier":{"type":"string","title":"Max Tier","description":"Maximum pipeline tier to execute. The endpoint tries lookup first, then escalates up to this tier. Options: lookup, consensus, quick, full.","default":"full"},"max_age_hours":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Max Age Hours","description":"Maximum cache age in hours for lookup hits. If the cached result is older than this, it's treated as a miss and the endpoint escalates."},"compact":{"type":"boolean","title":"Compact","description":"If true, returns claims and claim maps only — no evidence arrays.","default":false}},"type":"object","required":["claim"],"title":"SmartCheckRequest","description":"Request for the smart /agent/check endpoint with automatic tier fallback."},"SourceDiversity":{"properties":{"tierSpread":{"additionalProperties":{"type":"integer"},"propertyNames":{"$ref":"#/components/schemas/EvidenceTier"},"type":"object","title":"Tierspread","description":"Count of evidence items per tier (primary, reporting, commentary)"},"uniqueDomains":{"type":"integer","title":"Uniquedomains","description":"Number of distinct source domains in the evidence set"},"typeCoverage":{"type":"integer","title":"Typecoverage","description":"Number of distinct source types represented (max 6)"}},"type":"object","required":["tierSpread","uniqueDomains","typeCoverage"],"title":"SourceDiversity","description":"Source diversity breakdown within the evidence landscape."},"SourcesClaimSources":{"properties":{"claimPosition":{"type":"integer","title":"Claimposition","description":"Claim position (0-indexed)"},"claimText":{"type":"string","title":"Claimtext","description":"Claim text"},"included":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Included","description":"Sources included in the final evidence set"},"filtered":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Filtered","description":"Sources excluded with filter stage and reason"}},"type":"object","required":["claimPosition","claimText","included","filtered"],"title":"SourcesClaimSources","description":"Sources for a single claim with filter stage breakdown."},"SourcesResponse":{"properties":{"checkId":{"type":"string","title":"Checkid","description":"Check ID"},"totalSources":{"type":"integer","title":"Totalsources","description":"Total raw sources reviewed"},"includedCount":{"type":"integer","title":"Includedcount","description":"Sources included in final evidence set"},"filteredCount":{"type":"integer","title":"Filteredcount","description":"Sources filtered out"},"legacyCheck":{"type":"boolean","title":"Legacycheck","description":"Whether this is a pre-receipt-system check with limited data"},"message":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Message","description":"Status or info message"},"claims":{"anyOf":[{"items":{"$ref":"#/components/schemas/SourcesClaimSources"},"type":"array"},{"type":"null"}],"title":"Claims","description":"Per-claim source breakdown"},"filterBreakdown":{"anyOf":[{"additionalProperties":{"type":"integer"},"type":"object"},{"type":"null"}],"title":"Filterbreakdown","description":"Count of sources excluded at each pipeline stage"}},"type":"object","required":["checkId","totalSources","includedCount","filteredCount","legacyCheck"],"title":"SourcesResponse","description":"All sources reviewed during evidence research, including filtered items."},"TierStats":{"properties":{"count":{"type":"integer","title":"Count","description":"Number of completed transactions"},"totalPence":{"type":"integer","title":"Totalpence","description":"Total amount charged in pence (GBP)"}},"type":"object","required":["count","totalPence"],"title":"TierStats","description":"Usage statistics for a single pipeline tier."},"TimeoutErrorResponse":{"properties":{"detail":{"type":"string","title":"Detail","description":"Timeout message"}},"type":"object","required":["detail"],"title":"TimeoutErrorResponse","description":"Pipeline timeout error (504).","example":{"detail":"Pipeline timed out. Credits have been refunded."}},"UpdateBountyRequest":{"properties":{"text":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Text","description":"Bounty text describing what evidence would help resolve this element (max 200 chars). Set to null to clear."}},"type":"object","title":"UpdateBountyRequest","description":"Update the bounty text on a claim element (Seeker feature)."},"ValidationError":{"properties":{"loc":{"items":{"anyOf":[{"type":"string"},{"type":"integer"}]},"type":"array","title":"Location"},"msg":{"type":"string","title":"Message"},"type":{"type":"string","title":"Error Type"}},"type":"object","required":["loc","msg","type"],"title":"ValidationError"},"VerifySuccessResponse":{"properties":{"valid":{"type":"boolean","title":"Valid","description":"Always true on successful verification","default":true},"checkId":{"type":"string","title":"Checkid","description":"Verified check ID"},"signedAt":{"type":"string","title":"Signedat","description":"When the manifest was signed (ISO 8601)"},"kid":{"type":"string","title":"Kid","description":"Signing key ID"},"executedTier":{"anyOf":[{"$ref":"#/components/schemas/PipelineTier"},{"type":"null"}],"description":"Pipeline tier used for this check"},"pipelineFingerprint":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Pipelinefingerprint","description":"SHA-256 fingerprint of pipeline model configuration (first 12 chars)"}},"type":"object","required":["checkId","signedAt","kid"],"title":"VerifySuccessResponse","description":"Successful manifest verification — data integrity confirmed.","example":{"checkId":"abc-123","executedTier":"full","kid":"k1","pipelineFingerprint":"a1b2c3d4e5f6","signedAt":"2026-03-10T14:31:25Z","valid":true}},"VideoItem":{"properties":{"id":{"type":"string","title":"Id","description":"Database ID"},"claimId":{"type":"string","title":"Claimid","description":"Parent claim ID"},"videoId":{"type":"string","title":"Videoid","description":"YouTube video ID"},"title":{"type":"string","title":"Title","description":"Video title"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description","description":"Video description excerpt"},"channelName":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Channelname","description":"YouTube channel name"},"channelId":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Channelid","description":"YouTube channel ID"},"publishDate":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Publishdate","description":"Video publish date (ISO 8601)"},"videoUrl":{"type":"string","title":"Videourl","description":"Full YouTube watch URL"},"thumbnailUrl":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Thumbnailurl","description":"Video thumbnail URL"},"duration":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Duration","description":"Video duration in ISO 8601 format"},"tierLabel":{"anyOf":[{"$ref":"#/components/schemas/EvidenceTier"},{"type":"null"}],"description":"Source tier classification for this video"},"typeLabel":{"anyOf":[{"$ref":"#/components/schemas/EvidenceType"},{"type":"null"}],"description":"Source type classification for this video"}},"type":"object","required":["id","claimId","videoId","title","videoUrl"],"title":"VideoItem","description":"A video recommendation from YouTube."},"VideosResponse":{"properties":{"checkId":{"type":"string","title":"Checkid","description":"Check ID"},"videos":{"items":{"$ref":"#/components/schemas/VideoItem"},"type":"array","title":"Videos","description":"Video recommendations"}},"type":"object","required":["checkId","videos"],"title":"VideosResponse","description":"Video recommendations for a check or claim."},"WaitlistRequest":{"properties":{"email":{"type":"string","title":"Email"},"source":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Source","default":"landing"}},"type":"object","required":["email"],"title":"WaitlistRequest"},"WebhookCreatedResponse":{"properties":{"id":{"type":"string","title":"Id","description":"Webhook database ID"},"url":{"type":"string","title":"Url","description":"HTTPS URL that will receive events"},"events":{"items":{"type":"string"},"type":"array","title":"Events","description":"Events this webhook is subscribed to (e.g. check.completed, check.failed)"},"secret":{"type":"string","title":"Secret","description":"HMAC signing secret (shown once). Use to verify X-Tru8-Signature headers on incoming payloads."},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description","description":"Webhook label"},"created_at":{"type":"string","format":"date-time","title":"Created At","description":"Creation timestamp"}},"type":"object","required":["id","url","events","secret","created_at"],"title":"WebhookCreatedResponse","description":"Returned once at creation. The signing `secret` is shown once — store it to verify payloads."},"WebhookListItem":{"properties":{"id":{"type":"string","title":"Id","description":"Webhook database ID"},"url":{"type":"string","title":"Url","description":"HTTPS URL receiving events"},"events":{"items":{"type":"string"},"type":"array","title":"Events","description":"Subscribed events"},"is_active":{"type":"boolean","title":"Is Active","description":"Whether the webhook is currently active"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description","description":"Webhook label"},"last_triggered_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Last Triggered At","description":"Last time this webhook was triggered"},"failure_count":{"type":"integer","title":"Failure Count","description":"Consecutive delivery failures (webhook is deactivated after 10)"},"created_at":{"type":"string","format":"date-time","title":"Created At","description":"Creation timestamp"}},"type":"object","required":["id","url","events","is_active","failure_count","created_at"],"title":"WebhookListItem","description":"Webhook summary (secret is never returned after creation)."},"WebhookListResponse":{"properties":{"webhooks":{"items":{"$ref":"#/components/schemas/WebhookListItem"},"type":"array","title":"Webhooks","description":"Webhooks, newest first. Secrets are never included."}},"type":"object","required":["webhooks"],"title":"WebhookListResponse","description":"All webhooks for the authenticated user."}},"securitySchemes":{"HTTPBearer":{"type":"http","scheme":"bearer"}}}}