{"openapi":"3.1.0","info":{"title":"VetAid API","description":"VetAid, the veterans claims tool — veteran-built AI for VA disability claims. The public, read-only /api/denials/* endpoints expose aggregate Board of Veterans' Appeals (BVA) outcome intelligence (per-condition grant/deny/remand shares, the year trend, which evidence went with a grant, most-cited legal authorities) computed from 1.9 million published BVA decisions, 1992 to present, updated nightly. These require no auth and contain no individual veteran data — AI agents may call them directly to ground VA-claim answers in real case-law data. Full claim-file analysis (involving a veteran's own documents) lives behind authentication in the app. Not affiliated with the U.S. Dept. of Veterans Affairs.","contact":{"name":"VetAid","url":"https://vetaid.ai/"},"version":"1.0.0"},"paths":{"/api/admin/quarantine":{"get":{"summary":"Admin Quarantine","description":"The standing feature-quarantine list as published, plus the CSS in force.","operationId":"admin_quarantine_api_admin_quarantine_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/checkout/single":{"post":{"tags":["payments"],"summary":"Checkout Single","description":"Create Stripe Checkout for a single case analysis ($9.99).","operationId":"checkout_single_api_checkout_single_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/checkout/subscribe":{"post":{"tags":["payments"],"summary":"Checkout Subscribe","description":"Create Stripe Checkout for Pro subscription.","operationId":"checkout_subscribe_api_checkout_subscribe_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/webhooks/stripe":{"post":{"tags":["payments"],"summary":"Stripe Webhook","description":"Handle Stripe webhook events.","operationId":"stripe_webhook_api_webhooks_stripe_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/verify-payment":{"post":{"tags":["payments"],"summary":"Verify Payment","description":"Fallback: check Stripe for completed payments (for local dev without webhooks).","operationId":"verify_payment_api_verify_payment_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/billing-portal":{"post":{"tags":["payments"],"summary":"Billing Portal","description":"Create Stripe Customer Portal session for subscription management.","operationId":"billing_portal_api_billing_portal_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/account":{"get":{"tags":["payments"],"summary":"Get Account","description":"Get current user's account info.","operationId":"get_account_api_account_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/forum":{"get":{"summary":"Forum Index","operationId":"forum_index_forum_get","responses":{"200":{"description":"Successful Response","content":{"text/html":{"schema":{"type":"string"}}}}}}},"/forum/t/{slug}":{"get":{"summary":"Forum Thread","operationId":"forum_thread_forum_t__slug__get","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","title":"Slug"}}],"responses":{"200":{"description":"Successful Response","content":{"text/html":{"schema":{"type":"string"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/forum/post":{"post":{"summary":"Forum Post","description":"A real person posts. Crisis text is intercepted before anything else happens.","operationId":"forum_post_api_forum_post_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/cron/forum-tick":{"post":{"summary":"Forum Tick","description":"Generate due persona replies. Same cron pattern as the other scheduled jobs.","operationId":"forum_tick_api_cron_forum_tick_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/forum/moderation":{"get":{"summary":"Moderation Queue","description":"Threads a human needs to look at. Crisis flags surface here and nowhere else.","operationId":"moderation_queue_api_forum_moderation_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/":{"get":{"summary":"Home","operationId":"home__get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/app":{"get":{"summary":"App Page","operationId":"app_page_app_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/c/{case_id}":{"get":{"summary":"Case Deep Link","description":"Deep link to one case — the URL transactional email should use.\n\nDeliberately a path segment rather than /app?case=<id>: a delivered\n\"your analysis is ready\" email arrived with the '=' and the two hex\ndigits after it consumed, leaving ?case<junk> and no recoverable id. A\npath segment contains no '=', so nothing downstream can eat it. The\nredirect rebuilds the query string the app actually reads.\n\nNo authorization here — this only reshapes a URL. The app resolves the\nid against /api/cases, which is scoped to the signed-in user.","operationId":"case_deep_link_c__case_id__get","parameters":[{"name":"case_id","in":"path","required":true,"schema":{"type":"string","title":"Case Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/health":{"get":{"summary":"Health","operationId":"health_api_health_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/public/stats":{"get":{"summary":"Public Stats","description":"Aggregate-only stats — no PII. Safe to expose publicly.\n\nPass ?exclude_owners=true to filter out the owner test accounts\n(dwaynemorise007@gmail.com + sellhairmakemoney@gmail.com) from all\ncounts — gives a clean read on real user activity.","operationId":"public_stats_api_public_stats_get","parameters":[{"name":"exclude_owners","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"Exclude Owners"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/config":{"get":{"summary":"Config","operationId":"config_api_config_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/track-referral":{"post":{"summary":"Track Referral","description":"Store first-touch attribution (UTM + gclid + referrer-derived source).\n\nAnonymous calls are a quiet no-op — the va_ft first-touch cookie carries\ntheir data to signup instead. (This endpoint used to require auth and\n401'd ~45 times/week for visitors whose session wasn't live yet, silently\ndiscarding the attribution it existed to capture.)","operationId":"track_referral_api_track_referral_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/public/chat":{"post":{"summary":"Public Chat Endpoint","description":"Landing page help bot — no auth required, strict rate limiting.","operationId":"public_chat_endpoint_api_public_chat_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/public/decode-letter":{"post":{"summary":"Public Decode Letter","description":"Read one decision letter with no account. Rate-limited per IP; the file\nis processed in memory and discarded; PII is redacted from the text before the\nanalysis model call. Photos (and scanned PDF pages local OCR can't read) go to\nthe vision OCR model unredacted - the decoder page says so.","operationId":"public_decode_letter_api_public_decode_letter_post","requestBody":{"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_public_decode_letter_api_public_decode_letter_post"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/bva/evidence/cases":{"get":{"summary":"Bva Evidence Cases Api","description":"The decisions behind one cell of /bva/evidence: citations with links to\nthe decision text on va.gov. Public, read-only, aggregate corpus data.","operationId":"bva_evidence_cases_api_api_bva_evidence_cases_get","parameters":[{"name":"feature","in":"query","required":true,"schema":{"type":"string","title":"Feature"}},{"name":"present","in":"query","required":false,"schema":{"type":"integer","default":1,"title":"Present"}},{"name":"disposition","in":"query","required":false,"schema":{"type":"string","default":"","title":"Disposition"}},{"name":"condition","in":"query","required":false,"schema":{"type":"string","default":"","title":"Condition"}},{"name":"benefit","in":"query","required":false,"schema":{"type":"string","default":"service_connection","title":"Benefit"}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","default":0,"title":"Offset"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/bva/evidence/cases":{"get":{"summary":"Bva Evidence Cases Page","description":"Human page for one cell's provenance — every fraction on /bva/evidence opens here.","operationId":"bva_evidence_cases_page_bva_evidence_cases_get","parameters":[{"name":"feature","in":"query","required":true,"schema":{"type":"string","title":"Feature"}},{"name":"present","in":"query","required":false,"schema":{"type":"integer","default":1,"title":"Present"}},{"name":"disposition","in":"query","required":false,"schema":{"type":"string","default":"","title":"Disposition"}},{"name":"condition","in":"query","required":false,"schema":{"type":"string","default":"","title":"Condition"}},{"name":"benefit","in":"query","required":false,"schema":{"type":"string","default":"service_connection","title":"Benefit"}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","default":0,"title":"Offset"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/bva/find":{"get":{"summary":"Bva Find Api","description":"Board decision finder (JSON). Filters: condition, benefit, disposition\n(granted|denied|remanded|dismissed|other|withdrawn|vacated|moot|referred, or\na comma list), judge, year_from, year_to, series, with, without, q,\nsingle_issue, sort, offset, limit (1-100). Rows and counts are issues.","operationId":"bva_find_api_api_bva_find_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/bva/find.csv":{"get":{"summary":"Bva Find Csv","description":"Same filters as /api/bva/find; up to 2,000 issue rows (limit=1-2000,\noffset= for the next file). The file ends with '#' lines naming its filters\nand whether it holds the whole slice.","operationId":"bva_find_csv_api_bva_find_csv_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/bva/find/meta":{"get":{"summary":"Bva Find Meta","description":"Vocabulary for the finder: conditions, benefits, judges (with name\nvariants), evidence features with labels.","operationId":"bva_find_meta_api_bva_find_meta_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/bva/find":{"get":{"summary":"Bva Find Page","description":"Human finder page: server-rendered from the query string (works with no\nJS); ?fragment=1 returns only the results block for live filtering. Every\noutcome, including 400/429/503/504, is an HTML page or fragment.","operationId":"bva_find_page_bva_find_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/bva/evidence":{"get":{"summary":"Bva Evidence Lookup","description":"Measured present-vs-absent rows for one condition (public, read-only,\nfrom the published evidence build). For agents and the app alike.","operationId":"bva_evidence_lookup_api_bva_evidence_get","parameters":[{"name":"condition","in":"query","required":false,"schema":{"type":"string","default":"","title":"Condition"}},{"name":"benefit","in":"query","required":false,"schema":{"type":"string","default":"service_connection","title":"Benefit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/pulse":{"post":{"summary":"Pulse Beacon","description":"Section-level attention beacon (static/js/pulse.js — fleet pattern from\nVividDisplays). Anonymous by design: no IP/UA stored; DNT respected client-\nside. Fire-and-forget into the fleet Supabase `pulse` table so future\nconversion work can see which SECTIONS people actually read.","operationId":"pulse_beacon_api_pulse_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/track/pageview":{"post":{"summary":"Track Pageview","description":"Lightweight page-view beacon. Called by a <script> on every public page.\nCaptures: path, referrer (truncated), UTM tags. NEVER captures PII.\nFor logged-in users: optionally extracts user_id from Authorization Bearer\nso we can attribute the event to a specific user without exposing email.","operationId":"track_pageview_api_track_pageview_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/admin/events":{"get":{"summary":"Admin Events","description":"Read recent events. Cron-secret-gated. For Hermes + manual ops dashboards.\n\nQuery params:\n    since_hours (default 24)\n    type        (optional event-type filter, e.g. document_uploaded)\n    user_id     (optional user-scope filter — full Supabase UUID)\n    case_id     (optional case-scope filter — full case UUID)\n    limit       (default 500, max 5000)\n    summary=true returns aggregated counts only, no individual rows\n    names=true   returns distinct type/event_name values only (uncapped window)","operationId":"admin_events_api_admin_events_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/admin/metrics":{"get":{"summary":"Admin Metrics","description":"Owner-only metrics dashboard data.","operationId":"admin_metrics_api_admin_metrics_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/admin/funnel":{"get":{"summary":"Admin Funnel","description":"Cron-secret-gated growth funnel + attribution for the nightly autopilot.\nExcludes the owner + test accounts (@vetaid-test.local / @example.com) so the\nnumbers reflect REAL users. Read-only. Returns real signups by window, signups\nby referral source (7d), and the signup→analysis activation funnel (7d).","operationId":"admin_funnel_api_admin_funnel_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/admin/ads-report":{"get":{"summary":"Ads Report","description":"Google Ads funnel report — signups, analyses, purchases by UTM source.","operationId":"ads_report_api_admin_ads_report_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/admin/users-activity":{"get":{"summary":"Users Activity","description":"Per-user engagement — who signed up and what they actually did.\n\nReturns one row per user with counts of cases, documents, analyses,\nand last activity timestamp. Lets you spot organic users who dropped off\nvs. converted.","operationId":"users_activity_api_admin_users_activity_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/admin/user-detail":{"get":{"summary":"User Detail","description":"Deep dive on a single user — full case + document + analysis timeline.\n\nUsed to diagnose specific conversion problems (who dropped off where).","operationId":"user_detail_api_admin_user_detail_get","parameters":[{"name":"email","in":"query","required":true,"schema":{"type":"string","title":"Email"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/admin/reclassify-docs":{"post":{"summary":"Reclassify Docs","description":"Re-run detect_doc_type on existing documents using the current classifier.\n\nDefaults to dry-run. Pass apply=true to actually write back to DB.\nScope with email= or case_id= to limit blast radius.","operationId":"reclassify_docs_api_admin_reclassify_docs_post","parameters":[{"name":"email","in":"query","required":false,"schema":{"type":"string","default":"","title":"Email"}},{"name":"case_id","in":"query","required":false,"schema":{"type":"string","default":"","title":"Case Id"}},{"name":"apply","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"Apply"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/admin/trigger-analysis":{"post":{"summary":"Admin Trigger Analysis","description":"Owner-only: re-run analysis stages on any case, used for Sentinel bug-fix follow-ups.\n\nstages: optional comma-separated stage keys. Default = all 9 core stages.","operationId":"admin_trigger_analysis_api_admin_trigger_analysis_post","parameters":[{"name":"case_id","in":"query","required":true,"schema":{"type":"string","title":"Case Id"}},{"name":"stages","in":"query","required":false,"schema":{"type":"string","default":"","title":"Stages"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/cron/sentinel-scan":{"post":{"summary":"Cron Sentinel Scan","description":"Nightly Sentinel pass: handles pending bug-fix notifications across affected users.\n\nFor each pending bug fix:\n  1. Send self_audit_notice email to each affected user\n  2. Trigger re-analysis in background\n  3. Mark the user as owed a corrected-report follow-up in sentinel_pending_followups.json\n\nFor each pending follow-up whose re-analysis appears complete:\n  4. Recompile profile, regen PDF, send corrected-report email\n  5. Remove from pending_followups","operationId":"cron_sentinel_scan_api_cron_sentinel_scan_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/cron/welcome-new-users":{"post":{"summary":"Cron Welcome New Users","description":"DISABLED 2026-04-24 — Dwayne disabled welcome sends. Re-engagement and\nself-audit (bug-fix) sends remain active via sentinel-scan + reengagement-scan.\nEndpoint kept 200-OK so existing cron-job.org hits don't alarm.","operationId":"cron_welcome_new_users_api_cron_welcome_new_users_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/admin/migrate-encrypt-cases":{"post":{"summary":"Admin Migrate Encrypt Cases","description":"One-shot migration: encrypt PHI columns on legacy cases rows.\nIdempotent — safe to call repeatedly. Returns counts per column.","operationId":"admin_migrate_encrypt_cases_api_admin_migrate_encrypt_cases_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/admin/recent-signups":{"get":{"summary":"Recent Signups","description":"Cron-secret-gated. Returns the most recent N signups with masked emails.\nUsed for quick \"who signed up?\" checks without owner JWT auth.","operationId":"recent_signups_api_admin_recent_signups_get","parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","default":10,"title":"Limit"}},{"name":"exclude_owners","in":"query","required":false,"schema":{"type":"boolean","default":true,"title":"Exclude Owners"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/admin/purge-profiles":{"post":{"summary":"Admin Purge Profiles","description":"Remove rows from the app's own sign-up list (profiles.db) by exact user id.\n\nCron-secret-gated (X-Cron-Secret header only). Body: {\"ids\": [...], \"go\": false}.\nNothing else in the app deletes a profiles row, so an account removed from\nSupabase (e.g. the Sep 28 2026 DD214 test users) stays in the public\nsignups_total forever. Refuses the whole request (409, nothing deleted) if\nany id is not in profiles or still owns a case. Dry run unless go is true;\non go it first copies profiles.db to <db dir>/backups/profiles.<UTC>.db with\nthe sqlite backup API, and returns the deleted rows so the caller keeps a copy.","operationId":"admin_purge_profiles_api_admin_purge_profiles_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/admin/condition-coverage":{"get":{"summary":"Condition Coverage","description":"Cron-secret-gated. Aggregates the condition vocabulary across ALL cases\n(rated_conditions + denied_conditions + claimed_conditions) with no PII.\nUsed to find content gaps: which conditions do real users actually have\nthat we don't have blog/qa articles for?","operationId":"condition_coverage_api_admin_condition_coverage_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/admin/env-status":{"get":{"summary":"Admin Env Status","description":"Report which critical environment variables are configured. Cron-secret-gated.\nOnly returns presence/absence — never exposes the actual value.","operationId":"admin_env_status_api_admin_env_status_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/admin/check-doc-quality":{"post":{"summary":"Admin Check Doc Quality","description":"Scan every completed document_generator and dbq_fill stage across all\ncases and flag any that look like the raw-JSON-rendering bug:\n\n  - documents[i].content is empty AND structured_data has fields (UI may\n    fall back to JSON.stringify)\n  - dbqs[i] is missing veteran_info/medical_history/nexus_language (bare\n    skeleton — likely a generation failure that would render as raw JSON)\n  - exam_prep result has no cheat_sheet AND no raw_text (UI would fall\n    back to JSON.stringify)\n\nCron-secret-gated. Read-only — does not modify anything. Returns a list\nof cases that need re-analysis.","operationId":"admin_check_doc_quality_api_admin_check_doc_quality_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/admin/grant-credits":{"post":{"summary":"Admin Grant Credits","description":"Grant credits to a user by email. Cron-secret-gated.\n\nQuery params:\n    email   — recipient email (required)\n    credits — number to grant (required, integer)\n    mode    — 'add' (default; increments existing balance) or 'set' (overwrites)\n\nReturns the updated profile slice. Logs a credit_grant event.\n\nUseful for promos, marketing campaigns, refer-a-friend, \"sorry your\nfirst analysis didn't work, here's another\", etc.","operationId":"admin_grant_credits_api_admin_grant_credits_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/admin/topup-existing-users":{"post":{"summary":"Admin Topup Existing Users","description":"One-shot: top up every free-tier user to at least N credits.\nIdempotent — only bumps users who currently have less than N.\n\nQuery params:\n    target (default 2) — minimum credits each free user should have","operationId":"admin_topup_existing_users_api_admin_topup_existing_users_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/admin/rebalance-credits":{"post":{"summary":"Admin Rebalance Credits","description":"One-shot rebalance for the 2026-07 engine upgrade (deeper analyses).\nCron-secret-gated. Idempotent.\n\nRule (free-plan, non-owner profiles only):\n  credits == 2 AND no stripe_customer_id  -> set to 1  (free grant resize)\n  credits == 0                            -> set to 1  (goodwill grant)\n  everything else                         -> untouched, reported\n\nProfiles with a stripe_customer_id are NEVER reduced — they've been\nthrough Stripe checkout, so a balance of 2 may include purchased credits.\n\nQuery params:\n    dry_run — '1' (default) reports what WOULD change without writing.\n              '0' applies the changes and logs credit_grant events.","operationId":"admin_rebalance_credits_api_admin_rebalance_credits_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/admin/migrate-encrypt-other-phi":{"post":{"summary":"Admin Migrate Encrypt Other Phi","description":"Encrypt analyses.result, portal_messages.content, portal_documents.content.\nIdempotent.","operationId":"admin_migrate_encrypt_other_phi_api_admin_migrate_encrypt_other_phi_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/admin/migrate-encrypt-uploaded-files":{"post":{"summary":"Admin Migrate Encrypt Uploaded Files","description":"Walk uploads_dir and encrypt any plaintext file bytes in place.\nIdempotent — files already starting with the Fernet prefix are skipped.\n\nRender's request timeout is ~30s; large directories will 502. Use\nmax_files (default 50) to batch — call repeatedly until 'done'==True.\nReturns status dict with progress counters.","operationId":"admin_migrate_encrypt_uploaded_files_api_admin_migrate_encrypt_uploaded_files_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/cron/hermes-watch":{"post":{"summary":"Cron Hermes Watch","description":"Run one pass of the Hermes behavior watcher.\n\nRecommended schedule: every 6 hours via cron-job.org.\nWrites observation log, findings JSON, and rolling memory to persistent disk.\nOptionally emails Dwayne a digest if Hermes flags digest_worthy.","operationId":"cron_hermes_watch_api_cron_hermes_watch_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/admin/hermes-findings":{"get":{"summary":"Admin Hermes Findings","description":"Read-only: return latest Hermes findings JSON. Cron-secret-gated.","operationId":"admin_hermes_findings_api_admin_hermes_findings_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/admin/sentinel-overview":{"post":{"summary":"Admin Sentinel Overview","description":"Returns every profile with a Sentinel-relevant snapshot: days since signup,\ndocs uploaded, claims entered, ratings parsed, analysis stages completed,\ndays since last Sentinel contact. Cron-secret-gated.\n\nQuery params:\n    since_days (default 60) — only show profiles created in last N days","operationId":"admin_sentinel_overview_api_admin_sentinel_overview_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/cron/reengagement-scan":{"post":{"summary":"Cron Reengagement Scan","description":"Scan for stalled/inactive users and fire re-engagement emails.\n\nThree states (each gets a different template):\n  A. needs_decision_letter — has claimed_conditions but no rated_conditions\n  B. stalled_analysis — has docs uploaded ≥48h ago but <6 completed analysis stages\n  C. inactive_check_in — ≥9 stages completed AND case.updated_at older than 30d\n\nDedup: any user who received ANY re_engagement_* email in the last\nre_engagement_cooldown_days (default 14) is skipped.\n\nQuery params:\n    dry_run=true (default false) — don't send, just count\n    limit (default 50) — per-call cap (Resend 100/day free tier)\n    cooldown_days (default 14)\n    stalled_min_hours (default 48) — min age of upload before \"stalled\"\n    inactive_days (default 30) — cutoff for check-in template","operationId":"cron_reengagement_scan_api_cron_reengagement_scan_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/admin":{"get":{"summary":"Admin Page","operationId":"admin_page_admin_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/preview":{"get":{"summary":"Preview Page","description":"New homepage design — review before swapping to /. noindex'd in HTML head.","operationId":"preview_page_preview_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/ads/denied":{"get":{"summary":"Ads Denied","operationId":"ads_denied_ads_denied_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/ads/cp-exam":{"get":{"summary":"Ads Cp Exam","operationId":"ads_cp_exam_ads_cp_exam_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/ads/rating":{"get":{"summary":"Ads Rating","operationId":"ads_rating_ads_rating_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/me":{"get":{"summary":"Get Me","operationId":"get_me_api_me_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/profile":{"get":{"summary":"Get Profile","description":"Full user profile including display_name, plan, credits, timestamps, and case count.\n\nAlso backfills an empty referral_source from the first-touch cookie —\nthe safety net for signups whose JS attribution call never fired.","operationId":"get_profile_api_profile_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}},"patch":{"summary":"Update Profile","description":"Update editable profile fields (currently: display_name).","operationId":"update_profile_api_profile_patch","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/profile/accept-disclaimer":{"post":{"summary":"Accept Disclaimer","description":"Record that the user has accepted the upload disclaimer.","operationId":"accept_disclaimer_api_profile_accept_disclaimer_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/research-consent":{"get":{"summary":"Research Consent Status","description":"Current opt-in state for anonymized research use of decision letters.","operationId":"research_consent_status_api_research_consent_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}},"post":{"summary":"Research Consent Set","description":"Set (or revoke) research consent. Scope: VA-authored decision letters\nonly — medical records, statements, and exams are never included.","operationId":"research_consent_set_api_research_consent_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/admin/case-debug/{case_id}":{"get":{"summary":"Admin Case Debug","description":"READ-ONLY case + analyses dump for orchestration debugging.\n\nCron-secret gated. Use to understand what specific users actually saw\nfrom their runs (e.g., what the first organic conversion got from a\nno-docs analysis). Results are truncated per-stage to keep responses\nmanageable for the admin endpoint.","operationId":"admin_case_debug_api_admin_case_debug__case_id__get","parameters":[{"name":"case_id","in":"path","required":true,"schema":{"type":"string","title":"Case Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/admin/cleanup-zombie-analyses":{"post":{"summary":"Admin Cleanup Zombie Analyses","description":"Mark long-pending analyses as failed. Cron-secret gated.\n\nRunners that died before completing leave rows stuck at status=pending\nforever (observed during wave-3 OOM crashes pre-semaphore fix). This\ncleans them so admin views aren't cluttered with zombies.\n\nPass case_id to scope to one case, or omit to scan all cases.","operationId":"admin_cleanup_zombie_analyses_api_admin_cleanup_zombie_analyses_post","parameters":[{"name":"case_id","in":"query","required":false,"schema":{"type":"string","default":"","title":"Case Id"}},{"name":"older_than_min","in":"query","required":false,"schema":{"type":"integer","default":30,"title":"Older Than Min"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/admin/cron-trigger-analysis":{"post":{"summary":"Admin Cron Trigger Analysis","description":"Cron-secret variant of /api/admin/trigger-analysis.\n\nLets owner-side spot checks kick a re-analysis without needing the\nlogged-in JWT (used to verify denial-intel changes flow into prompts).","operationId":"admin_cron_trigger_analysis_api_admin_cron_trigger_analysis_post","parameters":[{"name":"case_id","in":"query","required":true,"schema":{"type":"string","title":"Case Id"}},{"name":"stages","in":"query","required":false,"schema":{"type":"string","default":"","title":"Stages"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/admin/cases-by-email":{"get":{"summary":"Admin Cases By Email","description":"List case_ids for a given user email. Cron-secret gated.\n\nUsed for owner-side spot checks (\"what does Dwayne's analysis look\nlike?\") without needing the logged-in JWT.","operationId":"admin_cases_by_email_api_admin_cases_by_email_get","parameters":[{"name":"email","in":"query","required":true,"schema":{"type":"string","title":"Email"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/admin/disk-info":{"get":{"summary":"Admin Disk Info","description":"Reports whether the Render persistent disk is mounted at /app/data\nand how much room is available. Cron-secret gated.\n\nIf `mounted` is false, prod is on ephemeral container storage — files\nwritten there disappear on next deploy. Attach a disk via the Render\ndashboard before importing the denial DB.","operationId":"admin_disk_info_api_admin_disk_info_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/admin/import-denial-db":{"post":{"summary":"Admin Import Denial Db","description":"One-shot: stream a denial_data.db file from a public URL onto the\nRender persistent disk at /app/data/denial_data.db. Cron-secret gated.\n\nBody: {\"url\": \"https://...\", \"expected_size_mb\": 721}\n\nStreams 1MB chunks to a tmp file beside the destination, then atomic\nrename. Existing file gets backed up to .bak so we can roll back if\nthe new copy is broken.","operationId":"admin_import_denial_db_api_admin_import_denial_db_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/admin/run-denial-migrations":{"post":{"summary":"Admin Run Denial Migrations","description":"Run the local reprocess_empty_outcomes + fix_decision_dates logic\nin-process against the production denial_data.db. Idempotent — safe to\nre-run. Cron-secret gated.","operationId":"admin_run_denial_migrations_api_admin_run_denial_migrations_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/cron/autopilot-report":{"post":{"summary":"Cron Autopilot Report","description":"Receive a structured summary from the nightly remote agent run.\n\nLets a future Claude session read what the agent did without anyone\nneeding to click through claude.ai/code/routines. The agent POSTs its\nfinal summary block here at end of run; we store it as an event so\n/api/admin/events can surface it.\n\nBody shape (flexible — extra fields preserved):\n    {\n      \"status\": \"SHIPPED_PR|PROPOSAL_ONLY|NOTHING_TO_FIX|ERROR\",\n      \"reason\": \"...\",\n      \"what_i_found\": \"...\",\n      \"what_i_changed\": \"...\",\n      \"pr_url\": \"...\",\n      \"diff\": \"...\",\n      \"forbidden_scope_issues\": \"...\",\n      \"next_run_hint\": \"...\"\n    }","operationId":"cron_autopilot_report_api_cron_autopilot_report_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/cron/nudge-fresh-unanalyzed":{"post":{"summary":"Cron Nudge Fresh Unanalyzed","description":"Find users who uploaded ≥1 doc but never kicked off analysis, and\nemail them a polite \"ready to analyze\" nudge.\n\nTargets the bounce point we discovered 2026-05-20: power-user chrisdawson71\nsigned up, came back 3 times, uploaded 15 docs over 9 minutes, then went\nsilent (likely went to bed at 3:33 AM their local time). 48-hour\nre-engagement threshold is too long for fresh signups — by 48h they've\nforgotten about us. This catches them inside the same day.\n\nCriteria for nudge:\n  - ≥1 `document_uploaded` event in the lookback window\n  - 0 `analysis_started` events for that user (ever)\n  - Last upload was between min_age_hours and max_age_hours ago\n  - User has not been nudged in cooldown_hours (idempotency)\n  - User is not an owner/test account\n\nQuery params:\n    dry_run=true (default false)\n    min_age_hours (default 4) — wait at least this long before nudging\n    max_age_hours (default 36) — give up after this; reengagement-scan takes over at 48h\n    cooldown_hours (default 72) — don't double-nudge\n    limit (default 20)","operationId":"cron_nudge_fresh_unanalyzed_api_cron_nudge_fresh_unanalyzed_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/contact":{"post":{"summary":"Submit Contact","description":"Inbound support ticket / bug report from the Help widget.\n\nAccepts both authenticated and anonymous submissions — vets in trouble\nshouldn't have to log in first. If a Bearer token is present we decode\nit for attribution; if not, we accept the user-provided email.\n\nRate-limited per-IP to prevent spam (5/hour). Emails the owner via Resend\nand logs as `support_ticket_submitted` so it shows up in the funnel.","operationId":"submit_contact_api_contact_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/cases":{"get":{"summary":"List Cases","operationId":"list_cases_api_cases_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}},"post":{"summary":"Create Case","operationId":"create_case_api_cases_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CaseCreateRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/cases/sample":{"post":{"summary":"Create Sample Case","description":"Create a pre-loaded demo case with 3 synthetic sample documents.\n\nLets curious-but-uncommitted users feel the analysis pipeline without\nhaving to upload their own VA paperwork in the moment. Same code path\nas a real case + real uploads — just with synthetic source files.\n\nRate-limited to 1 per hour per user so we don't get spammed.","operationId":"create_sample_case_api_cases_sample_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/cases/{case_id}":{"get":{"summary":"Get Case","operationId":"get_case_api_cases__case_id__get","parameters":[{"name":"case_id","in":"path","required":true,"schema":{"type":"string","title":"Case Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"patch":{"summary":"Update Case","operationId":"update_case_api_cases__case_id__patch","parameters":[{"name":"case_id","in":"path","required":true,"schema":{"type":"string","title":"Case Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CaseUpdateRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"summary":"Delete Case","operationId":"delete_case_api_cases__case_id__delete","parameters":[{"name":"case_id","in":"path","required":true,"schema":{"type":"string","title":"Case Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/admin/cleanup-orphan-uploads":{"post":{"summary":"Admin Cleanup Orphan Uploads","description":"Walk uploads_dir; for each case_id directory, check if a matching cases\nrow exists. If not, the case was deleted but the files weren't (legacy bug\nfixed 2026-04-28). Removes orphans. Idempotent.","operationId":"admin_cleanup_orphan_uploads_api_admin_cleanup_orphan_uploads_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/agent-keys":{"get":{"summary":"List Agent Keys","description":"List the user's agent keys (prefix + metadata only — never the hash\nor the full key).","operationId":"list_agent_keys_api_agent_keys_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}},"post":{"summary":"Create Agent Key","description":"Mint a personal agent API key. The plaintext key is shown ONCE here\nand never again — only its sha256 hash + a display prefix are stored.","operationId":"create_agent_key_api_agent_keys_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/agent-keys/{key_id}":{"delete":{"summary":"Revoke Agent Key","description":"Revoke one of the user's own agent keys. Scoped by user_id so a user\ncan never revoke another user's key.","operationId":"revoke_agent_key_api_agent_keys__key_id__delete","parameters":[{"name":"key_id","in":"path","required":true,"schema":{"type":"string","title":"Key Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/agent/v1/cases":{"get":{"summary":"Agent List Cases","description":"Return the agent-key owner's OWN cases only (read-only).","operationId":"agent_list_cases_api_agent_v1_cases_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/agent/v1/cases/{case_id}/analysis":{"get":{"summary":"Agent Case Analysis","description":"Return a per-stage analysis SUMMARY for one of the owner's cases.\n404s if the case isn't owned by the agent-key user (no cross-user/IDOR\naccess). Read-only — never runs a (paid) analysis.","operationId":"agent_case_analysis_api_agent_v1_cases__case_id__analysis_get","parameters":[{"name":"case_id","in":"path","required":true,"schema":{"type":"string","title":"Case Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/agent/v1/me":{"get":{"summary":"Agent Me","description":"Account summary for the agent-key owner (read scope): plan + remaining\ncredits, so an agent can check before spending a credit on an analysis.\nSingle profile read so plan and credits are consistent as of one moment.","operationId":"agent_me_api_agent_v1_me_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/agent/v1/cases/{case_id}/analyze":{"post":{"summary":"Agent Run Analysis","description":"Run the FULL analysis pipeline on one of the OWNER's cases, on the\nveteran's behalf. Requires a read_write-scoped agent key (explicit consent\nthe veteran minted). Credits follow the web app exactly: while\n_early_access_free() is on (permanently, owner decision 2026-08-17) nothing\nis spent and no 402 can fire; if it is ever turned off, a free-plan analysis\nspends a credit (402 when none remain, auto-refunded if the pipeline fails).\nIDOR-scoped (404 when the case isn't the key owner's). Hard cap: 5\nagent-initiated analyses per user per day so a leaked write key can't burn\nAPI spend.","operationId":"agent_run_analysis_api_agent_v1_cases__case_id__analyze_post","parameters":[{"name":"case_id","in":"path","required":true,"schema":{"type":"string","title":"Case Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/cases/{case_id}/documents":{"post":{"summary":"Upload Document","operationId":"upload_document_api_cases__case_id__documents_post","parameters":[{"name":"case_id","in":"path","required":true,"schema":{"type":"string","title":"Case Id"}}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_upload_document_api_cases__case_id__documents_post"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"get":{"summary":"List Documents","operationId":"list_documents_api_cases__case_id__documents_get","parameters":[{"name":"case_id","in":"path","required":true,"schema":{"type":"string","title":"Case Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/cases/{case_id}/documents/{doc_id}":{"delete":{"summary":"Delete Document","operationId":"delete_document_api_cases__case_id__documents__doc_id__delete","parameters":[{"name":"case_id","in":"path","required":true,"schema":{"type":"string","title":"Case Id"}},{"name":"doc_id","in":"path","required":true,"schema":{"type":"string","title":"Doc Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/cases/{case_id}/analyze":{"post":{"summary":"Start Analysis","description":"Start the AI analysis pipeline (runs in background).","operationId":"start_analysis_api_cases__case_id__analyze_post","parameters":[{"name":"case_id","in":"path","required":true,"schema":{"type":"string","title":"Case Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AnalysisRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/cases/{case_id}/analyze/{stage}":{"post":{"summary":"Run Stage","description":"Run a single analysis stage.","operationId":"run_stage_api_cases__case_id__analyze__stage__post","parameters":[{"name":"case_id","in":"path","required":true,"schema":{"type":"string","title":"Case Id"}},{"name":"stage","in":"path","required":true,"schema":{"type":"string","title":"Stage"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/cases/{case_id}/analysis":{"get":{"summary":"Get Analysis","description":"Get all analysis results for a case.","operationId":"get_analysis_api_cases__case_id__analysis_get","parameters":[{"name":"case_id","in":"path","required":true,"schema":{"type":"string","title":"Case Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/cases/{case_id}/analysis/{stage}":{"get":{"summary":"Get Stage Result","description":"Get a specific analysis stage result.","operationId":"get_stage_result_api_cases__case_id__analysis__stage__get","parameters":[{"name":"case_id","in":"path","required":true,"schema":{"type":"string","title":"Case Id"}},{"name":"stage","in":"path","required":true,"schema":{"type":"string","title":"Stage"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/cases/{case_id}/personalization-questions":{"post":{"summary":"Get Personalization Questions","description":"Generate targeted questions based on analysis results to personalize documents.","operationId":"get_personalization_questions_api_cases__case_id__personalization_questions_post","parameters":[{"name":"case_id","in":"path","required":true,"schema":{"type":"string","title":"Case Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/cases/{case_id}/personalize-documents":{"post":{"summary":"Personalize Documents","description":"Re-generate documents with veteran's personalized answers.","operationId":"personalize_documents_api_cases__case_id__personalize_documents_post","parameters":[{"name":"case_id","in":"path","required":true,"schema":{"type":"string","title":"Case Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/ai/analyze-dd214":{"post":{"summary":"Analyze Dd214","description":"AI extracts service information from an uploaded DD-214.","operationId":"analyze_dd214_api_ai_analyze_dd214_post","requestBody":{"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_analyze_dd214_api_ai_analyze_dd214_post"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/dev/dd214-doc":{"get":{"summary":"Get Dev Dd214 Doc","description":"Dev mode: check if DD-214 exists in dev_docs/dd214 folder.","operationId":"get_dev_dd214_doc_api_dev_dd214_doc_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/dev/analyze-local-dd214":{"post":{"summary":"Analyze Local Dd214","description":"Dev mode: read DD-214 from dev_docs/dd214 and analyze it.","operationId":"analyze_local_dd214_api_dev_analyze_local_dd214_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/dev/upload-dd214-to-case/{case_id}":{"post":{"summary":"Upload Dev Dd214 To Case","description":"Dev mode: upload DD-214 from dev_docs/dd214 folder as a case document.","operationId":"upload_dev_dd214_to_case_api_dev_upload_dd214_to_case__case_id__post","parameters":[{"name":"case_id","in":"path","required":true,"schema":{"type":"string","title":"Case Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/dev/upload-docs":{"get":{"summary":"List Dev Upload Docs","description":"Dev mode: list all documents available for case upload.","operationId":"list_dev_upload_docs_api_dev_upload_docs_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/dev/upload-all-to-case/{case_id}":{"post":{"summary":"Upload All Dev Docs To Case","description":"Dev mode: upload all docs from dev_docs/upload/ as case documents.","operationId":"upload_all_dev_docs_to_case_api_dev_upload_all_to_case__case_id__post","parameters":[{"name":"case_id","in":"path","required":true,"schema":{"type":"string","title":"Case Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/ai/analyze-denials":{"post":{"summary":"Analyze Denials","description":"AI analyzes uploaded denial/decision documents to extract denied conditions.","operationId":"analyze_denials_api_ai_analyze_denials_post","requestBody":{"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_analyze_denials_api_ai_analyze_denials_post"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/dev/denial-docs":{"get":{"summary":"Get Dev Denial Docs","description":"Dev mode: list available denial documents from dev_docs folder.","operationId":"get_dev_denial_docs_api_dev_denial_docs_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/dev/analyze-local-denials":{"post":{"summary":"Analyze Local Denials","description":"Dev mode: read denial docs from dev_docs folder and analyze them.","operationId":"analyze_local_denials_api_dev_analyze_local_denials_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/ai/analyze-ratings":{"post":{"summary":"Analyze Ratings","description":"AI analyzes uploaded decision documents to extract GRANTED/rated conditions.","operationId":"analyze_ratings_api_ai_analyze_ratings_post","requestBody":{"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_analyze_ratings_api_ai_analyze_ratings_post"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/dev/rated-docs":{"get":{"summary":"Get Dev Rated Docs","description":"Dev mode: list available rated condition documents from dev_docs/rated folder.","operationId":"get_dev_rated_docs_api_dev_rated_docs_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/dev/analyze-local-ratings":{"post":{"summary":"Analyze Local Ratings","description":"Dev mode: read rated docs from dev_docs/rated folder and analyze them.","operationId":"analyze_local_ratings_api_dev_analyze_local_ratings_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/ai/recommend-conditions":{"post":{"summary":"Recommend Conditions","description":"AI recommends conditions to claim based on service info and existing conditions.","operationId":"recommend_conditions_api_ai_recommend_conditions_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/va-math":{"post":{"summary":"Calculate Va Math","description":"Calculate VA combined disability rating.","operationId":"calculate_va_math_api_va_math_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/VAMathRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/va-math/pathfinder":{"post":{"summary":"Pathfinder","description":"Find paths to reach a target combined rating.","operationId":"pathfinder_api_va_math_pathfinder_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PathfinderRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/knowledge/secondary":{"post":{"summary":"Lookup Secondary","description":"Get secondary conditions for a primary condition.","operationId":"lookup_secondary_api_knowledge_secondary_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SecondaryLookupRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/knowledge/rating":{"post":{"summary":"Lookup Rating","description":"Get rating criteria for a condition.","operationId":"lookup_rating_api_knowledge_rating_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RatingLookupRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/knowledge/legal":{"post":{"summary":"Lookup Legal","description":"Get relevant legal authorities for a context.","operationId":"lookup_legal_api_knowledge_legal_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LegalLookupRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/knowledge/authorities":{"get":{"summary":"All Authorities","description":"Get all legal authorities.","operationId":"all_authorities_api_knowledge_authorities_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/knowledge/claim-types":{"get":{"summary":"All Claim Types","description":"Get all claim types and pathways.","operationId":"all_claim_types_api_knowledge_claim_types_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/knowledge/pact-act":{"get":{"summary":"Pact Act Info","description":"Get PACT Act presumptive conditions.","operationId":"pact_act_info_api_knowledge_pact_act_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/tools/evidence-check":{"post":{"summary":"Tools Evidence Check","description":"Free nexus-letter / DBQ evidence checker (rules in nexus_check.py).\nNo LLM call, no auth, nothing stored. It says whether a claim needs a\nnexus opinion; it never writes one.","operationId":"tools_evidence_check_api_tools_evidence_check_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/knowledge/secondary-map":{"get":{"summary":"Secondary Map","description":"Get full secondary conditions map.","operationId":"secondary_map_api_knowledge_secondary_map_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/knowledge/stages":{"get":{"summary":"Analysis Stages","description":"Get all analysis stage definitions.","operationId":"analysis_stages_api_knowledge_stages_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/v1/articles":{"get":{"summary":"List Articles","description":"List all available articles with metadata. Agent-accessible, no auth required.","operationId":"list_articles_api_v1_articles_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/v1/articles/{slug}":{"get":{"summary":"Get Article","description":"Get full structured content of a specific article. Agent-accessible.","operationId":"get_article_api_v1_articles__slug__get","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","title":"Slug"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/search":{"post":{"summary":"Search Articles Api","description":"Search articles by natural language query. Agent-accessible.","operationId":"search_articles_api_api_v1_search_post","requestBody":{"content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Request"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/knowledge-graph":{"get":{"summary":"Knowledge Graph","description":"Export full knowledge graph for agent consumption.","operationId":"knowledge_graph_api_v1_knowledge_graph_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/cases/{case_id}/benefits":{"get":{"summary":"Get Case Benefits","description":"Calculate priority group and benefits entitlements for a case.","operationId":"get_case_benefits_api_cases__case_id__benefits_get","parameters":[{"name":"case_id","in":"path","required":true,"schema":{"type":"string","title":"Case Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/facilities/search":{"post":{"summary":"Search Facilities","description":"Find healthcare facilities near a location.","operationId":"search_facilities_api_facilities_search_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FacilitySearchRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/reps/search":{"post":{"summary":"Search Representatives","description":"Accredited representatives near a ZIP, with the facts to judge them by.","operationId":"search_representatives_api_reps_search_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RepSearchRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/reps/verify/{registration_number}":{"get":{"summary":"Verify Representative","description":"Is this person still on the VA roster?\n\nThe reason this exists separately from search: a veteran who signed a\n21-22 six months ago has a representative of record, and the only way to\nlearn that person's accreditation has lapsed is to look again.","operationId":"verify_representative_api_reps_verify__registration_number__get","parameters":[{"name":"registration_number","in":"path","required":true,"schema":{"type":"string","title":"Registration Number"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/reps/lookup":{"get":{"summary":"Lookup Representatives","description":"Name or registration-number search over the roster, current and former\nmembers both (/representatives/check). Only public roster data in or out.","operationId":"lookup_representatives_api_reps_lookup_get","parameters":[{"name":"q","in":"query","required":true,"schema":{"type":"string","title":"Q"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/facilities/mission-act":{"post":{"summary":"Mission Act Check","description":"Check MISSION Act community care eligibility based on distance.","operationId":"mission_act_check_api_facilities_mission_act_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MissionActRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/cases/{case_id}/tracking/init":{"post":{"summary":"Init Tracking","description":"Initialize default claim tracking milestones for a case.","operationId":"init_tracking_api_cases__case_id__tracking_init_post","parameters":[{"name":"case_id","in":"path","required":true,"schema":{"type":"string","title":"Case Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/cases/{case_id}/tracking":{"get":{"summary":"Get Tracking","description":"Get all tracking milestones for a case.","operationId":"get_tracking_api_cases__case_id__tracking_get","parameters":[{"name":"case_id","in":"path","required":true,"schema":{"type":"string","title":"Case Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/cases/{case_id}/tracking/{milestone_id}":{"patch":{"summary":"Update Tracking","description":"Update a tracking milestone status/notes. AI processes N/A reasons.","operationId":"update_tracking_api_cases__case_id__tracking__milestone_id__patch","parameters":[{"name":"case_id","in":"path","required":true,"schema":{"type":"string","title":"Case Id"}},{"name":"milestone_id","in":"path","required":true,"schema":{"type":"string","title":"Milestone Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/denials/stats":{"get":{"summary":"Denial Stats","description":"Corpus-wide Board of Veterans' Appeals outcome statistics: how 4.1M issue\ndispositions across 1.9M published decisions (1992->present) actually came\nout, by year and by condition. Public, read-only, no PII.","operationId":"denial_stats_api_denials_stats_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/denials/condition/{condition}":{"get":{"summary":"Denial Condition Intel","description":"Everything measured for one condition: Board outcome shares (complete\nyears and all years), the year trend, which evidence went with a grant,\nthe denial reasons tagged in the sample, the authorities most cited, and the\ncounter-strategy for each reason. Public, read-only, no PII.","operationId":"denial_condition_intel_api_denials_condition__condition__get","parameters":[{"name":"condition","in":"path","required":true,"schema":{"type":"string","title":"Condition"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/denials/search":{"post":{"summary":"Denial Search","description":"Search denial decisions by condition, outcome, reason, denial type.","operationId":"denial_search_api_denials_search_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/denials/reversed/{condition}":{"get":{"summary":"Denial Reversed","description":"Get reversed/vacated decisions for a condition — what VA got wrong.","operationId":"denial_reversed_api_denials_reversed__condition__get","parameters":[{"name":"condition","in":"path","required":true,"schema":{"type":"string","title":"Condition"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","default":10,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/denials/reasoning/{condition}/{denial_type}":{"get":{"summary":"Denial Reasoning","description":"Get actual reasoning examples for a condition + denial type combo.","operationId":"denial_reasoning_api_denials_reasoning__condition___denial_type__get","parameters":[{"name":"condition","in":"path","required":true,"schema":{"type":"string","title":"Condition"}},{"name":"denial_type","in":"path","required":true,"schema":{"type":"string","title":"Denial Type"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","default":5,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/denials/authorities/top":{"get":{"summary":"Denial Top Authorities","description":"Most-cited legal authorities across the BVA corpus, ranked by the number\nof DISTINCT decisions that cite them. kind=cases|regulations|statutes;\ncondition= narrows to one condition bucket. Public, read-only, no PII.","operationId":"denial_top_authorities_api_denials_authorities_top_get","parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","default":25,"title":"Limit"}},{"name":"kind","in":"query","required":false,"schema":{"type":"string","default":"cases","title":"Kind"}},{"name":"condition","in":"query","required":false,"schema":{"type":"string","default":"","title":"Condition"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/denials/counters/{denial_type}":{"get":{"summary":"Denial Counter","description":"Get the counter-strategy for a specific denial type.","operationId":"denial_counter_api_denials_counters__denial_type__get","parameters":[{"name":"denial_type","in":"path","required":true,"schema":{"type":"string","title":"Denial Type"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/denials/intelligence":{"post":{"summary":"Denial Intelligence For Conditions","description":"Get merged denial intelligence for multiple conditions at once.","operationId":"denial_intelligence_for_conditions_api_denials_intelligence_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/bva/search":{"post":{"summary":"Bva Search","description":"Full-text search across 39K+ BVA decisions.","operationId":"bva_search_api_bva_search_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/cases/{case_id}/share":{"post":{"summary":"Create Share Link","description":"Create a shareable access link for attorney/VSO.","operationId":"create_share_link_api_cases__case_id__share_post","parameters":[{"name":"case_id","in":"path","required":true,"schema":{"type":"string","title":"Case Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/cases/{case_id}/shares":{"get":{"summary":"List Share Links","description":"List all share links for a case (owner only).","operationId":"list_share_links_api_cases__case_id__shares_get","parameters":[{"name":"case_id","in":"path","required":true,"schema":{"type":"string","title":"Case Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/shares/{link_id}":{"delete":{"summary":"Revoke Share Link","description":"Deactivate a share link.","operationId":"revoke_share_link_api_shares__link_id__delete","parameters":[{"name":"link_id","in":"path","required":true,"schema":{"type":"string","title":"Link Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/portal/validate":{"post":{"summary":"Validate Portal Access","description":"Validate a share code (and optional PIN) — public endpoint, rate-limited.","operationId":"validate_portal_access_api_portal_validate_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/portal/chat":{"post":{"summary":"Portal Chat Endpoint","description":"AI chat for the attorney/VSO portal — public (validated by share code).","operationId":"portal_chat_endpoint_api_portal_chat_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/cases/{case_id}/chat":{"post":{"summary":"Veteran Chat Endpoint","description":"AI chat for the authenticated veteran — full case context.","operationId":"veteran_chat_endpoint_api_cases__case_id__chat_post","parameters":[{"name":"case_id","in":"path","required":true,"schema":{"type":"string","title":"Case Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/portal/documents/{link_id}":{"get":{"summary":"Get Portal Docs","description":"Get documents shared through the portal — requires share code auth.","operationId":"get_portal_docs_api_portal_documents__link_id__get","parameters":[{"name":"link_id","in":"path","required":true,"schema":{"type":"string","title":"Link Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/portal/document/{doc_id}/text":{"get":{"summary":"Get Portal Doc Text","description":"Get the extracted text of a case document — requires share code auth.","operationId":"get_portal_doc_text_api_portal_document__doc_id__text_get","parameters":[{"name":"doc_id","in":"path","required":true,"schema":{"type":"string","title":"Doc Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/portal/document/{doc_id}/download":{"get":{"summary":"Download Portal Doc","description":"Download the original uploaded file (PDF, image, etc.) — requires share code auth.","operationId":"download_portal_doc_api_portal_document__doc_id__download_get","parameters":[{"name":"doc_id","in":"path","required":true,"schema":{"type":"string","title":"Doc Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/cases/{case_id}/documents/{doc_id}/download":{"get":{"summary":"Download Case Doc","description":"Download the original uploaded file for the case owner.\nDecrypts on the fly — bytes are encrypted at rest.","operationId":"download_case_doc_api_cases__case_id__documents__doc_id__download_get","parameters":[{"name":"case_id","in":"path","required":true,"schema":{"type":"string","title":"Case Id"}},{"name":"doc_id","in":"path","required":true,"schema":{"type":"string","title":"Doc Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/portal":{"get":{"summary":"Portal Page","description":"Serve the attorney/VSO portal page.","operationId":"portal_page_portal_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/terms":{"get":{"summary":"Legal Aliases","operationId":"legal_aliases_terms_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/privacy":{"get":{"summary":"Legal Aliases","operationId":"legal_aliases_privacy_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/legal":{"get":{"summary":"Legal Page","description":"Serve the TOS / Privacy Policy / AI Disclosure page.\n\nRouted through _render_legal so /legal carries a canonical too — the file itself has\nnone, which left three legal documents at one URL with no canonical and one generic\ntitle.","operationId":"legal_page_legal_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/portal/consent":{"post":{"summary":"Portal Consent","description":"Record consent acceptance for a portal share link.","operationId":"portal_consent_api_portal_consent_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/cases/{case_id}/consent":{"post":{"summary":"Case Consent","description":"Record consent acceptance for a case (app dashboard).","operationId":"case_consent_api_cases__case_id__consent_post","parameters":[{"name":"case_id","in":"path","required":true,"schema":{"type":"string","title":"Case Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/cases/{case_id}/forms":{"get":{"summary":"List Forms For Case","description":"List all supported forms with their generation status for this case.","operationId":"list_forms_for_case_api_cases__case_id__forms_get","parameters":[{"name":"case_id","in":"path","required":true,"schema":{"type":"string","title":"Case Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/cases/{case_id}/forms/{form_id}/generate":{"post":{"summary":"Generate Form Pdf","description":"Generate (or re-generate) a filled PDF for the given form.\nSynchronous; expect 5-30s depending on gap_fill and DeepSeek latency.\nPDF is encrypted at rest and downloadable via the download endpoint.","operationId":"generate_form_pdf_api_cases__case_id__forms__form_id__generate_post","parameters":[{"name":"case_id","in":"path","required":true,"schema":{"type":"string","title":"Case Id"}},{"name":"form_id","in":"path","required":true,"schema":{"type":"string","title":"Form Id"}},{"name":"gap_fill","in":"query","required":false,"schema":{"type":"boolean","default":true,"title":"Gap Fill"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/cases/{case_id}/forms/{form_id}/download":{"get":{"summary":"Download Form Pdf","description":"Decrypt and serve the most recently generated PDF for this case + form.","operationId":"download_form_pdf_api_cases__case_id__forms__form_id__download_get","parameters":[{"name":"case_id","in":"path","required":true,"schema":{"type":"string","title":"Case Id"}},{"name":"form_id","in":"path","required":true,"schema":{"type":"string","title":"Form Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/cases/{case_id}/form-details":{"get":{"summary":"Get Form Details","description":"Return the saved form_details for this case (fast, no LLM).","operationId":"get_form_details_api_cases__case_id__form_details_get","parameters":[{"name":"case_id","in":"path","required":true,"schema":{"type":"string","title":"Case Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"summary":"Save Form Details","description":"Save the veteran-supplied form_details (whitelisted keys only; no SSN).","operationId":"save_form_details_api_cases__case_id__form_details_post","parameters":[{"name":"case_id","in":"path","required":true,"schema":{"type":"string","title":"Case Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/cases/{case_id}/form-details/extract":{"post":{"summary":"Extract Form Details","description":"Best-effort extraction of contact info from the case documents (slow, LLM).\nReturns only contract keys found; never an SSN.","operationId":"extract_form_details_api_cases__case_id__form_details_extract_post","parameters":[{"name":"case_id","in":"path","required":true,"schema":{"type":"string","title":"Case Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/cases/{case_id}/ptsd-stressors":{"get":{"summary":"Get Ptsd Stressors","description":"Return the saved ptsd_stressors list for this case (fast, no LLM).","operationId":"get_ptsd_stressors_api_cases__case_id__ptsd_stressors_get","parameters":[{"name":"case_id","in":"path","required":true,"schema":{"type":"string","title":"Case Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"summary":"Save Ptsd Stressors","description":"Save the veteran-supplied ptsd_stressors (whitelisted keys only; type forced into enum).","operationId":"save_ptsd_stressors_api_cases__case_id__ptsd_stressors_post","parameters":[{"name":"case_id","in":"path","required":true,"schema":{"type":"string","title":"Case Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/cases/{case_id}/ptsd-stressors/extract":{"post":{"summary":"Extract Ptsd Stressors","description":"Best-effort extraction of PTSD stressor events from the case documents (slow, LLM).\nReturns only events actually found in the docs; never fabricated.","operationId":"extract_ptsd_stressors_api_cases__case_id__ptsd_stressors_extract_post","parameters":[{"name":"case_id","in":"path","required":true,"schema":{"type":"string","title":"Case Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/cases/{case_id}/dbq-pack":{"get":{"summary":"Get Dbq Pack","description":"Return a print-friendly DBQ-styled HTML page rendering the latest dbq_fill\nanalysis. Veteran takes to private physician for clinical-finding signoff.","operationId":"get_dbq_pack_api_cases__case_id__dbq_pack_get","parameters":[{"name":"case_id","in":"path","required":true,"schema":{"type":"string","title":"Case Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/cases/{case_id}/exam-pack":{"get":{"summary":"Get Exam Pack","description":"Return a print-friendly HTML page rendering the latest exam_prep analysis.\nVeteran can print to PDF or view on phone offline (after caching the page).\nReturns 412 (Precondition Failed) if exam_prep stage hasn't been run yet.","operationId":"get_exam_pack_api_cases__case_id__exam_pack_get","parameters":[{"name":"case_id","in":"path","required":true,"schema":{"type":"string","title":"Case Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/cases/{case_id}/recommended-articles":{"get":{"summary":"Recommended Articles","description":"Return blog articles most relevant to this case's conditions.\n\nUsed by the dashboard \"Further Reading for Your Case\" panel and by the\ngenerated letter packs / DBQ forms to surface deeper-dive content\nmatching the user's actual situation.","operationId":"recommended_articles_api_cases__case_id__recommended_articles_get","parameters":[{"name":"case_id","in":"path","required":true,"schema":{"type":"string","title":"Case Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/cases/{case_id}/dbq-form/{condition_index}":{"get":{"summary":"Get Dbq Form","description":"Return the official-form facsimile for ONE condition's DBQ from the\nlatest dbq_fill analysis. Veteran takes this to their appointment and\nreads each section's pre-filled response when the doctor asks about it.\n\nQuery params:\n    format=html (default) — returns styled HTML for in-browser viewing\n    format=pdf            — returns a PDF for download","operationId":"get_dbq_form_api_cases__case_id__dbq_form__condition_index__get","parameters":[{"name":"case_id","in":"path","required":true,"schema":{"type":"string","title":"Case Id"}},{"name":"condition_index","in":"path","required":true,"schema":{"type":"integer","title":"Condition Index"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/cases/{case_id}/dbq-forms-index":{"get":{"summary":"Get Dbq Forms Index","description":"List all DBQs available for this case so the dashboard can build a\n'pick which condition' selector before opening the form facsimile.","operationId":"get_dbq_forms_index_api_cases__case_id__dbq_forms_index_get","parameters":[{"name":"case_id","in":"path","required":true,"schema":{"type":"string","title":"Case Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/cases/{case_id}/live-companion":{"get":{"summary":"Get Live Companion","description":"Phone-optimized live companion for use DURING a C&P exam or doctor's\nappointment. Veteran taps the matching question topic, reads the optimized\nresponse aloud. Sourced from the exam_prep stage output.","operationId":"get_live_companion_api_cases__case_id__live_companion_get","parameters":[{"name":"case_id","in":"path","required":true,"schema":{"type":"string","title":"Case Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/cases/{case_id}/letter-pack/{doc_index}":{"get":{"summary":"Get Letter Pack","description":"Return a print-friendly letterhead HTML page (or PDF) for one of the\ndocuments produced by the document_generator stage. Auto-fills the\nveteran's name, VA file number, and today's date; highlights\nphysician-fill placeholders.\n\nQuery params:\n    format=html (default) — returns styled HTML\n    format=pdf            — returns a PDF download","operationId":"get_letter_pack_api_cases__case_id__letter_pack__doc_index__get","parameters":[{"name":"case_id","in":"path","required":true,"schema":{"type":"string","title":"Case Id"}},{"name":"doc_index","in":"path","required":true,"schema":{"type":"integer","title":"Doc Index"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/cases/{case_id}/vso-brief":{"get":{"summary":"Get Vso Brief","description":"Print-ready one-pager for the veteran's accredited representative.\n\nQuery params:\n    format=html (default) — styled, print-friendly HTML\n    format=pdf            — PDF download","operationId":"get_vso_brief_api_cases__case_id__vso_brief_get","parameters":[{"name":"case_id","in":"path","required":true,"schema":{"type":"string","title":"Case Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/admin/site-analytics":{"get":{"summary":"Admin Site Analytics","description":"Cron-secret-gated. The single dashboard for site-optimization decisions.\nCombines static-page tracking + /app funnel events + error data.","operationId":"admin_site_analytics_api_admin_site_analytics_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/admin/feature-usage":{"get":{"summary":"Admin Feature Usage","description":"Cron-secret-gated. Aggregates feature-level engagement events into\nactionable buckets:\n\n  tools_by_clicks     — which AI tool tiles users actually click\n  tabs_by_dwell       — which dashboard tabs users actually read (vs skim)\n  docs_by_opens       — which generated docs users actually open\n\nUse this to find clutter candidates: features in the \"rarely clicked\"\nbucket are info-overload that should be demoted or hidden.","operationId":"admin_feature_usage_api_admin_feature_usage_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/admin/attention-report":{"get":{"summary":"Admin Attention Report","description":"Cron-secret-gated. Answers \"what do people NOT bother looking at?\"\n\nJoins the visibility signal (element_visible — fired when a tagged element\nis >=50% on screen for >=1s, carrying visible_sec) with engagement signals\n(tab_dwell / tool_clicked / doc_card_opened) and page scroll-depth. Then\ncross-references against the FULL set of data-vis-track elements in\napp.html so we can flag elements that NO ONE ever even had on screen.\n\nPer tracked element we classify:\n  NEVER_SEEN  — 0 visibility events (hidden behind an unused tab, or below\n                a fold nobody scrolls to)\n  GLANCED     — seen but avg on-screen time < 2s (scrolled past, ignored)\n  READ        — seen with real dwell\n\nThis is the \"is it dead weight?\" report: NEVER_SEEN + GLANCED elements are\ncandidates to remove, demote, or move up the page.","operationId":"admin_attention_report_api_admin_attention_report_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/sitemap.xml":{"get":{"summary":"Sitemap","operationId":"sitemap_sitemap_xml_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/feat":{"post":{"summary":"Api Feat","description":"Element-level seen/click beacon (feat_track.py) -> Supabase feat_events. Non-blocking, no PII.","operationId":"api_feat_api_feat_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/cursor":{"post":{"summary":"Api Cursor","description":"Cursor/scroll/touch trace beacon (cursor_track.py) -> Supabase cursor_events.\nNon-blocking, coordinates only, no PII.","operationId":"api_cursor_api_cursor_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/subscribe":{"post":{"summary":"Api Subscribe","description":"Newsletter opt-in. Stores email + consent; returns the unsubscribe token. No other PII.","operationId":"api_subscribe_api_subscribe_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/unsubscribe":{"get":{"summary":"Unsubscribe","description":"One-click unsubscribe (token in the email link). Also the landing for Sentinel emails.\n\nKept for links already sitting in people's inboxes; new email should use\n/u/<token>.","operationId":"unsubscribe_unsubscribe_get","responses":{"200":{"description":"Successful Response","content":{"text/html":{"schema":{"type":"string"}}}}}}},"/u/{token}":{"get":{"summary":"Unsubscribe Path","description":"Path-form unsubscribe — the shape new email should link to.\n\nThe token is 24 hex chars (db.py: sha256(...)[:24]), so the query form\n?token=<hex> is exactly the '=' followed by hex that was consumed in\ntransit on a real send. A dead unsubscribe link is the one defect this\nemail genuinely cannot ship with, so the token travels as a path\nsegment where no '=' exists to be eaten.","operationId":"unsubscribe_path_u__token__get","parameters":[{"name":"token","in":"path","required":true,"schema":{"type":"string","title":"Token"}}],"responses":{"200":{"description":"Successful Response","content":{"text/html":{"schema":{"type":"string"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/robots.txt":{"get":{"summary":"Robots","operationId":"robots_robots_txt_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/llms.txt":{"get":{"summary":"Llms Txt","operationId":"llms_txt_llms_txt_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/7e3c9a1f4b8d2e6a05c7f1b9d3a8e6042.txt":{"get":{"summary":"Indexnow Key","operationId":"indexnow_key_7e3c9a1f4b8d2e6a05c7f1b9d3a8e6042_txt_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/c1f4a97d3b5e48d2a6f80c9e2d715b4a.txt":{"get":{"summary":"Indexnow Fleet Key","operationId":"indexnow_fleet_key_c1f4a97d3b5e48d2a6f80c9e2d715b4a_txt_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/.well-known/mcp-registry-auth":{"get":{"summary":"Mcp Registry Auth","operationId":"mcp_registry_auth__well_known_mcp_registry_auth_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/.well-known/ai-plugin.json":{"get":{"summary":"Ai Plugin Manifest","description":"Agent-discovery manifest. Lets a person's AI agent discover VetAid's\npublic, read-only BVA outcome-intelligence API (no auth, no veteran PII)\nand ground VA-claim answers in real case-law data. Full claim-file\nanalysis stays behind auth in the app.","operationId":"ai_plugin_manifest__well_known_ai_plugin_json_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/18e026d3a8625e94e40841e78f9e8397.txt":{"get":{"summary":"Indexnow Key","description":"IndexNow verification key — must be served at root for Bing to accept submissions.","operationId":"indexnow_key_18e026d3a8625e94e40841e78f9e8397_txt_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/how-it-works":{"get":{"summary":"How It Works Page","operationId":"how_it_works_page_how_it_works_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/pricing":{"get":{"summary":"Pricing Page","operationId":"pricing_page_pricing_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/best-ai-for-va-claims":{"get":{"summary":"Best Ai Landing","operationId":"best_ai_landing_best_ai_for_va_claims_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/about":{"get":{"summary":"About Page","description":"Canonical description of VetAid, the veterans claims tool (PLAN identity_oct11).","operationId":"about_page_about_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/missed-secondary-conditions":{"get":{"summary":"Missed Secondaries Hub","operationId":"missed_secondaries_hub_missed_secondary_conditions_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/cp-examiner-errors":{"get":{"summary":"Cp Examiner Errors Hub","operationId":"cp_examiner_errors_hub_cp_examiner_errors_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/bva":{"get":{"summary":"Bva Index","operationId":"bva_index_bva_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/bva/condition/{slug}":{"get":{"summary":"Bva Condition","operationId":"bva_condition_bva_condition__slug__get","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","title":"Slug"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/bva/outcomes":{"get":{"summary":"Bva Outcomes","operationId":"bva_outcomes_bva_outcomes_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/bva/reversals":{"get":{"summary":"Bva Reversals Index","operationId":"bva_reversals_index_bva_reversals_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/bva/reversals/{cond_slug}":{"get":{"summary":"Bva Reversals Condition","operationId":"bva_reversals_condition_bva_reversals__cond_slug__get","parameters":[{"name":"cond_slug","in":"path","required":true,"schema":{"type":"string","title":"Cond Slug"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/bva/dataset":{"get":{"summary":"Bva Dataset Page","operationId":"bva_dataset_page_bva_dataset_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/bva/evidence":{"get":{"summary":"Bva Evidence Index","operationId":"bva_evidence_index_bva_evidence_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/bva/evidence/{cond_slug}":{"get":{"summary":"Bva Evidence Condition","operationId":"bva_evidence_condition_bva_evidence__cond_slug__get","parameters":[{"name":"cond_slug","in":"path","required":true,"schema":{"type":"string","title":"Cond Slug"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/bva/judges":{"get":{"summary":"Bva Judges Index","operationId":"bva_judges_index_bva_judges_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/bva/judges/{judge_slug}":{"get":{"summary":"Bva Judge Page","operationId":"bva_judge_page_bva_judges__judge_slug__get","parameters":[{"name":"judge_slug","in":"path","required":true,"schema":{"type":"string","title":"Judge Slug"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/bva/{case_number}":{"get":{"summary":"Bva Decision","operationId":"bva_decision_bva__case_number__get","parameters":[{"name":"case_number","in":"path","required":true,"schema":{"type":"string","title":"Case Number"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/m21/changes":{"get":{"summary":"M21 Changes Page","description":"The VBA-manual change log (generate_m21_changes_page.py from the weekly\nKnowVA version archive diffed on trading-01).","operationId":"m21_changes_page_m21_changes_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/m21/changes":{"get":{"summary":"M21 Changes Api","description":"Manual changes, filterable by condition (free text, matched to the site's\ncondition vocabulary), claim topic (tdiu, smc, exams, nexus, ...) and date.","operationId":"m21_changes_api_api_m21_changes_get","parameters":[{"name":"condition","in":"query","required":false,"schema":{"type":"string","default":"","title":"Condition"}},{"name":"topic","in":"query","required":false,"schema":{"type":"string","default":"","title":"Topic"}},{"name":"since","in":"query","required":false,"schema":{"type":"string","default":"","title":"Since"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","default":100,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/cron/m21-alerts":{"post":{"summary":"Cron M21 Alerts","description":"The living case file: match this week's manual changes against every\nsaved case's conditions and tell the veteran.\n\nDRY-RUN BY DEFAULT. Sends only when the Render env M21_ALERTS_ENABLED=1 is\nset AND ?dry_run=true is not passed — the send switch is the owner's call.\nIdempotent per (user, article, version) via the events log, so a re-run\nnever double-sends. Events carry ids and counts, never email addresses.\n\nQuery params: since=YYYY-MM-DD (default 8 days ago) · limit (max emails,\ndefault 50) · dry_run=true.","operationId":"cron_m21_alerts_api_cron_m21_alerts_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/cfr":{"get":{"summary":"Cfr Hub","description":"Procedural 38 CFR guide hub (gen_cfr_procedural.py).","operationId":"cfr_hub_cfr_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/cfr/{sec}":{"get":{"summary":"Cfr Section","operationId":"cfr_section_cfr__sec__get","parameters":[{"name":"sec","in":"path","required":true,"schema":{"type":"string","title":"Sec"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/pro":{"get":{"summary":"Pro Hub","description":"Professional hub — free tools for VSOs / accredited reps (B2B lane).","operationId":"pro_hub_pro_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/tools":{"get":{"summary":"Tools Index","description":"Tools hub — lists the interactive calculators under /tools/*.","operationId":"tools_index_tools_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/tools/":{"get":{"summary":"Tools Index Slash","description":"Relative 301 so /tools/ never downgrades to http:// (Starlette's\nredirect_slashes builds an absolute http URL behind Render's proxy).","operationId":"tools_index_slash_tools__get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/tools/{slug}":{"get":{"summary":"Serve Tool","operationId":"serve_tool_tools__slug__get","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","title":"Slug"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/decode-letter":{"get":{"summary":"Read Document Alias","description":"AI-assistant demand for a read my document page (create lane, 2026-09-17..19:\nvetaid.ai/read-document seen, outside path_map). 301 to the no-account\ndecision-letter reader so the demand resolves instead of 404ing.","operationId":"read_document_alias_decode_letter_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/read-letter":{"get":{"summary":"Read Document Alias","description":"AI-assistant demand for a read my document page (create lane, 2026-09-17..19:\nvetaid.ai/read-document seen, outside path_map). 301 to the no-account\ndecision-letter reader so the demand resolves instead of 404ing.","operationId":"read_document_alias_read_letter_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/read-document":{"get":{"summary":"Read Document Alias","description":"AI-assistant demand for a read my document page (create lane, 2026-09-17..19:\nvetaid.ai/read-document seen, outside path_map). 301 to the no-account\ndecision-letter reader so the demand resolves instead of 404ing.","operationId":"read_document_alias_read_document_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/guides":{"get":{"summary":"Guides Index","description":"VA how-to guides listing page.","operationId":"guides_index_guides_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/guides/{slug}":{"get":{"summary":"Guides Page","description":"Individual VA how-to guide. Tolerates trailing .html/.htm the same\nway /blog/{slug} does, for stray external/AI-cited links.","operationId":"guides_page_guides__slug__get","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","title":"Slug"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/companies":{"get":{"summary":"Companies Index","description":"Index of company accountability records.","operationId":"companies_index_companies_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/companies/{slug}":{"get":{"summary":"Companies Page","description":"Per-company accountability record. Built by scripts/gen_company_pages.py\nfrom data_moat/companies/*.json. Same slug tolerance as /guides and /qa.","operationId":"companies_page_companies__slug__get","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","title":"Slug"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/representatives":{"get":{"summary":"Representatives Index","description":"National index and ZIP search for VA-accredited representatives.","operationId":"representatives_index_representatives_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/representatives/{state}":{"get":{"summary":"Representatives State","operationId":"representatives_state_representatives__state__get","parameters":[{"name":"state","in":"path","required":true,"schema":{"type":"string","title":"State"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/representatives/{state}/{city}":{"get":{"summary":"Representatives City","operationId":"representatives_city_representatives__state___city__get","parameters":[{"name":"state","in":"path","required":true,"schema":{"type":"string","title":"State"}},{"name":"city","in":"path","required":true,"schema":{"type":"string","title":"City"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/qa":{"get":{"summary":"Qa Index","description":"Q&A listing page.","operationId":"qa_index_qa_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/qa/{slug}":{"get":{"summary":"Qa Answer","description":"Individual Q&A answer page. Tolerates trailing .html and .htm\nsuffixes plus path traversal attempts so transient 404s on those\nURL variants stop polluting Search Console.","operationId":"qa_answer_qa__slug__get","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","title":"Slug"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/qa/search":{"get":{"summary":"Qa Search","description":"Search Q&A questions for autocomplete.","operationId":"qa_search_api_v1_qa_search_get","parameters":[{"name":"q","in":"query","required":false,"schema":{"type":"string","default":"","title":"Q"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","default":10,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/blog":{"get":{"summary":"Blog Index","description":"Blog listing page.","operationId":"blog_index_blog_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/rating-code/":{"get":{"summary":"Rating Code Index","description":"Index of all 724 diagnostic-code pages, grouped by body system.\n\nThis 404'd until 2026-08-06, which meant the whole /rating-code corpus was\norphaned — reachable only from sitemap.xml, with no page on the site linking\nto any of it. Bing had crawled only a minority even after 600 URL\nsubmissions; submission is rationed (100/day) and is only a hint, whereas\ninternal links are free and permanent.","operationId":"rating_code_index_rating_code__get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/rating-code":{"get":{"summary":"Rating Code Index","description":"Index of all 724 diagnostic-code pages, grouped by body system.\n\nThis 404'd until 2026-08-06, which meant the whole /rating-code corpus was\norphaned — reachable only from sitemap.xml, with no page on the site linking\nto any of it. Bing had crawled only a minority even after 600 URL\nsubmissions; submission is rationed (100/day) and is only a hint, whereas\ninternal links are free and permanent.","operationId":"rating_code_index_rating_code_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/rating-code/{code}":{"get":{"summary":"Rating Code Page","description":"38 CFR Part 4 diagnostic-code reference pages (built by gen_cfr_pages.py).\n\nBing's AI Performance data shows we already take the largest share of\nCopilot citations on regulation-code queries (38 cfr 7913 = 54.2%), so\nthese get their own identity-matched namespace rather than living under\n/blog, and can be measured separately.","operationId":"rating_code_page_rating_code__code__get","parameters":[{"name":"code","in":"path","required":true,"schema":{"type":"string","title":"Code"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/rating-codes/":{"get":{"summary":"Rating Codes Plural Index","description":"AI assistants and searchers guess the PLURAL of the hub (create-lane\ndemand report 2026-09-02: vetaid.ai/rating-codes asked for, 404'd). The hub\nis /rating-code; a permanent redirect serves the demand without minting a\nduplicate page for the create lane to write.","operationId":"rating_codes_plural_index_rating_codes__get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/rating-codes":{"get":{"summary":"Rating Codes Plural Index","description":"AI assistants and searchers guess the PLURAL of the hub (create-lane\ndemand report 2026-09-02: vetaid.ai/rating-codes asked for, 404'd). The hub\nis /rating-code; a permanent redirect serves the demand without minting a\nduplicate page for the create lane to write.","operationId":"rating_codes_plural_index_rating_codes_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/rating-codes/{code}":{"get":{"summary":"Rating Codes Plural Page","operationId":"rating_codes_plural_page_rating_codes__code__get","parameters":[{"name":"code","in":"path","required":true,"schema":{"type":"string","title":"Code"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/blog/{slug}":{"get":{"summary":"Blog Article","description":"Individual blog article.","operationId":"blog_article_blog__slug__get","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","title":"Slug"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/admin/build-denial-public":{"post":{"summary":"Admin Build Denial Public","description":"Start (or report) the background build of the redacted court-text table\nthe /api/denials/* endpoints serve from. Cron-secret gated.","operationId":"admin_build_denial_public_api_admin_build_denial_public_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}}},"components":{"schemas":{"AnalysisRequest":{"properties":{"stages":{"items":{"type":"string"},"type":"array","title":"Stages"}},"type":"object","title":"AnalysisRequest"},"Body_analyze_dd214_api_ai_analyze_dd214_post":{"properties":{"file":{"type":"string","format":"binary","title":"File"}},"type":"object","title":"Body_analyze_dd214_api_ai_analyze_dd214_post"},"Body_analyze_denials_api_ai_analyze_denials_post":{"properties":{"files":{"items":{"type":"string","format":"binary"},"type":"array","title":"Files"}},"type":"object","title":"Body_analyze_denials_api_ai_analyze_denials_post"},"Body_analyze_ratings_api_ai_analyze_ratings_post":{"properties":{"files":{"items":{"type":"string","format":"binary"},"type":"array","title":"Files"}},"type":"object","title":"Body_analyze_ratings_api_ai_analyze_ratings_post"},"Body_public_decode_letter_api_public_decode_letter_post":{"properties":{"file":{"type":"string","format":"binary","title":"File"},"text":{"type":"string","title":"Text"}},"type":"object","title":"Body_public_decode_letter_api_public_decode_letter_post"},"Body_upload_document_api_cases__case_id__documents_post":{"properties":{"file":{"type":"string","format":"binary","title":"File"}},"type":"object","required":["file"],"title":"Body_upload_document_api_cases__case_id__documents_post"},"CaseCreateRequest":{"properties":{"veteran_name":{"type":"string","title":"Veteran Name"},"va_file_number":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Va File Number"},"branch":{"type":"string","title":"Branch","default":""},"service_start":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Service Start"},"service_end":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Service End"},"service_locations":{"items":{"type":"string"},"type":"array","title":"Service Locations"},"current_rating":{"type":"integer","title":"Current Rating","default":0},"rated_conditions":{"items":{"$ref":"#/components/schemas/RatedCondition"},"type":"array","title":"Rated Conditions"},"denied_conditions":{"items":{"$ref":"#/components/schemas/DeniedCondition"},"type":"array","title":"Denied Conditions"},"claimed_conditions":{"items":{"type":"string"},"type":"array","title":"Claimed Conditions"}},"type":"object","required":["veteran_name"],"title":"CaseCreateRequest"},"CaseUpdateRequest":{"properties":{"veteran_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Veteran Name"},"va_file_number":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Va File Number"},"branch":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Branch"},"service_start":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Service Start"},"service_end":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Service End"},"service_locations":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Service Locations"},"current_rating":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Current Rating"},"rated_conditions":{"anyOf":[{"items":{"$ref":"#/components/schemas/RatedCondition"},"type":"array"},{"type":"null"}],"title":"Rated Conditions"},"denied_conditions":{"anyOf":[{"items":{"$ref":"#/components/schemas/DeniedCondition"},"type":"array"},{"type":"null"}],"title":"Denied Conditions"},"claimed_conditions":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Claimed Conditions"},"status":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Status"}},"type":"object","title":"CaseUpdateRequest"},"DeniedCondition":{"properties":{"name":{"type":"string","title":"Name"},"denial_reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Denial Reason"},"denial_date":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Denial Date"},"notes":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Notes"}},"type":"object","required":["name"],"title":"DeniedCondition"},"FacilitySearchRequest":{"properties":{"lat":{"type":"number","maximum":90.0,"minimum":-90.0,"title":"Lat"},"lon":{"type":"number","maximum":180.0,"minimum":-180.0,"title":"Lon"},"radius_miles":{"type":"number","maximum":200.0,"minimum":1.0,"title":"Radius Miles","default":40},"categories":{"items":{"type":"string"},"type":"array","title":"Categories"},"va_only":{"type":"boolean","title":"Va Only","default":false},"limit":{"type":"integer","maximum":100.0,"minimum":1.0,"title":"Limit","default":20}},"type":"object","required":["lat","lon"],"title":"FacilitySearchRequest"},"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"LegalLookupRequest":{"properties":{"context":{"type":"string","title":"Context"}},"type":"object","required":["context"],"title":"LegalLookupRequest"},"MissionActRequest":{"properties":{"lat":{"type":"number","maximum":90.0,"minimum":-90.0,"title":"Lat"},"lon":{"type":"number","maximum":180.0,"minimum":-180.0,"title":"Lon"},"service_type":{"type":"string","pattern":"^(primary_care|mental_health|urgent_care|specialty|audiology|optometry|dental|emergency)$","title":"Service Type","default":"primary_care"}},"type":"object","required":["lat","lon"],"title":"MissionActRequest"},"PathfinderRequest":{"properties":{"current_ratings":{"items":{"type":"integer"},"type":"array","title":"Current Ratings"},"target":{"type":"integer","title":"Target","default":100},"possible_additions":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Possible Additions"}},"type":"object","required":["current_ratings"],"title":"PathfinderRequest"},"RatedCondition":{"properties":{"name":{"type":"string","title":"Name"},"rating":{"type":"integer","title":"Rating","default":0},"diagnostic_code":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Diagnostic Code"},"effective_date":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Effective Date"},"notes":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Notes"}},"type":"object","required":["name"],"title":"RatedCondition"},"RatingLookupRequest":{"properties":{"condition":{"type":"string","title":"Condition"}},"type":"object","required":["condition"],"title":"RatingLookupRequest"},"RepSearchRequest":{"properties":{"zip_code":{"anyOf":[{"type":"string","pattern":"^\\d{5}(-\\d{4})?$"},{"type":"null"}],"title":"Zip Code"},"state":{"anyOf":[{"type":"string","pattern":"^[A-Za-z]{2}$"},{"type":"null"}],"title":"State"},"prefer":{"anyOf":[{"type":"string","pattern":"^(representative|attorney|claims_agent)$"},{"type":"null"}],"title":"Prefer"},"radius_miles":{"type":"number","maximum":500.0,"minimum":1.0,"title":"Radius Miles","default":100},"limit":{"type":"integer","maximum":50.0,"minimum":1.0,"title":"Limit","default":8}},"type":"object","title":"RepSearchRequest","description":"Find VA-accredited representatives near a veteran.\n\nZIP is the usual input because it is the one location fact a veteran can\ngive without an address lookup; state is the fallback for the ZIPs that have\nno Census ZCTA (PO-box-only ZIPs)."},"SecondaryLookupRequest":{"properties":{"primary_condition":{"type":"string","title":"Primary Condition"}},"type":"object","required":["primary_condition"],"title":"SecondaryLookupRequest"},"VAMathRequest":{"properties":{"ratings":{"items":{"type":"integer"},"type":"array","title":"Ratings"}},"type":"object","required":["ratings"],"title":"VAMathRequest"},"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"}}}}