{"openapi":"3.1.0","info":{"title":"LMCP API","version":"0.1.0"},"paths":{"/runtime/latest":{"get":{"summary":"Get Runtime Latest","description":"Retorna la URL del runtime Python (tarball) más reciente para npm/download.js.\n`machine_id` alimenta la supresión de loops (LMC-210) y, lmcp-api#100, el canary: una\nallow-list de machine ids recibe la versión siguiente antes que la flota.","operationId":"get_runtime_latest_runtime_latest_get","parameters":[{"name":"machine_id","in":"query","required":false,"schema":{"type":"string","default":"","title":"Machine Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/tool-counts":{"get":{"summary":"Get Tool Counts","description":"Canonical tool counts for public copy. The floor is the only publishable value.","operationId":"get_tool_counts_tool_counts_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/latest":{"get":{"summary":"Get Latest","operationId":"get_latest_latest_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/download":{"get":{"summary":"Redirect To Latest","description":"Redirige al ZIP más reciente. Usado por install.sh.","operationId":"redirect_to_latest_download_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/appcast.xml":{"get":{"summary":"Get Appcast","operationId":"get_appcast_appcast_xml_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/releases":{"get":{"summary":"Public Releases","description":"Release notes públicas (sin admin key) — usadas por la settings web UI.","operationId":"public_releases_releases_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/admin/versions":{"post":{"summary":"Admin Publish Version","operationId":"admin_publish_version_admin_versions_post","parameters":[{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/VersionRequest"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"get":{"summary":"Admin List Versions","operationId":"admin_list_versions_admin_versions_get","parameters":[{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/versions/{version}/notes":{"patch":{"summary":"Admin Edit Version Notes","operationId":"admin_edit_version_notes_admin_versions__version__notes_patch","parameters":[{"name":"version","in":"path","required":true,"schema":{"type":"string","title":"Version"}},{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/VersionNotesRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/canary":{"get":{"summary":"Admin Canary List","description":"Per platform: the canary version, its active machines, who/when, and each machine's last\nheartbeat with `reported` — computed by `_canary_machine_status`, the same rule promote's gate\nuses, so the panel (lmcp-admin#95) and the promote button can never disagree. The release\nworkflow reads this (and stops if the platform's list is empty); the panel renders it.","operationId":"admin_canary_list_admin_canary_get","parameters":[{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/canary/audit":{"get":{"summary":"Admin Canary Audit","description":"lmcp-admin#84: who did what to the canary, newest first — the log_event rows the canary\nendpoints write (set, machine added/removed, cleared, promoted with `forced`). The actor is the\nadmin key: the panel says so.","operationId":"admin_canary_audit_admin_canary_audit_get","parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","default":100,"title":"Limit"}},{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/canary/{platform}":{"put":{"summary":"Admin Canary Set Version","description":"Set the canary version for a platform. Refuse a version that is not strictly higher than the\nline's current maximum — the same publication-order bar `admin_publish_version` enforces (never\noffer a build the fleet already passed). windows is allowed as of #108 PR3: `get_runtime_latest`\nnow excludes the win-% canary from the public serve and hands it only to a listed machine, so a\nset no longer leaks the row to the fleet. `line_query(version_line(...))` compares a win-% set\nagainst the win-% line, a darwin set against the darwin line.","operationId":"admin_canary_set_version_admin_canary__platform__put","parameters":[{"name":"platform","in":"path","required":true,"schema":{"type":"string","title":"Platform"}},{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CanaryVersionRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"summary":"Admin Canary Clear","description":"Clear (abort) the platform's canary: drop the version row and soft-remove every machine.\n\n#108 O7 (lmcp-win#192): for windows this is NOT a promote. The public Windows serve picks the\nhighest `win-%` row by released_at, held back only by the serve-time exclusion on the active\ncanary_release row — so dropping that row would publish the already-registered `win-<v>` to the\nwhole fleet. Stamp the canary's win row `withdrawn_at` BEFORE clearing, so the public serve keeps\nskipping it; only an explicit promote (which does not withdraw) serves it. A later set-version of\nthe same version clears the stamp (re-canarying un-withdraws). darwin needs none of this: its\npublic serve is gated on `is_latest`, which a canary row never carries until promote flips it.","operationId":"admin_canary_clear_admin_canary__platform__delete","parameters":[{"name":"platform","in":"path","required":true,"schema":{"type":"string","title":"Platform"}},{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/canary/{platform}/machines":{"post":{"summary":"Admin Canary Add Machines","description":"Add machines to the platform's canary list (idempotent per machine). `for_version` records\nthe canary version active when each was added (audit).","operationId":"admin_canary_add_machines_admin_canary__platform__machines_post","parameters":[{"name":"platform","in":"path","required":true,"schema":{"type":"string","title":"Platform"}},{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CanaryMachinesRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/canary/{platform}/machines/{machine_id}":{"delete":{"summary":"Admin Canary Remove Machine","description":"Soft-remove a machine from the list (keeps the audit row via removed_at).","operationId":"admin_canary_remove_machine_admin_canary__platform__machines__machine_id__delete","parameters":[{"name":"platform","in":"path","required":true,"schema":{"type":"string","title":"Platform"}},{"name":"machine_id","in":"path","required":true,"schema":{"type":"string","title":"Machine Id"}},{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/canary/{platform}/promote":{"post":{"summary":"Admin Canary Promote","description":"#108 condition 1 — release the canary to everyone, with NO second CI run (the release's\n`canario` stage already uploaded the artifacts to R2 and registered the row). darwin: flip\n`is_latest` to the canary version — the row already carries the artifact the canary verified,\nso the same-artifact guarantee holds by construction. windows: clearing the canary lets the\n`win-%` row become the public highest (PR3 adds its serve-time exclusion). Then clear the\ncanary. 409 if no canary is set; idempotent; audited.\n\n#128 review:\n- BLOCKER 2 — the 3.0.417 gate: at least one ACTIVE canary machine must have reported the canary\n  version (installed or running it), or the release is unvalidated → 409 with the per-machine\n  status. `force=true` overrides it (audited).\n- BLOCKER 1 — inside the lock, re-check that the canary is a darwin row STRICTLY newer than the\n  fleet, or promoting it would downgrade everyone.","operationId":"admin_canary_promote_admin_canary__platform__promote_post","parameters":[{"name":"platform","in":"path","required":true,"schema":{"type":"string","title":"Platform"}},{"name":"force","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"Force"}},{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/versions/highest":{"get":{"summary":"Public Versions Highest","description":"lmcp-api#89: the highest version number ever registered on each release line, and nothing\nelse — the bar the publication-order guard (#1549) holds a new publish to. lmcp-win's build\npre-flight needs exactly this number; reading it from /admin/versions forced ADMIN_KEY into an\nenvironment with no reviewer. Same rule as the guard: every row of the line (withdrawn and\ncanary rows included), compared by number with utils.version_order, never by date.","operationId":"public_versions_highest_versions_highest_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/admin/canary/{platform}/health":{"get":{"summary":"Admin Canary Health","description":"The canary's health, per platform (lmcp-api#108, colibird-ai/.github#85): what the person\ndeciding \"Release to everyone\" in the panel reads. Read-only, admin key only, fail-closed (a\ndatabase error is a 503, never a green). Every signal says whether it could be measured; \"not\nmeasured\" is never 0. Reads only the canary machines' rows, from the moment the canary was set\n(the `heartbeats` index is (machine_id, created_at DESC)).","operationId":"admin_canary_health_admin_canary__platform__health_get","parameters":[{"name":"platform","in":"path","required":true,"schema":{"type":"string","title":"Platform"}},{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/account-link/redeem":{"post":{"summary":"Post Account Link Redeem","operationId":"post_account_link_redeem_account_link_redeem_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RedeemRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/account-link/unlink":{"post":{"summary":"Post Account Link Unlink","description":"The machine leaves its account (Settings → «Unlink account»). `{unlinked}`; idempotent.","operationId":"post_account_link_unlink_account_link_unlink_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UnlinkRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/account-link/code":{"post":{"summary":"Post Account Link Code","description":"Device-code linking (contract account-link-code.v1): a code for the user to type in «My LMCP».","operationId":"post_account_link_code_account_link_code_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CodeRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/account-link/code/approve":{"post":{"summary":"Post Account Link Code Approve","description":"lmcp-api#417 K2-L: the tray's approve or deny of a pending link (account-link-code.v1).","operationId":"post_account_link_code_approve_account_link_code_approve_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CodeApproveRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/account-link/net-probe":{"post":{"summary":"Post Account Link Net Probe","description":"Design Q2: no credentials; only the site's exact origin (its own CORS in main.py); the\naddress that reached this host, never a forwarded one.","operationId":"post_account_link_net_probe_account_link_net_probe_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/account-link/code/status":{"post":{"summary":"Post Account Link Code Status","operationId":"post_account_link_code_status_account_link_code_status_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CodeStatusRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/web/auth/start":{"post":{"summary":"Web Auth Start","operationId":"web_auth_start_web_auth_start_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthStart"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/web/auth/callback":{"post":{"summary":"Web Auth Callback","operationId":"web_auth_callback_web_auth_callback_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthCallback"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/web/auth/onetap/nonce":{"post":{"summary":"Web Onetap Nonce","operationId":"web_onetap_nonce_web_auth_onetap_nonce_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OneTapNonce"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/web/auth/onetap":{"post":{"summary":"Web Onetap","operationId":"web_onetap_web_auth_onetap_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OneTap"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/web/auth/email/start":{"post":{"summary":"Web Email Start","operationId":"web_email_start_web_auth_email_start_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailStart"}}},"required":true},"responses":{"202":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/web/auth/email/verify":{"post":{"summary":"Web Email Verify","operationId":"web_email_verify_web_auth_email_verify_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailVerify"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/web/auth/facebook/data-deletion":{"post":{"summary":"Web Facebook Data Deletion","operationId":"web_facebook_data_deletion_web_auth_facebook_data_deletion_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FacebookDeletion"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/web/privacy/deletion/{code}":{"get":{"summary":"Web Privacy Deletion","operationId":"web_privacy_deletion_web_privacy_deletion__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"}}}}}}},"/web/session/resolve":{"post":{"summary":"Web Session Resolve","description":"The gate's check; the only route that renews (a new id after 24 h: `new_session`).","operationId":"web_session_resolve_web_session_resolve_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/web/session/logout":{"post":{"summary":"Web Session Logout","operationId":"web_session_logout_web_session_logout_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/web/session/logout-all":{"post":{"summary":"Web Session Logout All","operationId":"web_session_logout_all_web_session_logout_all_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/web/account/measure":{"post":{"summary":"Web Account Measure","description":"lmcp-api#418: «stop measuring me», per account. Idempotent; a change is audited with the\naccount id and the new value only (no email, no address).","operationId":"web_account_measure_web_account_measure_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MeasureChoice"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/web/me/installs":{"get":{"summary":"Web Me Installs","operationId":"web_me_installs_web_me_installs_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/web/me/installs/{link_id}":{"delete":{"summary":"Web Me Unlink","operationId":"web_me_unlink_web_me_installs__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"}}}}}}},"/web/me/sessions":{"get":{"summary":"Web Me Sessions","operationId":"web_me_sessions_web_me_sessions_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/web/me/sessions/{session_ref}":{"delete":{"summary":"Web Me Session Revoke","operationId":"web_me_session_revoke_web_me_sessions__session_ref__delete","parameters":[{"name":"session_ref","in":"path","required":true,"schema":{"type":"string","title":"Session Ref"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/web/me/delete":{"post":{"summary":"Web Me Delete","description":"GDPR delete; the session must come from a sign-in in the last 15 minutes.","operationId":"web_me_delete_web_me_delete_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/web/me/link-code/preview":{"post":{"summary":"Web Me Link Code Preview","operationId":"web_me_link_code_preview_web_me_link_code_preview_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LinkCodePreview"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/web/me/link-code/confirm":{"post":{"summary":"Web Me Link Code Confirm","operationId":"web_me_link_code_confirm_web_me_link_code_confirm_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LinkCodeConfirm"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/web/config":{"get":{"summary":"Web Config Get","description":"The sign-in sheet's switches; the web caches it 60 s. A provider without both env values\nis not listed; email needs WEB_OTP_KEY.","operationId":"web_config_get_web_config_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/admin/web-accounts":{"get":{"summary":"Admin Web Accounts","operationId":"admin_web_accounts_admin_web_accounts_get","parameters":[{"name":"q","in":"query","required":false,"schema":{"type":"string","default":"","title":"Q"}},{"name":"cursor","in":"query","required":false,"schema":{"type":"string","default":"","title":"Cursor"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","default":50,"title":"Limit"}},{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/web-accounts/{account_id}":{"get":{"summary":"Admin Web Account","operationId":"admin_web_account_admin_web_accounts__account_id__get","parameters":[{"name":"account_id","in":"path","required":true,"schema":{"type":"integer","title":"Account Id"}},{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/web-accounts/{account_id}/links/{machine_id}":{"delete":{"summary":"Admin Unlink","operationId":"admin_unlink_admin_web_accounts__account_id__links__machine_id__delete","parameters":[{"name":"account_id","in":"path","required":true,"schema":{"type":"integer","title":"Account Id"}},{"name":"machine_id","in":"path","required":true,"schema":{"type":"string","title":"Machine Id"}},{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/web-accounts/{account_id}/links":{"delete":{"summary":"Admin Unlink By Token","operationId":"admin_unlink_by_token_admin_web_accounts__account_id__links_delete","parameters":[{"name":"account_id","in":"path","required":true,"schema":{"type":"integer","title":"Account Id"}},{"name":"token_hash12","in":"query","required":false,"schema":{"type":"string","default":"","title":"Token Hash12"}},{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/web-config":{"post":{"summary":"Admin Web Config","operationId":"admin_web_config_admin_web_config_post","parameters":[{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebConfig"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/artifacts/{name}":{"get":{"summary":"Get Artifact","operationId":"get_artifact_artifacts__name__get","parameters":[{"name":"name","in":"path","required":true,"schema":{"type":"string","title":"Name"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/notify":{"post":{"summary":"Post Notify","operationId":"post_notify_notify_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotifyRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/track":{"post":{"summary":"Post Track","description":"Track frontend events (page_view, copy_command, modal_open, etc.) for funnel analytics.","operationId":"post_track_track_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TrackEvent"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/track-drops":{"get":{"summary":"Admin Track Drops","description":"Descartes de /track por razón, desde el arranque de ESTE proceso.\n\nPor proceso y en memoria, igual que el dict que los produce: se reinicia en cada deploy\ny no suma entre réplicas. Sirve para la proporción y el orden de magnitud, no como serie\nhistórica — y eso es exactamente lo que no se podía saber antes (#3445).","operationId":"admin_track_drops_admin_track_drops_get","parameters":[{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/quota-identity":{"get":{"summary":"Admin Quota Identity","description":"lmcp-api#104: where the quota identity of the five public write routes comes from, and how\noften they met their per-address limit.\n\n`sources` and `blocked` are per process since start (they reset on deploy, like\n/admin/track-drops). `blocked_by_day` reads the `*_blocked` rate-limit events, which survive\ndeploys, so a before/after of a change to the identity can be compared by day (UTC).\n/community/vote logs no event when it drops a ballot: it is only in `blocked`.","operationId":"admin_quota_identity_admin_quota_identity_get","parameters":[{"name":"days","in":"query","required":false,"schema":{"type":"integer","default":14,"title":"Days"}},{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/guides/popularity":{"get":{"summary":"Get Guides Popularity","description":"Public: page views per guide slug (last N days) so the /guides index can\nauto-order by what people actually read. Guide page views are identified the\nsame way /admin/guide-funnel does — source='guide' + ref='guide-<slug>' (the\nper-guide tracker tags them; the generic `path` field is NOT set on guide\nviews, which is why a path-based match returns nothing). Only aggregates\nleave the backend.\n\nCached GUIDES_POPULARITY_TTL_SECONDS per `days` (#333). A failed read answers the last body,\nor an empty map when there has never been one: the only consumer (lmcp-web) already reads a\nfailure as an empty map, and this route never answers 500 for a database hiccup.","operationId":"get_guides_popularity_guides_popularity_get","parameters":[{"name":"days","in":"query","required":false,"schema":{"type":"integer","default":30,"title":"Days"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/download-request":{"post":{"summary":"Post Download Request","description":"Captura email antes de descargar. Guarda en notify_emails y envía link por Resend.","operationId":"post_download_request_download_request_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DownloadRequestBody"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/waitlist":{"post":{"summary":"Post Waitlist","description":"Public Linux/mobile waitlist capture from the landing page. The hero\ninstall panel shows this to unsupported-platform visitors instead of an\ninstall command they can't run — turning dead traffic into leads.\nIdempotent on (email, os).","operationId":"post_waitlist_waitlist_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WaitlistBody"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/community/submit":{"post":{"summary":"Post Community Submit","description":"A community-submitted workflow for the /recipes section. Stored as `pending` for\nmoderation — NEVER auto-published. Turnstile is verified in the web route; here we\nrate-limit (same open-relay guard as /download-request) and persist for review.","operationId":"post_community_submit_community_submit_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CommunitySubmitBody"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/community/approved":{"get":{"summary":"Get Community Approved","description":"Public: the approved community workflows shown on /recipes, most-voted first.\nOnly rows a moderator explicitly approved are ever returned — pending/rejected\nnever leak. The id is exposed so visitors can upvote.","operationId":"get_community_approved_community_approved_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/community/skills":{"get":{"summary":"Get Community Skills","description":"Public: approved community submissions that carry an installable recipe manifest.\nThe client's recipe_discover lists these; recipe_install fetches one by id and\nimports its manifest. Only moderator-approved rows with a manifest are ever returned —\npending/rejected and plain-text (no-manifest) submissions never leak here.\n\nWith ?id=N, returns the single skill's full manifest (what recipe_install needs);\nwithout it, the catalog (manifest omitted to keep the list light).","operationId":"get_community_skills_community_skills_get","parameters":[{"name":"id","in":"query","required":false,"schema":{"type":"integer","default":0,"title":"Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/community/vote":{"post":{"summary":"Post Community Vote","description":"One vote per visitor (vid) per workflow — the unique constraint makes voting\nidempotent, so re-clicks never double-count. Only approved submissions can be\nvoted. Rate-limited per IP to keep drive-by scripts from stuffing the ballot.","operationId":"post_community_vote_community_vote_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CommunityVoteBody"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/community":{"get":{"summary":"Admin Community","operationId":"admin_community_admin_community_get","parameters":[{"name":"status","in":"query","required":false,"schema":{"type":"string","default":"pending","title":"Status"}},{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/community/review":{"post":{"summary":"Admin Community Review","operationId":"admin_community_review_admin_community_review_post","parameters":[{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CommunityReviewBody"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/blog/comments":{"post":{"summary":"Post Blog Comment","description":"A visitor comment on a blog/guide entry. Stored `pending` — never rendered\nuntil a moderator approves it (the public GET only ever serves approved rows).","operationId":"post_blog_comment_blog_comments_post","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BlogCommentBody"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"get":{"summary":"Get Blog Comments","description":"Public: APPROVED comments for one entry, oldest first (threading is resolved\nclient-side via parent_id). Pending/rejected rows never leave this endpoint.","operationId":"get_blog_comments_blog_comments_get","parameters":[{"name":"slug","in":"query","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"}}}}}}},"/admin/blog-comments":{"get":{"summary":"Admin Blog Comments","operationId":"admin_blog_comments_admin_blog_comments_get","parameters":[{"name":"status","in":"query","required":false,"schema":{"type":"string","default":"pending","title":"Status"}},{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/blog-comments/moderate":{"post":{"summary":"Admin Blog Comments Moderate","operationId":"admin_blog_comments_moderate_admin_blog_comments_moderate_post","parameters":[{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BlogCommentModerateBody"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/blog-comments/reply":{"post":{"summary":"Admin Blog Comments Reply","description":"Team reply: inserted pre-approved with is_team=true. Replying to a pending\ncomment approves the parent too — a visible reply needs a visible parent.","operationId":"admin_blog_comments_reply_admin_blog_comments_reply_post","parameters":[{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BlogCommentReplyBody"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/blog/posts":{"post":{"summary":"Post Blog Post","description":"A user-written blog post or discussion topic. Stored `pending` — a moderator\nreviews before anything renders; approval emails the author the live URL.","operationId":"post_blog_post_blog_posts_post","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BlogPostBody"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"get":{"summary":"Get Blog Posts","description":"Public: APPROVED posts/topics, newest first, with a plain-text excerpt.","operationId":"get_blog_posts_blog_posts_get","parameters":[{"name":"kind","in":"query","required":false,"schema":{"type":"string","default":"post","title":"Kind"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","default":50,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/blog/posts/{slug}":{"get":{"summary":"Get Blog Post","description":"Public: one APPROVED post/topic, full body. Pending/rejected 404 — they\ndon't exist as far as the public web is concerned.","operationId":"get_blog_post_blog_posts__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"}}}}}}},"/admin/blog-posts":{"get":{"summary":"Admin Blog Posts","operationId":"admin_blog_posts_admin_blog_posts_get","parameters":[{"name":"status","in":"query","required":false,"schema":{"type":"string","default":"pending","title":"Status"}},{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/blog-posts/moderate":{"post":{"summary":"Admin Blog Posts Moderate","operationId":"admin_blog_posts_moderate_admin_blog_posts_moderate_post","parameters":[{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BlogPostModerateBody"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/email-status/{resend_email_id}":{"get":{"summary":"Admin Email Status","description":"Consulta el status de delivery de un email en Resend.","operationId":"admin_email_status_admin_email_status__resend_email_id__get","parameters":[{"name":"resend_email_id","in":"path","required":true,"schema":{"type":"string","title":"Resend Email Id"}},{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/charging/switch":{"get":{"summary":"Admin Charging Switch Get","operationId":"admin_charging_switch_get_admin_charging_switch_get","parameters":[{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"summary":"Admin Charging Switch Set","operationId":"admin_charging_switch_set_admin_charging_switch_post","parameters":[{"name":"force","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"Force"}},{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChargingSwitchRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"summary":"Admin Charging Switch Clear","description":"#112 O1: clear the switch back to pre-switch / dormant. Audited with the previous value.","operationId":"admin_charging_switch_clear_admin_charging_switch_delete","parameters":[{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/validate":{"post":{"summary":"Validate License","operationId":"validate_license_validate_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidateRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/trial/validate":{"post":{"summary":"Trial Validate","description":"Validate the trial against the server.\n\n#112 unit 3: behind the charging switch (`get_charging_switch_date`) this expresses a real\n14-day trial counted from first connection, plus the 30-day grace an EXISTING machine is owed\nfrom the switch date S. The switch ships ABSENT, so pre-switch is BACKWARD-COMPATIBLE (#140 O2):\nthe existing fields are unchanged (days_left 3650, never expired, same install_date) and it only\nADDS `state`/`code` — not byte-identical, but no existing reader breaks. `exempt_tools` (the tools\nthat keep working at expiry) is NOT echoed here: it is a client-enforced contract constant\n(GO answer b, in license-activation.v1.json).","operationId":"trial_validate_trial_validate_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TrialValidateRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/licenses":{"get":{"summary":"Admin List Licenses","operationId":"admin_list_licenses_admin_licenses_get","parameters":[{"name":"search","in":"query","required":false,"schema":{"type":"string","default":"","title":"Search"}},{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/generate":{"post":{"summary":"Admin Generate License","operationId":"admin_generate_license_admin_generate_post","parameters":[{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenerateRequest"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/revoke":{"post":{"summary":"Admin Revoke License","operationId":"admin_revoke_license_admin_revoke_post","parameters":[{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RevokeRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/clean-installs":{"post":{"summary":"Admin Clean Installs","description":"Limpia historial de instalaciones y heartbeats.","operationId":"admin_clean_installs_admin_clean_installs_post","parameters":[{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/trial-users":{"get":{"summary":"Admin Trial Users","description":"Usuarios activos: combina tunnel_tokens + heartbeats por machine_id.","operationId":"admin_trial_users_admin_trial_users_get","parameters":[{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/board-email":{"post":{"summary":"Admin Board Email","operationId":"admin_board_email_admin_board_email_post","parameters":[{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BoardEmailRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/client-update-attempted":{"post":{"summary":"Post Client Update Attempted","operationId":"post_client_update_attempted_client_update_attempted_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ClientUpdateAttemptedRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/update-attempt":{"post":{"summary":"Post Update Attempt","description":"Un evento por intento de auto-update, con esquema cerrado (#2682).\n\nExiste separado de /install/step porque aquél lleva un `detail` de texto libre que\nsólo se trunca: texto libre es por donde se filtra una ruta con el nombre de usuario\nadentro. Acá etapa, resultado y motivo se validan contra listas blancas, así que la\nsanitización es del servidor y no una convención que el cliente deba recordar.\n\nUn vocabulario desconocido se RECHAZA en vez de guardarse: aceptarlo convertiría el\ncampo enumerado en el campo libre que se quiso evitar.","operationId":"post_update_attempt_update_attempt_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateAttemptBody"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/client-tray-event":{"post":{"summary":"Post Client Tray Event","operationId":"post_client_tray_event_client_tray_event_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ClientTrayEventRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/diagnostics":{"post":{"summary":"Post Diagnostic","description":"Recibe un reporte de diagnóstico enviado por un usuario via run_diagnostics.","operationId":"post_diagnostic_diagnostics_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DiagnosticRequest"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/diagnostics":{"get":{"summary":"Admin Diagnostics","description":"Agregado de reportes de diagnóstico: top problemas y últimos reportes.","operationId":"admin_diagnostics_admin_diagnostics_get","parameters":[{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/qa-reports":{"post":{"summary":"Post Qa Report","description":"Recibe un reporte de QA automático enviado por Cowork.","operationId":"post_qa_report_qa_reports_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/QAReportRequest"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/tool-catalog":{"get":{"summary":"Tool Catalog","description":"Public macOS tool names + counts for /.well-known/mcp.json and discovery.\n\nReturns the ADVERTISED set only (== api/tool-count-floor.json's ceiling),\nfiltering the never-advertised stubs so this surface matches the local +\ncloud catalogs. total == macos == advertised count; the raw catalog is never\nexposed here, which is what made /.well-known/mcp.json drift (served the raw\n170 instead of the advertised 162).","operationId":"tool_catalog_tool_catalog_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/admin/tool-list":{"get":{"summary":"Admin Tool List","description":"Returns the list of tool names from data_tools.json (server's real tool set).","operationId":"admin_tool_list_admin_tool_list_get","parameters":[{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/qa-reports":{"get":{"summary":"Admin Qa Reports","description":"Lista reportes de QA automáticos. Los más recientes primero.\n\nExcludes the Go-server variant's submissions by default (run_id 'go-*',\nversion '0.1.0' — e.g. go-linux/go-windows). Those run a separate, often\nstub QA suite with non-LMCP tool names (emit_args/api_gateway/…) and would\notherwise hide the real macOS LMCP runs (71+ tools, ~98% coverage) since the\npanel shows latest-by-time. Pass include_go=true to see them.","operationId":"admin_qa_reports_admin_qa_reports_get","parameters":[{"name":"include_go","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"Include Go"}},{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/qa-reports/{run_id}":{"get":{"summary":"Admin Qa Report Detail","description":"Detalle completo de un run de QA.","operationId":"admin_qa_report_detail_admin_qa_reports__run_id__get","parameters":[{"name":"run_id","in":"path","required":true,"schema":{"type":"string","title":"Run Id"}},{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/trigger-qa":{"post":{"summary":"Admin Trigger Qa","description":"Called by CI after a successful client deploy (or manually) to signal the\nQA Monitor that a full regression run is needed. Logs a qa_run_requested event\nwhich the agent reads in its next heartbeat.","operationId":"admin_trigger_qa_admin_trigger_qa_post","parameters":[{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/QATriggerRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/settings-event":{"post":{"summary":"Post Settings Event","description":"Record a settings.html wizard or nudge banner event.","operationId":"post_settings_event_settings_event_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SettingsEventRequest"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/events":{"post":{"summary":"Post Client Event","description":"Ingest a manifest-driven client telemetry event (TelemetryEngine.fire posts\nhere for <telemetry> tags). This route did not exist, so those events never\nlanded (mail/calendar/reminders_tool_called = 0 rows). Whitelisted, sanitized,\nand bounded — no PII (tags are tool name / boolean flags by manifest design).","operationId":"post_client_event_events_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ClientEventRequest"}}},"required":true},"responses":{"202":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/friction-signal":{"post":{"summary":"Post Friction Signal","description":"Ingest an anonymous, content-free friction signal (categories only, no PII).","operationId":"post_friction_signal_friction_signal_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FrictionSignalRequest"}}},"required":true},"responses":{"202":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/feedback":{"post":{"summary":"Post Feedback","description":"Recibe feedback del usuario. Retorna un case_id único.","operationId":"post_feedback_feedback_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FeedbackRequest"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/feedback/mine":{"get":{"summary":"Get My Feedback","description":"Retorna feedback/bugs reportados por este machine_id o email.","operationId":"get_my_feedback_feedback_mine_get","parameters":[{"name":"machine_id","in":"query","required":false,"schema":{"type":"string","default":"","title":"Machine Id"}},{"name":"email","in":"query","required":false,"schema":{"type":"string","default":"","title":"Email"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/feedback/{case_id}/close":{"post":{"summary":"Close Feedback","description":"Cierra un bug/feature request (solo admin).\n\nAntes no pedía credencial — era el único de los tres mutadores sin `require_admin`, así\nque conocer un FB-XXXXXX alcanzaba para cerrar el caso de otro. Y la resolución se\nconcatenaba a `message`: reabrir restauraba el estado pero no el texto, de modo que el\noriginal del usuario se perdía para siempre. Ahora va a `resolution_note`, que ya existía\npara /admin/resolve-feedback y estaba sin usar en esta ruta.","operationId":"close_feedback_feedback__case_id__close_post","parameters":[{"name":"case_id","in":"path","required":true,"schema":{"type":"string","title":"Case Id"}},{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CloseFeedbackRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/feedback/{case_id}/reopen":{"post":{"summary":"Reopen Feedback","description":"Re-abre un caso cerrado (solo admin).","operationId":"reopen_feedback_feedback__case_id__reopen_post","parameters":[{"name":"case_id","in":"path","required":true,"schema":{"type":"string","title":"Case Id"}},{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/feedback/{case_id}":{"delete":{"summary":"Delete Feedback","description":"Borrado lógico de un caso (solo admin). Pone status = 'deleted'.\n\nDeja actor y momento: un borrado sin rastro es indistinguible de una pérdida de datos, y\nel 2026-08-29 había 658 filas en ese estado sin forma de saber quién ni por qué.","operationId":"delete_feedback_feedback__case_id__delete","parameters":[{"name":"case_id","in":"path","required":true,"schema":{"type":"string","title":"Case Id"}},{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/feedback/{case_id}/set-status":{"post":{"summary":"Admin Set Feedback Status","operationId":"admin_set_feedback_status_admin_feedback__case_id__set_status_post","parameters":[{"name":"case_id","in":"path","required":true,"schema":{"type":"string","title":"Case Id"}},{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetFeedbackStatusRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/feedback":{"get":{"summary":"Admin List Feedback","description":"List feedback rows with optional type and status filters.\n\nQuery params:\n  type   — un tipo cualquiera de los que existan (optional, empty = all types). NO hay\n           lista blanca: hoy conviven bug/feature/integration/uninstall/help/logs/qa y\n           fijar el conjunto acá esconde el que aparezca mañana.\n  status — 'open' | 'triaged' | 'closed' | 'resolved' | 'deleted' (optional, empty = all\n           except deleted). El filtro es exacto: 'open' NO trae los 'triaged' (leídos y\n           archivados en un issue, todavía pendientes); los pendientes son los dos.\n           'resolved' lo escribe /admin/resolve-feedback junto con la\n           evidencia (disposition / resolved_by / resolution_note); el SELECT * de\n           abajo las devuelve solas, que es la mitad que a problem_reports le faltaba\n           y hacia la nota ilegible por la API (#2191).\n  limit  — max rows to return (default 200, capped at 500)\n  offset — desde qué fila, para paginar el resto\n\nDevuelve la lista tal cual (el contrato de los llamadores no cambia) y el total en el\nheader `X-Total-Count`. `X-Open-Count` y `X-Triaged-Count` cuentan los pendientes de cada\nclase para el mismo filtro de tipo, sin importar el filtro de estado ni la página. Truncar está bien; truncar en silencio no: el 2026-08-28 había\n234 casos abiertos y el panel mostraba 146 (medición de la sesión Customer, #2507). Son\ndos cortes encadenados y ninguno visible en la UI: el endpoint devolvía 200 filas de\nCUALQUIER estado, y el panel filtraba por tipo sobre esa página ya recortada.","operationId":"admin_list_feedback_admin_feedback_get","parameters":[{"name":"type","in":"query","required":false,"schema":{"type":"string","default":"","title":"Type"}},{"name":"status","in":"query","required":false,"schema":{"type":"string","default":"","title":"Status"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","default":200,"title":"Limit"}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","default":0,"title":"Offset"}},{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/feedback/{case_id}/set-filed-issue":{"post":{"summary":"Admin Set Feedback Filed Issue","description":"Record the issue a feedback request was filed on (colibird-ai/.github#40). Writes only\n`filed_issue`, never `status`; the same value twice is a no-op.","operationId":"admin_set_feedback_filed_issue_admin_feedback__case_id__set_filed_issue_post","parameters":[{"name":"case_id","in":"path","required":true,"schema":{"type":"string","title":"Case Id"}},{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetFiledIssueRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/feedback/reply-drafts":{"get":{"summary":"Admin Feedback Reply Drafts","description":"The cases that await a reply draft for `stage`, oldest first. No message text.","operationId":"admin_feedback_reply_drafts_admin_feedback_reply_drafts_get","parameters":[{"name":"stage","in":"query","required":true,"schema":{"type":"string","title":"Stage"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","default":200,"title":"Limit"}},{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/feedback/{case_id}/reply-draft-created":{"post":{"summary":"Admin Feedback Reply Draft Created","description":"Remember that the draft for this case and stage exists. Once: a repeat changes nothing and\nanswers with the first moment. 409 for a case that does not await a draft for that stage.","operationId":"admin_feedback_reply_draft_created_admin_feedback__case_id__reply_draft_created_post","parameters":[{"name":"case_id","in":"path","required":true,"schema":{"type":"string","title":"Case Id"}},{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReplyDraftCreatedRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/feedback/purge-deleted":{"post":{"summary":"Admin Purge Deleted Feedback","description":"Purga (hard-delete) permanentemente el feedback ya soft-deleted, fuera de la\nventana de retención (#2514).\n\n- `dry_run=true` (default): solo cuenta y audita, no borra nada. Seguro de llamar\n  en cualquier momento.\n- Para borrar de verdad hacen falta LAS DOS: `dry_run=false` Y `confirm=true` —\n  una sola no alcanza, para que un query param mal tipeado no dispare un borrado\n  real por accidente.\n- `min_age_days=30` (default) es la política estándar de retención. `0` purga\n  TODO lo actualmente soft-deleted sin importar antigüedad — autorización\n  explícita del 2026-08-29 (issue #2514) para el lote histórico acumulado antes\n  de que existiera esta política; pensado para usarse una sola vez.","operationId":"admin_purge_deleted_feedback_admin_feedback_purge_deleted_post","parameters":[{"name":"dry_run","in":"query","required":false,"schema":{"type":"boolean","default":true,"title":"Dry Run"}},{"name":"min_age_days","in":"query","required":false,"schema":{"type":"integer","default":30,"title":"Min Age Days"}},{"name":"confirm","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"Confirm"}},{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/feedback/purge-log":{"get":{"summary":"Admin Feedback Purge Log","description":"Auditoría de cada corrida de la purga (manual o del barrido diario).","operationId":"admin_feedback_purge_log_admin_feedback_purge_log_get","parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","default":50,"title":"Limit"}},{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/problem-reports":{"post":{"summary":"Post Problem Report","description":"Receives a structured problem report from the LMCP server (Swift tool\n`report_problem`). Stores the snapshot, log tail, and activity ring in\na dedicated table so the team can filter by tool/version/TCC state.","operationId":"post_problem_report_problem_reports_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemReportRequest"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/problem-reports":{"get":{"summary":"Admin List Problem Reports","description":"Returns recent problem reports with full context. Filters compose.\n\nEvery row carries `internal` (see _report_is_internal). It is a label, not a filter:\ninternal rows are still returned, in the same order and under the same cap.\n\nPublica el total en `X-Total-Count` y acepta `offset` — mismo arreglo que #2506 hizo\npara /admin/feedback (#2508). Medido contra producción el 2026-08-29:\n`?status=closed` y `?status=resolved` devolvían 50 cada uno, que es el `limit` por\ndefecto, no el conteo — nada en la respuesta distinguía \"hay 50\" de \"hay 50 de 500\".\nEl COUNT reutiliza la MISMA lista `where` que el SELECT: un COUNT con su propio filtro\na mano se desincroniza en cuanto alguien agrega un filtro a uno de los dos.","operationId":"admin_list_problem_reports_admin_problem_reports_get","parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","default":50,"title":"Limit"}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","default":0,"title":"Offset"}},{"name":"status","in":"query","required":false,"schema":{"type":"string","default":"open","title":"Status"}},{"name":"tool","in":"query","required":false,"schema":{"type":"string","default":"","title":"Tool"}},{"name":"version","in":"query","required":false,"schema":{"type":"string","default":"","title":"Version"}},{"name":"machine_id","in":"query","required":false,"schema":{"type":"string","default":"","title":"Machine Id"}},{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/problem-reports/{case_id}/close":{"post":{"summary":"Admin Close Problem Report","operationId":"admin_close_problem_report_admin_problem_reports__case_id__close_post","parameters":[{"name":"case_id","in":"path","required":true,"schema":{"type":"string","title":"Case Id"}},{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/problem-reports/purge-pii":{"post":{"summary":"Admin Purge Pii From Reports","description":"Strip PII fields (logs, activity, user_request, expected) from ALL problem reports.","operationId":"admin_purge_pii_from_reports_admin_problem_reports_purge_pii_post","parameters":[{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/problem-reports/{case_id}":{"delete":{"summary":"Admin Delete Problem Report","description":"Permanently delete a problem report and all its data (GDPR compliance).","operationId":"admin_delete_problem_report_admin_problem_reports__case_id__delete","parameters":[{"name":"case_id","in":"path","required":true,"schema":{"type":"string","title":"Case Id"}},{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/problem-reports/{case_id}/reopen":{"post":{"summary":"Admin Reopen Problem Report","operationId":"admin_reopen_problem_report_admin_problem_reports__case_id__reopen_post","parameters":[{"name":"case_id","in":"path","required":true,"schema":{"type":"string","title":"Case Id"}},{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/bulk-close-problem-reports":{"post":{"summary":"Admin Bulk Close Problem Reports","operationId":"admin_bulk_close_problem_reports_admin_bulk_close_problem_reports_post","parameters":[{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BulkCloseProblemReportsRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/connected-agents":{"get":{"summary":"Admin Connected Agents","description":"Which AI agents users actually have connected, unified across the three\nsurfaces (none of which existed in one place before):\n  • desktop  — local stdio clients (Claude Desktop, Cursor, VS Code, CLI…) from heartbeats (7d)\n  • web_oauth — cloud web AIs that bound via OAuth (ChatGPT, Claude.ai) — live grants\n  • web_url  — cloud web AIs that bound via ?token= in the URL (Grok, Claude.ai)\nTest/probe identities are excluded. Counts are distinct machines (desktop) or\ndistinct tokens (web = distinct user installs).\n\n`hours` (default 720 = 30d) filters the time-windowed surfaces — web_url, the\nDiscovery panel, and the cloud→install conversion — so you can zoom into a recent\nwindow (e.g. ?hours=1 / 6 / 24) to diagnose a spike. desktop (7d heartbeat) and\nweb_oauth (live grants) are not time-windowed.","operationId":"admin_connected_agents_admin_connected_agents_get","parameters":[{"name":"hours","in":"query","required":false,"schema":{"type":"integer","default":720,"title":"Hours"}},{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/satisfied-installs":{"get":{"summary":"Admin Satisfied Installs","description":"North-star metric for the 100-satisfied-installs/day goal.\n\nSatisfied = activated (made tool calls) + breadth (≥8 distinct tools) +\nretained (active ≥7d after first seen). Returns:\n  • daily new-machine rate (last 14d) vs the 100/day target,\n  • satisfaction rate over a *mature* cohort (first seen 7–37d ago, so it\n    had time to retain),\n  • the breadth→retention cohort comparison that justifies the breadth gate.","operationId":"admin_satisfied_installs_admin_satisfied_installs_get","parameters":[{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/churned-machines":{"get":{"summary":"Admin Churned Machines","operationId":"admin_churned_machines_admin_churned_machines_get","parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":500,"minimum":1,"default":50,"title":"Limit"}},{"name":"tools_per_machine","in":"query","required":false,"schema":{"type":"integer","default":5,"title":"Tools Per Machine"}},{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/churn-triggers":{"get":{"summary":"Admin Churn Triggers Get","description":"Identifica maquinas elegibles para outreach de churn.","operationId":"admin_churn_triggers_get_admin_churn_triggers_get","parameters":[{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"summary":"Admin Churn Triggers Post","description":"Ejecuta los churn triggers pendientes.","operationId":"admin_churn_triggers_post_admin_churn_triggers_post","parameters":[{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/unstable-installs":{"get":{"summary":"Admin Unstable Installs","description":"Machines whose install/update went UNSTABLE — the FB-7D50B0 (M4) class: a fresh\ninstall that then crash/restart-loops, so helper-backed tools (Contacts/Calendar/\nReminders) time out or fall back to a missing helper.\n\nTwo signals:\n  • flapping_machines — tray_restarted events with flapping=true (the tray restarted\n    again within 120s). DIRECT signal; needs a client >= the build that emits it.\n  • unstable_install_machines — a burst of tool_errors within 20 min of an `install`\n    event. INFERRED signal; works retroactively on existing data (would have flagged\n    M4 ~12:17 today, before the manual problem report).\nTest/probe machines are excluded.","operationId":"admin_unstable_installs_admin_unstable_installs_get","parameters":[{"name":"hours","in":"query","required":false,"schema":{"type":"integer","default":48,"title":"Hours"}},{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/tool-performance":{"get":{"summary":"Admin Tool Performance","description":"Per-tool latency telemetry + the fleet performance KPI, so we can MEASURE and drive down\ntool slowness over time (not just cap it). Source: mcp_requests.latency_ms — the cloud-connector\nround-trip, i.e. the latency the user actually experiences. tools/call only.\n\nKPI `tool_latency_sla` = % of tool calls that complete under `slow_ms` (default 10s). Higher is\nbetter; the goal is to push it up. The per-tool table (worst p95 first) says where to optimize.","operationId":"admin_tool_performance_admin_tool_performance_get","parameters":[{"name":"days","in":"query","required":false,"schema":{"type":"integer","default":7,"title":"Days"}},{"name":"slow_ms","in":"query","required":false,"schema":{"type":"integer","default":10000,"title":"Slow Ms"}},{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/multilingual":{"get":{"summary":"Admin Multilingual","description":"F-007 multilingual-discovery telemetry: does the fleet, working in a non-English language,\nactually reach + call tools after the multilingual keyword rollout?\n\nSignal: the DETECTED LANGUAGE of each cloud tool call's text arguments (logged as an ISO code on\n`cloud_data_tool_called` — never the text itself). A call whose args are in Spanish reaching\n`search_emails` is direct evidence that discovery worked in Spanish. Honest limits: the tool\nSEARCH itself is client-side and invisible; only cloud calls with detectable text args are\ncounted (no-arg/proper-noun calls → lang null); local-socket calls aren't tagged yet.\n\nKPI `multilingual_reach` = share of language-detected calls that are NON-English — the fraction\nof measurable usage coming from other languages. The per-language table shows how many distinct\ndomains each language reaches (breadth = the product is usable in that language).","operationId":"admin_multilingual_admin_multilingual_get","parameters":[{"name":"days","in":"query","required":false,"schema":{"type":"integer","default":30,"title":"Days"}},{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/fleet-health":{"get":{"summary":"Admin Fleet Health","description":"Fleet health signals derived from heartbeat data. No client changes needed.","operationId":"admin_fleet_health_admin_fleet_health_get","parameters":[{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/email/test":{"post":{"summary":"Admin Test Email","operationId":"admin_test_email_admin_email_test_post","parameters":[{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TestEmailRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/send-outreach-email":{"post":{"summary":"Send Outreach Email","description":"Send an outreach email using an approved campaign. Deduped by (to, approval_ref).","operationId":"send_outreach_email_admin_send_outreach_email_post","parameters":[{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SendOutreachEmailRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/conversion-funnel":{"get":{"summary":"Admin Conversion Funnel","description":"Funnel de conversion canonico de 6 pasos (ADR conversion-analytics).\n\n`tz` (an IANA name) cuts the days at 00:00 of that zone instead of UTC, for every step and\nfor `activation.matures_at`, and the answer then says so in `timezone`. Without it nothing\nchanges: the same UTC days, the same queries with the same parameters, the same answer.\n\n#62: a parameter it does not take is a 422 that names it (`?days=30` used to answer the\ndefault 30-day funnel in silence), and the answer states the window it computed in `window`\n(`from`/`to` inclusive days, and the time zone they are cut in).","operationId":"admin_conversion_funnel_admin_conversion_funnel_get","parameters":[{"name":"from","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"From"}},{"name":"to","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"To"}},{"name":"tz","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Tz"}},{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/funnel-detail":{"get":{"summary":"Admin Funnel Detail","description":"Detalle de usuarios por etapa del funnel.","operationId":"admin_funnel_detail_admin_funnel_detail_get","parameters":[{"name":"stage","in":"query","required":true,"schema":{"type":"string","title":"Stage"}},{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/waitlist":{"get":{"summary":"Admin Waitlist","description":"List all waitlist signups, grouped by OS.","operationId":"admin_waitlist_admin_waitlist_get","parameters":[{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/notify":{"get":{"summary":"Admin Notify","description":"Email sign-ups (notify_emails) as a demand signal: aggregates only, no addresses.\n\nPer origin (tray /notify, landing /download, other) per day and per ISO week over the last\n`days` UTC days, all-time totals, and the unsubscribes (notify_unsubscribed). CI addresses\n(`@local-mcp.test`) are excluded. The addresses themselves are in /admin/download-emails.\nA parameter it does not take is a 422 that names it (#62).","operationId":"admin_notify_admin_notify_get","parameters":[{"name":"days","in":"query","required":false,"schema":{"type":"integer","maximum":365,"minimum":1,"default":30,"title":"Days"}},{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/cloud-detail":{"get":{"summary":"Admin Cloud Detail","description":"Detalle de cards del Cloud Connector, Cloud->Local Funnel y KPIs principales.","operationId":"admin_cloud_detail_admin_cloud_detail_get","parameters":[{"name":"stage","in":"query","required":true,"schema":{"type":"string","title":"Stage"}},{"name":"from","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"From"}},{"name":"to","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"To"}},{"name":"include_probes","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"Include Probes"}},{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/install-sources":{"get":{"summary":"Admin Install Sources","description":"Installs agrupados por UTM source.","operationId":"admin_install_sources_admin_install_sources_get","parameters":[{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/guide-funnel":{"get":{"summary":"Admin Guide Funnel","description":"Per-guide browser visit/click funnel with separately attributed installs.\n\nBrowser visits and CTA clickers share a visitor id, so visit-to-click is a\nmeaningful rate. Installs are distinct machine ids attributed by guide ref in\nthe same time window, NOT a cohort joined to browser clickers. Never divide\ninstalls by clicks. Direct-DMG installs carry no ref (R2 is ref-agnostic).\n\nThe guide identity is read from `path` FIRST and from `ref` only as a fallback,\nbecause `ref` is being handed over to acquisition channel on page_view in lmcp-web:\na visit would start arriving as `ref='web-direct'` and this report would read\nvisits=0 / clicks=N per guide — not a shifted number, a broken conversion rate that\nlooks like the traffic died. Clicks keep `ref='guide-<slug>'` on purpose (content\ncredit), so they resolve through the fallback and the same expression serves both.\n\nReading both shapes is what lets this ship BEFORE the emitter without a zero window:\nmeasured against production 2026-09-18, 30 days, 0 of 8176 guide page_views carried\n`path` at all (it is not even a key on them), while 8172 carried `ref='guide-%'`.\nControl for that zero: `(none)`-source page_views were 5875 of 5877 WITH `path`, so\nthe field was visible to the query and the guide zero was real. Drop the fallback\nonly once `path` coverage is measured to be complete. Checked against production the\nsame day: the old query and this one return the same 216 rows with 0 rows differing.\nThe totals themselves drift with the rolling window (5383 visits / 949 clicks on one\nrun, 5382 / 948 an hour later) — the invariant is the zero, not the sums.\n\nBoth branches are guarded by an anchored match instead of a bare prefix strip: a\n`path` of `/en` or a `ref` of `web-direct` would otherwise survive the strip\nunchanged and be grouped as if it were a slug, inventing a guide out of a homepage\nvisit — which is the very confusion the emitter change exists to end.\n\nThe fallback fires when `path` is ABSENT, never when it is present and does not\nmatch, and the difference is not stylistic. 73 of the 95 guides link to\n`/download?ref=guide-<slug>` in their body, so production already carries 173\npage_views in 30 days whose `ref` says `guide-*` on a path that is not a guide\n(139 on /download, 16 on /en, 15 on /de/download, 2 on /enterprise, 1 on\n/es/download). A COALESCE would treat \"did not match\" as \"try the ref\" and count\nevery one of them as a visit to the guide that sent the user — failing in the\ndirection that inflates, and crediting a real slug, which is what makes it hard to\nsee. The `source='guide'` equality also excludes them today, because the emitter\nonly sets `source` when the PATH is content; this CASE means the report does not\ndepend on that second, separately-owned guarantee staying true.\n\n`source='guide'` still scopes this (the edge stream is `guide-edge`, see :1767);\nthat exclusion is load-bearing at ~6.4x, so it must not be relaxed to `guide%`.","operationId":"admin_guide_funnel_admin_guide_funnel_get","parameters":[{"name":"days","in":"query","required":false,"schema":{"type":"integer","default":30,"title":"Days"}},{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/web-ai-funnel":{"get":{"summary":"Admin Web Ai Funnel","description":"Web-AI connect funnel (WS6): does the tray connect flow convert to real connections?\n\nIntent stages are machine-keyed (tray events carry machine_id): opened a per-agent\nconnect panel (tray_web_ai_setup_clicked) -> copied the connector URL\n(tray_connector_url_copied) -> engaged further (tray_web_ai_guide_clicked or the IDE\ntray_mcp_deeplink_clicked). The connection stage is the outcome: cloud_connector_session\nrows with token_state='connected' (a web AI actually bound through the relay), by\nai_client. NOTE: the connection event is session/token-keyed (no machine_id), so it is\nan AGGREGATE outcome over the same window, not a per-machine join to the intent stages —\nread it as \"tray connect intent\" vs \"connections observed\", not a single funnel rate.","operationId":"admin_web_ai_funnel_admin_web_ai_funnel_get","parameters":[{"name":"days","in":"query","required":false,"schema":{"type":"integer","default":30,"title":"Days"}},{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/prompt-copies":{"get":{"summary":"Admin Prompt Copies","description":"Which recipe/guide prompts get copied. `copy_prompt` events are tagged\nref='recipe-<slug>'|'guide-<slug>', source='recipe'|'guide' by the CopyPrompt /\nCopyableBlockquote components. A demand + activation signal: copy the prompt ->\npaste into Claude/ChatGPT with LMCP connected -> it runs on the user's Mac.\nRanks prompts by total copies (and unique copiers) so we ship more of what people\nactually want to run.","operationId":"admin_prompt_copies_admin_prompt_copies_get","parameters":[{"name":"days","in":"query","required":false,"schema":{"type":"integer","default":30,"title":"Days"}},{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/help-questions":{"get":{"summary":"Admin Help Questions","description":"Questions typed into the Help Center search (/help). Each `help_question`\nevent carries the query + how many results the on-device search returned.\nZero-result queries are content gaps — write the missing guide/FAQ/doc. Grouped\nby normalized query so the same question asked 30 times ranks once.","operationId":"admin_help_questions_admin_help_questions_get","parameters":[{"name":"days","in":"query","required":false,"schema":{"type":"integer","default":30,"title":"Days"}},{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/install-refs":{"get":{"summary":"Admin Install Refs","description":"Installs by attribution ref (e.g. llms, github, reddit-*).\n\n?daily=true  → daily time-series per ref (filtered to named refs only,\n               excludes fingerprint hashes like 'bbb2c7c1').\n?days=N      → lookback window (default 90).\n?frm=YYYY-MM-DD&to=YYYY-MM-DD → explicit date range (inclusive); overrides days.\n?ref=github  → filter to a single ref (daily mode only).","operationId":"admin_install_refs_admin_install_refs_get","parameters":[{"name":"daily","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"Daily"}},{"name":"days","in":"query","required":false,"schema":{"type":"integer","default":90,"title":"Days"}},{"name":"ref","in":"query","required":false,"schema":{"type":"string","default":"","title":"Ref"}},{"name":"frm","in":"query","required":false,"schema":{"type":"string","default":"","title":"Frm"}},{"name":"to","in":"query","required":false,"schema":{"type":"string","default":"","title":"To"}},{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/install-step-funnel":{"get":{"summary":"Admin Install Step Funnel","description":"Install drop-off funnel from `install_step` telemetry.\n\nReturns, for the same time window the install-refs panel uses:\n  - steps:    distinct machines reaching each step (ok), ordered as a\n              retention funnel (most machines first), with fail counts.\n  - failures: every fail step with its `detail` reason + platform.\n\nCOHORT-SCOPED: the funnel only counts machines whose `start` step falls in\nthe window (= installs that began in the window). Without this, a machine\nthat installed months ago via npx but keeps heartbeating would drag its\nhistorical `route` event into every window, making the live DMG-vs-npx mix\nlook stuck on npx. Steps cluster within minutes of `start`, so scoping by\nstart-in-window gives the true per-install funnel.\n\nNote: the granular step funnel only covers the curl/install.sh path. The\nnotarized DMG-app completes via `config_written`, not these steps — so this\ndiagnoses where curl installers drop, not total completion.","operationId":"admin_install_step_funnel_admin_install_step_funnel_get","parameters":[{"name":"days","in":"query","required":false,"schema":{"type":"integer","default":90,"title":"Days"}},{"name":"frm","in":"query","required":false,"schema":{"type":"string","default":"","title":"Frm"}},{"name":"to","in":"query","required":false,"schema":{"type":"string","default":"","title":"To"}},{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/install-step-counts":{"get":{"summary":"Admin Install Step Counts","description":"Per-step `install_step` counts, SPLIT BY PLATFORM, over a declared window (default 7 days).\n\nShape (lmcp-admin #153): {window_days, platforms: {darwin|windows|other: {total_installs,\nsteps: [{step, installs, ok, fail}]}}}. All three platform keys are always present (empty when a\nplatform had no install in the window). `steps` lists every step the events carry, in\n`_INSTALL_STEP_SEQ` order (unknown last), so the card holds no second list. `total_installs` is\nthe max step count within the platform (the card's 100% base — no dependency on a `start` step);\nit is NOT a distinct-install count, and `ok + fail` need not equal `installs` (an identity may be\nin both, and statuses other than ok/fail are in neither) — label it as a base, not as installs.\n\nIdentity is the install, not the machine: early install.sh steps fire before a machine_id exists\nbut carry a `fingerprint`, so count DISTINCT COALESCE(machine_id, fingerprint). Test machines\nexcluded; `ok`/`fail` split by `status`.","operationId":"admin_install_step_counts_admin_install_step_counts_get","parameters":[{"name":"days","in":"query","required":false,"schema":{"type":"integer","default":7,"title":"Days"}},{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/install-funnel":{"get":{"summary":"Admin Install Funnel","description":"Funnel de instalaciones: todas las fuentes (pre-token, curl, npm).","operationId":"admin_install_funnel_admin_install_funnel_get","parameters":[{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/aggregates/status":{"get":{"summary":"Admin Aggregates Status","description":"lmcp-api#79: the hourly summaries' watermark and its lag behind the last closed UTC hour;\n`stale` when it is more than 3 hours behind (the job stopped or keeps failing). The alert reads\nthis; nothing else does yet.","operationId":"admin_aggregates_status_admin_aggregates_status_get","parameters":[{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/server-source":{"get":{"summary":"Admin Server Source","description":"ADR-0004: which server binary active machines run — `embedded` (notarized\nserver inside LocalMCPTray.app) vs `standalone` (npm download in\n~/.local/share/local-mcp/bin) vs `other`/`unknown` (old clients pre-reporting).\nWhen `standalone` trends to ~0 among active macOS machines, the npm standalone\ndownload can be retired.","operationId":"admin_server_source_admin_server_source_get","parameters":[{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/download-emails":{"get":{"summary":"Admin Download Emails","description":"Emails captured by the email-capture flows, newest first (notify_emails):\n  - landing download step (/download): has a `vid`, no machine link;\n  - tray \"contact\" form (/notify): linked to a `machine_id`.\n`link_sent` = a download link was emailed via Resend. Lets us see download-intent\nsignups even though the landing path doesn't attribute to a machine.","operationId":"admin_download_emails_admin_download_emails_get","parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","default":300,"title":"Limit"}},{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/machines":{"get":{"summary":"Admin Machines","description":"Vista por maquina: incluye lost users (npm instalado pero server nunca corrio).\n\nOrdena y filtra sobre la FLOTA, no sobre la página. `sort` y `filter` son opcionales y\nsus defaults son el comportamiento que el panel tenía, así que un cliente viejo que\npida ?limit=300&offset=0 recibe lo mismo que antes (#1598).","operationId":"admin_machines_admin_machines_get","parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","default":300,"title":"Limit"}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","default":0,"title":"Offset"}},{"name":"sort","in":"query","required":false,"schema":{"type":"string","default":"installed","title":"Sort"}},{"name":"filter","in":"query","required":false,"schema":{"type":"string","default":"all","title":"Filter"}},{"name":"q","in":"query","required":false,"schema":{"type":"string","default":"","title":"Q"}},{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/power-users":{"get":{"summary":"Admin Power Users","description":"Engagement / power-user view from tool_call_events (the real per-call log; call_count is\nsummed, not row-counted). Two cuts:\n  • months  — per calendar month: active machines + how many cross each usage threshold\n    (>10 calls per active day on average, and >50 / >100 / >500 total calls in the month).\n  • tiers_30d — machines bucketed by total calls in the last 30 days, each with the top tools\n    that tier actually uses (summed call_count).\n'User' = machine_id (tool calls key on the machine, not the account). Test/probe machines excluded.","operationId":"admin_power_users_admin_power_users_get","parameters":[{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/zero-call-machines":{"get":{"summary":"Admin Zero Call Machines","operationId":"admin_zero_call_machines_admin_zero_call_machines_get","parameters":[{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/stuck-machines":{"get":{"summary":"Admin Stuck Machines","operationId":"admin_stuck_machines_admin_stuck_machines_get","parameters":[{"name":"older_than_days","in":"query","required":false,"schema":{"type":"integer","default":2,"title":"Older Than Days"}},{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/blasts/preview/{template_id}":{"get":{"summary":"Admin Blast Preview","operationId":"admin_blast_preview_admin_blasts_preview__template_id__get","parameters":[{"name":"template_id","in":"path","required":true,"schema":{"type":"string","title":"Template Id"}},{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/stuck-machines/blast":{"post":{"summary":"Admin Stuck Machines Blast","description":"Email all stuck machines that have an email address with reinstall instructions.","operationId":"admin_stuck_machines_blast_admin_stuck_machines_blast_post","parameters":[{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StuckMachinesBlastRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/activation-nudge/blast":{"post":{"summary":"Admin Activation Nudge Blast","description":"Send 24h activation nudge emails to zero-call machines.","operationId":"admin_activation_nudge_blast_admin_activation_nudge_blast_post","parameters":[{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ActivationNudgeBlastRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/reinstall-blast":{"post":{"summary":"Admin Reinstall Blast","description":"Send reinstall instructions to update_broken zero-call machines (LMC-576).\n\nDEPRECATED CANDIDATE (audit H-09, 2026-04-26): grep across the repo\nfinds zero frontend callers. Verify no manual curl / external agent\nrelies on it for 30 days, then remove. If kept, wire a UI consumer\nin the admin Outreach panel alongside the other blasts.","operationId":"admin_reinstall_blast_admin_reinstall_blast_post","parameters":[{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReinstallBlastRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/machines/{machine_id}/timeline":{"get":{"summary":"Machine Timeline","description":"Historial completo de una maquina.","operationId":"machine_timeline_admin_machines__machine_id__timeline_get","parameters":[{"name":"machine_id","in":"path","required":true,"schema":{"type":"string","title":"Machine Id"}},{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/machines/{machine_id}/tool-call-breakdown":{"get":{"summary":"Machine Tool Call Breakdown","description":"Returns local vs cloud tool call counts for a single machine.","operationId":"machine_tool_call_breakdown_admin_machines__machine_id__tool_call_breakdown_get","parameters":[{"name":"machine_id","in":"path","required":true,"schema":{"type":"string","title":"Machine Id"}},{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/machine-telemetry":{"get":{"summary":"Admin Machine Telemetry","description":"Per-machine telemetry to confirm/deny a feedback claim. Privacy-safe:\nkeyed only on the pseudonymous machine_id; returns NO PII.\n\nReturns for `machine_id`: total_tool_calls + first/last call (lifetime,\nmachine_tool_stats); recent per-tool error rows (tool_name, error_type,\ncount, last_seen, version) over the last `days`; tcc_status, server_version,\nrunning_version + running_stale + stale (latest heartbeat vs latest release);\nplus a `verdict` block of booleans the detectors can branch on directly.","operationId":"admin_machine_telemetry_admin_machine_telemetry_get","parameters":[{"name":"machine_id","in":"query","required":true,"schema":{"type":"string","title":"Machine Id"}},{"name":"days","in":"query","required":false,"schema":{"type":"integer","default":30,"title":"Days"}},{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/resource-health":{"get":{"summary":"Admin Resource Health","description":"Cuanta maquina esta gastando de mas, y por que (#2143).\n\nExiste porque el caso que lo motivo llego por CORREO: un usuario escribio contando que\nLMCP le comia 30-50% de CPU y que la busqueda por cuerpo llevaba dos dias sin terminar.\nCuando fuimos a mirar, la misma firma estaba en varias maquinas desde hacia dos semanas\ny nadie la habia visto, porque el dato no lo miraba nadie.\n\n`mail_index_state = 'stuck'` es la senal sin interpretacion: el indice esta reintentando\nen bucle, no construyendose. Un porcentaje de CPU dice CUANTO; esto dice QUIEN.\n\nSolo pseudonimo: machine_id, nunca email ni contenido.","operationId":"admin_resource_health_admin_resource_health_get","parameters":[{"name":"hours","in":"query","required":false,"schema":{"type":"integer","default":24,"title":"Hours"}},{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/machines/{machine_id}/mark-emailed":{"post":{"summary":"Mark Emailed","description":"Record that an outreach email was sent to a machine's user.","operationId":"mark_emailed_admin_machines__machine_id__mark_emailed_post","parameters":[{"name":"machine_id","in":"path","required":true,"schema":{"type":"string","title":"Machine Id"}},{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MarkEmailedRequest"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/machines/{machine_id}/email-history":{"get":{"summary":"Email History","description":"Return all outreach emails recorded for a machine.","operationId":"email_history_admin_machines__machine_id__email_history_get","parameters":[{"name":"machine_id","in":"path","required":true,"schema":{"type":"string","title":"Machine Id"}},{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/machines/{machine_id}/notify":{"post":{"summary":"Machine Notify","description":"Queue a tray push_message for a specific machine.","operationId":"machine_notify_admin_machines__machine_id__notify_post","parameters":[{"name":"machine_id","in":"path","required":true,"schema":{"type":"string","title":"Machine Id"}},{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MachineNotifyRequest"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/notify/broadcast":{"post":{"summary":"Notify Broadcast","description":"Send a one-off announcement to the notify_emails list (minus unsubscribes).\n\ndry_run (default) sends ONE test email to test_to and reports the real\nrecipient count without touching anyone else. A real send is idempotent:\nbroadcast_sends records every delivery, so re-running skips anyone already\nmailed for this broadcast id.","operationId":"notify_broadcast_admin_notify_broadcast_post","parameters":[{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BroadcastRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/unsubscribe":{"get":{"summary":"Unsubscribe","description":"Public one-click unsubscribe from notify announcements. HMAC-gated so a\nthird party can't unsubscribe an arbitrary email by guessing the URL.","operationId":"unsubscribe_unsubscribe_get","parameters":[{"name":"email","in":"query","required":true,"schema":{"type":"string","title":"Email"}},{"name":"token","in":"query","required":true,"schema":{"type":"string","title":"Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/agent-reports":{"get":{"summary":"Admin Agent Reports","description":"Lista reportes enviados por agentes AI.","operationId":"admin_agent_reports_admin_agent_reports_get","parameters":[{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/tool-usage":{"get":{"summary":"Admin Tool Usage","description":"All 79+ tools with local + cloud usage metrics.","operationId":"admin_tool_usage_admin_tool_usage_get","parameters":[{"name":"range","in":"query","required":false,"schema":{"type":"string","default":"all","title":"Range"}},{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/user-journeys":{"get":{"summary":"Admin User Journeys","description":"Unified user journeys: one row per machine with all funnel stages joined.","operationId":"admin_user_journeys_admin_user_journeys_get","parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","default":200,"title":"Limit"}},{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/dashboard":{"get":{"summary":"Admin Dashboard","description":"Dashboard completo de adopcion y uso del producto.","operationId":"admin_dashboard_admin_dashboard_get","parameters":[{"name":"from","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"From"}},{"name":"to","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"To"}},{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/version-stats":{"get":{"summary":"Admin Version Stats","description":"Estadisticas de versiones activas en los ultimos 7 dias.","operationId":"admin_version_stats_admin_version_stats_get","parameters":[{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/tcc-recovery":{"get":{"summary":"Admin Tcc Recovery","description":"TCC block→recovery funnel — the churn lever. Of machines that hit a\nCalendar/Contacts/Reminders permission wall in the window (a tool of that service\nreturned permission_denied / tcc_* ), what happened next:\n  - recovered: every blocked service is now granted (effective state from outcomes)\n  - partial:   some but not all blocked services granted\n  - stuck_active: still denied AND still active (last heartbeat <7d) → INTERVENTION TARGET\n  - churned_or_inactive: no heartbeat in 7d\nThe `stuck_machines` list is who to nudge (active, blocked, recoverable).","operationId":"admin_tcc_recovery_admin_tcc_recovery_get","parameters":[{"name":"days","in":"query","required":false,"schema":{"type":"integer","default":30,"title":"Days"}},{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/activation-funnel":{"get":{"summary":"Admin Activation Funnel","description":"First-run activation funnel for machines installed in the window. Splits the\nNON-activated (0 successful tool calls) into two churn causes needing different fixes:\n  - blocked_at_activation: tried tools but hit a permission wall (TCC/FDA/governance)\n    → recoverable; nudge to grant.\n  - never_tried: no calls AND no errors → the AI never surfaced/called tools (discovery /\n    onboarding gap), not a permission problem.\nactivated = >=1 SUCCESSFUL call (total_tool_calls counts successes). Validated against\nprod (127 installs/14d → 62% activated, 48 never_tried, 0 blocked → discovery is the gap).","operationId":"admin_activation_funnel_admin_activation_funnel_get","parameters":[{"name":"days","in":"query","required":false,"schema":{"type":"integer","default":14,"title":"Days"}},{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/never-activated":{"get":{"summary":"Admin Never Activated","description":"Re-engagement watchlist: machines that CONFIGURED a client (emitted mcp_tools_listed)\nbut made 0 successful tool calls — the configure→use cliff, the #1 activation bottleneck.\nEach row = a real-but-dormant install: client, version, when configured, last seen. Newest\nconfig first (freshest leads). Excludes non-macOS (Go server / amd64) and internal/test.\nFeeds re-engagement (the configured-never-called cohort) + Paperclip detectors.","operationId":"admin_never_activated_admin_never_activated_get","parameters":[{"name":"days","in":"query","required":false,"schema":{"type":"integer","default":30,"title":"Days"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","default":100,"title":"Limit"}},{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/tool-errors":{"get":{"summary":"Admin Tool Errors","description":"Fleet-wide tool error breakdown over a time window.\n\nWindow: pass `hours` for a fine-grained window (e.g. 1, 6, 24) — useful to\nconfirm a freshly-shipped fix — or `days` (default 7). `hours` wins when > 0.\n\nErrors with an active time-based dismissal are hidden (dismissed_fleet).\nErrors marked fixed-in-version (mark-tool-error-fixed) are hidden as long as\nthey only recur on builds < that version (fixed_fleet); the moment they\nreappear on a build >= the fix version they re-surface in the active fleet\nflagged `regressed`.\n\n`version` (optional) restricts the breakdown to a single client version;\n`available_versions` lists every version present in the window for the picker.","operationId":"admin_tool_errors_admin_tool_errors_get","parameters":[{"name":"days","in":"query","required":false,"schema":{"type":"integer","default":7,"title":"Days"}},{"name":"version","in":"query","required":false,"schema":{"type":"string","default":"","title":"Version"}},{"name":"hours","in":"query","required":false,"schema":{"type":"integer","default":0,"title":"Hours"}},{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/install-component-stats":{"get":{"summary":"Admin Install Component Stats","description":"Wacli and tray install success rates from install_completed events.\n\nDEPRECATED CANDIDATE (audit H-09, 2026-04-26): grep across the repo\nfinds zero frontend callers. Verify no manual curl / external agent\nrelies on it for 30 days, then remove. If kept, surface in the Funnel\ntab next to the install funnel.","operationId":"admin_install_component_stats_admin_install_component_stats_get","parameters":[{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/cf-analytics":{"get":{"summary":"Admin Cf Analytics","description":"Page views, unique visitors y top countries de Cloudflare.","operationId":"admin_cf_analytics_admin_cf_analytics_get","parameters":[{"name":"from","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"From"}},{"name":"to","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"To"}},{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/cf-snapshot":{"post":{"summary":"Admin Cf Snapshot","operationId":"admin_cf_snapshot_admin_cf_snapshot_post","parameters":[{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/uninstalls":{"get":{"summary":"Admin Uninstalls","description":"`limit` bounds only the `uninstalls` list returned for the panel — `summary` is\nalways computed over the full universe of uninstall events (#1616). Before this fix\nthe SQL itself carried `LIMIT %s`, so a percentage like `reinstalled_pct` and the\n`top_reasons` ranking were silently computed over whichever ≤100 rows sorted first,\nnot over \"everyone who uninstalled\" — same defect class as #1598/#1602's fleet\nsnapshot, just with a percentage instead of a raw count.","operationId":"admin_uninstalls_admin_uninstalls_get","parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","default":100,"title":"Limit"}},{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/intent-segments":{"get":{"summary":"Admin Intent Segments","description":"Segment the fleet by Job-To-Be-Done from aggregate per-tool telemetry.\n\n~92% of tool usage is local stdio (no call sequence — see /admin/cloud-detail\nfor the thin cloud-relay sample), so real journeys can't be reconstructed.\nWhat we CAN do is map each machine's TOOL BASKET (over the window) through the\nJTBD taxonomy to answer \"what are users trying to accomplish\". Volume comes\nfrom tool_call_events (summed per machine+tool over the window). Meta/plumbing\nJTBDs (System & setup) are excluded from intent segmentation unless\ninclude_meta=true. Unmapped tools are surfaced so the taxonomy stays honest.","operationId":"admin_intent_segments_admin_intent_segments_get","parameters":[{"name":"days","in":"query","required":false,"schema":{"type":"integer","maximum":180,"minimum":1,"default":30,"title":"Days"}},{"name":"include_meta","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"Include Meta"}},{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/journeys":{"get":{"summary":"Admin Journeys","description":"Rebuild real tool journeys from session_journey events (the ordered per-run\nsequences the client flushes on heartbeat). Answers \"what do users chain, and\nwhere does it break\" for the local fleet — the 92% with no per-call sequence\nelsewhere. Break point = the step a run ABORTS on (last step failed or >15s).","operationId":"admin_journeys_admin_journeys_get","parameters":[{"name":"days","in":"query","required":false,"schema":{"type":"integer","maximum":90,"minimum":1,"default":14,"title":"Days"}},{"name":"min_len","in":"query","required":false,"schema":{"type":"integer","maximum":40,"minimum":1,"default":1,"title":"Min Len"}},{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/pulse":{"get":{"summary":"Admin Pulse","description":"Pulse — the OKR scorecard + 'needs attention', computed ONCE on the canonical\nmetrics layer (metrics.py). This is the single trusted KPI source for the admin\nhome (admin redesign Phase 1). Every number here uses the same DAU/real-machine\ndefinition, so it cannot disagree with itself across tabs.","operationId":"admin_pulse_admin_pulse_get","parameters":[{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/growth":{"get":{"summary":"Admin Growth","description":"Growth — the ONE acquisition→activation→retention funnel (admin redesign\nPhase 2), replacing the four overlapping funnels (conversion / conversion-funnel\n/ onboarding-breakdown / dashboard). Built on the canonical metrics layer.\n\nHonest about units: the machine funnel (Install→Activate→Retain) is strictly\ndedupable per machine. 'Visitors' is top-of-funnel CONTEXT only — browser→machine\nis the dead pre_tokens attribution, so we do NOT fake a visitor→install rate.\nChannel attribution uses the real `ref` (sparse — most installs are unknown).","operationId":"admin_growth_admin_growth_get","parameters":[{"name":"days","in":"query","required":false,"schema":{"type":"integer","maximum":90,"minimum":1,"default":30,"title":"Days"}},{"name":"horizon","in":"query","required":false,"schema":{"type":"integer","maximum":14,"minimum":1,"default":7,"title":"Horizon"}},{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/frustration":{"get":{"summary":"Admin Frustration","description":"Privacy-safe friction/frustration signal — the content-free replacement for the\nrich report_problem capture lost in the April GDPR hardening. Aggregates the\nagent-reported / auto-detected `friction_signal` events (categories only, no user\ncontent) so we can see WHERE users get stuck and prioritize, like we used to.","operationId":"admin_frustration_admin_frustration_get","parameters":[{"name":"days","in":"query","required":false,"schema":{"type":"integer","maximum":90,"minimum":1,"default":14,"title":"Days"}},{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/engagement":{"get":{"summary":"Admin Engagement","description":"Engagement — usage→retention signals (admin redesign Phase 3): breadth→retention\n(the #1 retention lever), tool reach, and the churn cohort (for outreach). Canonical\nmetrics layer. Pairs with /admin/intent-segments + /admin/journeys in the same tab.","operationId":"admin_engagement_admin_engagement_get","parameters":[{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/problems":{"get":{"summary":"Admin Problems","description":"Problems — everything broken for users in ONE ranked place (admin redesign\nPhase 4): open problem reports + fleet tool-errors (ranked by reach) + latest QA\n+ GitHub issues. Fleet errors use the canonical tool-error breakdown; GitHub is\nbest-effort. Replaces the scattered QA/error/report summaries.","operationId":"admin_problems_admin_problems_get","parameters":[{"name":"days","in":"query","required":false,"schema":{"type":"integer","maximum":30,"minimum":1,"default":7,"title":"Days"}},{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/send-digest":{"post":{"summary":"Admin Send Digest","description":"Send the autonomous board digest via Resend — Tray-independent. The autonomous\ncycle POSTs its HTML digest here instead of relying on the send_email MCP tool, so\nthe email is delivered even when LMCP is uninstalled/closed on the host machine\n(the MCP path needs the local Tray; this does not). Recipients default to the board\nlist (lanchuske@gmail.com + ceo@colibird.co).","operationId":"admin_send_digest_admin_send_digest_post","parameters":[{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SendDigestRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/onboarding-funnel":{"get":{"summary":"Admin Onboarding Funnel","description":"Onboarding funnel: per-step conversion + median dwell, permission\ngranted/denied by type, top requested-but-missing apps, language demand, and\nactivation (completed → first_tool_call). Window-bounded; aggregated in\nPython to avoid heavy GROUP BY (the activation-funnel timeout lesson).","operationId":"admin_onboarding_funnel_admin_onboarding_funnel_get","parameters":[{"name":"days","in":"query","required":false,"schema":{"type":"integer","default":30,"title":"Days"}},{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/contacts":{"get":{"summary":"Admin Contacts","operationId":"admin_contacts_admin_contacts_get","parameters":[{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/discovery/web":{"get":{"summary":"Discovery Web","description":"Human web discovery: visitors by referrer channel → install intent.","operationId":"discovery_web_admin_discovery_web_get","parameters":[{"name":"days","in":"query","required":false,"schema":{"type":"integer","maximum":180,"minimum":1,"default":30,"title":"Days"}},{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/discovery/agents":{"get":{"summary":"Discovery Agents","description":"Agent/MCP discovery: /mcp connector sessions by ai_client.","operationId":"discovery_agents_admin_discovery_agents_get","parameters":[{"name":"days","in":"query","required":false,"schema":{"type":"integer","maximum":180,"minimum":1,"default":14,"title":"Days"}},{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/discovery/registries":{"get":{"summary":"Discovery Registries","description":"Programmatic discovery: installs attributed to a registry / directory / tagged command.\n\nnpm *downloads* (the top-of-funnel) come from the public npm API client-side; here we count\nthe installs that actually landed with a registry/directory ref. `.well-known`/`llms.txt`\n*fetches* live only in Cloudflare (see Reach view) — they don't emit an app event.","operationId":"discovery_registries_admin_discovery_registries_get","parameters":[{"name":"days","in":"query","required":false,"schema":{"type":"integer","maximum":180,"minimum":1,"default":30,"title":"Days"}},{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/discovery/search":{"get":{"summary":"Discovery Search","description":"GSC (Google Search Console) — organic search queries/pages/trend from the latest\ngsc_daily snapshot (populated by LMCP/scripts/gsc-pull.py). Returns configured=False when\nthe table is empty / not yet pulled, so the frontend can show a setup hint.","operationId":"discovery_search_admin_discovery_search_get","parameters":[{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/chatgpt-autoconnect":{"get":{"summary":"Chatgpt Autoconnect","description":"Journey del auto-connect de ChatGPT por intento (run_id), más nuevo primero.\n\nCada run: la secuencia de stages con outcome/url, el último stage alcanzado, y los stages que\nfallaron con su `ui_dump` (el DOM real para escribir el próximo fix sin adivinar).","operationId":"chatgpt_autoconnect_admin_chatgpt_autoconnect_get","parameters":[{"name":"hours","in":"query","required":false,"schema":{"type":"integer","maximum":720,"minimum":1,"default":48,"title":"Hours"}},{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/tool-discovery":{"get":{"summary":"Tool Discovery","operationId":"tool_discovery_admin_tool_discovery_get","parameters":[{"name":"days","in":"query","required":false,"schema":{"type":"integer","maximum":180,"minimum":1,"default":14,"title":"Days"}},{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/suggestion/pending":{"get":{"summary":"Suggestion Pending","description":"CLIENT delivery endpoint (mirrors /survey/pending). Returns the connected-but-unused first-task\nsuggestion for this machine, or {} when there's nothing to suggest OR the machine is still inside\nthe post-show cooldown (one-shot semantics). Content is English v1 — the AI relays it in the user's\nlanguage; `lang` is accepted for a future localized framing. No auth: keyed by machine_id like the\nsurvey feed; it only ever returns the machine's own connected-but-unused task.","operationId":"suggestion_pending_suggestion_pending_get","parameters":[{"name":"machine_id","in":"query","required":true,"schema":{"type":"string","title":"Machine Id"}},{"name":"lang","in":"query","required":false,"schema":{"type":"string","default":"en","title":"Lang"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/suggestion/event":{"post":{"summary":"Suggestion Event","description":"Record a suggestion-delivery event (the client fires 'shown' when it attaches a suggestion to a\ntool result). Also the cooldown source: a 'shown' here suppresses re-suggesting for the window.","operationId":"suggestion_event_suggestion_event_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuggestionEventBody"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/suggested-task":{"get":{"summary":"Suggested Task","description":"The suggestion for one machine — validate quality/personalization against a real install.","operationId":"suggested_task_admin_suggested_task_get","parameters":[{"name":"machine_id","in":"query","required":true,"schema":{"type":"string","title":"Machine Id"}},{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/suggested-tasks":{"get":{"summary":"Suggested Tasks","description":"Aggregate validation over active machines: coverage (how many get a suggestion) + the\ndistribution of suggested domains. Batched (latest services per machine + all tool usage) so\nit's a couple of queries, not one per machine.","operationId":"suggested_tasks_admin_suggested_tasks_get","parameters":[{"name":"days","in":"query","required":false,"schema":{"type":"integer","maximum":180,"minimum":1,"default":60,"title":"Days"}},{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/engagement-buckets":{"get":{"summary":"Engagement","description":"Bucket every alive machine (heartbeat ≤3d) by real tool usage: engaged (a tool call within\n`days`), silent_abandonment (used tools once but not within `days`), never_used. Returns the\nengaged retention % — the honest denominator vs heartbeat-alive.","operationId":"engagement_admin_engagement_buckets_get","parameters":[{"name":"days","in":"query","required":false,"schema":{"type":"integer","maximum":180,"minimum":1,"default":14,"title":"Days"}},{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/silent-abandonment":{"get":{"summary":"Silent Abandonment","description":"The re-engagement outreach list: alive machines (heartbeat ≤3d) that used tools once but not\nwithin `days`, with days-since-last-use, the last tool they called, version and locale. Ordered\noldest-quiet first — they already installed + configured, then something made them stop.","operationId":"silent_abandonment_admin_silent_abandonment_get","parameters":[{"name":"days","in":"query","required":false,"schema":{"type":"integer","maximum":180,"minimum":1,"default":14,"title":"Days"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":1000,"minimum":1,"default":200,"title":"Limit"}},{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/roadmap-counts":{"get":{"summary":"Roadmap Counts","description":"Distinct people per published roadmap item (no auth). One query per TTL per process.","operationId":"roadmap_counts_roadmap_counts_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/download-attribution/token":{"post":{"summary":"Post Download Attribution Token","description":"Mint a download token only for the trusted first-party web service.\n\nlmcp-web#373 part 2: the mint also returns `status_handle`, a second random value that\ncan only read this download's stage (GET /download-attribution/stage). The token goes\nonly into the file's provenance; the handle stays in the page's memory.","operationId":"post_download_attribution_token_download_attribution_token_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DownloadAttributionRequest"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/download-attribution/owner":{"post":{"summary":"Post Download Attribution Owner","description":"lmcp-api#403: is this `dt` bound to this session's account (and still able to link)?\n`{same}` only; the same `false` for unknown, anonymous, foreign, expired and an empty session.\n\nlmcp-api#409: with `session` OMITTED, `{same: false, anonymous}`, where `anonymous` is true\nonly for a live anonymous `dt` (exists, no account, unexpired, unconsumed) and false for every\nother case alike. `session: null` stays a 422.","operationId":"post_download_attribution_owner_download_attribution_owner_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DownloadOwnerRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/download-attribution/stage":{"get":{"summary":"Get Download Attribution Stage","description":"The installer's stage for the one download a status handle was minted with.\n\nlmcp-web#373 part 2. `Authorization: Bearer <status_handle>`, through the web proxy only.\nThe answer is `{\"stage\": ...}` and nothing else: no vid, ref, src, timestamps, platform,\ninstall key or machine. A malformed, unknown or expired handle gets the same `404 {}`.","operationId":"get_download_attribution_stage_download_attribution_stage_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}},"post":{"summary":"Post Download Attribution Stage","description":"An installer reports «opened» or «installing» for its download (lmcp-api#216).\n\nKeyed by the one-use token, like consume, and it does not consume it. Idempotent and\nforward only. The answer is `{\"accepted\": bool}` and the same for a malformed, unknown,\nexpired, consumed or backward report: it never says which tokens exist.","operationId":"post_download_attribution_stage_download_attribution_stage_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DownloadStageReport"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/download-attribution/consume":{"post":{"summary":"Post Download Attribution Consume","description":"Redeem a bearer token once.\n\nlmcp-api#325: when the token was minted with a visit id (the site sends one only after an\nanalytics yes), the answer adds `vid`, so the installer can send it on its install event.\nWithout one the key is absent and the answer is byte for byte what it always was. `ref` and\n`src` are never returned.","operationId":"post_download_attribution_consume_download_attribution_consume_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DownloadAttributionConsumeRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/install-event":{"post":{"summary":"Post Install Event","description":"Registra eventos del install script (start/complete/failed).\n\nFor install_script_fetched events (no stage), tags is_bot=true when the\nuser-agent matches a known non-human fetcher pattern. The install funnel\ndashboard subtracts those from the real-conversion denominator so we can\nmeasure actual user conversion instead of being drowned in bot noise.","operationId":"post_install_event_install_event_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InstallEventRequest"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/install/step":{"post":{"summary":"Post Install Step","description":"Logs one install step. Used by install.sh and install-windows.ps1.\nEach step of the installer POSTs here so we can see where users drop off.","operationId":"post_install_step_install_step_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InstallStepBody"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/install/journey":{"get":{"summary":"Get Install Journey","description":"Given any identifier (IP, machine_id, or fingerprint), returns ALL related\nevents across the entire funnel: landing → install → heartbeat → tool use.","operationId":"get_install_journey_install_journey_get","parameters":[{"name":"ip","in":"query","required":false,"schema":{"type":"string","default":"","title":"Ip"}},{"name":"machine_id","in":"query","required":false,"schema":{"type":"string","default":"","title":"Machine Id"}},{"name":"fingerprint","in":"query","required":false,"schema":{"type":"string","default":"","title":"Fingerprint"}},{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/install/registered":{"post":{"summary":"Post Install Registered","operationId":"post_install_registered_install_registered_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InstallRegisteredRequest"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/setup-step":{"post":{"summary":"Post Setup Step","description":"Granular setup funnel telemetry.  Every step of config writing is logged\nhere so we can see exactly where installs fail without waiting for a heartbeat\n(which never comes for machines where config writing failed).","operationId":"post_setup_step_setup_step_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetupStepRequest"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/welcome-event":{"post":{"summary":"Post Welcome Event","description":"Telemetry from the post-install welcome wizard.","operationId":"post_welcome_event_welcome_event_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WelcomeEventRequest"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/welcome-status":{"get":{"summary":"Welcome Status","description":"Polled by the welcome page to flip to 'connected' once the machine makes its\nFIRST tool call (real activation signal, not heartbeat). Returns no PII —\nkeyed only on the pseudonymous machine_id.","operationId":"welcome_status_welcome_status_get","parameters":[{"name":"machine_id","in":"query","required":true,"schema":{"type":"string","maxLength":64,"title":"Machine Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/uninstall-event":{"post":{"summary":"Post Uninstall Event","description":"Fired by the --uninstall flag in install.sh. Tracks voluntary uninstalls.","operationId":"post_uninstall_event_uninstall_event_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UninstallEventRequest"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/install/npm":{"post":{"summary":"Npm Install Ping","description":"Registra una instalación via npm (postinstall o setup).","operationId":"npm_install_ping_install_npm_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/NpmInstallRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/install/ping":{"post":{"summary":"Install Ping","description":"El install script llama a este endpoint al terminar para registrar la instalación.\n\nAlso backfills claimed_at if it's null. The /install/started ping is fired\nfire-and-forget by install.sh in the background ('&>/dev/null &'); a transient\nDNS or network blip drops it silently and the install completes without ever\nmarking claimed_at. Investigation 2026-04-11 found the only successful cloud\ninstall in 7d had installed_at set but claimed_at null for exactly this reason.\nTreating /install/ping as a backfill is idempotent and closes the funnel.","operationId":"install_ping_install_ping_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InstallPingRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/install/started/{pre_token}":{"post":{"summary":"Install Started Ping","description":"Marks that the install script started running. Idempotent.","operationId":"install_started_ping_install_started__pre_token__post","parameters":[{"name":"pre_token","in":"path","required":true,"schema":{"type":"string","title":"Pre Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/setup/status/{pre_token}":{"get":{"summary":"Setup Status","description":"Returns install progress for a pre_token. Used by /setup/<token> page polling\nand by the setup_status MCP tool so agents can check if user installed.","operationId":"setup_status_setup_status__pre_token__get","parameters":[{"name":"pre_token","in":"path","required":true,"schema":{"type":"string","title":"Pre Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/setup/download/{pre_token}":{"get":{"summary":"Setup Download Dmg","description":"DMG download CTA for the setup page (cloud web→install). Logs the download\nintent per pre_token — so we can see DMG-channel demand even before the\nlocalmcp:// deep-link claim sets installed_at — then redirects to the latest\nsigned .dmg app.","operationId":"setup_download_dmg_setup_download__pre_token__get","parameters":[{"name":"pre_token","in":"path","required":true,"schema":{"type":"string","title":"Pre Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/setup/opened/{pre_token}":{"post":{"summary":"Setup Page Opened","description":"Marks that the user opened the setup page — the CLICK on the install link.\n\nPersists pre_tokens.opened_at (first open only) so the funnel\nlink_shown → opened → installed is queryable per token, not just via events.","operationId":"setup_page_opened_setup_opened__pre_token__post","parameters":[{"name":"pre_token","in":"path","required":true,"schema":{"type":"string","title":"Pre Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/setup/email/{pre_token}":{"post":{"summary":"Setup Capture Email","description":"Capture email submitted on the setup page after successful install (LMC-887).\n\nStores email in pre_tokens and calls _resolve_user to link it to the machine\n(using install_machine_id stored by /install/ping).","operationId":"setup_capture_email_setup_email__pre_token__post","parameters":[{"name":"pre_token","in":"path","required":true,"schema":{"type":"string","title":"Pre Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetupEmailBody"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/setup/event/{pre_token}":{"post":{"summary":"Setup Page Event","description":"Track granular conversion events on the setup page.","operationId":"setup_page_event_setup_event__pre_token__post","parameters":[{"name":"pre_token","in":"path","required":true,"schema":{"type":"string","title":"Pre Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetupEventBody"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/settings/register":{"post":{"summary":"Settings Register Email","description":"Capture email from local-mcp.com/settings page or POST /config in settings.html (LMC-887).\n\nCalled when a user submits the email form on /settings?m=<machine_id>,\nor from the Connect tab in the local settings UI (which passes cloud_token too).\nLinks email to machine_id and optionally to tunnel token.","operationId":"settings_register_email_settings_register_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SettingsRegisterRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/email/verify-request":{"post":{"summary":"Email Verify Request","description":"Send a confirm-your-email link. Called after the user saves their email in Settings so we\ncan verify it's real. Idempotent: no-op (sent:false) if the address is already verified.","operationId":"email_verify_request_email_verify_request_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SettingsRegisterRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/verify-email":{"get":{"summary":"Verify Email","description":"Land page for the confirm link — marks the address verified.","operationId":"verify_email_verify_email_get","parameters":[{"name":"token","in":"query","required":true,"schema":{"type":"string","title":"Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/email/verified":{"get":{"summary":"Email Verified","description":"Whether an address has a confirmed verification (for the Settings UI badge).","operationId":"email_verified_email_verified_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"}}}}}}},"/admin/onboarding-protocol-telemetry":{"get":{"summary":"Admin Onboarding Protocol Telemetry","description":"Aggregates JSON-RPC protocol rejections (mcp_requests.response_type LIKE 'protocol_%').\nThese occur *before* an onboarding_sessions row exists — not joinable, but shows drop-off\nfrom malformed clients. Shown on the Admin → Onboarding tab.","operationId":"admin_onboarding_protocol_telemetry_admin_onboarding_protocol_telemetry_get","parameters":[{"name":"hours","in":"query","required":false,"schema":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"Rolling window on mcp_requests.created_at (and events.created_at); omit for all time","title":"Hours"},"description":"Rolling window on mcp_requests.created_at (and events.created_at); omit for all time"},{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/onboarding-sessions":{"get":{"summary":"Admin Onboarding Sessions","description":"Lista sesiones de onboarding con métricas de conversión + micro-funnel\npor sesión (setup_opened, install_started, install_completed).\n\nAdds to the previous shape:\n  rows[*].ai_client / ai_client_version / os / country / city / isp\n                     user_agent  (from the first cloud_connector_session event)\n  rows[*].pre_token_claimed / pre_token_installed\n                     (bool flags — pre_token micro-funnel per session)\n  rows[*].setup_page_opened\n                     (bool flag from events)\n  rows[*].install_started_at / installed_at / install_version / install_os\n                     (from pre_tokens row attributed to this session)\n  funnel — now includes the full drop-off chain:\n      total, discovered, setup_opened, install_started,\n      install_completed, resolved, conversion_pct\n\nNew filters:\n  ai_client — exact match on cloud_connector_session.ai_client\n  os        — exact match on detected OS (macos/windows/linux/ios/android)\n  country   — exact match on geo country code (e.g. \"US\", \"AR\")\n  min_calls — rows with call_count >= this value\n  exclude_tests (default true) — strip known test/probe clients\n  hours — if set (>0), only sessions active in the last N hours\n           (onboarding_sessions.updated_at; captures ongoing retries/activity)","operationId":"admin_onboarding_sessions_admin_onboarding_sessions_get","parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","default":50,"title":"Limit"}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","default":0,"title":"Offset"}},{"name":"resolved","in":"query","required":false,"schema":{"type":"boolean","title":"Resolved"}},{"name":"situation","in":"query","required":false,"schema":{"type":"string","title":"Situation"}},{"name":"ai_client","in":"query","required":false,"schema":{"type":"string","title":"Ai Client"}},{"name":"os","in":"query","required":false,"schema":{"type":"string","title":"Os"}},{"name":"country","in":"query","required":false,"schema":{"type":"string","title":"Country"}},{"name":"min_calls","in":"query","required":false,"schema":{"type":"integer","title":"Min Calls"}},{"name":"exclude_tests","in":"query","required":false,"schema":{"type":"boolean","default":true,"title":"Exclude Tests"}},{"name":"hours","in":"query","required":false,"schema":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"Only sessions whose onboarding_sessions.updated_at falls in the last N hours","title":"Hours"},"description":"Only sessions whose onboarding_sessions.updated_at falls in the last N hours"},{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/onboarding-sessions/{session_id}":{"get":{"summary":"Admin Onboarding Session Detail","description":"Detalle de una sesión: requests MCP + eventos + estado del pre_token.","operationId":"admin_onboarding_session_detail_admin_onboarding_sessions__session_id__get","parameters":[{"name":"session_id","in":"path","required":true,"schema":{"type":"string","title":"Session Id"}},{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/onboarding-breakdown":{"get":{"summary":"Admin Onboarding Breakdown","description":"Breakdown de conversión por dimensión. Devuelve sessions / resolved / % para\ncada valor de la dimensión, ordenado por volumen descendente. Útil para\nidentificar dónde está el drop-off: qué AI clients convierten, qué OS, etc.\n\nArgs:\n    dim: ai_client | os | country | city\n    exclude_tests: strip known test/probe clients from both numerator and\n                   denominator. Default true to match the main dashboard.\n    hours: if set (>0), only sessions active in the last N hours\n           (onboarding_sessions.updated_at), same as /admin/onboarding-sessions.","operationId":"admin_onboarding_breakdown_admin_onboarding_breakdown_get","parameters":[{"name":"dim","in":"query","required":false,"schema":{"type":"string","default":"ai_client","title":"Dim"}},{"name":"exclude_tests","in":"query","required":false,"schema":{"type":"boolean","default":true,"title":"Exclude Tests"}},{"name":"hours","in":"query","required":false,"schema":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"Same rolling window as /admin/onboarding-sessions (updated_at)","title":"Hours"},"description":"Same rolling window as /admin/onboarding-sessions (updated_at)"},{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/funnel-users":{"get":{"summary":"Admin Funnel Users","description":"Builds an identity graph from all events, clusters IPs/fingerprints/machine_ids\nthat share an IP within a time window, and returns each user's funnel progress.\n\nReturns a list of \"persons\" — each with their furthest funnel stage,\nall known identifiers, platform, and timeline of key events.","operationId":"admin_funnel_users_admin_funnel_users_get","parameters":[{"name":"days","in":"query","required":false,"schema":{"type":"integer","default":7,"title":"Days"}},{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/conversion":{"get":{"summary":"Admin Conversion","description":"End-to-end conversion funnel combining install telemetry, heartbeats,\ntool usage, and cloud connector data. Replaces the separate Funnel and\nOnboarding tabs with a single actionable view.\n\nReturns:\n  funnel: 7-stage top-level conversion numbers\n  substeps: detailed install sub-steps by OS\n  cloud_connector: mini-funnel for /mcp cloud path\n  persons: list of users with journey details\n  drop_offs: where users fall off between stages","operationId":"admin_conversion_admin_conversion_get","parameters":[{"name":"days","in":"query","required":false,"schema":{"type":"integer","default":7,"title":"Days"}},{"name":"os_filter","in":"query","required":false,"schema":{"type":"string","default":"all","title":"Os Filter"}},{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/referral/code":{"post":{"summary":"Post Referral Code","description":"Idempotently return the owner machine's referral code + shareable link.\nThe link rides the existing attribution channel via ref=r-<code>.","operationId":"post_referral_code_referral_code_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReferralCodeRequest"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/referral/click":{"post":{"summary":"Post Referral Click","description":"Logged when someone opens a /r/<code> link (the web /r route fires this).","operationId":"post_referral_click_referral_click_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReferralClickRequest"}}},"required":true},"responses":{"202":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/referral":{"get":{"summary":"Admin Referral","description":"Member-get-member funnel + k-factor. Stages: codes → clicks → referred\ninstalls (ref r-<code>) → referred ACTIVATED (tool_calls>0). Attribution counts\na referral only when the referred machine activates, never on install alone.","operationId":"admin_referral_admin_referral_get","parameters":[{"name":"days","in":"query","required":false,"schema":{"type":"integer","default":90,"title":"Days"}},{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/referral/invites":{"post":{"summary":"Post Referral Invites","description":"Create per-recipient invite records and return their unique links. Called by\nthe create_referral_invites tool right before the agent sends the emails. Idempotent\nper (owner, recipient email) so re-running the flow reuses the same link.","operationId":"post_referral_invites_referral_invites_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReferralInvitesRequest"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/referral/my-invites":{"get":{"summary":"Get Referral My Invites","description":"The referrer's own invites + derived status (sent → installed → activated),\nfor the Settings page. Keyed on machine_id (the local settings page reads it\nfrom /status).","operationId":"get_referral_my_invites_referral_my_invites_get","parameters":[{"name":"machine_id","in":"query","required":false,"schema":{"type":"string","default":"","title":"Machine Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/survey/pending":{"get":{"summary":"Survey Pending","description":"The machine's pending survey, i18n-resolved to `lang`. Sticky: keeps returning\nthe same survey until it's answered or dismissed. {\"survey\": null} if none.\n\nEligibility is TARGETING + expiry only (#2758): a row in survey_targets, unanswered and\nundismissed, on an active survey that has not closed. There is no usage threshold.","operationId":"survey_pending_survey_pending_get","parameters":[{"name":"machine_id","in":"query","required":true,"schema":{"type":"string","title":"Machine Id"}},{"name":"lang","in":"query","required":false,"schema":{"type":"string","default":"en","title":"Lang"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/survey/event":{"post":{"summary":"Survey Event","description":"Stamp a funnel column (shown/opened/skipped/dismissed) — first-write-wins.\n`skipped` also increments skip_count.\n\n`gate_declined` is a DIAGNOSTIC event (not a funnel column): the client fires it once per run when\na survey is targeted + cached but the gate still won't show it (reason = already_shown /\nskipped_this_session). Log-only so we can see, fleet-wide, WHY a targeted survey stays hidden —\nthe delivery-debug signal added with the cache-warmup fix. `sessions_lt_min:x/y` was a third\nreason until #2758 removed the threshold; clients that predate it can still send it, so the\nhandler keeps accepting any reason string rather than validating against a list.","operationId":"survey_event_survey_event_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SurveyEventBody"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/survey/response":{"post":{"summary":"Survey Response","description":"Store the response (upsert per machine) and mark the target answered.","operationId":"survey_response_survey_response_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SurveyResponseBody"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/surveys":{"get":{"summary":"Admin List Surveys","description":"All surveys with funnel counters.","operationId":"admin_list_surveys_admin_surveys_get","parameters":[{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"summary":"Admin Create Survey","description":"Create a survey. Validates the question shape (types + i18n objects).","operationId":"admin_create_survey_admin_surveys_post","parameters":[{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SurveyCreateBody"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/surveys/translate":{"post":{"summary":"Admin Translate Survey","description":"Fill every survey label (title, questions, options, scale endpoints) with translations for all\nsupported languages, from the English text. Existing non-English values are preserved.","operationId":"admin_translate_survey_admin_surveys_translate_post","parameters":[{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TranslateBody"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/surveys/{survey_id}":{"patch":{"summary":"Admin Patch Survey","description":"Activate/deactivate or tweak a survey's gating fields, title, or questions (visual editor).","operationId":"admin_patch_survey_admin_surveys__survey_id__patch","parameters":[{"name":"survey_id","in":"path","required":true,"schema":{"type":"integer","title":"Survey Id"}},{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SurveyPatchBody"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"summary":"Admin Delete Survey","description":"Permanently delete a survey and (via ON DELETE CASCADE) its targets + responses.\n\nPREVIEW BY DEFAULT. Without ?confirm=true this reports what the delete would destroy and\nchanges nothing. The count matters because the CASCADE is invisible from the call site: the\nrequest says \"delete survey 8\" and the FK quietly takes every answer anyone ever gave it.\nOn 2026-08-08 we reconstructed 19 deleted responses across resets and survey deletions, and the\nonly signal left was a row counter — no record of whose answers they were.\n\n\"The UI confirms\" was the old safeguard, and it isn't one: the endpoint is called from curl and\nfrom agents far more often than from the UI, and neither sees that dialog.","operationId":"admin_delete_survey_admin_surveys__survey_id__delete","parameters":[{"name":"survey_id","in":"path","required":true,"schema":{"type":"integer","title":"Survey Id"}},{"name":"confirm","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"Confirm"}},{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/surveys/{survey_id}/targets":{"post":{"summary":"Admin Assign Targets","description":"Bulk-assign machines to a survey (idempotent — ON CONFLICT DO NOTHING).\n\nFatigue cap (spec §14.2): by default, skip any machine that ANSWERED a DIFFERENT survey in the\nlast 30 days — repeated (blocking) surveys read as nagging and drive uninstalls, and that's\nimpossible to undo once you've burned users. Pass ?ignore_fatigue=true for a deliberate re-survey.","operationId":"admin_assign_targets_admin_surveys__survey_id__targets_post","parameters":[{"name":"survey_id","in":"path","required":true,"schema":{"type":"integer","title":"Survey Id"}},{"name":"ignore_fatigue","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"Ignore Fatigue"}},{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TargetsBody"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"summary":"Admin Unassign Targets","description":"Unassign machines that haven't answered yet.","operationId":"admin_unassign_targets_admin_surveys__survey_id__targets_delete","parameters":[{"name":"survey_id","in":"path","required":true,"schema":{"type":"integer","title":"Survey Id"}},{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TargetsBody"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"get":{"summary":"Admin List Targets","description":"The machines assigned to this survey + each one's funnel status — so the admin can see who's\nassigned and unassign (or re-assign) individually.","operationId":"admin_list_targets_admin_surveys__survey_id__targets_get","parameters":[{"name":"survey_id","in":"path","required":true,"schema":{"type":"integer","title":"Survey Id"}},{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/surveys/{survey_id}/reset":{"post":{"summary":"Admin Reset Targets","description":"Reset a machine's survey state for RE-TESTING: deletes its stored response and clears the\ntarget's funnel columns + token while KEEPING the assignment, so /survey/pending serves the\nsurvey again. Built for the self-test loop (Dario, 2026-08-07: three answers deep with no way\nto retry). Resetting a real user's target re-surveys them — deliberate admin action.","operationId":"admin_reset_targets_admin_surveys__survey_id__reset_post","parameters":[{"name":"survey_id","in":"path","required":true,"schema":{"type":"integer","title":"Survey Id"}},{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TargetsBody"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/surveys/assign-machines":{"get":{"summary":"Admin Assign Machines","description":"Lightweight machine list for the survey assignment panel. /admin/machines takes ~20s/page\n(full-history DISTINCT ON + an events UNION for first_seen) and the panel paged it serially —\nminutes of 'Loading machines…'. Assignment only needs recently-alive machines and the segment\nfields, so: one query over the last `days` of heartbeats + tool totals. Sub-second.","operationId":"admin_assign_machines_admin_surveys_assign_machines_get","parameters":[{"name":"days","in":"query","required":false,"schema":{"type":"integer","default":30,"title":"Days"}},{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/survey-assignments":{"get":{"summary":"Admin Survey Assignments","description":"Every machine that has ≥1 survey assigned, grouped, with each survey + its status — the\nsurvey-relevant machine view for the Surveys tab (distinct from the global Contacts directory).","operationId":"admin_survey_assignments_admin_survey_assignments_get","parameters":[{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/surveys/{survey_id}/results":{"get":{"summary":"Admin Survey Results","description":"Every response joined to the machine's behavior (country/version/tool_calls/services)\n— the behavior-next-to-the-answer that is 80% of the value — plus a per-question aggregate.","operationId":"admin_survey_results_admin_surveys__survey_id__results_get","parameters":[{"name":"survey_id","in":"path","required":true,"schema":{"type":"integer","title":"Survey Id"}},{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/surveys/{survey_id}/results.csv":{"get":{"summary":"Admin Survey Results Csv","description":"Flat CSV export: one row per response, one column per question + behavior fields.","operationId":"admin_survey_results_csv_admin_surveys__survey_id__results_csv_get","parameters":[{"name":"survey_id","in":"path","required":true,"schema":{"type":"integer","title":"Survey Id"}},{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/public/reviews":{"get":{"summary":"Public Reviews","description":"The aggregate over every APPROVED rating (consent never decides whether a score counts) and the\nnewest reviews whose text and name were consented and approved. No auth. Clearing the in-process\ncache on a moderation does not purge Cloudflare or the site: a removal is gone everywhere within\nabout two minutes (max-age 60 here, 60 in process).","operationId":"public_reviews_public_reviews_get","parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":50,"minimum":1,"default":20,"title":"Limit"}},{"name":"lang","in":"query","required":false,"schema":{"anyOf":[{"enum":["en","es","pt","fr","de","it","nl","zh","ja","ko"],"type":"string"},{"type":"null"}],"title":"Lang"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/reviews":{"get":{"summary":"Admin Pending","description":"The pre-moderation queue: oldest first, no rating, plus how many waited over 7 days.","operationId":"admin_pending_admin_reviews_get","parameters":[{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/reviews/{public_id}/approve":{"post":{"summary":"Admin Approve","operationId":"admin_approve_admin_reviews__public_id__approve_post","parameters":[{"name":"public_id","in":"path","required":true,"schema":{"type":"string","title":"Public Id"}},{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ModerationBody","default":{"actor":"admin"}}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/reviews/{public_id}/remove":{"post":{"summary":"Admin Remove","description":"Removes text and name (the score stays counted). Reasons: personal_data, abuse, withdrawn.","operationId":"admin_remove_admin_reviews__public_id__remove_post","parameters":[{"name":"public_id","in":"path","required":true,"schema":{"type":"string","title":"Public Id"}},{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ModerationBody"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/checkout/create-session":{"post":{"summary":"Create Checkout Session","description":"Crea una Stripe Checkout Session y retorna la URL de pago.","operationId":"create_checkout_session_checkout_create_session_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/webhook/stripe":{"post":{"summary":"Stripe Webhook","operationId":"stripe_webhook_webhook_stripe_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/admin/oauth-stats":{"get":{"summary":"Admin Oauth Stats","description":"Aggregate OAuth funnel metrics for the cloud connector flow.\nReturns counters and conversion rates for last 1h / 24h / 7d windows.\nUsed by the admin dashboard to spot drops in the OAuth surface health\nindependently of the post-deploy / scheduled health checks.","operationId":"admin_oauth_stats_admin_oauth_stats_get","parameters":[{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/oauth-client-auth":{"get":{"summary":"Admin Oauth Client Auth","description":"lmcp-api#33: registrations by the token-endpoint auth method they asked for, and failed\nclient authentications by reason. Counts only — never a secret, never a client id.","operationId":"admin_oauth_client_auth_admin_oauth_client_auth_get","parameters":[{"name":"hours","in":"query","required":false,"schema":{"type":"integer","default":24,"title":"Hours"}},{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/.well-known/oauth-protected-resource/mcp":{"get":{"summary":"Oauth Protected Resource","description":"RFC 9728 — points clients to the auth server for this MCP resource.","operationId":"oauth_protected_resource__well_known_oauth_protected_resource_mcp_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/.well-known/oauth-protected-resource":{"get":{"summary":"Oauth Protected Resource","description":"RFC 9728 — points clients to the auth server for this MCP resource.","operationId":"oauth_protected_resource__well_known_oauth_protected_resource_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/.well-known/oauth-authorization-server/mcp":{"get":{"summary":"Oauth Authorization Server","description":"RFC 8414 — auth server metadata for OAuth 2.0 discovery.","operationId":"oauth_authorization_server__well_known_oauth_authorization_server_mcp_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/.well-known/oauth-authorization-server":{"get":{"summary":"Oauth Authorization Server","description":"RFC 8414 — auth server metadata for OAuth 2.0 discovery.","operationId":"oauth_authorization_server__well_known_oauth_authorization_server_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/oauth/register":{"post":{"summary":"Oauth Register","description":"RFC 7591 — Dynamic Client Registration.\n\nA client that asks for `token_endpoint_auth_method` client_secret_post / client_secret_basic\ngets a client secret, once, in this response (lmcp-api#33). Any other value, or none, gets a\npublic client exactly as before (the RFC's confidential default is NOT applied: a client that\ndid not ask for a secret would then fail at the token endpoint).","operationId":"oauth_register_oauth_register_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OAuthRegisterRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/oauth/authorize":{"get":{"summary":"Oauth Authorize","description":"OAuth 2.0 §4.1.1 — Authorization Request. Renders login page.","operationId":"oauth_authorize_oauth_authorize_get","parameters":[{"name":"client_id","in":"query","required":false,"schema":{"type":"string","default":"","title":"Client Id"}},{"name":"redirect_uri","in":"query","required":false,"schema":{"type":"string","default":"","title":"Redirect Uri"}},{"name":"response_type","in":"query","required":false,"schema":{"type":"string","default":"","title":"Response Type"}},{"name":"state","in":"query","required":false,"schema":{"type":"string","default":"","title":"State"}},{"name":"code_challenge","in":"query","required":false,"schema":{"type":"string","default":"","title":"Code Challenge"}},{"name":"code_challenge_method","in":"query","required":false,"schema":{"type":"string","default":"","title":"Code Challenge Method"}},{"name":"scope","in":"query","required":false,"schema":{"type":"string","default":"","title":"Scope"}}],"responses":{"200":{"description":"Successful Response","content":{"text/html":{"schema":{"type":"string"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/oauth/approve":{"post":{"summary":"Oauth Approve","description":"Deprecated by #3722: /oauth/authorize no longer renders a token-paste\nform, so nothing legitimate POSTs here anymore — approval is native-tray-only,\nvia POST /oauth/tray-approve, which carries its own nonce (F-06's only\nauth-code emitter; unaffected by this route). Any request that still reaches\nthis route predates that removal (a stale cached tab, a bookmark) and gets\nthis explicit message instead of the old PKCE 400: the removed form's hidden\nfields never included code_challenge_method, so every real submit used to\nfail with the misleading \"Only PKCE S256 is supported\" — the bug #3722 was\nfiled over. Checked: neither web/app/oauth/approve/route.ts (a pure proxy)\nnor mac-swift/go-server post here — see #3722's PR for the sweep.","operationId":"oauth_approve_oauth_approve_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/oauth/demo-login":{"post":{"summary":"Oauth Demo Login","operationId":"oauth_demo_login_oauth_demo_login_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/oauth/token":{"post":{"summary":"Oauth Token","description":"OAuth 2.0 §4.1.3 + PKCE (RFC 7636) + refresh tokens (RFC 6749 §6) —\nexchange auth code for access token, OR refresh an expired access token.","operationId":"oauth_token_oauth_token_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/oauth/tray-approve":{"post":{"summary":"Oauth Tray Approve","description":"Tray → backend: approve the OAuth context bound to `nonce` using this\nMac's cloud_token. Mirrors /oauth/approve validation; single-use. The nonce only\nexists downstream of oauth_authorize/oauth_approve's PKCE checks.","operationId":"oauth_tray_approve_oauth_tray_approve_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/oauth/qa-approve":{"post":{"summary":"Oauth Qa Approve","description":"Approve the OAuth request bound to `nonce` under a QA grant. Body {nonce, cloud_token,\nsignature, grant}: `grant` is the QA grant file's text; `signature` is the device key's over\nqa_grant.approve_message. 404 while the server holds no QA key (= a server without support).","operationId":"oauth_qa_approve_oauth_qa_approve_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/admin/qa-grant-denylist":{"get":{"summary":"Admin Qa Denylist","operationId":"admin_qa_denylist_admin_qa_grant_denylist_get","parameters":[{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"summary":"Admin Qa Deny","description":"Refuse a QA grant serial (32 hex) or a QA key id from now on, on /oauth/qa-approve, and\nrevoke what was already issued under it (review C2), in the same transaction: the QA access\ntokens of every (machine, AI) it approved are revoked, their QA refresh tokens and unused QA\ncodes deleted. Normal (non-QA) credentials of the same machine and AI are left alone.","operationId":"admin_qa_deny_admin_qa_grant_denylist_post","parameters":[{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/QaDenyEntry"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/oauth/approve-status":{"get":{"summary":"Oauth Approve Status","description":"Authorize-page polling: pending|approved (+redirect_url once approved).\nThe redirect_url only ever targets the client's REGISTERED redirect_uri.\n\nlmcp-api#272: the page that opened /oauth/authorize holds a poll secret (`poll`; only its\nsha256 is on the nonce row, and the deep link never carries it). With\nLMCP_OAUTH_POLL_BINDING=1 the code goes only to that secret: any other poll reads `pending`\n(no oracle), so whoever holds just the nonce cannot collect the code. Off until the 3.0.421\nMac auto-connect sends it; meanwhile an unbound collection is counted\n(`oauth_approve_status_unbound`, no address). A nonce minted before this change has no hash.\n\nA collected row is kept as 'collected' until it expires (no longer deleted), so the tray's\nretry of /oauth/tray-approve still answers ok. The same page may read the same redirect again\nonly when ITS secret made the first collection (`collected_bound`, review B3); any other\nreader of a collected row gets `expired`, as before.","operationId":"oauth_approve_status_oauth_approve_status_get","parameters":[{"name":"nonce","in":"query","required":false,"schema":{"type":"string","default":"","title":"Nonce"}},{"name":"poll","in":"query","required":false,"schema":{"type":"string","default":"","title":"Poll"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/oauth/tray-approve-request":{"post":{"summary":"Oauth Tray Approve Request","description":"Funnel-only beacon, same endpoint for both stages (#3727 review — no new\nroute): 'tray_offered' (JS fired the deep link) or 'noapp' (the ~6s no-tray\ntimeout showed the noapp state). The actual approval handshake is\npage→localhost→tray→/oauth/tray-approve. Two literal calls, not one\nternary: test_paneles_cuentan_eventos_con_emisor.py's emitter-detector\nregex requires the type to be the literal first argument of _log_event.","operationId":"oauth_tray_approve_request_oauth_tray_approve_request_post","parameters":[{"name":"stage","in":"query","required":false,"schema":{"type":"string","default":"tray_offered","title":"Stage"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/oauth/revoke":{"post":{"summary":"RFC 7009 token revocation","description":"Revoking a refresh token disconnects that AI from that machine: it can no longer refresh, its own access tokens (lmcp-oa-…) stop working, and it leaves the machine's connected list; other AIs are untouched. Revoking a per-AI access token (lmcp-oa-…) ends that token only. An AI connected before per-AI tokens still holds the machine's own token until it re-authorizes or refreshes; revoking THAT token revokes the machine's token for every client and for the machine's own tunnel until the app gets a new one. (lmcp-api#48 option A; per-AI tokens lmcp-api#83.)","operationId":"oauth_revoke_oauth_revoke_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/oauth/list-tray-approvals":{"get":{"summary":"Oauth List Tray Approvals","description":"Deprecated. Always empty — the tray-approval flow was removed. Kept so\nolder deployed trays that still poll this get a clean empty 200, not a 404.","operationId":"oauth_list_tray_approvals_oauth_list_tray_approvals_get","parameters":[{"name":"token","in":"query","required":false,"schema":{"type":"string","default":"","title":"Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/oauth/connected-clients":{"get":{"summary":"Oauth Connected Clients","description":"The tray polls this with its cloud_token to learn which cloud AI clients\n(ChatGPT, Claude.ai, …) actually have an ACTIVE connector for THIS machine — i.e.\na non-expired OAuth refresh token issued to that client for this token. Lets the\nmenu bar show real connection status ('Connected' only when a grant exists) instead\nof inferring it from 'the app is installed' or 'the relay is up' (both false-positives).\nAuthenticated by the cloud_token itself — the same credential the relay uses.\nCached per token for a few seconds (see _CONNECTED_CLIENTS_TTL) — the poll rate would\notherwise saturate the API.\n\nResponse (no published contract; shipped trays ignore unknown fields): `clients[]` each carry\n`stale_token` (bool), and the top level carries it too. True = the machine's live tunnel is on\nANOTHER token (reinstall), so these grants cannot work: the tray may offer \"Reconnect this AI\".","operationId":"oauth_connected_clients_oauth_connected_clients_get","parameters":[{"name":"token","in":"query","required":false,"schema":{"type":"string","default":"","title":"Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/oauth/connected-clients/revoke":{"post":{"summary":"Oauth Connected Client Revoke","description":"lmcp-api#83: the tray's per-AI \"Disconnect\" (lmcp-mac#307, lmcp-win#247; 3.0.419).\n\nAuthenticated by the machine's OWN cloud token in `Authorization: Bearer <cloud_token>` (never\nin the URL). Disconnects ONE AI (`client_id`, as listed by GET /oauth/connected-clients) from\nTHIS machine: its per-AI access tokens stop working (within 30 s on every replica, at once on\nthe one that answered) and its refresh tokens are deleted, so it must re-authorize — through\nthe Approve dialog — to come back. Other AIs and the machine's relay are untouched.\n\n200 {\"revoked\": true, \"client_id\", \"access_tokens_revoked\", \"refresh_tokens_deleted\"}\n(+ \"residual_access\": \"none\" | \"machine_token\" — see the return below)\n400 {\"error\": \"invalid_request\"}  — no client_id\n401 {\"error\": \"invalid_token\"}    — missing/unknown/revoked machine token\n404 {\"error\": \"not_connected\"}    — that AI holds nothing on this machine","operationId":"oauth_connected_client_revoke_oauth_connected_clients_revoke_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConnectedClientRevoke"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/oauth/complete-tray-approval":{"post":{"summary":"Oauth Complete Tray Approval","description":"Deprecated. The tray-approval flow was removed; no pending requests exist\nto complete. Kept as an inert 200 stub so older deployed trays that POST here\non a click don't get a 404. Always reports the request as expired.","operationId":"oauth_complete_tray_approval_oauth_complete_tray_approval_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OAuthCompleteTrayApproval"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/demo-credentials":{"post":{"summary":"Admin Create Demo Credential","description":"Creates a reviewer credential with a server-generated password, returned ONCE. The demo\nmachine must be online and flagged: its routing token is pinned from its live tunnel, and\nan ambiguous match (an impostor claiming the same machine_id) refuses instead of guessing.\nCheck the returned tunnel_token_prefix against the demo Mac's config before handing it out.","operationId":"admin_create_demo_credential_admin_demo_credentials_post","parameters":[{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DemoCredentialCreate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"get":{"summary":"Admin List Demo Credentials","operationId":"admin_list_demo_credentials_admin_demo_credentials_get","parameters":[{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/demo-credentials/{credential_id}/revoke":{"post":{"summary":"Admin Revoke Demo Credential","description":"Revokes the credential and every token, refresh token and code it issued.","operationId":"admin_revoke_demo_credential_admin_demo_credentials__credential_id__revoke_post","parameters":[{"name":"credential_id","in":"path","required":true,"schema":{"type":"integer","title":"Credential Id"}},{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/tunnel/connector-keys":{"get":{"summary":"Connector Key List","operationId":"connector_key_list_tunnel_connector_keys_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}},"post":{"summary":"Connector Key Create","description":"Mint a key for one connector. 200 {id, label, key, created_at} (the key, once);\n400 no label; 401 not a live machine token; 409 LIVE_MAX live keys; 429 MINTS_PER_HOUR\nreached; 503 minting switched off or a DB failure.","operationId":"connector_key_create_tunnel_connector_keys_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConnectorKeyCreate"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/tunnel/connector-keys/{key_id}/revoke":{"post":{"summary":"Connector Key Revoke","description":"Revoke one key of THIS machine, at once. Nothing else is touched: not the machine token,\nnot another key, not any OAuth AI. 404 when it is not a live key of this machine.","operationId":"connector_key_revoke_tunnel_connector_keys__key_id__revoke_post","parameters":[{"name":"key_id","in":"path","required":true,"schema":{"type":"integer","title":"Key Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/tunnel/approval-request":{"get":{"summary":"Tunnel Approval Request","description":"The approval alert's content for `nonce` (lmcp-api#270/#272). `Authorization: Bearer\n<machine token>`. 200 {nonce_status, client, origin, same_network, origin_match, expires_at} ·\n400 invalid_request · 401 invalid_token · 404 not_found (unknown, expired or no longer\npending) · 429 rate_limited.","operationId":"tunnel_approval_request_tunnel_approval_request_get","parameters":[{"name":"nonce","in":"query","required":false,"schema":{"type":"string","default":"","title":"Nonce"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/tunnel/grants":{"post":{"summary":"Tunnel Grants","description":"Every web-AI grant of this machine across ALL its live tokens (lmcp-api#270).\n`Authorization: Bearer <a live token of this machine>`, body {machine_id, client_time,\nsignature}: the live device key's signature over grants_message(..., \"list\", \"*\", ...).\n200 {machine_id, grants[]} · 400 invalid_request · 401 invalid_token | stale_request |\nbad_signature · 403 machine_mismatch · 409 no_device_key · 429 rate_limited.","operationId":"tunnel_grants_tunnel_grants_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/tunnel/grants/revoke":{"post":{"summary":"Tunnel Grants Revoke","description":"Revoke ONE grant of this machine, on any of its live tokens (lmcp-api#270). Body\n{machine_id, grant_id, client_time, signature}, signed over grants_message(..., \"revoke\",\ngrant_id, ...). The AI's per-AI tokens stop working (at once on this replica, within 30 s on\nthe others), its refresh tokens and pending codes are deleted; other grants and the machine\ntoken are untouched. 200 {revoked, grant_id, access_tokens_revoked, refresh_tokens_deleted,\nresidual_access} · 404 not_connected · 409 not_revocable (an AI bound by the machine token in\nits URL) · the refusals of /tunnel/grants.","operationId":"tunnel_grants_revoke_tunnel_grants_revoke_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/tunnel/relink/start":{"post":{"summary":"Tunnel Relink Start","description":"Mail a one-time code to the account of the presented token (lmcp-api#258). 202 always\n{request_id, request_secret, email_hint, expires_in}, whether or not the request is eligible ·\n400 invalid_request · 401 invalid_token · 429 rate_limited (per address) · 503 disabled.","operationId":"tunnel_relink_start_tunnel_relink_start_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/tunnel/relink/grants":{"post":{"summary":"Tunnel Relink Grants","description":"What would move with the relink, for the tray's checkbox list: OAuth apps, connector keys and\nqp-token connectors, by name and verified domain, never their origin (review B-1). 410 once the\nrequest is expired, out of attempts or used.","operationId":"tunnel_relink_grants_tunnel_relink_grants_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/tunnel/relink/complete":{"post":{"summary":"Tunnel Relink Complete","description":"Rotate this computer's own token for the account, with the mailed code (lmcp-api#258).\n200 {token, kept_clients, revoked_clients} · 400 invalid_request · 401 invalid_token | bad_code ·\n403 key_required · 409 not_eligible | token_in_use · 410 expired · 429 rate_limited · 503 disabled.","operationId":"tunnel_relink_complete_tunnel_relink_complete_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/evernote/oauth/start":{"post":{"summary":"Evernote Oauth Start","description":"Leg 1+2: get a request token (signed) and return the authorize URL.","operationId":"evernote_oauth_start_evernote_oauth_start_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EvernoteStartRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/evernote/oauth/finish":{"post":{"summary":"Evernote Oauth Finish","description":"Leg 3: exchange the verified request token for the access token.\n\nReturns the Evernote authentication token + the user's NoteStore URL, which\nthe client stores locally and uses for all (local) Thrift/EDAM API calls.","operationId":"evernote_oauth_finish_evernote_oauth_finish_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EvernoteFinishRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/tunnel/data-enable":{"post":{"summary":"Tunnel Set Data Enabled","description":"Toggles cloud_data_enabled for a tunnel token. The token itself is the credential\n(no admin auth needed) — only the user holding the token can flip their own flag.\nCalled by the local Swift server when user toggles 'Cloud access' in tray (WEB AI CLIENTS).","operationId":"tunnel_set_data_enabled_tunnel_data_enable_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TunnelDataEnableRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/tunnel/rotate":{"post":{"summary":"Tunnel Rotate Token","description":"Rotates a tunnel token: revokes the PRESENTED token and issues a replacement with the\nsame identity (email/license/machine), settings, approval and last-seen time. The token is the credential (same trust\nmodel as /tunnel/data-enable): only its holder can rotate it, and it rotates only itself. Old\ntoken stops working immediately; the local server must be given the new token (config.json\ncloud_token) and restarted.\n\nlmcp-api#262: this used to revoke EVERY live token of the presented token's machine. A machine\nid is not a secret and register-anon mints a token for any machine id without authentication,\nso anyone could cut a machine off (its approved token, its web-AI connectors) and receive a\nfresh token of that machine, which a grandfathered key (routing_bound false) then routed on. A\ntoken proves nothing about its siblings, so it cannot revoke them. The response shape is\nunchanged: the caller sends {token} and reads `token` (the Mac tray,\nMenuBarView.rotateCloudToken; any client may call it under\ncontracts/relay-token-rotate.v1.json).","operationId":"tunnel_rotate_token_tunnel_rotate_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TunnelRotateRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/tunnel/revoke":{"post":{"summary":"Tunnel Revoke Token","description":"Revokes a tunnel token outright (no replacement). Cuts web-AI access\nimmediately: the relay stops accepting it and the cloud connector rejects\nits sessions. The token is the credential — same trust model as /tunnel/rotate,\nonly its holder can revoke it. To reconnect later, the local server issues a fresh\ntoken on its next registration (delete cloud_token in config.json + restart).\n\nlmcp-api#269: the presented token always revokes itself. The machine's OTHER live tokens go\ntoo only when the machine's live device key vouches for the presented token\n(_token_vouched_by_live_key). This used to revoke every live token of the machine on any\nof them, and register-anon mints one for any machine_id without authentication, so anyone\ncould cut a machine's relay. The answer keeps {revoked, next} and adds `revoked_count`;\nthe only caller is the Mac uninstaller (mac/uninstall.sh and lmcp-admin's served copy),\nwhich reads curl's exit status only.","operationId":"tunnel_revoke_token_tunnel_revoke_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TunnelRevokeRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/tunnel/uninstall":{"post":{"summary":"Tunnel Uninstall","description":"lmcp-api#297: a client says at uninstall that its identity is gone. Two independent parts.\n\nThe token part (utils/identity_retire.retire_token): the presented token row and what was\nissued under it. The signed part (retire_signed), read only with LMCP_RETIRE_SIGNED=1: the\nsigner's enrollment, its key and every token of it. A signed part that is refused retires\nnothing by itself and never blocks the token part. With the switch on, rule R-a: a token\nwhose row carries ANOTHER non-empty machine id than the one the request names is not retired\n(a computer running on another computer's token must not cut it).\n\nOne answer, 200 {\"ok\": true}, for every well-formed request (live, revoked or never-issued\ntoken, any signature), so the endpoint says neither whether a token or a machine exists nor\nwhat was retired. A never-issued token, an id without a live key and a repeat write nothing,\nnot even an event: a flood leaves no rows behind but its address's one counter (which also\nbounds the refusal events). 400 for a body that is not the shape, 429 per address.","operationId":"tunnel_uninstall_tunnel_uninstall_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TunnelUninstallRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/tunnel/connector-token":{"post":{"summary":"Tunnel Connector Token","description":"#2033: mints a qp-bound connector identifier for a web AI whose connector UI has a\nsingle URL field — Grok, and every web AI on Windows until #2158 ships working OAuth\nthere (see copyConnectorForAgent in go-server). The real tunnel_token authenticates\nTHIS call via the JSON body — never a query string, or this endpoint would repeat the\nexact mistake it exists to fix (enforced by FastAPI's body-model binding, not by hand:\n`token` is a Pydantic field, so a `?token=` on this URL is simply ignored).\n\nThe returned qp_token is NOT the tunnel_token — a distinct value, one per (machine,\nkind), resolved back to the real token by _resolve_qp_connector_token. It is EQUALLY\ncapable if it leaks (authenticates tools/call exactly like the real token); the point is\nblast radius, not severity: re-minting a kind revokes only that kind's previous qp_token,\nleaving the real tunnel_token and every other kind's binding untouched — unlike\n/tunnel/rotate, which replaces the real token itself. #2326's point-of-use approval does\nNOT (yet) cover this path — see #2033 for why.","operationId":"tunnel_connector_token_tunnel_connector_token_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TunnelConnectorTokenRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/clients/catalog":{"get":{"summary":"Clients Catalog","description":"Catálogo de clientes MCP **locales** que LMCP detecta y configura.\n\n`platform` acota a `macos` o `windows` y devuelve sólo los clientes con rutas en esa\nplataforma. Vacío devuelve todo, con las rutas de ambas.\n\nNO incluye los AI web (ChatGPT web, Claude.ai, Grok): ésos no tienen archivo local y se\nconectan por conector de cuenta o URL tokenizada — viven en `/onboarding/connect-guides`.\n\nPerplexity SÍ está acá, y es el único que está en los dos lados a propósito: su AI web se\nconecta por URL (connect-guides) y su app de escritorio se detecta acá. No es un duplicado;\nel `_nota` de su entrada en ai_clients_catalog.json explica por qué borrar uno pierde un\ncaso. Este párrafo decía lo contrario desde #3403 y mandaba a diseñar sobre una respuesta\nque este endpoint nunca dio.\n\nMientras `RETENER_CLASE_D` esté en True, las entradas clase D NO salen por acá aunque estén\nen el catálogo: se detectan y no se ofrecen, y ningún cliente publicado sabe mostrarlas.\n\nEl consumidor DEBE ignorar toda entrada cuyo `cfgSchema` no conozca, en vez de caer a\nun default: escribir `mcpServers` en un archivo que espera otro formato corrompe la\nconfiguración del usuario y reporta éxito.","operationId":"clients_catalog_clients_catalog_get","parameters":[{"name":"platform","in":"query","required":false,"schema":{"type":"string","default":"","title":"Platform"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/clients/catalog/published":{"get":{"summary":"Clients Catalog Published","description":"Por plataforma, `{version, writes}`: el build publicado que consume el catálogo servido\n(null = ninguno todavía: el publicado configura su lista propia) y los cfgSchema que escribe.\nSi el archivo no se puede leer, falla ruidoso: el sitio cae a su línea genérica en vez de\npintar «automático» con datos que no existen.","operationId":"clients_catalog_published_clients_catalog_published_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/onboarding/connect-guides":{"get":{"summary":"Onboarding Connect Guides","description":"Step-by-step web-AI connection guides per agent (ChatGPT/Claude.ai/Grok)\nin the user's language + how each forms its connection URL (token-in-URL vs\nOAuth). Served from the backend so the steps can be updated when those\nproducts change their UI WITHOUT a client deploy. Unknown langs → English.\n`platform=windows` words the approval step for a PC instead of a Mac (#468); default mac.","operationId":"onboarding_connect_guides_onboarding_connect_guides_get","parameters":[{"name":"lang","in":"query","required":false,"schema":{"type":"string","default":"en","title":"Lang"}},{"name":"platform","in":"query","required":false,"schema":{"type":"string","default":"mac","title":"Platform"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/onboarding-help":{"post":{"summary":"Onboarding Help","description":"Lead from the onboarding 'Didn't work? We'll help' escape hatch on a manual\nstep. The user volunteered an email so support can reach them (anti-churn);\nstored as feedback → visible in /admin/feedback (Paperclip-consumed). The\nanonymous funnel counter is the SEPARATE onboarding_help_requested event\n(no email); this row carries the PII the user chose to share.","operationId":"onboarding_help_onboarding_help_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OnboardingHelpRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/tunnel/token":{"post":{"summary":"Tunnel Get Or Create Token","description":"Emite un tunnel token NUEVO para esta máquina. El email es dato de contacto, nunca la cuenta.\n\nlmcp-api#229: el endpoint no tiene autenticación y el email nadie lo verificó. Escribirlo en\n`tunnel_tokens.email` —la columna que leía la resolución por email (el claim del pre-token\ny el conector `lmcp-pre-`, retirada en #358)— dejaba que cualquiera que supiera una\ndirección la pre-registrara: la resolución del dueño caía en el token del atacante, o daba\n409 (ambigua) si el dueño ya tenía una máquina, y un dueño nuevo recibía `recovery` sin token.\nAhora el token sale con email NULL y la dirección va a `contact_email` (#226: la ve sólo\nquien tiene el token; ninguna resolución la lee; nada la promueve).\n\nLa respuesta es SIEMPRE `{token, email}` con un token recién emitido, tenga o no relay esa\ndirección: el endpoint ya no lee filas existentes, así que no hay oráculo de enumeración ni\nforma de devolver un token ajeno (F-17, #3352). El cliente Mac clasifica por `token` antes\nque por `recovery` (CloudTunnel.classify), así que lo guarda como en un primer registro.","operationId":"tunnel_get_or_create_token_tunnel_token_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TunnelTokenRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/tunnel/register-anon":{"post":{"summary":"Tunnel Register Anon","description":"Issue an anonymous tunnel token keyed on machine_id.\n\nF-18 (2026-08-07): this used to return the EXISTING token when the machine already had\none — no auth, and not even filtered by `email IS NULL`, so it handed out the tokens of\nregistered users too. A machine_id is not a secret (lmcp_state returns it to the model),\nso that branch was a credential-harvesting endpoint: anyone who knew a machine_id could\nread out its live token. Since #2109 this RE-EMITS a fresh token instead of 409ing (see\nthe comment below); F-18's invariant survives that change because it was never about\nrefusing the request, only about never ECHOING the existing one. A second token can't\nhijack the first: `_forward_to_tunnel` routes strictly by TOKEN\n(`active_tunnels[token]`), never by machine_id — if that ever grows a machine_id\nfallback, this analysis is invalid and needs re-review (#2129).\n\nCost, accepted knowingly: reinstalling after losing config.json no longer recovers the\nrelay here. There is no recovery path for anon installs until the Keychain key (F-03/F-04)\nlands — with an email there is one (see /tunnel/token).","operationId":"tunnel_register_anon_tunnel_register_anon_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TunnelAnonRegisterRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/tunnel/enroll":{"post":{"summary":"Tunnel Enroll","description":"Bind a device public key to a machine_id (ADR-0009). The private key never leaves the\ndevice (Secure Enclave on Mac); this only ever receives the PUBLIC key + a proof of the\nright to enroll it. Additive alongside the bearer token during the migration window.\n\nproof.kind:\n  - \"tofu\"   : first enroll for a machine (no live key yet). First-wins; a second tofu is\n               refused. TOFU is safe because enrollment happens at install, before the\n               machine_id is exposed to any AI.\n  - \"bearer\" : migration — the machine's existing bearer token proves ownership; binds the\n               key and supersedes the token as the auth path.\n  - \"sig\"    : rotation — signed by the CURRENT live key over enroll_message(mid, new_pub);\n               only the old key's holder can swap it, and the old key dies.","operationId":"tunnel_enroll_tunnel_enroll_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TunnelEnrollRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/tunnel/approve":{"post":{"summary":"Tunnel Approve","operationId":"tunnel_approve_tunnel_approve_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/tunnel/reissue":{"post":{"summary":"Tunnel Reissue","operationId":"tunnel_reissue_tunnel_reissue_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/tunnel/bind":{"post":{"summary":"Tunnel Bind","operationId":"tunnel_bind_tunnel_bind_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/tunnel/key/replace":{"post":{"summary":"Tunnel Key Replace","operationId":"tunnel_key_replace_tunnel_key_replace_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/admin/approvals":{"get":{"summary":"Admin Approvals","description":"How the machines seen in the window got their relay approval — per platform, counted by\nMACHINE (a machine is approved if ANY of its live tokens is), split by how the FIRST approval\nwas made (lmcp-api#38's approved_via): `tray_button`, `oauth_dialog`, `not_recorded`\n(approved before the column, incl. the 2026-09-29 backfill — never read as \"dialog\"), and\n`not_approved`. Test machines and @local-mcp.test are excluded. Bounded: tunnel_tokens only,\na window, grouped — no heartbeat scan.","operationId":"admin_approvals_admin_approvals_get","parameters":[{"name":"hours","in":"query","required":false,"schema":{"type":"integer","maximum":720,"minimum":1,"default":168,"title":"Hours"}},{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/device-keys":{"get":{"summary":"Admin Device Keys","description":"Where the device-key rollout is (lmcp-api#69): per platform, machines seen in the window\nthat have a live key, that have proved they can sign (`signs_approvals_at`), and that have no\nkey at all (section 8's count — the ones still on the OAuth path). Plus, over the window, how\nmany different-key enrolments were refused (`key_mismatch`) and how many heartbeats claimed\nanother machine's token (`token_machine_mismatch`). Bounded: tunnel_tokens/keys + an indexed\nevents window. lmcp-api#350: a machine id can hold several live keys (one per operating-system\nuser); a machine still counts once, `live_keys` is how many keys they hold together and\n`several_keys` how many machines hold more than one.\n\n`key_mismatch_refused` is the signal to watch (#91 review obs 2): once a bearer proof never\nreplaces a live key, a token holder can be the FIRST to enrol a key on a still-keyless machine\n(section 8-A), and the owner's later enrol is then `409 key_mismatch` until an admin reset —\nwhere before the bearer enrol silently healed it. A rising count here is where that shows.","operationId":"admin_device_keys_admin_device_keys_get","parameters":[{"name":"hours","in":"query","required":false,"schema":{"type":"integer","maximum":720,"minimum":1,"default":168,"title":"Hours"}},{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/tunnel-keys/reset":{"post":{"summary":"Admin Tunnel Keys Reset","description":"Revoke the live device key of ONE machine (lmcp-api#69, section 7-A: a machine that lost\nits key needs a person in the loop). The next enrol is a first enrol. Admin-key only.\n\nlmcp-api#264: the reset also revokes the machine's live tokens that nobody can vouch for once\nthe key is gone. A token is VOUCHED FOR when the live key signed for it: it is bound to that\nkey in tunnel_key_tokens (bearer proof, signed approval, reissue, and their rotate / `sig`\nsuccessors). An unsigned-dialog approval never writes a binding, and while a key enrolled\nafter #261 is live, a token it has not proven is approved exactly that way (#263) — so anyone\nwho minted one for this machine_id could get it approved, and with the key gone R2 would let\nthat token enrol the next key first. So:\n  - a key that routes only on its own tokens (routing_bound): every live token NOT bound to it\n    is revoked;\n  - a grandfathered key (routing_bound false, including its `sig` successors), whose\n    machine-wide ratchet may have let unsigned approvals through: every live token neither\n    bound to it nor approved before its `sig` chain began is revoked.\nThe owner's token approved through an unsigned dialog is therefore revoked too: confirm the\nowner's token with them and name it in `keep_token_prefix` (its 12-character prefix, or the\nwhole token); it must match exactly one live token of the machine, or nothing changes (400).\nA machine with no live key is left untouched. If the key itself is a squatter's, the tokens\nit proved are the squatter's: keep the owner's by name, and revoke the rest by hand.\n\nConsequence to know before using it (#91 review obs 1): this also DROPS the ratchet — the\nmachine becomes 'cannot sign yet' until it re-earns it, and the first enrol after a reset is\nopen to whoever holds a surviving token for that machine (exactly section 8-A's keyless\nwindow). So reset a machine only when its owner is about to re-enrol, and watch\n`key_mismatch_refused` in /admin/device-keys for a key that did not come from the owner.","operationId":"admin_tunnel_keys_reset_admin_tunnel_keys_reset_post","parameters":[{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TunnelKeyResetRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/tunnel/claim":{"post":{"summary":"Tunnel Claim Pre Token","description":"The app claims a pre-token from the onboarding and gets a NEW tunnel token.\n\nlmcp-api#358: this answered the existing live token of (address, machine id). Neither is\nproven here: the address is typed, the pre-token's machine id is set by /install/ping and its\naddress by the set-up page, all without authentication, so anyone holding an old pre-token\ncould read out another person's token. Now every claim mints, as /tunnel/token does (#229):\n`email` NULL, the address in `contact_email`, under the mint limits (_mint_guarded). No\nanswer carries a token that existed before the call, and a repeat mints again.\n\nNo row is read by address: the 403 «Token revocado» for an address whose rows were all\nrevoked is gone (review of #358). It protected nothing once every claim mints a token of its\nown, anyone could lift or cause it for an (address, machine id) pair, and it told a caller\nwhether an address had revoked rows. A revoked token stays revoked; the claim never revives\none. The claim is a retired path (no pre-token has been minted since 2026-06-12).","operationId":"tunnel_claim_pre_token_tunnel_claim_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TunnelClaimRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/tunnel/catalog":{"post":{"summary":"Tunnel Catalog","description":"ADR-0010: a go-server tunnel registers the catalog of tools it implements, keyed by\nits tool_catalog_hash. Called ONLY when a hello_ok returned catalog_needed:true (cache-miss\nor eviction), so it's rare despite tunnel churn.\n\nNo auth needed: the hash is validated against the content (sha256), so a caller can only\nregister a (hash, tools) pair that is internally consistent — it cannot make a hash map to\na different list of tools without a sha256 collision. A bogus hash that no hello ever sends\nis inert: filtering only kicks in for a tunnel whose declared hash matches, and unknown\nhashes fail open to the full catalog.","operationId":"tunnel_catalog_tunnel_catalog_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TunnelCatalogBody"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/tunnel/schemas":{"post":{"summary":"Tunnel Schemas","description":"A go-server registers the SCHEMAS it implements, keyed by their own hash. Called only\nwhen a hello_ok returned schemas_needed:true, so it is rare despite tunnel churn.\n\nWhy this exists at all, and why it is not folded into /tunnel/catalog: that endpoint keys\non the NAMES hash, which two servers with the same tool names and different parameters\nshare exactly. Serving schemas out of a names-keyed entry would hand one server's contract\nto the other — the HIGH review's P1 on this PR.\n\nSame auth argument as /tunnel/catalog, and it is what makes 'no auth' safe here too: the\nhash is validated against the content, so a caller can only register a (hash, schemas)\npair that is internally consistent. A hash no hello ever declares is inert, and an\nunknown hash substitutes NOTHING rather than falling open.\n\nThe payload is the artifact's own shape, validated by the artifact's own validator — one\ncontract, two transports (file for CI, wire for production).","operationId":"tunnel_schemas_tunnel_schemas_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TunnelSchemasBody"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/tunnel/client-disconnect":{"post":{"summary":"Tunnel Client Disconnect","description":"The Mac client reports WHY its tunnel dropped — the server only ever sees a\ngeneric 1006 on the socket, which can't distinguish a NAT/TCP drop from the\nclient's own watchdog force-reconnect (ping_failed) or a graceful redeploy.\nLogged to infra_events so /admin/relay-health can break churn down by the\nreal client-side cause (LMCA cloud-relay churn investigation, 2026-06-05).","operationId":"tunnel_client_disconnect_tunnel_client_disconnect_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ClientDisconnectBody"}}},"required":true},"responses":{"202":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/mcp/{path}":{"post":{"summary":"Cloud Mcp Proxy","description":"Proxy cloud → LMCP via WebSocket tunnel.\nSin token o sin cliente activo: devuelve respuesta MCP de onboarding.","operationId":"cloud_mcp_proxy_mcp__path__post","parameters":[{"name":"path","in":"path","required":true,"schema":{"type":"string","title":"Path"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"options":{"summary":"Cloud Mcp Proxy","description":"Proxy cloud → LMCP via WebSocket tunnel.\nSin token o sin cliente activo: devuelve respuesta MCP de onboarding.","operationId":"cloud_mcp_proxy_mcp__path__post","parameters":[{"name":"path","in":"path","required":true,"schema":{"type":"string","title":"Path"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"summary":"Cloud Mcp Proxy","description":"Proxy cloud → LMCP via WebSocket tunnel.\nSin token o sin cliente activo: devuelve respuesta MCP de onboarding.","operationId":"cloud_mcp_proxy_mcp__path__post","parameters":[{"name":"path","in":"path","required":true,"schema":{"type":"string","title":"Path"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"summary":"Cloud Mcp Proxy","description":"Proxy cloud → LMCP via WebSocket tunnel.\nSin token o sin cliente activo: devuelve respuesta MCP de onboarding.","operationId":"cloud_mcp_proxy_mcp__path__post","parameters":[{"name":"path","in":"path","required":true,"schema":{"type":"string","title":"Path"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"get":{"summary":"Cloud Mcp Proxy","description":"Proxy cloud → LMCP via WebSocket tunnel.\nSin token o sin cliente activo: devuelve respuesta MCP de onboarding.","operationId":"cloud_mcp_proxy_mcp__path__post","parameters":[{"name":"path","in":"path","required":true,"schema":{"type":"string","title":"Path"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/mcp":{"post":{"summary":"Cloud Mcp Proxy","description":"Proxy cloud → LMCP via WebSocket tunnel.\nSin token o sin cliente activo: devuelve respuesta MCP de onboarding.","operationId":"cloud_mcp_proxy_mcp_post","parameters":[{"name":"path","in":"query","required":false,"schema":{"type":"string","default":"","title":"Path"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"options":{"summary":"Cloud Mcp Proxy","description":"Proxy cloud → LMCP via WebSocket tunnel.\nSin token o sin cliente activo: devuelve respuesta MCP de onboarding.","operationId":"cloud_mcp_proxy_mcp_post","parameters":[{"name":"path","in":"query","required":false,"schema":{"type":"string","default":"","title":"Path"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"summary":"Cloud Mcp Proxy","description":"Proxy cloud → LMCP via WebSocket tunnel.\nSin token o sin cliente activo: devuelve respuesta MCP de onboarding.","operationId":"cloud_mcp_proxy_mcp_post","parameters":[{"name":"path","in":"query","required":false,"schema":{"type":"string","default":"","title":"Path"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"summary":"Cloud Mcp Proxy","description":"Proxy cloud → LMCP via WebSocket tunnel.\nSin token o sin cliente activo: devuelve respuesta MCP de onboarding.","operationId":"cloud_mcp_proxy_mcp_post","parameters":[{"name":"path","in":"query","required":false,"schema":{"type":"string","default":"","title":"Path"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"get":{"summary":"Cloud Mcp Proxy","description":"Proxy cloud → LMCP via WebSocket tunnel.\nSin token o sin cliente activo: devuelve respuesta MCP de onboarding.","operationId":"cloud_mcp_proxy_mcp_post","parameters":[{"name":"path","in":"query","required":false,"schema":{"type":"string","default":"","title":"Path"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/mcp.":{"get":{"summary":"Cloud Mcp Trailing Dot Redirect","description":"#3796: trailing-dot FAQ copy-paste (`/mcp.`) draws ~96 404s/week; redirect to\n`/mcp`, preserving the query string (token-in-query auth). 308 keeps POST a POST\n(301/302 downgrade it to GET on many clients). A separate static route for the\nliteral \"/mcp.\" string — it cannot shadow \"/mcp\" or \"/mcp?...\", which match by\npath only. OPTIONS is answered directly (redirecting a CORS preflight is a\nnetwork error per the Fetch spec) instead of redirected.","operationId":"cloud_mcp_trailing_dot_redirect_mcp__post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}},"put":{"summary":"Cloud Mcp Trailing Dot Redirect","description":"#3796: trailing-dot FAQ copy-paste (`/mcp.`) draws ~96 404s/week; redirect to\n`/mcp`, preserving the query string (token-in-query auth). 308 keeps POST a POST\n(301/302 downgrade it to GET on many clients). A separate static route for the\nliteral \"/mcp.\" string — it cannot shadow \"/mcp\" or \"/mcp?...\", which match by\npath only. OPTIONS is answered directly (redirecting a CORS preflight is a\nnetwork error per the Fetch spec) instead of redirected.","operationId":"cloud_mcp_trailing_dot_redirect_mcp__post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}},"post":{"summary":"Cloud Mcp Trailing Dot Redirect","description":"#3796: trailing-dot FAQ copy-paste (`/mcp.`) draws ~96 404s/week; redirect to\n`/mcp`, preserving the query string (token-in-query auth). 308 keeps POST a POST\n(301/302 downgrade it to GET on many clients). A separate static route for the\nliteral \"/mcp.\" string — it cannot shadow \"/mcp\" or \"/mcp?...\", which match by\npath only. OPTIONS is answered directly (redirecting a CORS preflight is a\nnetwork error per the Fetch spec) instead of redirected.","operationId":"cloud_mcp_trailing_dot_redirect_mcp__post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}},"delete":{"summary":"Cloud Mcp Trailing Dot Redirect","description":"#3796: trailing-dot FAQ copy-paste (`/mcp.`) draws ~96 404s/week; redirect to\n`/mcp`, preserving the query string (token-in-query auth). 308 keeps POST a POST\n(301/302 downgrade it to GET on many clients). A separate static route for the\nliteral \"/mcp.\" string — it cannot shadow \"/mcp\" or \"/mcp?...\", which match by\npath only. OPTIONS is answered directly (redirecting a CORS preflight is a\nnetwork error per the Fetch spec) instead of redirected.","operationId":"cloud_mcp_trailing_dot_redirect_mcp__post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}},"options":{"summary":"Cloud Mcp Trailing Dot Redirect","description":"#3796: trailing-dot FAQ copy-paste (`/mcp.`) draws ~96 404s/week; redirect to\n`/mcp`, preserving the query string (token-in-query auth). 308 keeps POST a POST\n(301/302 downgrade it to GET on many clients). A separate static route for the\nliteral \"/mcp.\" string — it cannot shadow \"/mcp\" or \"/mcp?...\", which match by\npath only. OPTIONS is answered directly (redirecting a CORS preflight is a\nnetwork error per the Fetch spec) instead of redirected.","operationId":"cloud_mcp_trailing_dot_redirect_mcp__post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/admin/tunnel-token":{"get":{"summary":"Admin Get Tunnel Token","description":"Token activo de una identidad de TEST. Existe porque /tunnel/token dejó de devolver\nsecretos existentes (F-17) y el pre-deploy suite usa una identidad sintética FIJA que ya\ntiene token, así que necesita una vía para recuperarlo.\n\nSOLO responde para TLDs reservados (RFC 2606/6761), nunca para un usuario real. Agregar\nun endpoint que devuelve tokens para arreglar endpoints que devuelven tokens sería\nabsurdo si quedara igual de explotable: `require_admin` valida el x-admin-key, que estuvo\nhardcodeado en CLAUDE.md hasta cf1fc79e y sigue recuperable en el historial de git, o sea\nque hasta que se rote hay que tratarlo como comprometido. Con este filtro, alguien con esa\nkey no obtiene acá el token de nadie — solo el de una casilla que no existe.","operationId":"admin_get_tunnel_token_admin_tunnel_token_get","parameters":[{"name":"email","in":"query","required":true,"schema":{"type":"string","title":"Email"}},{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/mcp-request-counts":{"get":{"summary":"Admin Mcp Request Counts","description":"lmcp-api#11 phase 0: /mcp requests per UTC day by one dimension.\n\n`protocol_version`: every valid request by the version it declares (`none` = declared none,\nwhich is also every post-handshake request of a 2024-11-05/2025-03-26 client; `other-date` =\na date that is no MCP revision; `other` = not a date). `initialize_protocol_version`: the\nhandshakes by the version asked for — the number a cutoff decision needs. `public_host`\n(lmcp-api#76): apex | www | direct (reached this API without the web front); `www_client`:\nthe client family of the www requests; `www_auth`: token | none for www requests (what a\nredirect would break is an authenticated www connector). The tag can be forged by calling\nthe origin directly: read it as a decision aid. Today's row lags by\nup to a minute per process (counts are persisted once a minute).","operationId":"admin_mcp_request_counts_admin_mcp_request_counts_get","parameters":[{"name":"dimension","in":"query","required":false,"schema":{"enum":["protocol_version","initialize_protocol_version","public_host","www_client","www_auth"],"type":"string","default":"protocol_version","title":"Dimension"}},{"name":"days","in":"query","required":false,"schema":{"type":"integer","maximum":365,"minimum":1,"default":30,"title":"Days"}},{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/tunnels":{"get":{"summary":"Admin List Tunnels","description":"Lista conexiones de tunnel activas en memoria.","operationId":"admin_list_tunnels_admin_tunnels_get","parameters":[{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/cloud-activation":{"get":{"summary":"Admin Cloud Activation","description":"Funnel canónico de activación web-AI (2026-06-10, backlog 'Web AI / Cloud\nRelay'): instalado → relay conectado → forwarding ON → web AI vinculado →\nuso real (tunnel_data_forwarded). Resuelve la contradicción 9-vs-587: los\ntokens del pre-deploy suite nunca llegan a forwarded (no tienen tunnel), así\nque 'web_ai_active' cuenta SOLO uso real. `bound_by_kind` incluye\n_GROK_INFERRED_KIND como bucket propio (#2789) — bound, pero no confirmado\ncomo grok; nunca se suma al bucket 'grok'.","operationId":"admin_cloud_activation_admin_cloud_activation_get","parameters":[{"name":"days","in":"query","required":false,"schema":{"type":"integer","maximum":90,"minimum":1,"default":14,"title":"Days"}},{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/relay-health":{"get":{"summary":"Admin Relay Health","description":"Cloud-relay (tunnel) reliability — connect/disconnect churn, session\nlifetime and disconnect reasons. Reads infra_events (NOT events — tunnel_*\nevents are routed there by log_event), which is why this never surfaced in\nthe funnel dashboards. Plus the live in-memory active tunnels.","operationId":"admin_relay_health_admin_relay_health_get","parameters":[{"name":"days","in":"query","required":false,"schema":{"type":"integer","maximum":90,"minimum":1,"default":7,"title":"Days"}},{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/stats":{"get":{"summary":"Admin Stats","operationId":"admin_stats_admin_stats_get","parameters":[{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/logs":{"post":{"summary":"Receive Client Logs","description":"Recibe un bundle de logs del cliente macOS.\nRequiere header x-token para asociar al usuario.","operationId":"receive_client_logs_logs_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/admin/mcp-logs":{"get":{"summary":"Admin Mcp Logs","description":"Lista requests MCP con filtros opcionales.","operationId":"admin_mcp_logs_admin_mcp_logs_get","parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","default":100,"title":"Limit"}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","default":0,"title":"Offset"}},{"name":"method","in":"query","required":false,"schema":{"type":"string","title":"Method"}},{"name":"tool","in":"query","required":false,"schema":{"type":"string","title":"Tool"}},{"name":"response_type","in":"query","required":false,"schema":{"type":"string","title":"Response Type"}},{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/mcp-logs/purge-snapshots":{"post":{"summary":"Admin Purge Mcp Snapshots","description":"Snapshot columns dropped from schema (GDPR 2026-05-01). No-op.","operationId":"admin_purge_mcp_snapshots_admin_mcp_logs_purge_snapshots_post","parameters":[{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/mcp-logs/summary":{"get":{"summary":"Admin Mcp Logs Summary","description":"Resumen agregado: top tools, response types, latencia promedio.","operationId":"admin_mcp_logs_summary_admin_mcp_logs_summary_get","parameters":[{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/messages":{"post":{"summary":"Admin Create Message","description":"Crea un nuevo push message para mostrar en el tray.\n\nBody fields:\n  message: str (required) — the message body\n  min_version, max_version: str (optional) — semver bounds\n  active: bool (default true) — if false, the row is created as a draft\n                                and NOT broadcast to live tunnels\n  broadcast: bool (default true) — explicit override; set false to test\n                                   message creation without pushing\n\nBroadcast respects:\n  - active flag (no broadcast if active=false)\n  - broadcast flag (no broadcast if explicitly false)\n  - min_version / max_version bounds when applied to each tunnel's\n    last_version (looked up from tunnel_tokens)\n\nCaught in QA admin sweep 2026-04-10: previous version always\nbroadcast immediately to ALL tunnels regardless of active or version\nfilters, so an admin testing a draft message would push it to every\nlive user.","operationId":"admin_create_message_admin_messages_post","parameters":[{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","title":"Body"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"get":{"summary":"Admin List Messages","description":"Lista todos los push messages.","operationId":"admin_list_messages_admin_messages_get","parameters":[{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/messages/{msg_id}":{"delete":{"summary":"Admin Delete Message","description":"Desactiva un push message por ID.","operationId":"admin_delete_message_admin_messages__msg_id__delete","parameters":[{"name":"msg_id","in":"path","required":true,"schema":{"type":"integer","title":"Msg Id"}},{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/connectors":{"get":{"summary":"Admin Connectors","operationId":"admin_connectors_admin_connectors_get","parameters":[{"name":"days","in":"query","required":false,"schema":{"type":"integer","default":30,"title":"Days"}},{"name":"min_machines","in":"query","required":false,"schema":{"type":"integer","default":20,"title":"Min Machines"}},{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/agent/mesh/create":{"post":{"summary":"Mesh Create","description":"Start a mesh with this machine as its first member.","operationId":"mesh_create_agent_mesh_create_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateBody"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/agent/mesh/invite":{"post":{"summary":"Mesh Invite","description":"Mint a single-use pairing code so another machine can join this mesh.","operationId":"mesh_invite_agent_mesh_invite_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/agent/mesh/join":{"post":{"summary":"Mesh Join","description":"Join a mesh by claiming a pairing code. This is the enrollment step.","operationId":"mesh_join_agent_mesh_join_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/JoinBody"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/agent/mesh/leave":{"post":{"summary":"Mesh Leave","description":"Leave the mesh. Immediate: the machine stops being listed and reachable.","operationId":"mesh_leave_agent_mesh_leave_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/agent/mesh/revoke":{"post":{"summary":"Mesh Revoke","description":"Expel another machine from this mesh.\n\nWithout this, a pairing code that leaked — pasted in a chat, caught on a\nshared screen — makes whoever claims it a PERMANENT member, reading every\nbroadcast and the whole directory, and the only remedy is editing the\ndatabase by hand. Any member can revoke any other: the mesh is one person's\nmachines, so there is no privilege to escalate between them.","operationId":"mesh_revoke_agent_mesh_revoke_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RevokeBody"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/agent/checkin":{"post":{"summary":"Agent Checkin","description":"Announce this agent's presence (role, repo, capabilities) with a TTL.","operationId":"agent_checkin_agent_checkin_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CheckinBody"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/agent/stage":{"post":{"summary":"Agent Stage","description":"§5.4: a stage the reader reports for its own messages, under its (instance, epoch).","operationId":"agent_stage_agent_stage_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StageBody"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/agent/wake_state":{"post":{"summary":"Agent Wake State","description":"§5.2: a revalidation or a loss, reported by the instance that holds the binding.","operationId":"agent_wake_state_agent_wake_state_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WakeBody"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/agent/wake_lease":{"post":{"summary":"Agent Wake Lease","description":"§5.11: checked right before each prompt; writes nothing. A 409 cancels the prompt.","operationId":"agent_wake_lease_agent_wake_lease_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WakeBody"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/agent/agents":{"get":{"summary":"Agents List","description":"The mesh directory: who is up, on which machine, doing what.\n\nMachines appear as handles, never as machine_id — publishing machine_ids\nwould hand any mesh member the one string that /tunnel/register-anon trades\nfor another machine's tunnel token.\n\nDevuelve PRESENCIA (`agents`) y también MEMBRESÍA (`members_total`), que son cosas\ndistintas y se confundían: la lista sale de `agent_checkins`, así que una máquina\ninscripta pero sin check-in vigente no figura — ni siquiera la que pregunta.","operationId":"agents_list_agent_agents_get","parameters":[{"name":"include_stale","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"Include Stale"}},{"name":"agent_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Your own agent_id: reading the directory counts as your activity and renews YOUR presence. Without it nobody is renewed.","title":"Agent Id"},"description":"Your own agent_id: reading the directory counts as your activity and renews YOUR presence. Without it nobody is renewed."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/agent/send":{"post":{"summary":"Agent Send","description":"Send a message to a machine in the mesh (or to one agent on it).","operationId":"agent_send_agent_send_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SendBody"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/agent/ack":{"post":{"summary":"Agent Ack","description":"Acknowledge messages this agent actually looked at.\n\nENTREGADO y ACUSADO son dos hechos distintos y por eso viven en columnas distintas.\n`read_at` lo escribe agent_inbox en el mismo SELECT que saca la fila: significa que\nel mensaje salió hacia ese agente, y queda escrito aunque el proceso muera entre la\nrespuesta HTTP y el agente mirándola. `acked_at` sólo lo escribe el agente, acá.\n\nSi esto fuera un UPDATE de read_at, los dos hechos serían indistinguibles y la\npregunta del emisor tendría respuesta siempre-sí. Tienen que poder discrepar.","operationId":"agent_ack_agent_ack_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AckBody"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/agent/sent":{"get":{"summary":"Agent Sent","description":"Lo que mandó esta máquina, con quién lo recibió y quién lo acusó.\n\nEs la mitad que faltaba del canal: hasta ahora agent_send devolvía y ahí se acababa,\ny el emisor no tenía forma de saber nada. El dato de entrega ya existía en\nagent_message_reads desde el principio — nadie lo consultaba nunca.\n\nLa respuesta NO lleva machine_id. La columna `reader` es 'machine_id:agent_id', así\nque exponerla cruda filtraría el identificador que todo el resto del mesh esconde\ndetrás del handle; por eso el reader se une contra la membresía por prefijo y sale\ncomo handle + agent_id.","operationId":"agent_sent_agent_sent_get","parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":20,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/agent/inbox":{"get":{"summary":"Agent Inbox","description":"Messages for this machine that this agent has not read yet.\n\nlmcp-mac#543: with `peek=true` it is a read and nothing else. It serves what this reader\nhas not ACKNOWLEDGED (a delivered message comes back until `agent_ack` names it) and writes\nnothing about the messages; the delivered mark is then written by the acknowledgement.\nWithout `peek` (every client up to 3.0.420, and a tray's background poll) nothing changes:\nthe same statements, and serving a message stamps it delivered, which is what keeps those\nclients from getting it twice.\n\nReads are per agent, so a broadcast to the machine reaches every agent on it\ninstead of the first one to poll swallowing it.\n\nDelivery is at-least-once, not exactly-once: the SELECT and the read-marking\nINSERT are separate statements under READ COMMITTED, so two concurrent polls\nby the same agent_id can both return the same message. Nothing is lost; a\nmessage can repeat. Coordination messages are idempotent to act on (a second\n`freeze` means what the first one meant), so this is left as is rather than\npaying for SELECT ... FOR UPDATE SKIP LOCKED.","operationId":"agent_inbox_agent_inbox_get","parameters":[{"name":"agent_id","in":"query","required":true,"schema":{"type":"string","description":"Who reads (an agent session)","title":"Agent Id"},"description":"Who reads (an agent session)"},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":50,"title":"Limit"}},{"name":"background","in":"query","required":false,"schema":{"type":"boolean","description":"true when the client's automatic consumer makes the call, not the agent: it does not count as activity and does not renew presence.","default":false,"title":"Background"},"description":"true when the client's automatic consumer makes the call, not the agent: it does not count as activity and does not renew presence."},{"name":"peek","in":"query","required":false,"schema":{"type":"boolean","description":"true to read without marking: the messages this agent has not acknowledged are served and nothing is written about them; agent_ack then marks them delivered and acknowledged. Without it, serving a message marks it delivered.","default":false,"title":"Peek"},"description":"true to read without marking: the messages this agent has not acknowledged are served and nothing is written about them; agent_ack then marks them delivered and acknowledged. Without it, serving a message marks it delivered."},{"name":"wake_token","in":"query","required":false,"schema":{"anyOf":[{"type":"string","maxLength":64},{"type":"null"}],"description":"The token of an auto-wake prompt (MESH_WAKE_STATES only).","title":"Wake Token"},"description":"The token of an auto-wake prompt (MESH_WAKE_STATES only)."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/agent/verify":{"post":{"summary":"Agent Verify","operationId":"agent_verify_agent_verify_post","parameters":[{"name":"x-verifier-key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Verifier-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/VerifyBody"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/mcpdemo":{"get":{"summary":"Mcpdemo","description":"Public MCP endpoint for the Interbanking treasury demo (no token).","operationId":"mcpdemo_mcpdemo_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}},"put":{"summary":"Mcpdemo","description":"Public MCP endpoint for the Interbanking treasury demo (no token).","operationId":"mcpdemo_mcpdemo_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}},"post":{"summary":"Mcpdemo","description":"Public MCP endpoint for the Interbanking treasury demo (no token).","operationId":"mcpdemo_mcpdemo_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}},"delete":{"summary":"Mcpdemo","description":"Public MCP endpoint for the Interbanking treasury demo (no token).","operationId":"mcpdemo_mcpdemo_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}},"options":{"summary":"Mcpdemo","description":"Public MCP endpoint for the Interbanking treasury demo (no token).","operationId":"mcpdemo_mcpdemo_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}},"head":{"summary":"Mcpdemo","description":"Public MCP endpoint for the Interbanking treasury demo (no token).","operationId":"mcpdemo_mcpdemo_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/launch-event":{"post":{"summary":"Post Launch Event","description":"Store one launch event. Stores the declared fields and nothing else: no IP, no user\nagent, no geo. An undeclared field, or a `reason` / `launch_path` outside its set, is\ndropped without logging its name or value.","operationId":"post_launch_event_launch_event_post","responses":{"202":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/admin/launch-failures":{"get":{"summary":"Admin Launch Failures","description":"Launches reported by the npm wrapper, by package version and outcome, and the machines\nno heartbeat followed. Counts are distinct machines; `events` is the raw rows.","operationId":"admin_launch_failures_admin_launch_failures_get","parameters":[{"name":"hours","in":"query","required":false,"schema":{"type":"integer","default":24,"title":"Hours"}},{"name":"grace_minutes","in":"query","required":false,"schema":{"type":"integer","default":35,"title":"Grace Minutes"}},{"name":"include_test","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"Include Test"}},{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/connections":{"get":{"summary":"Admin Connections","description":"Connections by AI client, origin and launch path, from each machine's latest heartbeat\nin the window. `machines` is distinct machine_id; ai_client is always a catalog id, null\n(not reported), `unrecognized` (a name in no catalog entry) or `no-client-yet` (a server\nthat reports and has had no `initialize`).","operationId":"admin_connections_admin_connections_get","parameters":[{"name":"hours","in":"query","required":false,"schema":{"type":"integer","default":24,"title":"Hours"}},{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/error-kinds":{"get":{"summary":"Admin Error Kinds","operationId":"admin_error_kinds_admin_error_kinds_get","parameters":[{"name":"include_test","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"Include Test"}},{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/error-kinds/resolve":{"post":{"summary":"Admin Resolve Error Kind","description":"A malformed body is 400 with what is wrong; nothing is stored.","operationId":"admin_resolve_error_kind_admin_error_kinds_resolve_post","parameters":[{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"summary":"Admin Unresolve Error Kind","operationId":"admin_unresolve_error_kind_admin_error_kinds_resolve_delete","parameters":[{"name":"kind","in":"query","required":false,"schema":{"type":"string","default":"","title":"Kind"}},{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/exclusion-candidates":{"get":{"summary":"Admin Exclusion Candidates","operationId":"admin_exclusion_candidates_admin_exclusion_candidates_get","parameters":[{"name":"version","in":"query","required":false,"schema":{"type":"string","pattern":"^\\d+(\\.\\d+){1,3}$","default":"3.0.421","title":"Version"}},{"name":"twin_seconds","in":"query","required":false,"schema":{"type":"integer","maximum":86400,"minimum":1,"default":120,"title":"Twin Seconds"}},{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/connection-health":{"get":{"summary":"Admin Connection Health","description":"Raw counts per bucket and web-AI client family for the window and the same window on each\nof the previous 7 days. No thresholds and no state: see the module docstring.","operationId":"admin_connection_health_admin_connection_health_get","parameters":[{"name":"hours","in":"query","required":false,"schema":{"type":"integer","maximum":24,"minimum":1,"default":1,"title":"Hours"}},{"name":"end","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"End"}},{"name":"bucket_minutes","in":"query","required":false,"schema":{"type":"integer","default":15,"title":"Bucket Minutes"}},{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/install-cohorts":{"get":{"summary":"Admin Install Cohorts","description":"Weekly first-install cohorts per platform for the last `weeks` Monday-weeks (UTC), the\ncurrent one included. Shares are fractions of the row's installs, null when not measurable.","operationId":"admin_install_cohorts_admin_install_cohorts_get","parameters":[{"name":"weeks","in":"query","required":false,"schema":{"type":"integer","maximum":26,"minimum":1,"default":12,"title":"Weeks"}},{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/account-funnel":{"get":{"summary":"Admin Account Funnel","operationId":"admin_account_funnel_admin_account_funnel_get","parameters":[{"name":"window","in":"query","required":false,"schema":{"type":"string","default":"30d","title":"Window"}},{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/friction-causes":{"get":{"summary":"Admin Friction Causes","description":"Top tools by friction signals, and for each the leading causes (error_code x env x\ncall_shape). `coverage` is the share of signals in the window that carry an error_code and\na trail (the acceptance of .github#188 is 95% or more).","operationId":"admin_friction_causes_admin_friction_causes_get","parameters":[{"name":"days","in":"query","required":false,"schema":{"type":"integer","maximum":90,"minimum":1,"default":14,"title":"Days"}},{"name":"top_tools","in":"query","required":false,"schema":{"type":"integer","maximum":50,"minimum":1,"default":10,"title":"Top Tools"}},{"name":"per_tool","in":"query","required":false,"schema":{"type":"integer","maximum":20,"minimum":1,"default":5,"title":"Per Tool"}},{"name":"tool","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Tool"}},{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/barrier-survey":{"get":{"summary":"Admin Barrier Survey","operationId":"admin_barrier_survey_admin_barrier_survey_get","parameters":[{"name":"days","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Days"}},{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/update-failures":{"get":{"summary":"Admin Update Failures","description":"Per target version and platform: how many machines failed to update, and by which cause.\nA machine counts once per version and once per cause; a machine that failed for two causes\nis in both rows, so the rows of a version can add up to more than `machines_failed`.\n\n`not_applied` is apart from the failures: `previous_not_applied` are the machines that\nfound the update before this one still staged, by the version they run; `staged_not_applied`\nare the machines that staged this target and have no `applied` for it.\n\n`net_probe` (lmcp-mac#383) is apart from the versions: what the client's probe of each artifact\nhost role found after a transport failure, by platform and ASN, in machines.","operationId":"admin_update_failures_admin_update_failures_get","parameters":[{"name":"days","in":"query","required":false,"schema":{"type":"integer","maximum":90,"minimum":1,"default":14,"title":"Days"}},{"name":"platform","in":"query","required":false,"schema":{"type":"string","default":"","title":"Platform"}},{"name":"include_test","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"Include Test"}},{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/connectivity-geo":{"get":{"summary":"Admin Connectivity Geo","description":"lmcp-api#236. Read-only.\n\n- `update_failures`: failed update attempts (error/refused, not \"the previous update was never\n  applied\") of the last `days`, by country, ASN and error, counted in machines and attempts.\n  `by_country` / `by_asn` are the same failures rolled up.\n- `machines_without_api`: machines whose every event of the last `recent_hours` arrived via the\n  backchannel or delayed from the local queue (`total` is the count before `limit`).\n- `coverage`: how many events of the window carry a country / an ASN.\n- `probe`: the clients' connectivity matrix by country, ASN, target, stage and code, in machines.\n\nTest machines (metrics.test_exclusion) are left out unless `include_test`.","operationId":"admin_connectivity_geo_admin_connectivity_geo_get","parameters":[{"name":"days","in":"query","required":false,"schema":{"type":"integer","maximum":30,"minimum":1,"default":7,"title":"Days"}},{"name":"recent_hours","in":"query","required":false,"schema":{"type":"integer","maximum":720,"minimum":1,"default":72,"title":"Recent Hours"}},{"name":"platform","in":"query","required":false,"schema":{"type":"string","default":"","title":"Platform"}},{"name":"include_test","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"Include Test"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":500,"minimum":1,"default":100,"title":"Limit"}},{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/connectivity-geo/probe-rollup":{"get":{"summary":"Admin Connectivity Probe Rollup","description":"lmcp-api#304. Read-only, aggregates only: no machine id, no address.\n\nThe `probe` list of /admin/connectivity-geo stops at 500 rows ordered by machines, so the\nnetworks with few machines are lost and a sum over it is a floor. This is the same window and\nthe same rows, grouped here and not capped. Per target (always the four of the contract):\n\n- `machines`: distinct machines that reported the target; `failing`: those with at least one\n  probe that did not end `ok`; `ok` = `machines` - `failing`.\n- `by_country`, `by_asn`, `by_stage`: the FAILING machines of each group, most first. A machine\n  that failed from two networks or at two stages counts once in each group, so a breakdown can\n  add up to more than `failing`; `failing` is the total.\n\nNo small-group rule: like `probe`, a group of one machine is returned (finding the small\nnetworks is the point).","operationId":"admin_connectivity_probe_rollup_admin_connectivity_geo_probe_rollup_get","parameters":[{"name":"days","in":"query","required":false,"schema":{"type":"integer","maximum":30,"minimum":1,"default":7,"title":"Days"}},{"name":"platform","in":"query","required":false,"schema":{"type":"string","default":"","title":"Platform"}},{"name":"include_test","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"Include Test"}},{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/inbound-email":{"post":{"summary":"Post Inbound Email","operationId":"post_inbound_email_inbound_email_post","responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/public/stats":{"get":{"summary":"Public Stats Endpoint","description":"installs, ai_machines, tool_calls_total, rounded down. No auth. OFF (404) unless\nLMCP_PUBLIC_STATS=1: the site reads this route on its own, so serving it is publishing.","operationId":"public_stats_endpoint_public_stats_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/health":{"get":{"summary":"Health","description":"LIVENESS only: is this process running? Railway restarts the container on this.\n\nThe schema signal moved to /readyz (#2609). Restarting cannot fix a schema mismatch, so\nreporting one here bought a crash-loop instead of a fix, while a container that is merely\nbusy — or one waiting on migrations — looks dead. #2028's requirement (a failed schema\nmust not be invisible) is preserved by /readyz, which deploy-api.sh checks after every\ndeploy; it just stops being wired to the restart trigger.","operationId":"health_health_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/runtime/huella":{"get":{"summary":"Get Runtime Huella","description":"Qué CÓDIGO está corriendo de verdad, leído de los archivos del contenedor.\n\n`build_sha` no sirve para esto: es una variable que `scripts/deploy-api.sh` escribe ANTES\nde subir nada, así que un redeploy por cambio de variable la reporta con el código viejo\nadentro. Medido el 2026-09-16: el deploy dio verde y producción siguió sirviendo el árbol\nanterior durante tres deployments. Esto se calcula leyendo, no se puede satisfacer con una\netiqueta.","operationId":"get_runtime_huella_runtime_huella_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/readyz":{"get":{"summary":"Readyz","description":"READINESS: is this process fit to serve? Not wired to Railway's restart trigger.\n\n`db_migration` is `checking` until the background verification finishes, so a caller can\ntell \"not yet\" from \"wrong\" — collapsing those is what let a stale schema read as healthy\n(#2028).","operationId":"readyz_readyz_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/deployz":{"get":{"summary":"Deployz","description":"DEPLOY GATE: Railway's healthcheck (#61). 503 ONLY when this build is proven OLDER than\nthe database schema and no valid override names it — the 2026-09-29 image would have\nfailed here instead of serving for 18 hours.\n\nNever exits and never raises: a refused build just never goes live, the previous deployment\nkeeps serving, and `restartPolicyMaxRetries` is never involved. Railway stops reading this\nonce a deploy is live, so a schema that moves ahead later does not take this one down.\n`checking` is 503 only for DEPLOYZ_CHECKING_GRACE_S; `unknown` and `newer` are 200.","operationId":"deployz_deployz_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/heartbeat":{"post":{"summary":"Post Heartbeat","description":"Ping periódico desde la app. Actualiza last_seen_at en la licencia y guarda en heartbeats.\n\nlmcp-api#274 (colibird-ai/.github#189) — pacing contract with the clients:\n  * the response carries an integer `next_beat_s`: how long the client should wait before its next\n    liveness ping. Default 900 (HEARTBEAT_FLOOR_S), LMCP_HEARTBEAT_NEXT_BEAT_S overrides it, always\n    inside [300, 3600]. A client that does not know the field ignores it and keeps beating every\n    5 minutes, which every reader still supports.\n  * a beat that changed the state fingerprint or carries work (tool calls, errors, slow calls,\n    journeys) is stored as a heartbeats row; a pure liveness ping only refreshes `machines` and the\n    hourly liveness counter. A client sends at once when its state or batch changes, and otherwise\n    on `next_beat_s` (15 minutes floor).","operationId":"post_heartbeat_heartbeat_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HeartbeatRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/resolve-problem-report":{"post":{"summary":"Admin Resolve Problem Report","description":"Mark a problem report resolved so it drops off the open-problems pulse.\n\n- id / case_id: identify the report (one is required; id wins if both given).\n- disposition: fixed | wont_fix | duplicate | not_repro\n- resolved_by: autonomous | human (default human)\n- note: optional linkage, e.g. the issue key \"LMCAA-32\" that fixed it.","operationId":"admin_resolve_problem_report_admin_resolve_problem_report_post","parameters":[{"name":"id","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Id"}},{"name":"case_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Case Id"}},{"name":"disposition","in":"query","required":false,"schema":{"type":"string","default":"fixed","title":"Disposition"}},{"name":"resolved_by","in":"query","required":false,"schema":{"type":"string","default":"human","title":"Resolved By"}},{"name":"note","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Note"}},{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/resolve-feedback":{"post":{"summary":"Admin Resolve Feedback","description":"Mark a feedback item (e.g. a feature request) resolved/actioned.\n\n- id / case_id: identify the row (one is required; id wins if both given). `case_id` se\n  agrego el 2026-08-25 porque TODO lo demas del sistema habla FB-XXXXXX: los reportes, los\n  issues, las notas de cierre. Obligar al id de fila hacia que cerrar un caso requiriera una\n  consulta previa solo para traducir. Es la misma forma que ya tenia\n  /admin/resolve-problem-report, que acepta los dos.\n- disposition: actioned | shipped | wont_do | duplicate\n- resolved_by: autonomous | human (default human)\n- note: optional linkage, e.g. the issue key that shipped it.","operationId":"admin_resolve_feedback_admin_resolve_feedback_post","parameters":[{"name":"id","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Id"}},{"name":"case_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Case Id"}},{"name":"disposition","in":"query","required":false,"schema":{"type":"string","default":"actioned","title":"Disposition"}},{"name":"resolved_by","in":"query","required":false,"schema":{"type":"string","default":"human","title":"Resolved By"}},{"name":"note","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Note"}},{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/dismiss-tool-errors":{"post":{"summary":"Admin Dismiss Tool Errors","description":"Dismiss auto-detected tool errors from the Issues dashboard.\n\n- error_key: specific \"tool:error_type\" key. If omitted, dismisses ALL current fleet errors.\n- days: how long the dismissal lasts (default = 7). Max 90.\n- note: optional reason (e.g. \"fixed in v3.0.232\").\n- disposition: false_positive | non_actionable | fixed | escalated\n- dismissed_by: autonomous | human (default human)","operationId":"admin_dismiss_tool_errors_admin_dismiss_tool_errors_post","parameters":[{"name":"error_key","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Error Key"}},{"name":"days","in":"query","required":false,"schema":{"type":"integer","default":7,"title":"Days"}},{"name":"note","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Note"}},{"name":"disposition","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Disposition"}},{"name":"dismissed_by","in":"query","required":false,"schema":{"type":"string","default":"human","title":"Dismissed By"}},{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/mark-tool-error-fixed":{"post":{"summary":"Admin Mark Tool Error Fixed","description":"Mark an auto-detected tool error as fixed in a specific version.\n\nUnlike a time-based dismissal, this records the version the fix shipped in.\nThe Issues dashboard then hides the error while it only recurs on older builds\n(< fixed_in_version, expected from un-updated machines) but re-surfaces it as a\nREGRESSION the moment it reappears on a build >= fixed_in_version. To clear the\nmarker, delete the dismissal via DELETE /admin/tool-error-dismissals/{id}.","operationId":"admin_mark_tool_error_fixed_admin_mark_tool_error_fixed_post","parameters":[{"name":"error_key","in":"query","required":true,"schema":{"type":"string","title":"Error Key"}},{"name":"fixed_in_version","in":"query","required":true,"schema":{"type":"string","title":"Fixed In Version"}},{"name":"note","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Note"}},{"name":"dismissed_by","in":"query","required":false,"schema":{"type":"string","default":"human","title":"Dismissed By"}},{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/geo-status":{"get":{"summary":"Admin Geo Status","description":"lmcp-api#92: is a MaxMind key set, is a GeoLite2 database loaded, and its counters.\nNever the key, never an address: the way to watch the key's rollout from outside.","operationId":"admin_geo_status_admin_geo_status_get","parameters":[{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/tool-error-dismissals":{"get":{"summary":"Admin Get Tool Error Dismissals","description":"List active (non-expired) tool error dismissals.\n\n- dismissed_by: filter by 'autonomous' or 'human' (optional)","operationId":"admin_get_tool_error_dismissals_admin_tool_error_dismissals_get","parameters":[{"name":"dismissed_by","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Dismissed By"}},{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/tool-error-dismissals/{dismissal_id}":{"delete":{"summary":"Admin Delete Tool Error Dismissal","description":"Remove a specific dismissal (re-surface those errors).","operationId":"admin_delete_tool_error_dismissal_admin_tool_error_dismissals__dismissal_id__delete","parameters":[{"name":"dismissal_id","in":"path","required":true,"schema":{"type":"integer","title":"Dismissal Id"}},{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/dismiss-friction":{"post":{"summary":"Admin Dismiss Friction","description":"Dismiss a tool's friction signals from /admin/frustration.\n\n- tool: the tool name to dismiss (e.g. \"read_email\"). Required — bulk-all is\n  intentionally not offered (friction is meant to be worked per rough spot).\n- days: how long the dismissal lasts (default 14). Re-surfaces after, so an\n  unresolved rough spot comes back.\n- note: optional disposition reason (e.g. \"fixed jxa timeout in 3.0.266\").\n- disposition: one of false_positive | non_actionable | fixed | escalated\n- dismissed_by: 'autonomous' or 'human' (default 'human')","operationId":"admin_dismiss_friction_admin_dismiss_friction_post","parameters":[{"name":"tool","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Tool"}},{"name":"days","in":"query","required":false,"schema":{"type":"integer","default":14,"title":"Days"}},{"name":"note","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Note"}},{"name":"disposition","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Disposition"}},{"name":"dismissed_by","in":"query","required":false,"schema":{"type":"string","default":"human","title":"Dismissed By"}},{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/friction-dismissals":{"get":{"summary":"Admin Get Friction Dismissals","description":"List active (non-expired) friction dismissals.\n\n- dismissed_by: filter by 'autonomous' or 'human' (optional)","operationId":"admin_get_friction_dismissals_admin_friction_dismissals_get","parameters":[{"name":"dismissed_by","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Dismissed By"}},{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/friction-dismissals/{dismissal_id}":{"delete":{"summary":"Admin Delete Friction Dismissal","description":"Remove a specific friction dismissal (re-surface that tool's friction).","operationId":"admin_delete_friction_dismissal_admin_friction_dismissals__dismissal_id__delete","parameters":[{"name":"dismissal_id","in":"path","required":true,"schema":{"type":"integer","title":"Dismissal Id"}},{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/roadmap":{"get":{"summary":"Public Roadmap","description":"Feature requests públicos con votos — settings web UI.\n\nFilters by `type = 'feature'` (the structured field set by the Swift\nrequest_feature tool) instead of substring-matching the message body.\nThe previous ILIKE '%FEATURE%' rule pulled in any bug or log dump that\nhappened to contain the word 'feature' anywhere — for example bug\nreports that referenced features, or log uploads with 'feature' in\nthe stack trace — so the public Feature Requests modal showed a\nmix of bugs and features instead of just the real feature requests.","operationId":"public_roadmap_roadmap_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/roadmap/vote":{"post":{"summary":"Vote Feature","operationId":"vote_feature_roadmap_vote_post","requestBody":{"content":{"application/json":{"schema":{"type":"object","title":"Body"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/events":{"get":{"summary":"Admin List Events","operationId":"admin_list_events_admin_events_get","parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","default":50,"title":"Limit"}},{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/table-info/{table}":{"get":{"summary":"Admin Table Info","description":"Muestra columnas de una tabla.","operationId":"admin_table_info_admin_table_info__table__get","parameters":[{"name":"table","in":"path","required":true,"schema":{"type":"string","title":"Table"}},{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/testimonials":{"get":{"summary":"List Approved Testimonials","description":"Listar testimonials aprobados (público, para la landing).","operationId":"list_approved_testimonials_testimonials_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}},"post":{"summary":"Create Testimonial","description":"Crear un testimonial (queda pendiente de aprobación).","operationId":"create_testimonial_testimonials_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TestimonialCreate"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/testimonials":{"get":{"summary":"Admin List Testimonials","description":"Listar todos los testimonials para moderación.","operationId":"admin_list_testimonials_admin_testimonials_get","parameters":[{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/testimonials/{testimonial_id}":{"post":{"summary":"Admin Testimonial Action","description":"Aprobar o rechazar un testimonial.","operationId":"admin_testimonial_action_admin_testimonials__testimonial_id__post","parameters":[{"name":"testimonial_id","in":"path","required":true,"schema":{"type":"integer","title":"Testimonial Id"}},{"name":"x-admin-key","in":"header","required":true,"schema":{"type":"string","title":"X-Admin-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TestimonialAction"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/stats":{"get":{"summary":"Public Stats","description":"Estadísticas públicas para la landing page (sin auth). Cacheado 60s en\nproceso: el ticker en vivo de la home pollea por visitante, y estos agregados\nno necesitan ser más frescos que eso.","operationId":"public_stats_stats_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/runtime/tray-stale":{"get":{"summary":"Runtime Tray Stale","description":"Tells a freshly-started stdio proxy (npx local-mcp@latest) whether the tray\nserving THIS machine is running OLDER code than the bundle staged on disk — the\ndisk-vs-running lag (~half the fleet, 2026-06-13). The tray's own idle self-heal\n(applyDeferredTrayRestartIfIdle) only ships in 3.0.278+ and only runs once the tray\nis ALREADY executing 278+ code, so it can't unstick the pre-278 always-on tail. The\nproxy is the only always-fresh code on a stuck machine; it calls this and, if stale,\nrestarts the tray.\n\nAuthoritative signal: the latest heartbeat's running_version (compile-time VERSION =\nthe code actually executing) vs version (disk bundle). ServerCore.version is read\nfrom the on-disk Info.plist, so /status/IPC/lmcp_state all report the DISK version —\nonly the heartbeat exposes the true running version. Strict numeric older => stale.\nRead-only; machine_id is a UUID the caller already owns (no PII, no auth needed).","operationId":"runtime_tray_stale_runtime_tray_stale_get","parameters":[{"name":"machine_id","in":"query","required":false,"schema":{"type":"string","default":"","title":"Machine Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/runtime/tools-catalog":{"get":{"summary":"Runtime Tools Catalog","description":"Every advertised tool with its individual one-line description — powers\n/llms-full.txt so an LLM gets the complete per-tool reference in one fetch (llms.txt\nlists tools grouped by app, not one description each). Source: the same\ndata_tools.json the cloud connector serves (auto-generated; never hand-edited),\nfiltered to the advertised set.","operationId":"runtime_tools_catalog_runtime_tools_catalog_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/runtime/settings-ui":{"get":{"summary":"Get Settings Ui","description":"Serves the LMCP settings page HTML. Called by the binary when a manifest\nui.page for 'settings' is present. Reads api/static/settings.html (copied\nfrom mac/settings.html — both must be kept in sync).","operationId":"get_settings_ui_runtime_settings_ui_get","responses":{"200":{"description":"Successful Response","content":{"text/html":{"schema":{"type":"string"}}}}}}},"/runtime/help-ui":{"get":{"summary":"Get Help Ui","description":"Serves help.html for GET /help on the local StatusServer (optional manifest ui.page).","operationId":"get_help_ui_runtime_help_ui_get","responses":{"200":{"description":"Successful Response","content":{"text/html":{"schema":{"type":"string"}}}}}}}},"components":{"schemas":{"AckBody":{"properties":{"agent_id":{"type":"string","maxLength":64,"title":"Agent Id"},"message_ids":{"items":{"type":"integer"},"type":"array","maxItems":100,"minItems":1,"title":"Message Ids"},"background":{"type":"boolean","title":"Background","description":"true when the client's automatic consumer makes the call, not the agent: it does not count as activity and does not renew presence.","default":false}},"type":"object","required":["agent_id","message_ids"],"title":"AckBody"},"ActivationNudgeBlastRequest":{"properties":{"dry_run":{"type":"boolean","title":"Dry Run","default":false}},"type":"object","title":"ActivationNudgeBlastRequest"},"AuthCallback":{"properties":{"code":{"type":"string","title":"Code","default":""},"state":{"type":"string","title":"State","default":""},"error":{"type":"string","title":"Error","default":""},"browser_binding":{"type":"string","title":"Browser Binding","default":""},"ua_family":{"type":"string","title":"Ua Family","default":""},"os_family":{"type":"string","title":"Os Family","default":""},"locale":{"type":"string","title":"Locale","default":"en"},"user":{"type":"string","title":"User","default":""}},"type":"object","title":"AuthCallback"},"AuthStart":{"properties":{"provider":{"type":"string","title":"Provider","default":""},"return_to":{"type":"string","title":"Return To","default":""},"browser_binding":{"type":"string","title":"Browser Binding","default":""}},"type":"object","title":"AuthStart"},"BlogCommentBody":{"properties":{"slug":{"type":"string","title":"Slug"},"name":{"type":"string","title":"Name"},"body":{"type":"string","title":"Body"},"email":{"type":"string","title":"Email","default":""},"parent_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Parent Id"}},"type":"object","required":["slug","name","body"],"title":"BlogCommentBody"},"BlogCommentModerateBody":{"properties":{"id":{"type":"integer","title":"Id"},"action":{"type":"string","title":"Action"}},"type":"object","required":["id","action"],"title":"BlogCommentModerateBody"},"BlogCommentReplyBody":{"properties":{"id":{"type":"integer","title":"Id"},"body":{"type":"string","title":"Body"},"name":{"type":"string","title":"Name","default":"LMCP team"}},"type":"object","required":["id","body"],"title":"BlogCommentReplyBody"},"BlogPostBody":{"properties":{"kind":{"type":"string","title":"Kind"},"title":{"type":"string","title":"Title"},"body":{"type":"string","title":"Body"},"name":{"type":"string","title":"Name"},"email":{"type":"string","title":"Email"}},"type":"object","required":["kind","title","body","name","email"],"title":"BlogPostBody"},"BlogPostModerateBody":{"properties":{"id":{"type":"integer","title":"Id"},"action":{"type":"string","title":"Action"}},"type":"object","required":["id","action"],"title":"BlogPostModerateBody"},"BoardEmailRequest":{"properties":{"to":{"type":"string","title":"To","default":""},"cc":{"type":"string","title":"Cc","default":""},"subject":{"type":"string","title":"Subject","default":""},"html":{"type":"string","title":"Html","default":""},"text":{"type":"string","title":"Text","default":""}},"type":"object","title":"BoardEmailRequest"},"BroadcastRequest":{"properties":{"subject":{"type":"string","title":"Subject"},"body_md":{"type":"string","title":"Body Md"},"dry_run":{"type":"boolean","title":"Dry Run","default":true},"test_to":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Test To"}},"type":"object","required":["subject","body_md"],"title":"BroadcastRequest"},"BulkCloseProblemReportsRequest":{"properties":{"case_ids":{"items":{},"type":"array","title":"Case Ids","default":[]},"machine_id":{"type":"string","title":"Machine Id","default":""},"version":{"type":"string","title":"Version","default":""},"symptom_contains":{"type":"string","title":"Symptom Contains","default":""}},"type":"object","title":"BulkCloseProblemReportsRequest"},"CanaryMachinesRequest":{"properties":{"machine_ids":{"items":{},"type":"array","title":"Machine Ids","default":[]}},"type":"object","title":"CanaryMachinesRequest"},"CanaryVersionRequest":{"properties":{"version":{"type":"string","title":"Version","default":""}},"type":"object","title":"CanaryVersionRequest"},"ChargingSwitchRequest":{"properties":{"date":{"type":"string","title":"Date"}},"type":"object","required":["date"],"title":"ChargingSwitchRequest"},"CheckinBody":{"properties":{"agent_id":{"type":"string","maxLength":64,"title":"Agent Id"},"role":{"anyOf":[{"type":"string","maxLength":64},{"type":"null"}],"title":"Role"},"repo":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}],"title":"Repo"},"caps":{"items":{"type":"string","maxLength":64},"type":"array","maxItems":32,"title":"Caps"},"ttl_seconds":{"type":"integer","maximum":86400.0,"minimum":60.0,"title":"Ttl Seconds","default":900},"status":{"anyOf":[{"type":"string","maxLength":160},{"type":"null"}],"title":"Status"},"instance_id":{"title":"Instance Id"},"wake_state":{"title":"Wake State"},"wake_reason":{"title":"Wake Reason"},"wake_target":{"title":"Wake Target"}},"type":"object","required":["agent_id"],"title":"CheckinBody"},"ClientDisconnectBody":{"properties":{"machine_id":{"type":"string","title":"Machine Id","default":""},"reason":{"type":"string","title":"Reason","default":""},"detail":{"type":"string","title":"Detail","default":""},"session_seconds":{"type":"number","title":"Session Seconds","default":0.0}},"type":"object","title":"ClientDisconnectBody"},"ClientEventRequest":{"properties":{"delayed":{"anyOf":[{},{"type":"null"}],"title":"Delayed"},"offline_seconds":{"anyOf":[{},{"type":"null"}],"title":"Offline Seconds"},"via":{"anyOf":[{},{"type":"null"}],"title":"Via"},"type":{"type":"string","title":"Type"},"machine_id":{"type":"string","title":"Machine Id","default":""},"data":{"type":"object","title":"Data","default":{}},"source":{"type":"string","title":"Source","default":""}},"type":"object","required":["type"],"title":"ClientEventRequest"},"ClientTrayEventRequest":{"properties":{"delayed":{"anyOf":[{},{"type":"null"}],"title":"Delayed"},"offline_seconds":{"anyOf":[{},{"type":"null"}],"title":"Offline Seconds"},"via":{"anyOf":[{},{"type":"null"}],"title":"Via"},"event":{"type":"string","title":"Event","default":""},"machine_id":{"type":"string","title":"Machine Id","default":""},"from_version":{"type":"string","title":"From Version","default":""},"to_version":{"type":"string","title":"To Version","default":""},"versions_behind":{"type":"integer","title":"Versions Behind","default":0},"client_id":{"type":"string","title":"Client Id","default":""}},"type":"object","title":"ClientTrayEventRequest"},"ClientUpdateAttemptedRequest":{"properties":{"delayed":{"anyOf":[{},{"type":"null"}],"title":"Delayed"},"offline_seconds":{"anyOf":[{},{"type":"null"}],"title":"Offline Seconds"},"via":{"anyOf":[{},{"type":"null"}],"title":"Via"},"machine_id":{"type":"string","title":"Machine Id","default":""},"from_version":{"type":"string","title":"From Version","default":""},"to_version":{"type":"string","title":"To Version","default":""},"success":{"type":"boolean","title":"Success","default":false},"error":{"type":"string","title":"Error","default":""},"duration_ms":{"type":"integer","title":"Duration Ms","default":0},"consecutive_failures":{"type":"integer","title":"Consecutive Failures","default":0},"note":{"type":"string","title":"Note","default":""}},"type":"object","title":"ClientUpdateAttemptedRequest"},"CloseFeedbackRequest":{"properties":{"machine_id":{"type":"string","title":"Machine Id","default":""},"resolution":{"type":"string","title":"Resolution","default":""}},"type":"object","title":"CloseFeedbackRequest"},"CodeApproveRequest":{"properties":{"machine_id":{"type":"string","title":"Machine Id","default":""},"t":{"type":"integer","title":"T","default":0},"pending_id":{"type":"string","title":"Pending Id","default":""},"decision":{"type":"string","title":"Decision","default":""},"sig":{"type":"string","title":"Sig","default":""}},"type":"object","title":"CodeApproveRequest"},"CodeRequest":{"properties":{"machine_id":{"type":"string","title":"Machine Id","default":""},"t":{"type":"integer","title":"T","default":0},"label":{"type":"string","title":"Label","default":""},"sig":{"type":"string","title":"Sig","default":""}},"type":"object","title":"CodeRequest"},"CodeStatusRequest":{"properties":{"machine_id":{"type":"string","title":"Machine Id","default":""},"t":{"type":"integer","title":"T","default":0},"sig":{"type":"string","title":"Sig","default":""}},"type":"object","title":"CodeStatusRequest"},"CommunityReviewBody":{"properties":{"id":{"type":"integer","title":"Id"},"action":{"type":"string","title":"Action"},"reviewed_by":{"type":"string","title":"Reviewed By","default":"operator"}},"type":"object","required":["id","action"],"title":"CommunityReviewBody"},"CommunitySubmitBody":{"properties":{"workflow":{"type":"string","title":"Workflow"},"title":{"type":"string","title":"Title","default":""},"category":{"type":"string","title":"Category","default":""},"name":{"type":"string","title":"Name","default":""},"apps":{"type":"string","title":"Apps","default":""},"email":{"type":"string","title":"Email","default":""},"vid":{"type":"string","title":"Vid","default":""},"skill_token":{"type":"string","title":"Skill Token","default":""}},"type":"object","required":["workflow"],"title":"CommunitySubmitBody"},"CommunityVoteBody":{"properties":{"id":{"type":"integer","title":"Id"},"vid":{"type":"string","title":"Vid","default":""}},"type":"object","required":["id"],"title":"CommunityVoteBody"},"ConnectedClientRevoke":{"properties":{"client_id":{"type":"string","title":"Client Id"}},"type":"object","required":["client_id"],"title":"ConnectedClientRevoke"},"ConnectorKeyCreate":{"properties":{"label":{"type":"string","title":"Label","default":""}},"type":"object","title":"ConnectorKeyCreate"},"CreateBody":{"properties":{"label":{"anyOf":[{"type":"string","maxLength":120},{"type":"null"}],"title":"Label"}},"type":"object","title":"CreateBody"},"DemoCredentialCreate":{"properties":{"username":{"type":"string","title":"Username"},"machine_id":{"type":"string","title":"Machine Id"},"ttl_days":{"type":"integer","title":"Ttl Days","default":30},"note":{"type":"string","title":"Note","default":""}},"type":"object","required":["username","machine_id"],"title":"DemoCredentialCreate"},"DiagResultItem":{"properties":{"tool":{"type":"string","title":"Tool"},"status":{"type":"string","title":"Status"},"detail":{"type":"string","title":"Detail","default":""},"fix_hint":{"type":"string","title":"Fix Hint","default":""}},"type":"object","required":["tool","status"],"title":"DiagResultItem"},"DiagnosticRequest":{"properties":{"version":{"type":"string","title":"Version","default":""},"os_version":{"type":"string","title":"Os Version","default":""},"arch":{"type":"string","title":"Arch","default":""},"focus":{"type":"string","title":"Focus","default":""},"results":{"items":{"$ref":"#/components/schemas/DiagResultItem"},"type":"array","title":"Results"}},"type":"object","required":["results"],"title":"DiagnosticRequest"},"DownloadAttributionConsumeRequest":{"properties":{"token":{"type":"string","title":"Token"},"install_key":{"type":"string","title":"Install Key"}},"type":"object","required":["token","install_key"],"title":"DownloadAttributionConsumeRequest"},"DownloadAttributionRequest":{"properties":{"vid":{"type":"string","title":"Vid","default":""},"ref":{"type":"string","title":"Ref","default":""},"src":{"type":"string","title":"Src","default":""},"session":{"type":"string","title":"Session","default":""},"platform":{"type":"string","title":"Platform","default":""}},"type":"object","title":"DownloadAttributionRequest"},"DownloadOwnerRequest":{"properties":{"dt":{"type":"string","title":"Dt","default":""},"session":{"type":"string","title":"Session","default":""}},"type":"object","title":"DownloadOwnerRequest"},"DownloadRequestBody":{"properties":{"email":{"type":"string","title":"Email"},"locale":{"type":"string","title":"Locale","default":"en"},"vid":{"type":"string","title":"Vid","default":""},"purpose":{"type":"string","title":"Purpose","default":""},"ref":{"type":"string","title":"Ref","default":""}},"type":"object","required":["email"],"title":"DownloadRequestBody"},"DownloadStageReport":{"properties":{"token":{"type":"string","title":"Token"},"stage":{"type":"string","enum":["opened","installing"],"title":"Stage"}},"type":"object","required":["token","stage"],"title":"DownloadStageReport"},"EmailStart":{"properties":{"email":{"type":"string","title":"Email","default":""},"browser_binding":{"type":"string","title":"Browser Binding","default":""},"return_to":{"type":"string","title":"Return To","default":""},"locale":{"type":"string","title":"Locale","default":"en"}},"type":"object","title":"EmailStart"},"EmailVerify":{"properties":{"email":{"type":"string","title":"Email","default":""},"code":{"type":"string","title":"Code","default":""},"browser_binding":{"type":"string","title":"Browser Binding","default":""},"ua_family":{"type":"string","title":"Ua Family","default":""},"os_family":{"type":"string","title":"Os Family","default":""},"locale":{"type":"string","title":"Locale","default":"en"},"pending":{"type":"string","title":"Pending","default":""}},"type":"object","title":"EmailVerify"},"EvernoteFinishRequest":{"properties":{"oauth_token":{"type":"string","title":"Oauth Token"},"oauth_verifier":{"type":"string","title":"Oauth Verifier"}},"type":"object","required":["oauth_token","oauth_verifier"],"title":"EvernoteFinishRequest"},"EvernoteStartRequest":{"properties":{"callback_url":{"type":"string","title":"Callback Url"}},"type":"object","required":["callback_url"],"title":"EvernoteStartRequest"},"FacebookDeletion":{"properties":{"signed_request":{"type":"string","title":"Signed Request","default":""}},"type":"object","title":"FacebookDeletion"},"FeedbackRequest":{"properties":{"message":{"type":"string","title":"Message"},"type":{"type":"string","title":"Type","default":"bug"},"source":{"type":"string","title":"Source","default":"mcp"},"license_key":{"type":"string","title":"License Key","default":""},"version":{"type":"string","title":"Version","default":""},"email":{"type":"string","title":"Email","default":""},"machine_id":{"type":"string","title":"Machine Id","default":""},"path":{"type":"string","title":"Path","default":""},"via":{"type":"string","title":"Via","default":""},"platform":{"type":"string","title":"Platform","default":""}},"type":"object","required":["message"],"title":"FeedbackRequest"},"FrictionSignalRequest":{"properties":{"delayed":{"anyOf":[{},{"type":"null"}],"title":"Delayed"},"offline_seconds":{"anyOf":[{},{"type":"null"}],"title":"Offline Seconds"},"via":{"anyOf":[{},{"type":"null"}],"title":"Via"},"machine_id":{"type":"string","title":"Machine Id","default":""},"tool_attempted":{"type":"string","title":"Tool Attempted","default":""},"error_category":{"type":"string","title":"Error Category","default":""},"friction_signal":{"type":"string","title":"Friction Signal","default":""},"attempt_count":{"type":"integer","title":"Attempt Count","default":0},"version":{"type":"string","title":"Version","default":""},"os_version":{"type":"string","title":"Os Version","default":""},"ai_client":{"type":"string","title":"Ai Client","default":""},"source":{"type":"string","title":"Source","default":"agent"},"error_code":{"title":"Error Code"},"call_shape":{"title":"Call Shape"},"trail":{"title":"Trail"},"env":{"title":"Env"},"intent_category":{"title":"Intent Category"},"correlation_id":{"title":"Correlation Id"}},"type":"object","title":"FrictionSignalRequest"},"GenerateRequest":{"properties":{"email":{"type":"string","title":"Email"},"plan":{"type":"string","title":"Plan","default":"pro"},"months":{"type":"integer","title":"Months","default":6},"max_machines":{"type":"integer","title":"Max Machines","default":1},"send_email":{"type":"boolean","title":"Send Email","default":true}},"type":"object","required":["email"],"title":"GenerateRequest"},"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"HeartbeatRequest":{"properties":{"license_key":{"type":"string","title":"License Key","default":""},"cloud_token":{"type":"string","title":"Cloud Token","default":""},"license_email":{"type":"string","title":"License Email","default":""},"machine_id":{"type":"string","title":"Machine Id","default":""},"version":{"type":"string","title":"Version","default":""},"running_version":{"type":"string","title":"Running Version","default":""},"npm_version":{"type":"string","title":"Npm Version","default":""},"os_version":{"type":"string","title":"Os Version","default":""},"os_build":{"anyOf":[{},{"type":"null"}],"title":"Os Build"},"surface_v2_fallback":{"anyOf":[{},{"type":"null"}],"title":"Surface V2 Fallback"},"qa_mode":{"anyOf":[{},{"type":"null"}],"title":"Qa Mode"},"qa_grant_refused":{"anyOf":[{},{"type":"null"}],"title":"Qa Grant Refused"},"uptime_hrs":{"type":"number","title":"Uptime Hrs","default":0.0},"transport":{"type":"string","title":"Transport","default":""},"tool_calls":{"type":"integer","title":"Tool Calls","default":0},"tool_breakdown":{"type":"object","title":"Tool Breakdown","default":{}},"tray_version":{"type":"string","title":"Tray Version","default":""},"machine_label":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Machine Label"},"arch":{"type":"string","title":"Arch","default":""},"ref":{"type":"string","title":"Ref","default":""},"ai_client":{"type":"string","title":"Ai Client","default":""},"locale":{"type":"string","title":"Locale","default":""},"mem_available_mb":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Mem Available Mb"},"cpu_ms_total":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Cpu Ms Total"},"rss_mb":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Rss Mb"},"mail_index_state":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Mail Index State"},"mail_index_total":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Mail Index Total"},"mail_index_pending":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Mail Index Pending"},"mail_index_tick_ms":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Mail Index Tick Ms"},"mail_index_walk_ms":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Mail Index Walk Ms"},"mail_index_db_mb":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Mail Index Db Mb"},"rss_peak_mb":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Rss Peak Mb"},"mail_index_rss_delta_mb":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Mail Index Rss Delta Mb"},"web_sessions_open":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Web Sessions Open"},"web_sessions_oldest_min":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Web Sessions Oldest Min"},"session_count":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Session Count"},"feature_flags":{"type":"object","title":"Feature Flags","default":{}},"read_only":{"type":"boolean","title":"Read Only","default":false},"disabled_tools_count":{"type":"integer","title":"Disabled Tools Count","default":0},"account_permission_counts":{"anyOf":[{},{"type":"null"}],"title":"Account Permission Counts"},"mcp_paused":{"type":"boolean","title":"Mcp Paused","default":false},"ai_clients":{"items":{},"type":"array","title":"Ai Clients","default":[]},"ai_clients_state":{"anyOf":[{"type":"object"},{"type":"null"}],"title":"Ai Clients State"},"tools_ever_listed":{"type":"boolean","title":"Tools Ever Listed","default":false},"mcp_client":{"type":"string","title":"Mcp Client","default":""},"pid":{"type":"integer","title":"Pid","default":0},"started_at":{"type":"string","title":"Started At","default":""},"tcc_status":{"type":"object","title":"Tcc Status","default":{}},"tray_process_count":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Tray Process Count"},"services":{"type":"object","title":"Services","default":{}},"tool_errors":{"type":"object","title":"Tool Errors","default":{}},"tool_error_samples":{"type":"object","title":"Tool Error Samples","default":{}},"slow_tool_calls":{"type":"object","title":"Slow Tool Calls","default":{}},"cpu_pct":{"type":"number","title":"Cpu Pct","default":0.0},"large_responses":{"type":"object","title":"Large Responses","default":{}},"empty_results":{"type":"object","title":"Empty Results","default":{}},"terminal_usage":{"anyOf":[{},{"type":"null"}],"title":"Terminal Usage"},"manifest_version":{"type":"string","title":"Manifest Version","default":""},"m365_status":{"type":"string","title":"M365 Status","default":""},"server_source":{"type":"string","title":"Server Source","default":""},"tray_bundle_location":{"type":"string","title":"Tray Bundle Location","default":""},"origin":{"anyOf":[{},{"type":"null"}],"title":"Origin"},"launch_path":{"anyOf":[{},{"type":"null"}],"title":"Launch Path"},"connections":{"anyOf":[{},{"type":"null"}],"title":"Connections"},"journeys":{"items":{},"type":"array","title":"Journeys","default":[]}},"type":"object","title":"HeartbeatRequest"},"InstallEventRequest":{"properties":{"ip":{"type":"string","title":"Ip","default":""},"user_agent":{"type":"string","title":"User Agent","default":""},"ref":{"type":"string","title":"Ref","default":""},"stage":{"type":"string","title":"Stage","default":""},"source":{"type":"string","title":"Source","default":""},"install_id":{"type":"string","title":"Install Id","default":""},"has_node":{"type":"string","title":"Has Node","default":""},"has_brew":{"type":"string","title":"Has Brew","default":""},"client":{"type":"string","title":"Client","default":""},"client_id":{"type":"string","title":"Client Id","default":""},"client_name":{"type":"string","title":"Client Name","default":""},"event":{"type":"string","title":"Event","default":""},"wacli_ok":{"type":"boolean","title":"Wacli Ok"},"tray_ok":{"type":"boolean","title":"Tray Ok"},"clients":{"type":"string","title":"Clients","default":""},"email_prompt_result":{"type":"string","title":"Email Prompt Result","default":""},"machine_id":{"type":"string","title":"Machine Id","default":""},"cloud_token":{"type":"string","title":"Cloud Token","default":""},"version":{"type":"string","title":"Version","default":""},"os_version":{"type":"string","title":"Os Version","default":""},"arch":{"type":"string","title":"Arch","default":""},"email":{"type":"string","title":"Email","default":""},"channel":{"type":"string","title":"Channel","default":""},"pre_token":{"type":"string","title":"Pre Token","default":""},"method":{"type":"string","title":"Method","default":""},"vid":{"type":"string","title":"Vid","default":""}},"type":"object","title":"InstallEventRequest"},"InstallPingRequest":{"properties":{"pre_token":{"type":"string","title":"Pre Token"},"os_version":{"type":"string","title":"Os Version","default":""},"version":{"type":"string","title":"Version","default":""},"machine_id":{"type":"string","title":"Machine Id","default":""}},"type":"object","required":["pre_token"],"title":"InstallPingRequest"},"InstallRegisteredRequest":{"properties":{"anonymous_id":{"type":"string","title":"Anonymous Id","default":""},"machine_id":{"type":"string","title":"Machine Id","default":""},"channel":{"type":"string","title":"Channel","default":""},"version":{"type":"string","title":"Version","default":""},"platform":{"type":"string","title":"Platform","default":""},"arch":{"type":"string","title":"Arch","default":""}},"type":"object","title":"InstallRegisteredRequest","description":"Effective-install attribution emitted by the bootstrap (mcpb/server/index.js\nor `npx local-mcp`) the first time the runtime starts successfully on a machine.\nDistinct from `/install-event`: that one tracks each step of the install script;\nthis one is fired once per (anonymous_id, channel) by the JS bootstrap and\nmeasures *effective* installs (download → runtime running) for the MCPB funnel.\nSee docs/mcpb-distribution-plan.md §Ola2 item 9."},"InstallStepBody":{"properties":{"step":{"type":"string","title":"Step","default":""},"status":{"type":"string","title":"Status","default":""},"platform":{"type":"string","title":"Platform","default":""},"fingerprint":{"type":"string","title":"Fingerprint","default":""},"detail":{"type":"string","title":"Detail","default":""},"ref":{"type":"string","title":"Ref","default":""},"machine_id":{"type":"string","title":"Machine Id","default":""}},"type":"object","title":"InstallStepBody"},"JoinBody":{"properties":{"code":{"type":"string","title":"Code"},"label":{"anyOf":[{"type":"string","maxLength":120},{"type":"null"}],"title":"Label"}},"type":"object","required":["code"],"title":"JoinBody"},"LinkCodeConfirm":{"properties":{"preview_id":{"type":"string","title":"Preview Id","default":""}},"type":"object","title":"LinkCodeConfirm"},"LinkCodePreview":{"properties":{"code":{"type":"string","title":"Code","default":""},"probe_token":{"type":"string","title":"Probe Token","default":""}},"type":"object","title":"LinkCodePreview"},"MachineNotifyRequest":{"properties":{"message":{"type":"string","title":"Message"},"case_id":{"type":"string","title":"Case Id","default":""}},"type":"object","required":["message"],"title":"MachineNotifyRequest"},"MarkEmailedRequest":{"properties":{"email":{"type":"string","title":"Email"},"type":{"type":"string","title":"Type"}},"type":"object","required":["email","type"],"title":"MarkEmailedRequest"},"MeasureChoice":{"properties":{"measure":{"type":"boolean","title":"Measure"}},"type":"object","required":["measure"],"title":"MeasureChoice"},"ModerationBody":{"properties":{"reason":{"anyOf":[{"type":"string","enum":["personal_data","abuse","withdrawn"]},{"type":"null"}],"title":"Reason"},"note":{"anyOf":[{"type":"string","maxLength":80},{"type":"null"}],"title":"Note"},"actor":{"type":"string","maxLength":32,"minLength":1,"title":"Actor","default":"admin"}},"type":"object","title":"ModerationBody"},"NotifyRequest":{"properties":{"email":{"type":"string","title":"Email"},"machine_id":{"type":"string","title":"Machine Id","default":""},"vid":{"type":"string","title":"Vid","default":""}},"type":"object","required":["email"],"title":"NotifyRequest"},"NpmInstallRequest":{"properties":{"version":{"type":"string","title":"Version","default":""},"os_version":{"type":"string","title":"Os Version","default":""},"arch":{"type":"string","title":"Arch","default":""},"node_version":{"type":"string","title":"Node Version","default":""},"method":{"type":"string","title":"Method","default":"npm"},"machine_id":{"type":"string","title":"Machine Id","default":""},"clients_configured":{"items":{},"type":"array","title":"Clients Configured","default":[]},"source":{"type":"string","title":"Source","default":""},"ref":{"type":"string","title":"Ref","default":""},"email":{"type":"string","title":"Email","default":""}},"type":"object","title":"NpmInstallRequest"},"OAuthCompleteTrayApproval":{"properties":{"request_id":{"type":"string","title":"Request Id","default":""},"cloud_token":{"type":"string","title":"Cloud Token","default":""},"decision":{"type":"string","title":"Decision","default":"approve"}},"type":"object","title":"OAuthCompleteTrayApproval"},"OAuthRegisterRequest":{"properties":{"redirect_uris":{"items":{},"type":"array","title":"Redirect Uris","default":[]},"client_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Client Name"},"grant_types":{"anyOf":[{"items":{},"type":"array"},{"type":"null"}],"title":"Grant Types"},"response_types":{"anyOf":[{"items":{},"type":"array"},{"type":"null"}],"title":"Response Types"},"token_endpoint_auth_method":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Token Endpoint Auth Method"},"scope":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Scope"}},"type":"object","title":"OAuthRegisterRequest"},"OnboardingHelpRequest":{"properties":{"step_name":{"type":"string","title":"Step Name"},"email":{"type":"string","title":"Email"},"note":{"type":"string","title":"Note","default":""},"machine_id":{"type":"string","title":"Machine Id","default":""}},"type":"object","required":["step_name","email"],"title":"OnboardingHelpRequest"},"OneTap":{"properties":{"credential":{"type":"string","title":"Credential","default":""},"browser_binding":{"type":"string","title":"Browser Binding","default":""},"ua_family":{"type":"string","title":"Ua Family","default":""},"os_family":{"type":"string","title":"Os Family","default":""},"locale":{"type":"string","title":"Locale","default":"en"}},"type":"object","title":"OneTap"},"OneTapNonce":{"properties":{"browser_binding":{"type":"string","title":"Browser Binding","default":""},"return_to":{"type":"string","title":"Return To","default":""}},"type":"object","title":"OneTapNonce"},"ProblemReportRequest":{"properties":{"symptom":{"type":"string","title":"Symptom"},"snapshot":{"type":"object","title":"Snapshot"},"recent_logs":{"items":{},"type":"array","title":"Recent Logs","default":[]},"recent_activity":{"items":{},"type":"array","title":"Recent Activity","default":[]},"recent_errors":{"items":{},"type":"array","title":"Recent Errors","default":[]},"tool_attempted":{"type":"string","title":"Tool Attempted","default":""},"error_message":{"type":"string","title":"Error Message","default":""},"user_request":{"type":"string","title":"User Request","default":""},"expected":{"type":"string","title":"Expected","default":""}},"type":"object","required":["symptom","snapshot"],"title":"ProblemReportRequest"},"QAReportRequest":{"properties":{"run_id":{"type":"string","title":"Run Id"},"results":{"items":{"$ref":"#/components/schemas/QAResultItem"},"type":"array","title":"Results"},"duration_seconds":{"type":"integer","title":"Duration Seconds","default":0},"bugs_found":{"type":"integer","title":"Bugs Found","default":0},"notes":{"type":"string","title":"Notes","default":""},"version":{"type":"string","title":"Version","default":""}},"type":"object","required":["run_id","results"],"title":"QAReportRequest"},"QAResultItem":{"properties":{"tool":{"type":"string","title":"Tool"},"status":{"type":"string","title":"Status"},"detail":{"type":"string","title":"Detail","default":""}},"type":"object","required":["tool","status"],"title":"QAResultItem"},"QATriggerRequest":{"properties":{"version":{"type":"string","title":"Version","default":""},"notes":{"type":"string","title":"Notes","default":""},"source":{"type":"string","title":"Source","default":"manual"}},"type":"object","title":"QATriggerRequest"},"QaDenyEntry":{"properties":{"kind":{"type":"string","title":"Kind"},"value":{"type":"string","title":"Value"},"reason":{"type":"string","title":"Reason","default":""}},"type":"object","required":["kind","value"],"title":"QaDenyEntry"},"RedeemRequest":{"properties":{"machine_id":{"type":"string","title":"Machine Id","default":""},"dt":{"type":"string","title":"Dt","default":""},"t":{"type":"integer","title":"T","default":0},"sig":{"type":"string","title":"Sig","default":""}},"type":"object","title":"RedeemRequest"},"ReferralClickRequest":{"properties":{"code":{"type":"string","title":"Code","default":""}},"type":"object","title":"ReferralClickRequest"},"ReferralCodeRequest":{"properties":{"machine_id":{"type":"string","title":"Machine Id","default":""},"email":{"type":"string","title":"Email","default":""}},"type":"object","title":"ReferralCodeRequest"},"ReferralInviteRecipient":{"properties":{"name":{"type":"string","title":"Name","default":""},"email":{"type":"string","title":"Email","default":""}},"type":"object","title":"ReferralInviteRecipient"},"ReferralInvitesRequest":{"properties":{"machine_id":{"type":"string","title":"Machine Id","default":""},"email":{"type":"string","title":"Email","default":""},"lang":{"type":"string","title":"Lang","default":""},"recipients":{"items":{"$ref":"#/components/schemas/ReferralInviteRecipient"},"type":"array","title":"Recipients","default":[]}},"type":"object","title":"ReferralInvitesRequest"},"ReinstallBlastRequest":{"properties":{"dry_run":{"type":"boolean","title":"Dry Run","default":false}},"type":"object","title":"ReinstallBlastRequest"},"ReplyDraftCreatedRequest":{"properties":{"stage":{"type":"string","title":"Stage"}},"type":"object","required":["stage"],"title":"ReplyDraftCreatedRequest"},"RevokeBody":{"properties":{"handle":{"type":"string","maxLength":32,"title":"Handle"}},"type":"object","required":["handle"],"title":"RevokeBody"},"RevokeRequest":{"properties":{"key":{"type":"string","title":"Key"}},"type":"object","required":["key"],"title":"RevokeRequest"},"SendBody":{"properties":{"to":{"type":"string","maxLength":32,"title":"To","description":"Peer handle from agents_list"},"msg_type":{"type":"string","maxLength":32,"title":"Msg Type"},"payload":{"title":"Payload"},"to_agent":{"anyOf":[{"type":"string","maxLength":64},{"type":"null"}],"title":"To Agent"},"from_agent":{"anyOf":[{"type":"string","maxLength":64},{"type":"null"}],"title":"From Agent"},"in_reply_to":{"title":"In Reply To"}},"additionalProperties":false,"type":"object","required":["to","msg_type"],"title":"SendBody"},"SendDigestRequest":{"properties":{"subject":{"type":"string","title":"Subject"},"html":{"type":"string","title":"Html"},"to":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"To"}},"type":"object","required":["subject","html"],"title":"SendDigestRequest"},"SendOutreachEmailRequest":{"properties":{"to":{"type":"string","title":"To"},"subject":{"type":"string","title":"Subject"},"html_body":{"type":"string","title":"Html Body"},"approval_ref":{"type":"string","title":"Approval Ref"}},"type":"object","required":["to","subject","html_body","approval_ref"],"title":"SendOutreachEmailRequest"},"SetFeedbackStatusRequest":{"properties":{"status":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Status"},"type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Type"}},"type":"object","title":"SetFeedbackStatusRequest"},"SetFiledIssueRequest":{"properties":{"filed_issue":{"type":"string","title":"Filed Issue"}},"type":"object","required":["filed_issue"],"title":"SetFiledIssueRequest"},"SettingsEventRequest":{"properties":{"event":{"type":"string","title":"Event"},"machine_id":{"type":"string","title":"Machine Id","default":""},"step":{"type":"integer","title":"Step","default":-1},"cta":{"type":"string","title":"Cta","default":""},"version":{"type":"string","title":"Version","default":""}},"type":"object","required":["event"],"title":"SettingsEventRequest"},"SettingsRegisterRequest":{"properties":{"email":{"type":"string","title":"Email"},"machine_id":{"type":"string","title":"Machine Id","default":""},"cloud_token":{"type":"string","title":"Cloud Token","default":""}},"type":"object","required":["email"],"title":"SettingsRegisterRequest"},"SetupEmailBody":{"properties":{"email":{"type":"string","title":"Email"}},"type":"object","required":["email"],"title":"SetupEmailBody"},"SetupEventBody":{"properties":{"event":{"type":"string","title":"Event"},"os":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Os"}},"type":"object","required":["event"],"title":"SetupEventBody"},"SetupStepRequest":{"properties":{"machine_id":{"type":"string","title":"Machine Id","default":""},"install_id":{"type":"string","title":"Install Id","default":""},"method":{"type":"string","title":"Method","default":""},"step":{"type":"string","title":"Step","default":""},"status":{"type":"string","title":"Status","default":""},"client":{"type":"string","title":"Client","default":""},"error":{"type":"string","title":"Error","default":""},"ref":{"type":"string","title":"Ref","default":""},"existing_mcp_count":{"type":"integer","title":"Existing Mcp Count","default":-1},"preserved_servers":{"type":"string","title":"Preserved Servers","default":""},"clients_found":{"type":"string","title":"Clients Found","default":""},"clients_not_found":{"type":"string","title":"Clients Not Found","default":""},"tool_count":{"type":"integer","title":"Tool Count","default":-1},"binary_version":{"type":"string","title":"Binary Version","default":""},"npm_version":{"type":"string","title":"Npm Version","default":""}},"type":"object","title":"SetupStepRequest"},"StageBody":{"properties":{"agent_id":{"type":"string","maxLength":64,"title":"Agent Id"},"instance_id":{"type":"string","format":"uuid","title":"Instance Id"},"epoch":{"type":"integer","minimum":1.0,"title":"Epoch"},"wake_state":{"anyOf":[{"type":"string","maxLength":32},{"type":"null"}],"title":"Wake State"},"wake_reason":{"anyOf":[{"type":"string","maxLength":32},{"type":"null"}],"title":"Wake Reason"},"stage":{"type":"string","maxLength":32,"title":"Stage"},"message_ids":{"items":{"type":"integer"},"type":"array","maxItems":100,"minItems":1,"title":"Message Ids"},"attempt_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Attempt Id"},"token_sha256":{"anyOf":[{"type":"string","pattern":"^[0-9a-f]{64}$"},{"type":"null"}],"title":"Token Sha256"},"detail":{"anyOf":[{"type":"string","maxLength":32},{"type":"null"}],"title":"Detail"},"cap_id":{"anyOf":[{"type":"string","maxLength":64},{"type":"null"}],"title":"Cap Id"},"plan_sha256":{"anyOf":[{"type":"string","pattern":"^[0-9a-f]{64}$"},{"type":"null"}],"title":"Plan Sha256"},"steps":{"anyOf":[{"type":"integer","maximum":8.0,"minimum":1.0},{"type":"null"}],"title":"Steps"},"step":{"anyOf":[{"type":"integer","maximum":8.0,"minimum":1.0},{"type":"null"}],"title":"Step"},"execution_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Execution Id"},"observation_sha256":{"anyOf":[{"type":"string","pattern":"^[0-9a-f]{64}$"},{"type":"null"}],"title":"Observation Sha256"},"evidence_kind":{"anyOf":[{"type":"string","maxLength":32},{"type":"null"}],"title":"Evidence Kind"},"evidence_ref":{"anyOf":[{"type":"string","maxLength":300},{"type":"null"}],"title":"Evidence Ref"}},"additionalProperties":false,"type":"object","required":["agent_id","instance_id","epoch","stage","message_ids"],"title":"StageBody","description":"lmcp-api#426: one stage, reported by the reader for its own messages (§5.4)."},"StuckMachinesBlastRequest":{"properties":{"max_version":{"type":"string","title":"Max Version","default":""},"dry_run":{"type":"boolean","title":"Dry Run","default":false}},"type":"object","title":"StuckMachinesBlastRequest"},"SuggestionEventBody":{"properties":{"machine_id":{"type":"string","title":"Machine Id"},"event":{"type":"string","title":"Event"},"domain":{"type":"string","title":"Domain","default":""}},"type":"object","required":["machine_id","event"],"title":"SuggestionEventBody"},"SurveyCreateBody":{"properties":{"slug":{"type":"string","title":"Slug"},"title":{"type":"object","title":"Title"},"questions":{"items":{},"type":"array","title":"Questions"},"intro":{"anyOf":[{"type":"object"},{"type":"null"}],"title":"Intro"},"blocking":{"type":"boolean","title":"Blocking","default":true},"max_skips":{"type":"integer","title":"Max Skips","default":1},"min_sessions":{"type":"integer","title":"Min Sessions","default":3},"anonymous":{"type":"boolean","title":"Anonymous","default":false},"closes_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Closes At"}},"type":"object","required":["slug","title","questions"],"title":"SurveyCreateBody"},"SurveyEventBody":{"properties":{"machine_id":{"type":"string","title":"Machine Id"},"survey_id":{"type":"integer","title":"Survey Id"},"event":{"type":"string","title":"Event"},"reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Reason"},"source":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Source"}},"type":"object","required":["machine_id","survey_id","event"],"title":"SurveyEventBody"},"SurveyPatchBody":{"properties":{"active":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Active"},"blocking":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Blocking"},"min_sessions":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Min Sessions"},"max_skips":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Max Skips"},"closes_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Closes At"},"title":{"anyOf":[{"type":"object"},{"type":"null"}],"title":"Title"},"questions":{"anyOf":[{"items":{},"type":"array"},{"type":"null"}],"title":"Questions"}},"type":"object","title":"SurveyPatchBody"},"SurveyResponseBody":{"properties":{"machine_id":{"type":"string","title":"Machine Id"},"survey_id":{"type":"integer","title":"Survey Id"},"answers":{"type":"object","title":"Answers"},"locale":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Locale"},"version":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Version"},"response_token":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Response Token"},"source":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Source"}},"type":"object","required":["machine_id","survey_id","answers"],"title":"SurveyResponseBody"},"TargetsBody":{"properties":{"machine_ids":{"items":{},"type":"array","title":"Machine Ids"},"confirm":{"type":"boolean","title":"Confirm","default":false}},"type":"object","required":["machine_ids"],"title":"TargetsBody"},"TestEmailRequest":{"properties":{"to":{"type":"string","title":"To","default":""},"subject":{"type":"string","title":"Subject","default":"[LMCP] Test email — diagnostic"},"body":{"type":"string","title":"Body","default":"<p>Test from /admin/email/test — if you see this, the Resend wiring works.</p>"}},"type":"object","title":"TestEmailRequest"},"TestimonialAction":{"properties":{"action":{"type":"string","title":"Action"}},"type":"object","required":["action"],"title":"TestimonialAction"},"TestimonialCreate":{"properties":{"name":{"type":"string","title":"Name"},"role":{"type":"string","title":"Role","default":""},"message":{"type":"string","title":"Message"},"rating":{"type":"integer","title":"Rating","default":5},"source":{"type":"string","title":"Source","default":"web"},"machine_id":{"type":"string","title":"Machine Id","default":""}},"type":"object","required":["name","message"],"title":"TestimonialCreate"},"TrackEvent":{"properties":{"event":{"type":"string","title":"Event"},"referrer":{"type":"string","title":"Referrer","default":""},"section":{"type":"string","title":"Section","default":""},"variant":{"type":"string","title":"Variant","default":""},"hero_variant":{"type":"string","title":"Hero Variant","default":""},"section_variant":{"type":"string","title":"Section Variant","default":""},"cta_variant":{"type":"string","title":"Cta Variant","default":""},"visual_variant":{"type":"string","title":"Visual Variant","default":""},"positioning_variant":{"type":"string","title":"Positioning Variant","default":""},"eu_privacy_variant":{"type":"string","title":"Eu Privacy Variant","default":""},"ref":{"type":"string","title":"Ref","default":""},"vid":{"type":"string","title":"Vid","default":""},"path":{"type":"string","title":"Path","default":""},"src":{"type":"string","title":"Src","default":""},"command":{"type":"string","title":"Command","default":""},"detected_os":{"type":"string","title":"Detected Os","default":""},"action_id":{"type":"string","title":"Action Id","default":""},"version":{"type":"string","title":"Version","default":""},"install_variant":{"type":"string","title":"Install Variant","default":""},"source":{"type":"string","title":"Source","default":""},"platform":{"type":"string","title":"Platform","default":""},"locale":{"type":"string","title":"Locale","default":""},"utm_source":{"type":"string","title":"Utm Source","default":""},"utm_medium":{"type":"string","title":"Utm Medium","default":""},"utm_campaign":{"type":"string","title":"Utm Campaign","default":""},"depth":{"type":"integer","title":"Depth","default":0},"seconds":{"type":"integer","title":"Seconds","default":0},"experiment_id":{"type":"string","title":"Experiment Id","default":""},"variation_id":{"type":"string","title":"Variation Id","default":""},"query":{"type":"string","title":"Query","default":""},"results":{"type":"integer","title":"Results","default":-1},"page_type":{"type":"string","title":"Page Type","default":""},"choice":{"type":"string","title":"Choice","default":""},"block":{"type":"string","title":"Block","default":""},"target":{"type":"string","title":"Target","default":""},"answer":{"type":"string","title":"Answer","default":""},"other_text":{"type":"string","title":"Other Text","default":""},"kind":{"type":"string","title":"Kind","default":""},"method":{"type":"string","title":"Method","default":""},"message":{"type":"string","title":"Message","default":""},"file":{"type":"string","title":"File","default":""},"browser":{"type":"string","title":"Browser","default":""},"browser_major":{"type":"string","title":"Browser Major","default":""},"build":{"type":"string","title":"Build","default":""},"carga":{"type":"string","title":"Carga","default":""}},"type":"object","required":["event"],"title":"TrackEvent"},"TranslateBody":{"properties":{"questions":{"items":{},"type":"array","title":"Questions","default":[]},"title":{"anyOf":[{"type":"object"},{"type":"null"}],"title":"Title"}},"type":"object","title":"TranslateBody"},"TrialValidateRequest":{"properties":{"machine_id":{"type":"string","title":"Machine Id","default":""},"cloud_token":{"type":"string","title":"Cloud Token","default":""},"local_install_date":{"type":"string","title":"Local Install Date","default":""}},"type":"object","title":"TrialValidateRequest"},"TunnelAnonRegisterRequest":{"properties":{"machine_id":{"type":"string","title":"Machine Id","default":""}},"type":"object","title":"TunnelAnonRegisterRequest"},"TunnelCatalogBody":{"properties":{"machine_id":{"type":"string","title":"Machine Id","default":""},"platform":{"type":"string","title":"Platform","default":""},"hash":{"type":"string","title":"Hash","default":""},"tools":{"items":{"type":"string"},"type":"array","title":"Tools","default":[]}},"type":"object","title":"TunnelCatalogBody"},"TunnelClaimRequest":{"properties":{"pre_token":{"type":"string","title":"Pre Token"},"email":{"type":"string","title":"Email"},"license_key":{"type":"string","title":"License Key","default":""}},"type":"object","required":["pre_token","email"],"title":"TunnelClaimRequest"},"TunnelConnectorTokenRequest":{"properties":{"token":{"type":"string","title":"Token"},"kind":{"type":"string","title":"Kind","default":"other"}},"type":"object","required":["token"],"title":"TunnelConnectorTokenRequest"},"TunnelDataEnableRequest":{"properties":{"token":{"type":"string","title":"Token"},"enabled":{"type":"boolean","title":"Enabled","default":true}},"type":"object","required":["token"],"title":"TunnelDataEnableRequest"},"TunnelEnrollRequest":{"properties":{"machine_id":{"type":"string","title":"Machine Id","default":""},"public_key":{"type":"string","title":"Public Key","default":""},"alg":{"type":"string","title":"Alg","default":""},"proof":{"type":"object","title":"Proof","default":{}}},"type":"object","title":"TunnelEnrollRequest"},"TunnelKeyResetRequest":{"properties":{"machine_id":{"type":"string","title":"Machine Id","default":""},"keep_token_prefix":{"type":"string","title":"Keep Token Prefix","default":""}},"type":"object","title":"TunnelKeyResetRequest"},"TunnelRevokeRequest":{"properties":{"token":{"type":"string","title":"Token"}},"type":"object","required":["token"],"title":"TunnelRevokeRequest"},"TunnelRotateRequest":{"properties":{"token":{"type":"string","title":"Token"}},"type":"object","required":["token"],"title":"TunnelRotateRequest"},"TunnelSchemasBody":{"properties":{"machine_id":{"type":"string","title":"Machine Id","default":""},"catalog":{"type":"object","title":"Catalog","default":{}}},"type":"object","title":"TunnelSchemasBody"},"TunnelTokenRequest":{"properties":{"email":{"type":"string","title":"Email"},"license_key":{"type":"string","title":"License Key","default":""},"machine_id":{"type":"string","title":"Machine Id","default":""}},"type":"object","required":["email"],"title":"TunnelTokenRequest"},"TunnelUninstallRequest":{"properties":{"token":{"type":"string","title":"Token","default":""},"machine_id":{"title":"Machine Id"},"client_time":{"title":"Client Time"},"signature":{"title":"Signature"}},"type":"object","title":"TunnelUninstallRequest"},"UninstallEventRequest":{"properties":{"version":{"type":"string","title":"Version","default":""},"machine_id":{"type":"string","title":"Machine Id","default":""},"ref":{"type":"string","title":"Ref","default":""}},"type":"object","title":"UninstallEventRequest"},"UnlinkRequest":{"properties":{"machine_id":{"type":"string","title":"Machine Id","default":""},"t":{"type":"integer","title":"T","default":0},"sig":{"type":"string","title":"Sig","default":""}},"type":"object","title":"UnlinkRequest"},"UpdateAttemptBody":{"properties":{"delayed":{"anyOf":[{},{"type":"null"}],"title":"Delayed"},"offline_seconds":{"anyOf":[{},{"type":"null"}],"title":"Offline Seconds"},"via":{"anyOf":[{},{"type":"null"}],"title":"Via"},"machine_id":{"type":"string","title":"Machine Id","default":""},"current_version":{"type":"string","title":"Current Version","default":""},"target_version":{"type":"string","title":"Target Version","default":""},"stage":{"type":"string","title":"Stage","default":""},"result":{"type":"string","title":"Result","default":""},"reason":{"type":"string","title":"Reason","default":""},"platform":{"type":"string","title":"Platform","default":""},"arch":{"type":"string","title":"Arch","default":""},"component":{"anyOf":[{},{"type":"null"}],"title":"Component"},"rejected_by":{"anyOf":[{},{"type":"null"}],"title":"Rejected By"},"http_status":{"anyOf":[{},{"type":"null"}],"title":"Http Status"},"error_domain":{"anyOf":[{},{"type":"null"}],"title":"Error Domain"},"error_code":{"anyOf":[{},{"type":"null"}],"title":"Error Code"},"bytes_received":{"anyOf":[{},{"type":"null"}],"title":"Bytes Received"},"attempts":{"anyOf":[{},{"type":"null"}],"title":"Attempts"},"source":{"anyOf":[{},{"type":"null"}],"title":"Source"},"resumed":{"anyOf":[{},{"type":"null"}],"title":"Resumed"},"net_probe":{"anyOf":[{},{"type":"null"}],"title":"Net Probe"},"proxy":{"anyOf":[{},{"type":"null"}],"title":"Proxy"}},"type":"object","title":"UpdateAttemptBody"},"ValidateRequest":{"properties":{"key":{"type":"string","title":"Key"},"machine_id":{"type":"string","title":"Machine Id"}},"type":"object","required":["key","machine_id"],"title":"ValidateRequest"},"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"},"VerifyBody":{"properties":{"cap_id":{"type":"string","pattern":"^[0-9a-f]{32}$","title":"Cap Id"},"verdict":{"type":"string","enum":["verified","unverified"],"title":"Verdict"},"reason":{"anyOf":[{"type":"string","maxLength":32},{"type":"null"}],"title":"Reason"}},"additionalProperties":false,"type":"object","required":["cap_id","verdict"],"title":"VerifyBody"},"VersionNotesRequest":{"properties":{"notes":{"type":"string","title":"Notes"}},"type":"object","required":["notes"],"title":"VersionNotesRequest"},"VersionRequest":{"properties":{"version":{"type":"string","title":"Version"},"notes":{"type":"string","title":"Notes","default":""},"files":{"type":"object","title":"Files","default":{}},"download_url":{"type":"string","title":"Download Url","default":""},"dmg_url":{"type":"string","title":"Dmg Url","default":""},"sparkle_signature":{"type":"string","title":"Sparkle Signature","default":""},"file_size":{"type":"integer","title":"File Size","default":0},"min_os_version":{"type":"string","title":"Min Os Version","default":"13.0"},"set_latest":{"type":"boolean","title":"Set Latest","default":true},"platform":{"type":"string","title":"Platform","default":""},"commit_sha":{"type":"string","title":"Commit Sha","default":""},"allow_downgrade":{"type":"boolean","title":"Allow Downgrade","default":false},"downgrade_reason":{"type":"string","title":"Downgrade Reason","default":""},"promotion":{"type":"boolean","title":"Promotion","default":false}},"type":"object","required":["version"],"title":"VersionRequest"},"WaitlistBody":{"properties":{"email":{"type":"string","title":"Email"},"os":{"type":"string","title":"Os","default":""},"vid":{"type":"string","title":"Vid","default":""},"source":{"type":"string","title":"Source","default":"web"}},"type":"object","required":["email"],"title":"WaitlistBody"},"WakeBody":{"properties":{"agent_id":{"type":"string","maxLength":64,"title":"Agent Id"},"instance_id":{"type":"string","format":"uuid","title":"Instance Id"},"epoch":{"type":"integer","minimum":1.0,"title":"Epoch"},"wake_state":{"anyOf":[{"type":"string","maxLength":32},{"type":"null"}],"title":"Wake State"},"wake_reason":{"anyOf":[{"type":"string","maxLength":32},{"type":"null"}],"title":"Wake Reason"}},"additionalProperties":false,"type":"object","required":["agent_id","instance_id","epoch"],"title":"WakeBody"},"WebConfig":{"properties":{"web_download_gate":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Web Download Gate"},"account_link":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Account Link"},"account_link_local":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Account Link Local"},"vincular_un_clic":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Vincular Un Clic"},"encuesta_barreras":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Encuesta Barreras"}},"type":"object","title":"WebConfig"},"WelcomeEventRequest":{"properties":{"machine_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Machine Id"},"event":{"type":"string","title":"Event"},"client":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Client"},"ref":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Ref"}},"type":"object","required":["event"],"title":"WelcomeEventRequest"}}}}