{"openapi":"3.1.0","info":{"title":"Ooih Dashboard API","version":"0.1.0"},"paths":{"/api/auth/login":{"post":{"tags":["auth"],"summary":"Login","operationId":"login_api_auth_login_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LoginRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/auth/magic":{"post":{"tags":["auth"],"summary":"Magic Login","description":"Exchange a one-time magic token for a session cookie.","operationId":"magic_login_api_auth_magic_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MagicExchange"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/auth/app-token":{"post":{"tags":["auth"],"summary":"Issue App Token","description":"One-time token bridging a system-browser login into the app webview.\n\nThe native shell finishes OAuth in the system browser (the cookie lands\nTHERE), calls this from that browser session, and hands the token into\nits webview — which exchanges it via POST /api/auth/magic, the same path\nTelegram magic links already use. 60s TTL: it travels one deep link.","operationId":"issue_app_token_api_auth_app_token_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/auth/tg-login/start":{"post":{"tags":["auth"],"summary":"Tg Login Start","description":"Begin a web→Telegram login: mint a pending one-time token + the bot deep-link.\nThe browser polls /tg-login/status; the user confirms via /start weblogin_<token>.\n\nBrand-aware: the deep link points at the bot for the brand of the dashboard\nhost the request came from, so a dash.octodus.com login opens @octodus_bot,\nnot the octomatica default.","operationId":"tg_login_start_api_auth_tg_login_start_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/auth/tg-login/status":{"get":{"tags":["auth"],"summary":"Tg Login Status","description":"Poll a web→Telegram login. Returns `pending` until the user confirms in the bot;\nthen issues the session cookie ONCE (request → consumed) and returns the user.","operationId":"tg_login_status_api_auth_tg_login_status_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"}}}}}}},"/api/auth/telegram-webapp":{"post":{"tags":["auth"],"summary":"Telegram Webapp Auth","description":"Authenticate a Telegram Mini App session.\n\nValidates Telegram-signed initData, upserts the user, grants an auto-trial\nsubscription on first sign-in, attributes a referral if `ref_code` is set,\nand issues the standard session cookie.\n\nBrand-aware: initData is HMAC-signed with the bot the Mini App was launched\nfrom, so it is verified against the token for the brand of the request host —\nan Octodus Mini App (dash.octodus.com) against @octodus_bot, everything else\nagainst the octomatica default.","operationId":"telegram_webapp_auth_api_auth_telegram_webapp_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TelegramWebAppAuth"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/auth/yandex/start":{"get":{"tags":["auth"],"summary":"Yandex Login Start","description":"Begin the Yandex ID login: mint a CSRF state and redirect to Yandex.\n\nA LOGIN flow — there is no current user yet, so the OAuthState row has\nuser_id NULL (this is what distinguishes it from a future bind flow,\nwhich tags the state with the session's user_id).\n\n`next` (a same-origin path) is carried through the round-trip in the state's\nredirect_to, so a login started to CONTINUE somewhere — e.g. the OIDC\n/oauth/authorize hop that finishes git SSO on git.octodus.com — lands back\nthere instead of the default chat surface.","operationId":"yandex_login_start_api_auth_yandex_start_get","parameters":[{"name":"next","in":"query","required":false,"schema":{"type":"string","default":"","title":"Next"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/auth/yandex/callback":{"get":{"tags":["auth"],"summary":"Yandex Login Callback","description":"Finish the Yandex ID login: validate state, exchange code, resolve the\nuser, set the session cookie, land in the app.","operationId":"yandex_login_callback_api_auth_yandex_callback_get","parameters":[{"name":"state","in":"query","required":false,"schema":{"type":"string","default":"","title":"State"}},{"name":"code","in":"query","required":false,"schema":{"type":"string","default":"","title":"Code"}},{"name":"error","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Error"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/auth/logout":{"post":{"tags":["auth"],"summary":"Logout","operationId":"logout_api_auth_logout_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/auth/logto/session":{"post":{"tags":["auth"],"summary":"Logto Session","description":"Mint a first-class dash session from a Logto sign-in (Octodus brand).\n\nThe Next.js web app is the confidential OIDC client: it has already\ncompleted the /callback round-trip with @logto/next and holds the verified\nLogto claims. It calls this endpoint server-to-server, authenticated by the\nshared LOGTO_INTERNAL_SECRET, and forwards the resulting `token` Set-Cookie\nto the browser. We resolve the Logto identity into dash's OWN user (linking\nby *verified* email so a Logto login never duplicates an existing account,\nand never hands over an account on an unverified address) and set the normal\nsession cookie — the same cookie every other login path issues.\n\nFail safe: an unset internal secret DISABLES the endpoint. It is reachable\nfrom the browser through the /api proxy, so a blank secret must never\nauthorize a session mint.","operationId":"logto_session_api_auth_logto_session_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LogtoSessionRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/auth/me":{"get":{"tags":["auth"],"summary":"Me","operationId":"me_api_auth_me_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/admin/overview":{"get":{"tags":["admin"],"summary":"Overview","operationId":"overview_api_admin_overview_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/admin/users":{"get":{"tags":["admin"],"summary":"List Users","operationId":"list_users_api_admin_users_get","parameters":[{"name":"q","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Q"}},{"name":"role","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Role"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":2000,"default":50,"title":"Limit"}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","default":0,"title":"Offset"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["admin"],"summary":"Create User","operationId":"create_user_api_admin_users_post","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateUser"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/admin/users/{user_id}":{"get":{"tags":["admin"],"summary":"Get User","operationId":"get_user_api_admin_users__user_id__get","parameters":[{"name":"user_id","in":"path","required":true,"schema":{"type":"integer","title":"User Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["admin"],"summary":"Update User","operationId":"update_user_api_admin_users__user_id__put","parameters":[{"name":"user_id","in":"path","required":true,"schema":{"type":"integer","title":"User Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateUser"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/admin/users/{user_id}/spaces":{"get":{"tags":["admin"],"summary":"Get User Spaces","description":"Every space this user OWNS or is a MEMBER of — registered via space_members\nor present as a Telegram board member (by telegram_id) — for the admin user\npage. Owner spaces first. Independent of whether the user has spent anything\nthere (that's the separate 'Usage by Space' panel).","operationId":"get_user_spaces_api_admin_users__user_id__spaces_get","parameters":[{"name":"user_id","in":"path","required":true,"schema":{"type":"integer","title":"User Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/admin/users/{user_id}/energy":{"get":{"tags":["admin"],"summary":"User Energy","operationId":"user_energy_api_admin_users__user_id__energy_get","parameters":[{"name":"user_id","in":"path","required":true,"schema":{"type":"integer","title":"User Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/admin/subscriptions":{"post":{"tags":["admin"],"summary":"Create Subscription","operationId":"create_subscription_api_admin_subscriptions_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscriptionCreate"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/admin/subscriptions/{sub_id}":{"put":{"tags":["admin"],"summary":"Update Subscription","operationId":"update_subscription_api_admin_subscriptions__sub_id__put","parameters":[{"name":"sub_id","in":"path","required":true,"schema":{"type":"integer","title":"Sub Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscriptionUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["admin"],"summary":"Deactivate Subscription","operationId":"deactivate_subscription_api_admin_subscriptions__sub_id__delete","parameters":[{"name":"sub_id","in":"path","required":true,"schema":{"type":"integer","title":"Sub Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/admin/model-catalog":{"get":{"tags":["admin"],"summary":"List Model Catalog","description":"All catalog rows (enabled + disabled), in sort order — the admin\nengine-toggle listing (mirrors the bot's /gate/model-catalog projection).\n\nEach row also carries `space_count`: how many spaces are currently pinned to\nthat engine/model, so the admin Providers ON/OFF control can warn before an\nadmin turns an engine off (those spaces fail over to another engine, or are\npaused if none is available).","operationId":"list_model_catalog_api_admin_model_catalog_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/admin/model-catalog/{pin}":{"patch":{"tags":["admin"],"summary":"Patch Model Catalog","description":"Enable/disable (or relabel/reorder) a catalog model without a deploy —\nthe lever behind the owner picker's switchable set. 404 on unknown pin.\n\nDisabling is refused if it would leave ZERO enabled rows: the catalog is the\nonly source of truth for what's switchable, so an all-disabled catalog would\nstrand every space with no engine anyone could pick or run on.","operationId":"patch_model_catalog_api_admin_model_catalog__pin__patch","parameters":[{"name":"pin","in":"path","required":true,"schema":{"type":"string","title":"Pin"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ModelCatalogPatch"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/admin/context-comparison":{"get":{"tags":["admin"],"summary":"Context Comparison","description":"Daily avg turn context size + cache hit rate for Claude pooled turns, split\ninto orchestrator (claude-opus*) and sub-agent (claude-sonnet-4-6 / <synthetic>).\n\nThe old v1/v2 memory-architecture split is retired — the fleet is uniformly v2.\nEach cohort is charted on its own scale on the frontend, because the orchestrator\nnumber is per-turn context (~130k) while a sub-agent row is per-job cumulative\n(~millions); forcing them onto one axis buried the orchestrator line.\n\ncache hit % = sum(tokens_cached) / sum(tokens_input): how much of the context was\nserved from cache (cheap) vs fresh input.","operationId":"context_comparison_api_admin_context_comparison_get","parameters":[{"name":"days","in":"query","required":false,"schema":{"type":"integer","maximum":120,"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"}}}}}}},"/api/admin/usage":{"get":{"tags":["admin"],"summary":"Usage Stats","description":"Daily usage series — Telegram calls (`usage`) merged with web-chat turns\n(keyless `api_turns`, which never enter the usage ledger).\n\n`avg_duration_sec` comes from `Usage.duration_sec` only — `api_turns` has\nno equivalent column, so web-chat days that carry no Telegram usage report\n`avg_duration_sec: null`.\n\n`group_by=slug` returns `{\"grouped_by\": \"slug\", \"series\": {slug: [...]}}`\ninstead of the flat list, nesting the same per-date rows under each\nspace's slug for a one-round-trip multi-app comparison. Omit it for the\noriginal flat list (default, unchanged for existing callers).","operationId":"usage_stats_api_admin_usage_get","parameters":[{"name":"days","in":"query","required":false,"schema":{"type":"integer","maximum":365,"default":30,"title":"Days"}},{"name":"user_id","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"User Id"}},{"name":"chat_key","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Chat Key"}},{"name":"group_by","in":"query","required":false,"schema":{"anyOf":[{"type":"string","pattern":"^slug$"},{"type":"null"}],"title":"Group By"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/admin/spaces":{"get":{"tags":["admin"],"summary":"List Spaces","operationId":"list_spaces_api_admin_spaces_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/admin/spaces/list":{"get":{"tags":["admin"],"summary":"Admin Spaces List","description":"Filterable, paginated inventory of registered spaces only.","operationId":"admin_spaces_list_api_admin_spaces_list_get","parameters":[{"name":"q","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Q"}},{"name":"origin","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Origin"}},{"name":"brand","in":"query","required":false,"schema":{"type":"string","pattern":"^(all|octomatica|octodus)$","default":"all","title":"Brand"}},{"name":"archived","in":"query","required":false,"schema":{"type":"string","pattern":"^(active|archived|all)$","default":"active","title":"Archived"}},{"name":"owner_id","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Owner Id"}},{"name":"workspace_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Workspace Id"}},{"name":"sort","in":"query","required":false,"schema":{"type":"string","pattern":"^(title|created_at|last_activity|messages|cost)$","default":"title","title":"Sort"}},{"name":"direction","in":"query","required":false,"schema":{"type":"string","pattern":"^(asc|desc)$","default":"asc","title":"Direction"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":200,"minimum":1,"default":50,"title":"Limit"}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0,"default":0,"title":"Offset"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/admin/spaces/by-id/{space_id}":{"get":{"tags":["admin"],"summary":"Admin Space By Id","description":"Exact registered-space detail; child queries are scoped from the resolved row.","operationId":"admin_space_by_id_api_admin_spaces_by_id__space_id__get","parameters":[{"name":"space_id","in":"path","required":true,"schema":{"type":"integer","title":"Space Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/admin/spaces/by-key/{chat_key}":{"get":{"tags":["admin"],"summary":"Get Space Detail","description":"Per-space detail: registered members + everyone who's actually written\nin this chat (from the `usage` table) plus per-user totals. Used by the\nadmin Spaces page when an admin clicks a row to drill in.","operationId":"get_space_detail_api_admin_spaces_by_key__chat_key__get","parameters":[{"name":"chat_key","in":"path","required":true,"schema":{"type":"string","title":"Chat Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/admin/spaces/sessions":{"get":{"tags":["admin"],"summary":"All Spaces Sessions","description":"Return context sizes (tokens) for all spaces — orchestrator + sub-agents.","operationId":"all_spaces_sessions_api_admin_spaces_sessions_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/admin/subscriptions/usage":{"get":{"tags":["admin"],"summary":"Subscriptions Usage","description":"Per-subscription daily usage breakdown.","operationId":"subscriptions_usage_api_admin_subscriptions_usage_get","parameters":[{"name":"days","in":"query","required":false,"schema":{"type":"integer","maximum":365,"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"}}}}}}},"/api/admin/analytics/top-users":{"get":{"tags":["admin"],"summary":"Top Users By Cost","operationId":"top_users_by_cost_api_admin_analytics_top_users_get","parameters":[{"name":"days","in":"query","required":false,"schema":{"type":"integer","maximum":365,"default":30,"title":"Days"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"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"}}}}}}},"/api/admin/analytics/errors":{"get":{"tags":["admin"],"summary":"Errors Timeseries","description":"Daily infrastructure error counts for the overview performance graph.\n\nCounts container failures (exec/start) and sub-agent dispatch failures\nfrom container_events. Gap-filled with zeros so clean days show as 0\nrather than the chart interpolating across missing dates.","operationId":"errors_timeseries_api_admin_analytics_errors_get","parameters":[{"name":"days","in":"query","required":false,"schema":{"type":"integer","maximum":365,"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"}}}}}}},"/api/admin/analytics/context-size":{"get":{"tags":["admin"],"summary":"Context Size Analytics","description":"Daily average/max input tokens per space — tracks orchestrator start context.","operationId":"context_size_analytics_api_admin_analytics_context_size_get","parameters":[{"name":"days","in":"query","required":false,"schema":{"type":"integer","maximum":90,"default":30,"title":"Days"}},{"name":"space","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Space"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/admin/analytics/top-spaces":{"get":{"tags":["admin"],"summary":"Top Spaces By Cost","operationId":"top_spaces_by_cost_api_admin_analytics_top_spaces_get","parameters":[{"name":"days","in":"query","required":false,"schema":{"type":"integer","maximum":365,"default":30,"title":"Days"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"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"}}}}}}},"/api/admin/analytics/hourly":{"get":{"tags":["admin"],"summary":"Hourly Usage","operationId":"hourly_usage_api_admin_analytics_hourly_get","parameters":[{"name":"days","in":"query","required":false,"schema":{"type":"integer","maximum":30,"default":7,"title":"Days"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/admin/analytics/hourly-spaces":{"get":{"tags":["admin"],"summary":"Hourly Spaces Usage","description":"Per-hour × per-space cost over an explicit [start, end) window — the data\nbehind the admin \"today, hourly, which space consumed how much\" investigation\nchart. Telegram `usage` and keyless web `api_turns` are merged. Spaces beyond the\ntop `top` (by window cost) fold into an \"other\" series so the stacked chart stays\nlegible; empty hours are filled so the axis is continuous.\n\nBucketing is done in Python in TRUE UTC — deliberately NOT via SQL date()/extract,\nwhich render in the DB session timezone (prod is Europe/Berlin, not UTC) and would\nmislabel the hours. asyncpg returns timestamptz as UTC-aware datetimes regardless\nof session TZ, so flooring them to the hour in UTC is correct everywhere. The\nfrontend computes the day's UTC window and renders these UTC hours in the admin's\nlocal time, so labels are right whatever the server timezone.","operationId":"hourly_spaces_usage_api_admin_analytics_hourly_spaces_get","parameters":[{"name":"start","in":"query","required":true,"schema":{"type":"string","description":"window start, ISO-8601 (UTC)","title":"Start"},"description":"window start, ISO-8601 (UTC)"},{"name":"end","in":"query","required":true,"schema":{"type":"string","description":"window end, ISO-8601 (UTC), exclusive","title":"End"},"description":"window end, ISO-8601 (UTC), exclusive"},{"name":"top","in":"query","required":false,"schema":{"type":"integer","maximum":20,"minimum":1,"default":8,"title":"Top"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/admin/analytics/costs":{"get":{"tags":["admin"],"summary":"Cost Analytics","operationId":"cost_analytics_api_admin_analytics_costs_get","parameters":[{"name":"days","in":"query","required":false,"schema":{"type":"integer","maximum":365,"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"}}}}}}},"/api/admin/analytics/energy-timeline":{"get":{"tags":["admin"],"summary":"Energy Timeline","description":"Energy ledger over time, split into free admin grants / automatic\nsignup-referral bonuses / paid top-ups vs. what got spent — the admin\nOverview \"grants vs paid vs consumption\" panel (task #40, issue #487).\nBucketed adaptively (day/week/month, see `_pick_granularity`) and\ntruncated with an explicit `AT TIME ZONE 'UTC'` round-trip because the DB\nsession timezone is Europe/Berlin in prod and a bare `date_trunc` would\nmislabel bucket boundaries — same reasoning as `/analytics/hourly-spaces`.\n\nBucket definitions (amount_credit_micros; energy = micros / 1e6, USD = energy / 10):\n- free  = reason IN ('admin_grant','admin_action','operator_topup'), > 0\n- bonus = reason IN ('signup_credit','referral_signup_credit'), > 0\n- paid  = reason IN ('manual_topup','credit_purchase'), > 0\n- spent = reason IN ('usage','space_usage'), < 0 (reported as a positive amount)\n`referral_credit_commission` is a RUB-only commission row with no credit\namount (amount_credit_micros IS NULL) — it never matches any CASE above,\nnamed here so that exclusion reads as deliberate rather than an oversight.","operationId":"energy_timeline_api_admin_analytics_energy_timeline_get","parameters":[{"name":"days","in":"query","required":false,"schema":{"type":"integer","maximum":3650,"default":30,"title":"Days"}},{"name":"start","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"window start ISO-8601 (UTC); overrides `days`","title":"Start"},"description":"window start ISO-8601 (UTC); overrides `days`"},{"name":"end","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"window end ISO-8601 (UTC), exclusive","title":"End"},"description":"window end ISO-8601 (UTC), exclusive"},{"name":"all_time","in":"query","required":false,"schema":{"type":"boolean","description":"ignore days/start — use the earliest balance_transactions row as start","default":false,"title":"All Time"},"description":"ignore days/start — use the earliest balance_transactions row as start"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/admin/analytics/balance-trend":{"get":{"tags":["admin"],"summary":"Balance Trend","description":"Average + median ledger balance of ACTIVE users over time — a leading\nindicator (owner's framing, task #40/issue #487): a falling active-user\nbalance means people are spending down without topping back up (churn),\nor topping up smaller amounts, ahead of it showing up as fewer payments.\nDeliberately restricted to users active in a trailing window, not every\nbalance in the table: dead accounts and untouched signup-bonus balances\nwould dilute the signal with noise that has nothing to do with spend\nbehaviour. The window is the `active_window_days` param (default 30),\nalways echoed back in the response so the frontend can label it.\n\n\"Active at bucket B\" = >=1 debit (reason usage/space_usage,\namount_credit_micros < 0) in (B - active_window_days, B].\n\"Balance at bucket B\" = that user's `balance_after_credit_micros` on\ntheir latest transaction with created_at <= B — the ledger's own running\ntotal, not a client-side re-sum (same principle as\n`web/src/components/balance-chart.tsx` for a single user's history).\n\nBucketed day/week/month like `/analytics/energy-timeline`, same UTC\ndouble round-trip. Computed as a LATERAL \"last balance as of this bucket\"\njoin per (candidate user x bucket), backed by the existing\n`ix_balance_tx_user_created (user_id, created_at)` index — a bounded\njoin, not a per-day scan of the whole ledger. `candidates` is pre-filtered\nto users who transacted within [lo - active_window, hi] so a user who was\nnever near this window doesn't inflate the cross join. If this ever needs\nto go faster at a much larger user count, a `(reason, created_at)` index\nwould speed the `candidates`/EXISTS scans further — not added here since\nthe existing index already makes this fast at current data volumes and\nthis change intentionally doesn't touch the schema.","operationId":"balance_trend_api_admin_analytics_balance_trend_get","parameters":[{"name":"days","in":"query","required":false,"schema":{"type":"integer","maximum":3650,"default":30,"title":"Days"}},{"name":"start","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"window start ISO-8601 (UTC); overrides `days`","title":"Start"},"description":"window start ISO-8601 (UTC); overrides `days`"},{"name":"end","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"window end ISO-8601 (UTC), exclusive","title":"End"},"description":"window end ISO-8601 (UTC), exclusive"},{"name":"all_time","in":"query","required":false,"schema":{"type":"boolean","description":"ignore days/start — use the earliest balance_transactions row as start","default":false,"title":"All Time"},"description":"ignore days/start — use the earliest balance_transactions row as start"},{"name":"active_window_days","in":"query","required":false,"schema":{"type":"integer","maximum":90,"minimum":1,"description":"a user counts as 'active' at a bucket if they had a usage/space_usage debit within this many days before it","default":30,"title":"Active Window Days"},"description":"a user counts as 'active' at a bucket if they had a usage/space_usage debit within this many days before it"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/admin/analytics/cpm":{"get":{"tags":["admin"],"summary":"Cpm Analytics","operationId":"cpm_analytics_api_admin_analytics_cpm_get","parameters":[{"name":"days","in":"query","required":false,"schema":{"type":"integer","maximum":365,"default":30,"title":"Days"}},{"name":"user_id","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"User Id"}},{"name":"chat_key","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Chat Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/admin/analytics/subscription-spaces":{"get":{"tags":["admin"],"summary":"Subscription Space Analytics","description":"Provider × Space analytics.\n\nsubscription_id in the usage table stores two things depending on path:\n- Pool member name (string: emadexus, voterbird, shaddoteth) — from agent\n- User plan ID (numeric: 1, 2, 7) — from gate lease fallback\n\nWe normalize to a single \"provider_key\": string subscription_ids pass\nthrough (they ARE the provider), numeric ones fall back to the provider\ncolumn (anthropic_pool, openai, etc).","operationId":"subscription_space_analytics_api_admin_analytics_subscription_spaces_get","parameters":[{"name":"days","in":"query","required":false,"schema":{"type":"integer","maximum":365,"default":30,"title":"Days"}},{"name":"date_from","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Date From"}},{"name":"date_to","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Date To"}},{"name":"subscription_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Subscription Id"}},{"name":"chat_key","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Chat Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/admin/analytics/costs/per-user":{"get":{"tags":["admin"],"summary":"Cost Per User","description":"Per-user consumption — Telegram usage merged with web-chat turns.\n\nWeb (Yandex) accounts have no telegram_id, and web turns never enter the\nusage ledger, so both sources are aggregated and merged by users.id.","operationId":"cost_per_user_api_admin_analytics_costs_per_user_get","parameters":[{"name":"days","in":"query","required":false,"schema":{"type":"integer","maximum":365,"default":30,"title":"Days"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"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"}}}}}}},"/api/admin/analytics/breakdown":{"get":{"tags":["admin"],"summary":"Usage Breakdown By Dimension","description":"Unified admin usage breakdown by a single dimension (space | user | model |\nprovider). Defaults to the last `days`; pass an explicit [start, end) window\n(e.g. a single day) to scope the per-space / per-model tables to that range so a\ndate filter is actually honored. One query backs the per-space, per-user and\nper-model admin views. Costs use billed_cost_usd (what the customer is charged).","operationId":"usage_breakdown_by_dimension_api_admin_analytics_breakdown_get","parameters":[{"name":"dimension","in":"query","required":false,"schema":{"type":"string","pattern":"^(space|user|model|provider)$","default":"space","title":"Dimension"}},{"name":"days","in":"query","required":false,"schema":{"type":"integer","maximum":365,"default":30,"title":"Days"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":1000,"default":100,"title":"Limit"}},{"name":"start","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"window start ISO-8601 (UTC); overrides `days`","title":"Start"},"description":"window start ISO-8601 (UTC); overrides `days`"},{"name":"end","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"window end ISO-8601 (UTC), exclusive","title":"End"},"description":"window end ISO-8601 (UTC), exclusive"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/admin/tasks":{"get":{"tags":["admin-tasks"],"summary":"Admin List Tasks","description":"Admin: tasks across ALL spaces with filters (space, brand, state, assignee,\ncreator, title). Newest first, bounded. Each row carries its space chip + the\nflow name when the task is a flow step.","operationId":"admin_list_tasks_api_admin_tasks_get","parameters":[{"name":"space","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"filter to one space slug","title":"Space"},"description":"filter to one space slug"},{"name":"brand","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"filter to one brand","title":"Brand"},"description":"filter to one brand"},{"name":"state","in":"query","required":false,"schema":{"type":"string","pattern":"^(open|closed|done|cancelled|all)$","default":"all","title":"State"}},{"name":"assignee_user_id","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Assignee User Id"}},{"name":"creator_user_id","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Creator User Id"}},{"name":"q","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"case-insensitive title substring","title":"Q"},"description":"case-insensitive title substring"},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":500,"minimum":1,"default":100,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/admin/system":{"get":{"tags":["admin"],"summary":"System Status","operationId":"system_status_api_admin_system_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/admin/users/{user_id}/credentials":{"put":{"tags":["admin"],"summary":"Set User Credentials","operationId":"set_user_credentials_api_admin_users__user_id__credentials_put","parameters":[{"name":"user_id","in":"path","required":true,"schema":{"type":"integer","title":"User Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetCredentials"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/admin/teams":{"get":{"tags":["admin"],"summary":"List Teams","operationId":"list_teams_api_admin_teams_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}},"post":{"tags":["admin"],"summary":"Create Team","operationId":"create_team_api_admin_teams_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TeamCreate"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/admin/teams/{team_id}":{"get":{"tags":["admin"],"summary":"Get Team","operationId":"get_team_api_admin_teams__team_id__get","parameters":[{"name":"team_id","in":"path","required":true,"schema":{"type":"integer","title":"Team Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["admin"],"summary":"Update Team","operationId":"update_team_api_admin_teams__team_id__put","parameters":[{"name":"team_id","in":"path","required":true,"schema":{"type":"integer","title":"Team Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TeamUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/admin/settings":{"get":{"tags":["admin"],"summary":"Get Settings","operationId":"get_settings_api_admin_settings_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}},"put":{"tags":["admin"],"summary":"Update Setting","operationId":"update_setting_api_admin_settings_put","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SettingUpdate"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/admin/system/containers/mappings":{"get":{"tags":["admin"],"summary":"List Container Mappings","operationId":"list_container_mappings_api_admin_system_containers_mappings_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}},"put":{"tags":["admin"],"summary":"Upsert Container Mapping","operationId":"upsert_container_mapping_api_admin_system_containers_mappings_put","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MappingUpsert"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/admin/system/bill-infra":{"post":{"tags":["admin"],"summary":"Bill Infra","operationId":"bill_infra_api_admin_system_bill_infra_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/admin/providers":{"get":{"tags":["admin"],"summary":"List Providers","description":"List all Claude subscriptions used by the bot for inference.","operationId":"list_providers_api_admin_providers_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/admin/providers/pool":{"get":{"tags":["admin"],"summary":"Providers Pool","description":"How much capacity the fleet HAS right now, and when more arrives — for\nboth account pools, in one shape.\n\nThe Providers tab already renders each account's usage bars. What it could\nnever answer is the question the owner actually asks it (E, 2026-09-15: \"I\nwant to format the providers tab to see available capacity\"): how many\naccounts can serve a turn, how many are on their way out, and when the\nlimited ones come back.\n\nSURFACED, NOT RECOMPUTED. Both payloads are published by the bot\n(`tools/pool_capacity.write_dash_snapshot`, `tools/codex_capacity.write_dash_snapshot`)\nfrom the same gates that decide routing — `is_sub_exhausted`, the headroom\nreserve, `codex_pool._usable`. Re-deriving \"usable\" from the raw per-account\nfiles here would give the dashboard a second definition of servable, and the\ntwo would drift silently, which is the class of bug this whole feature\nexists to end. A missing snapshot degrades to `available: false` and the tab\nsays so, rather than drawing an empty bar that reads as 0% used.","operationId":"providers_pool_api_admin_providers_pool_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/admin/providers/capacity":{"get":{"tags":["admin"],"summary":"Providers Capacity","description":"The capacity-graph data feed (task #49 part 2): raw quota-snapshot points\nfrom `provider_quota_snapshots` over the window, overlaid with fleet SPEND\nfrom `usage` bucketed hourly, so the admin `/admin/capacity` page can plot\n\"when does power come back\" against \"how much are we spending\".\n\nSnapshots are returned as raw points (not pre-aggregated into a synthetic\nseries) — the frontend draws the capacity step-function and reset-window\nmarkers straight off `used_pct`/`reset_at`; that degrades gracefully to a\nsparse/near-empty chart while history accumulates, which a server-side\nresample would not.\n\nSpend is bucketed by hour in Python, in UTC (see `hourly_spaces_usage`'s\ndocstring for why: SQL `date_trunc`/`extract` render in the DB session\ntimezone, and `func.date()` isn't hourly-granular either), restricted to\n`usage.subscription_id`s that actually appear in this window's snapshots —\nthe provider pool IS the set of subscription ids the healthchecks report on.","operationId":"providers_capacity_api_admin_providers_capacity_get","parameters":[{"name":"hours","in":"query","required":false,"schema":{"type":"integer","maximum":2160,"minimum":1,"description":"lookback window in hours","default":72,"title":"Hours"},"description":"lookback window in hours"},{"name":"provider","in":"query","required":false,"schema":{"anyOf":[{"type":"string","pattern":"^(claude|codex)$"},{"type":"null"}],"title":"Provider"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/admin/providers/{provider_id}/disable":{"post":{"tags":["admin"],"summary":"Disable Provider","description":"Mark a provider disabled so it can't be activated or auto-rotated into.","operationId":"disable_provider_api_admin_providers__provider_id__disable_post","parameters":[{"name":"provider_id","in":"path","required":true,"schema":{"type":"string","title":"Provider Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DisableProviderRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/admin/providers/{provider_id}/enable":{"post":{"tags":["admin"],"summary":"Enable Provider","description":"Clear the disabled flag on a provider.","operationId":"enable_provider_api_admin_providers__provider_id__enable_post","parameters":[{"name":"provider_id","in":"path","required":true,"schema":{"type":"string","title":"Provider Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/admin/providers/{provider_id}/refresh-limits":{"post":{"tags":["admin"],"summary":"Refresh Provider Limits","description":"Force a Claude Code statusline refresh for one provider card.","operationId":"refresh_provider_limits_api_admin_providers__provider_id__refresh_limits_post","parameters":[{"name":"provider_id","in":"path","required":true,"schema":{"type":"string","title":"Provider Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/admin/providers/auth/start":{"post":{"tags":["admin"],"summary":"Start Provider Auth","description":"Start full Claude first-run flow in a temp HOME inside tmux.\n\nClaude's first run shows several screens in order — a welcome splash\n(auto-advances on a timer), a theme picker, then a login-method picker —\nbefore printing the OAuth URL. How fast each renders depends on cold-start\ntime, so firing a fixed number of Enters on a fixed schedule races the\nrender and gets stuck one screen short on a slow start. Instead we poll the\npane and accept the highlighted default on whichever known picker is\ncurrently showing, stopping as soon as the URL appears.","operationId":"start_provider_auth_api_admin_providers_auth_start_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddProviderRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/admin/providers/auth/code":{"post":{"tags":["admin"],"summary":"Submit Auth Code","description":"User pastes the OAuth code. We send it to the tmux session's 'Paste code' prompt.","operationId":"submit_auth_code_api_admin_providers_auth_code_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthCodeRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/admin/providers/add":{"post":{"tags":["admin"],"summary":"Add Provider","description":"Save the current live credentials as a provider (manual flow).","operationId":"add_provider_api_admin_providers_add_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddProviderRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/admin/providers/codex":{"get":{"tags":["admin"],"summary":"Codex Status","description":"The codex account POOL (accounts + usage + active) that opencode selection and\ncodex image-gen share. Before the pool is provisioned, surface the current single\n/root/.codex grant so the UI shows the live account (the first add migrates it in).","operationId":"codex_status_api_admin_providers_codex_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/admin/providers/codex/auth/start":{"post":{"tags":["admin"],"summary":"Codex Auth Start","description":"Add a codex account: run `codex login --device-auth` into a FRESH temp CODEX_HOME\n(never /root/.codex) and return the verification URL + one-time code. On approval the\ngrant is registered into the pool (see the poll endpoint). Re-authing an existing\naccount works too — register upserts by account id.","operationId":"codex_auth_start_api_admin_providers_codex_auth_start_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/admin/providers/codex/auth/status":{"get":{"tags":["admin"],"summary":"Codex Auth Poll","description":"Poll the in-flight codex device-auth: idle | polling | authorized | expired | error.","operationId":"codex_auth_poll_api_admin_providers_codex_auth_status_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/admin/providers/codex/accounts/{account_id}/disable":{"post":{"tags":["admin"],"summary":"Codex Account Disable","description":"Park a codex pool account: set its `disabled` flag so opencode selection and\nrotation skip it (honored live per turn, no bot reload). Refuses to disable the\nlast enabled+healthy account so the pool can't be emptied provider-wide.","operationId":"codex_account_disable_api_admin_providers_codex_accounts__account_id__disable_post","parameters":[{"name":"account_id","in":"path","required":true,"schema":{"type":"string","title":"Account Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/admin/providers/codex/accounts/{account_id}/enable":{"post":{"tags":["admin"],"summary":"Codex Account Enable","description":"Clear a codex pool account's `disabled` flag so it rejoins rotation.","operationId":"codex_account_enable_api_admin_providers_codex_accounts__account_id__enable_post","parameters":[{"name":"account_id","in":"path","required":true,"schema":{"type":"string","title":"Account Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/admin/providers/higgsfield":{"get":{"tags":["admin"],"summary":"Higgsfield Status","description":"Status of the shared higgsfield media-gen credential: logged-in/out + access-token\nexpiry + credential-lock presence. Never returns token material.","operationId":"higgsfield_status_api_admin_providers_higgsfield_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/admin/providers/higgsfield/auth/start":{"post":{"tags":["admin"],"summary":"Higgsfield Auth Start","description":"Run `higgsfield auth login --port <p>` on the host and return the\nclerk.higgsfield.ai/oauth/authorize URL. The login process stays alive — blocking on\nthe loopback callback port — until /complete relays the operator's callback (or it\ntimes out). Idempotent on double-click; refuses to start if a login is already running\non the host (e.g. a manual re-auth).","operationId":"higgsfield_auth_start_api_admin_providers_higgsfield_auth_start_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/admin/providers/higgsfield/auth/complete":{"post":{"tags":["admin"],"summary":"Higgsfield Auth Complete","description":"Finish the re-auth: validate the pasted loopback callback URL, relay it to the\nwaiting login's loopback port to complete the PKCE exchange, then confirm the shared\ncredential was rewritten. Returns the new expiry; never echoes token material.","operationId":"higgsfield_auth_complete_api_admin_providers_higgsfield_auth_complete_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HiggsfieldCompleteRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/admin/providers/{provider_id}":{"delete":{"tags":["admin"],"summary":"Remove Provider","description":"Remove a subscription.","operationId":"remove_provider_api_admin_providers__provider_id__delete","parameters":[{"name":"provider_id","in":"path","required":true,"schema":{"type":"string","title":"Provider Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/admin/api-keys":{"get":{"tags":["admin"],"summary":"List Api Keys","description":"List all external API keys with usage stats.","operationId":"list_api_keys_api_admin_api_keys_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/admin/api-keys/{key_id}":{"put":{"tags":["admin"],"summary":"Update Api Key","description":"Update an API key value in its env file.","operationId":"update_api_key_api_admin_api_keys__key_id__put","parameters":[{"name":"key_id","in":"path","required":true,"schema":{"type":"string","title":"Key Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateApiKeyRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/admin/workspaces":{"get":{"tags":["admin"],"summary":"Admin List Workspaces","description":"List all workspaces with members and bot config.","operationId":"admin_list_workspaces_api_admin_workspaces_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/admin/workspaces/{workspace_id}/members":{"post":{"tags":["admin"],"summary":"Add Workspace Member","operationId":"add_workspace_member_api_admin_workspaces__workspace_id__members_post","parameters":[{"name":"workspace_id","in":"path","required":true,"schema":{"type":"string","title":"Workspace Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddWorkspaceMember"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/admin/workspaces/{workspace_id}/members/{user_id}":{"delete":{"tags":["admin"],"summary":"Remove Workspace Member","operationId":"remove_workspace_member_api_admin_workspaces__workspace_id__members__user_id__delete","parameters":[{"name":"workspace_id","in":"path","required":true,"schema":{"type":"string","title":"Workspace Id"}},{"name":"user_id","in":"path","required":true,"schema":{"type":"integer","title":"User Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/admin/concurrency":{"get":{"tags":["admin"],"summary":"Get Concurrency","description":"Live concurrency stats: active orchestrators and sub-agents per space.","operationId":"get_concurrency_api_admin_concurrency_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/admin/concurrency/history":{"get":{"tags":["admin"],"summary":"Get Concurrency History","description":"Concurrency history for graphing (last 24h, 1-min resolution).","operationId":"get_concurrency_history_api_admin_concurrency_history_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/admin/concurrency/config":{"put":{"tags":["admin"],"summary":"Update Concurrency Config","description":"Update concurrency limits. Requires bot restart to take effect.","operationId":"update_concurrency_config_api_admin_concurrency_config_put","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConcurrencyConfig"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/admin/teams/{team_id}/invites":{"post":{"tags":["admin"],"summary":"Create Team Invite Admin","operationId":"create_team_invite_admin_api_admin_teams__team_id__invites_post","parameters":[{"name":"team_id","in":"path","required":true,"schema":{"type":"integer","title":"Team Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminTeamInviteCreate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"get":{"tags":["admin"],"summary":"List Team Invites Admin","operationId":"list_team_invites_admin_api_admin_teams__team_id__invites_get","parameters":[{"name":"team_id","in":"path","required":true,"schema":{"type":"integer","title":"Team Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/admin/teams/{team_id}/invites/{invite_id}":{"delete":{"tags":["admin"],"summary":"Revoke Team Invite Admin","operationId":"revoke_team_invite_admin_api_admin_teams__team_id__invites__invite_id__delete","parameters":[{"name":"team_id","in":"path","required":true,"schema":{"type":"integer","title":"Team Id"}},{"name":"invite_id","in":"path","required":true,"schema":{"type":"integer","title":"Invite Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/admin/containers":{"get":{"tags":["admin"],"summary":"List Containers","description":"Live view of space containers: status, uptime, image staleness, RAM.\n\nReads from Docker (source of truth) and joins with the spaces table for\nfriendly chat titles. No DB-backed pool registry — Docker is the registry.","operationId":"list_containers_api_admin_containers_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/admin/api-access-keys":{"get":{"tags":["admin"],"summary":"Api Access Keys","description":"All Phase-1 public API keys (octo_*) with owner attribution + per-key spend.","operationId":"api_access_keys_api_admin_api_access_keys_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}},"post":{"tags":["admin"],"summary":"Admin Mint Key","description":"Mint a public API key for any account (admin). Plaintext returned ONCE.","operationId":"admin_mint_key_api_admin_api_access_keys_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminMintKeyIn"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/admin/api-access-keys/{key_id}":{"patch":{"tags":["admin"],"summary":"Admin Edit Key","operationId":"admin_edit_key_api_admin_api_access_keys__key_id__patch","parameters":[{"name":"key_id","in":"path","required":true,"schema":{"type":"integer","title":"Key Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminEditKeyIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/admin/api-access-keys/{key_id}/revoke":{"post":{"tags":["admin"],"summary":"Admin Revoke Key","operationId":"admin_revoke_key_api_admin_api_access_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"}}}}}}},"/api/admin/spaces/owners":{"get":{"tags":["admin"],"summary":"Admin Spaces Owners","description":"Light list for the owner-assignment UI: every space with its current\nowner. The admin performs the ownership migration by hand from here.","operationId":"admin_spaces_owners_api_admin_spaces_owners_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/admin/spaces/{space_id}/owner":{"patch":{"tags":["admin"],"summary":"Admin Set Space Owner","operationId":"admin_set_space_owner_api_admin_spaces__space_id__owner_patch","parameters":[{"name":"space_id","in":"path","required":true,"schema":{"type":"integer","title":"Space Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/_SetSpaceOwner"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/admin/spaces/{space_id}/members":{"get":{"tags":["admin"],"summary":"Admin Space Members","description":"Owner-picker candidates: every active dash user (any user can be made the\nbilling owner — spaces without a synced Telegram board would otherwise have\nno candidates). Users who are actual board members of this space are flagged\n`is_member: true` so the UI can rank them first. Optional `?q=` filters by\nname / username / telegram_id.","operationId":"admin_space_members_api_admin_spaces__space_id__members_get","parameters":[{"name":"space_id","in":"path","required":true,"schema":{"type":"integer","title":"Space Id"}},{"name":"q","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Q"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/admin/spaces/usage":{"get":{"tags":["admin"],"summary":"Admin Spaces Usage","description":"SpaceUsage across all spaces, split into deployed Lizard APPS and IPRoyal\nPROXY egress (project_id `iproyal-<session>`). Apps group by (space, project);\nproxy aggregates by (space, topic=app, target=destination host) so per-space,\nper-app, per-destination cost is debuggable — not one opaque row per session.\nAuth: require_admin (browser-facing admin dashboard endpoint).","operationId":"admin_spaces_usage_api_admin_spaces_usage_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/admin/fleet-caps":{"get":{"tags":["admin"],"summary":"Admin Get Fleet Caps","operationId":"admin_get_fleet_caps_api_admin_fleet_caps_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}},"put":{"tags":["admin"],"summary":"Admin Set Fleet Caps","description":"Set/clear the fleet-wide caps. effort_cap and the deprecated scalar\nmodel_cap are full-replace (null clears). model_caps and model_cap_mode are\nPARTIAL updates: only the engine keys present are written (null clears,\nnon-empty string sets), and model_cap_mode is written only when present\n(off|auto|on); omitted engines/mode are left untouched. All validation runs\nBEFORE any write, so a 422 leaves the row exactly as it was.","operationId":"admin_set_fleet_caps_api_admin_fleet_caps_put","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FleetCapsUpdate"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/admin/attention":{"get":{"tags":["admin-attention"],"summary":"Attention","operationId":"attention_api_admin_attention_get","parameters":[{"name":"lang","in":"query","required":false,"schema":{"enum":["en","ru"],"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"}}}}}}},"/api/admin/attention/brief":{"post":{"tags":["admin-attention"],"summary":"Brief","operationId":"brief_api_admin_attention_brief_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BriefRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/admin/attention/brief/latest":{"get":{"tags":["admin-attention"],"summary":"Latest Brief","operationId":"latest_brief_api_admin_attention_brief_latest_get","parameters":[{"name":"lang","in":"query","required":false,"schema":{"enum":["en","ru"],"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"}}}}}}},"/api/admin/attention/brief/{run_id}":{"get":{"tags":["admin-attention"],"summary":"Poll Brief","operationId":"poll_brief_api_admin_attention_brief__run_id__get","parameters":[{"name":"run_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Run Id"}},{"name":"lang","in":"query","required":false,"schema":{"enum":["en","ru"],"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"}}}}}}},"/api/user/me":{"get":{"tags":["user"],"summary":"Me","operationId":"me_api_user_me_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/user/usage":{"get":{"tags":["user"],"summary":"My Usage","description":"`group_by=slug` returns `{\"grouped_by\": \"slug\", \"series\": {slug: [...]}}`\ninstead of the flat list, nesting per-date rows under each of the user's\nspaces for a one-round-trip multi-app comparison. Omit it for the\noriginal flat list (default, unchanged for existing callers).\n`avg_duration_sec` is null on days with no rows carrying a duration.","operationId":"my_usage_api_user_usage_get","parameters":[{"name":"days","in":"query","required":false,"schema":{"type":"integer","maximum":365,"default":30,"title":"Days"}},{"name":"chat_key","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Chat Key"}},{"name":"group_by","in":"query","required":false,"schema":{"anyOf":[{"type":"string","pattern":"^slug$"},{"type":"null"}],"title":"Group By"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/user/costs":{"get":{"tags":["user"],"summary":"My Costs","operationId":"my_costs_api_user_costs_get","parameters":[{"name":"days","in":"query","required":false,"schema":{"type":"integer","maximum":365,"default":30,"title":"Days"}},{"name":"chat_key","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Chat Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/user/create-feed":{"get":{"tags":["user"],"summary":"My Create Feed","operationId":"my_create_feed_api_user_create_feed_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/user/activity":{"get":{"tags":["user"],"summary":"My Activity","description":"Recent activity for the Home feed.\n\nCoalesces consecutive same-kind rows in the same chat that fall within a\n1-hour window into single events. A single bot turn fires several Usage\nrows; without coalescing the feed shows the same line ten times.\n\nReturns events sorted newest-first, capped at `limit`.","operationId":"my_activity_api_user_activity_get","parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":50,"default":10,"title":"Limit"}},{"name":"days","in":"query","required":false,"schema":{"type":"integer","maximum":30,"default":7,"title":"Days"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/user/subscription/deactivate":{"post":{"tags":["user"],"summary":"Deactivate Subscription","operationId":"deactivate_subscription_api_user_subscription_deactivate_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/user/transactions":{"get":{"tags":["user"],"summary":"My Transactions","description":"The caller's energy ledger — every credit/debit on their personal wallet.\n\nResolves pool-reference rows to the pool name so the UI can show\n'Pool top-up · Test Pool' instead of a bare pool_id.\n\n`kind=activity` excludes app-maintenance debits (reason='space_usage' — the\nhourly-per-app Lizard hosting charge, see space_billing.py); `kind=maintenance`\nreturns only them. Omitted returns everything, unchanged from before this\nfilter existed. Paired with GET /user/apps for the grouped by-app rollup\nthat replaces the flat per-charge list on the /billing/history maintenance\ntab.","operationId":"my_transactions_api_user_transactions_get","parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":200,"default":50,"title":"Limit"}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0,"default":0,"title":"Offset"}},{"name":"kind","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Kind"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/user/api-keys":{"get":{"tags":["user"],"summary":"Api Keys","description":"Per-key spend (today / this-month / all-time / turns) for the caller's own keys.","operationId":"api_keys_api_user_api_keys_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}},"post":{"tags":["user"],"summary":"Mint Api Key","description":"Mint a public API key. Plaintext returned ONCE. Self-serve forces the platform\nmarkup to 1.0; a space-bound key requires the caller to own that space. A key with\nno space binding defaults to space_scope='own' — it can only ever control the\nspaces it creates over the API, never the owner's existing spaces.","operationId":"mint_api_key_api_user_api_keys_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MintKeyIn"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/user/api-keys/{key_id}":{"patch":{"tags":["user"],"summary":"Edit Api Key","operationId":"edit_api_key_api_user_api_keys__key_id__patch","parameters":[{"name":"key_id","in":"path","required":true,"schema":{"type":"integer","title":"Key Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EditKeyIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/user/api-keys/{key_id}/revoke":{"post":{"tags":["user"],"summary":"Revoke Api Key","operationId":"revoke_api_key_api_user_api_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"}}}}}}},"/api/user/home-banner":{"get":{"tags":["user"],"summary":"Home Banner","description":"Admin-configured feed banner for the Home tab. The admin sets the\nsettings key `home_banner` to JSON {\"text\": ..., \"url\": ..., \"enabled\": true}\n(the /admin/settings KV editor).","operationId":"home_banner_api_user_home_banner_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/user/home-slides":{"get":{"tags":["user"],"summary":"Home Slides","description":"The Home feed carousel — admin-configured slides (settings key\n`home_slides`: JSON [{title?, text, url?, image_url?, enabled}], edited\non /admin/settings). One enabled slide renders as the banner strip,\nseveral — as a swipeable carousel. Legacy fallback: with no slides set,\nthe old single `home_banner` is wrapped as one slide so nothing that is\nlive today disappears.","operationId":"home_slides_api_user_home_slides_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/user/delete-account":{"post":{"tags":["user"],"summary":"Delete Account","description":"Soft-delete: PII wiped, api-spaces archived, ledger kept (accounting).\nRequired by App Store guideline 5.1.1(v) — in-app account deletion.\nstatus=\"deleted\" locks every login path (magic_login and get_current_user\nboth reject non-active users), so no hard row delete is needed.","operationId":"delete_account_api_user_delete_account_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeleteAccountBody"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/user/devices":{"post":{"tags":["user"],"summary":"Register Device","description":"Register this device for push (docs/plans/2026-08-28-apps-phase2.md).\nUpsert by token: a token seen on another account re-points to the CURRENT\nuser — a device follows whoever is signed in on it.","operationId":"register_device_api_user_devices_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeviceBody"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["user"],"summary":"Unregister Device","description":"Sign-out path: drop the token. Idempotent; only the owner's row dies.","operationId":"unregister_device_api_user_devices_delete","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeviceBody"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/ingest/magic-link":{"post":{"tags":["ingest"],"summary":"Create Magic Link","description":"Bot calls this to generate a 1h-valid login URL for a user by telegram_id.","operationId":"create_magic_link_api_ingest_magic_link_post","parameters":[{"name":"X-API-Key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MagicLinkRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/gate/provider-config":{"get":{"tags":["gate"],"summary":"Get Provider Config","operationId":"get_provider_config_api_gate_provider_config_get","parameters":[{"name":"X-API-Key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/gate/elevenlabs":{"post":{"tags":["gate"],"summary":"Elevenlabs Access","description":"Access gate for the ElevenLabs audio tool: admin-enabled OR Plus subscriber.\n\nCalled pre-flight by the ooih `ai` tool's audio action. Returns\n{enabled, admin_enabled, balance_energy, min_energy, reason}. When not\nenabled the tool relays `reason` to the user and generates/bills nothing.\nThe subscription is the space owner's (owner-pays), so any member of a\nsubscriber's space is covered. Pricing (2.0x) is independent — see the\nseed_elevenlabs_provider migration. Same gate mechanic as /gate/higgsfield.","operationId":"elevenlabs_access_api_gate_elevenlabs_post","parameters":[{"name":"X-API-Key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ElevenlabsAccessRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/gate/settings":{"get":{"tags":["gate"],"summary":"Get Gate Settings","description":"Read specific admin-editable Settings for the bot repo (emadex/ooih).\n\n`keys` is a comma-separated list. Only keys in GATE_SETTINGS_ALLOWLIST are\never returned; requested keys outside the allowlist are silently dropped.\nValues are returned raw (as stored) — the caller parses JSON if it expects it.","operationId":"get_gate_settings_api_gate_settings_get","parameters":[{"name":"keys","in":"query","required":true,"schema":{"type":"string","title":"Keys"}},{"name":"X-API-Key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/gate/higgsfield":{"post":{"tags":["gate"],"summary":"Higgsfield Access","description":"Access gate for the Higgsfield media tool: admin-enabled OR Plus subscriber.\n\nCalled pre-flight by the ooih `ai` tool's higgsfield action. Returns\n{enabled, admin_enabled, balance_energy, min_energy, reason}. When not\nenabled the tool relays `reason` to the user and generates/bills nothing.\nThe subscription is the space owner's (owner-pays), so any member of a\nsubscriber's space is covered. Pricing (2.0x) is independent — see the\nseed_higgsfield_provider migration.","operationId":"higgsfield_access_api_gate_higgsfield_post","parameters":[{"name":"X-API-Key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HiggsfieldAccessRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/gate/lease":{"post":{"tags":["gate"],"summary":"Create Run Lease","description":"Authorize one billable run without exposing provider credentials.","operationId":"create_run_lease_api_gate_lease_post","parameters":[{"name":"X-API-Key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LeaseRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/gate/report":{"post":{"tags":["gate"],"summary":"Report Usage","description":"Bot instance calls this after each call to report consumption.","operationId":"report_usage_api_gate_report_post","parameters":[{"name":"X-API-Key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UsageReport"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/gate/verify":{"post":{"tags":["gate"],"summary":"Verify User","description":"Verify a user has access. Returns their role and permissions.","operationId":"verify_user_api_gate_verify_post","parameters":[{"name":"X-API-Key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/VerifyRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/gate/spaces/upsert":{"post":{"tags":["gate"],"summary":"Gate Spaces Upsert","description":"Register or update a space, scoped to the calling workspace.","operationId":"gate_spaces_upsert_api_gate_spaces_upsert_post","parameters":[{"name":"X-API-Key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SpaceUpsertRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/gate/spaces/{slug}/brand":{"put":{"tags":["gate"],"summary":"Gate Set Space Brand","description":"Set a space's durable ``brand`` (the DB-authoritative source of truth the bot's\n(chat_id, brand) reverse lookup resolves on). Called by the fleet bot when it\ndetects a brand SWAP on a group (e.g. @octomatica_bot removed, @octodus_bot\nadded): the SAME group keeps its slug — and therefore all its memory/history —\nbut flips brand.\n\nKeyed by ``slug`` (not chat_id): the slug row is the authoritative, history-\nbearing space, so the swap ends with exactly ONE row carrying the new brand.\nThe (chat_id, brand) UNIQUE (uq_spaces_chat_id_brand) means a plain re-brand\ncould collide with a stale sibling row already at (chat_id, new_brand) — the\nfreshly-provisioned duplicate the new-brand bot may have created before the\nswap was detected. We remove that duplicate first (the slug row wins; the\nduplicate carries no group history), then flip the slug row in place, so the\nresult is the single branded row keyed by slug. Scoped to the calling\nworkspace; setting the brand a space already has is a no-op success.","operationId":"gate_set_space_brand_api_gate_spaces__slug__brand_put","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","title":"Slug"}},{"name":"X-API-Key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SpaceBrandRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/gate/spaces/{slug}/lang":{"put":{"tags":["gate"],"summary":"Gate Set Space Lang","description":"Set a space's onboarding ``language`` (the DB-authoritative source of truth\nthe bot resolves via load_spaces()[slug].language). Body accepts ``language``\n(what the client sends) or ``lang``. Keyed by slug, scoped to the calling\nworkspace; unknown slug → 404, empty language → 422.","operationId":"gate_set_space_lang_api_gate_spaces__slug__lang_put","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","title":"Slug"}},{"name":"X-API-Key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SpaceLangRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/gate/spaces/{slug}":{"put":{"tags":["gate"],"summary":"Gate Set Space Timezone","description":"Set a space's ``timezone`` (the DB-authoritative value that drives the chat\nheader clock and how scheduled tasks / reminders are interpreted).\n\nThe orchestrator's ``set_timezone`` tool has always PUT here; the route never\nexisted, so every call 404'd and only ever landed through its\n``POST /spaces/upsert`` fallback — an INSERT-or-update keyed on chat_id, which\nneeds a chat_id the tool often does not have and can write columns nobody asked\nit to. Keyed by slug and scoped to the calling workspace, exactly like\n``PUT /spaces/{slug}/lang``.\n\nThe IANA name is validated HERE as well as in the tool — the endpoint does not\ntrust the caller — so a bad zone is a 422, never a poisoned column that breaks\nevery later schedule for that space.\n\nA 404 carries a STRUCTURED detail (``{\"error\": \"space_not_found\", \"slug\": …}``)\nrather than a bare string: an unknown space and a missing route both answer 404,\nand the bug this route fixes hid for months precisely because the caller could\nnot tell the two apart. FastAPI's own no-such-route 404 has no ``error`` key.","operationId":"gate_set_space_timezone_api_gate_spaces__slug__put","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","title":"Slug"}},{"name":"X-API-Key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SpaceTimezoneRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/gate/spaces/{slug}/settings":{"post":{"tags":["gate"],"summary":"Gate Set Space Settings","description":"Set one or more durable per-space settings (the DB-authoritative source of\ntruth the bot reads off the gate spaces payload). Keyed by SLUG, scoped to the\ncalling workspace — exactly like PUT /spaces/{slug}/lang.\n\nBody is a JSON object drawn from an allowlist: booleans\n(``_SPACE_BOOL_SETTING_KEYS`` — ``subagent_status_badge``,\n``flows_auto_split``) and validated strings (``flows_checkin`` —\n``\"daily HH:MM\"`` 24h or ``\"off\"``; ``subagent_status_badge_mode`` — one of\n``_BADGE_MODES``). Empty body or any unknown key → 422; a value of the wrong\ntype / shape → 422; a badge mode and boolean that contradict → 422; unknown\nslug → 404. Returns ``{ok, slug, **settings}``.","operationId":"gate_set_space_settings_api_gate_spaces__slug__settings_post","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","title":"Slug"}},{"name":"X-API-Key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Data"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/gate/spaces/migrate-chat-id":{"post":{"tags":["gate"],"summary":"Gate Spaces Migrate Chat Id","description":"Supergroup migration: move a space's Telegram chat_id (old -> new) in place,\nkeeping the slug + all data. Scoped to the calling workspace.\n\nMoves BOTH the spaces row AND the board: members resolve via\nboards.telegram_chat_id (NOT spaces.chat_id), so moving only the spaces row\nstrands every member under the old id and the space goes memberless (the\norchs then can't see it). Idempotent — each table matches on the OLD id, so a\npartially-applied migration (spaces row already moved, board not — the exact\nstuck state we hit) is completed by re-calling. If a board already exists at\nthe new id (auto-created when the bot first saw the new supergroup), its\nmembers are merged in and the old board dropped (members are unique per\n(board_id, telegram_user_id)).","operationId":"gate_spaces_migrate_chat_id_api_gate_spaces_migrate_chat_id_post","parameters":[{"name":"X-API-Key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SpaceMigrateChatIdRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/gate/spaces/delete":{"post":{"tags":["gate"],"summary":"Gate Spaces Delete","description":"Remove a space, scoped to the calling workspace.","operationId":"gate_spaces_delete_api_gate_spaces_delete_post","parameters":[{"name":"X-API-Key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SpaceDeleteRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/gate/space/{slug}/git-owner":{"get":{"tags":["gate"],"summary":"Space Git Owner","description":"The space owner's git identity (email + Forgejo username), so the deploy\nhook can grant them access to their space's org. Email + preferred_username\nmatch exactly what the OIDC SSO login provisions, so a pre-created account\nlinks to the owner on their first sign-in.","operationId":"space_git_owner_api_gate_space__slug__git_owner_get","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","title":"Slug"}},{"name":"X-API-Key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/gate/workspaces":{"get":{"tags":["gate"],"summary":"List Workspaces","operationId":"list_workspaces_api_gate_workspaces_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}},"post":{"tags":["gate"],"summary":"Create Workspace","description":"Create a new workspace and assign its admin.","operationId":"create_workspace_api_gate_workspaces_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateWorkspace"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/gate/spaces":{"get":{"tags":["gate"],"summary":"List Spaces","description":"Return all spaces belonging to this workspace.","operationId":"list_spaces_api_gate_spaces_get","parameters":[{"name":"X-API-Key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/gate/model-catalog":{"get":{"tags":["gate"],"summary":"Gate Model Catalog","description":"The full switchable engine/model catalog for the bot — ALL rows, enabled\nand disabled, in sort order. The bot filters to enabled itself for the\npicker and keeps the disabled rows to reverse-map historical sessions.\n\nEach row carries `admin_only`: an admin-only pin is enabled fleet-wide but\nthe bot must hide it from non-admin users (the dash hides it on every other\nsurface); the bot filters per acting user off this flag.\n\nPremium eligibility (issue #394): every row also carries `min_balance_energy`\nand `min_spent_energy` (NULL = no threshold). When `space` (a slug) is given\nthe response resolves the space's owner (owner-pays billing principal; the\nbot passes the CHAIN ROOT's slug for cross-space chains) and adds, per row,\n`eligible` + `ineligible_reason` (balance|spent|both|admin_only|null) plus a\ntop-level `owner: {user_id, balance_energy, spent_energy}`. Admin-only pins\nread ineligible here; the bot applies the admin exemption itself.","operationId":"gate_model_catalog_api_gate_model_catalog_get","parameters":[{"name":"space","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Space"}},{"name":"X-API-Key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/gate/fleet-caps":{"get":{"tags":["gate"],"summary":"Get Fleet Caps","description":"Fleet-wide effort/model caps, polled per-turn by every agent. Cheap: one\nPK lookup. All null when unset (no row, or the columns are null). ooih fails\nopen when `model_caps` is absent, so serving it is purely additive.\n\n`model_cap_mode` (ooih #1395/#1376) tells the data plane HOW to apply the\nper-engine model_caps (off|auto|on); an unset fleet serves \"off\", and ooih\ntreats a missing/unknown mode as \"off\" too, so this is purely additive.","operationId":"get_fleet_caps_api_gate_fleet_caps_get","parameters":[{"name":"X-API-Key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/gate/spaces/{slug}/model-eligibility":{"get":{"tags":["gate"],"summary":"Gate Space Model Eligibility","description":"Cheap per-space premium-pin eligibility (issue #394): the same owner-pays\ncomputation as `/model-catalog?space=`, projected to just the eligibility\nfields. `{owner: {user_id, balance_energy, spent_energy} | null, pins: [{pin,\neligible, ineligible_reason, min_balance_energy, min_spent_energy}]}`.\n\nOwner = the space's owner (billing principal). For a cross-space chain the\nbot passes the CHAIN ROOT's slug, exactly as `billing_chat_key` at lease\ntime. Admin-only pins read ineligible; the bot applies the admin exemption.","operationId":"gate_space_model_eligibility_api_gate_spaces__slug__model_eligibility_get","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","title":"Slug"}},{"name":"X-API-Key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/gate/spaces/by-chat/{chat_id}":{"get":{"tags":["gate"],"summary":"Get Space By Chat","description":"Reverse lookup: Telegram chat_id -> space, scoped to workspace.\n\nBrand-qualified: a private chat_id is a user's own Telegram id, identical\nacross every fleet bot they DM, so the same chat_id can key one space per\nbrand. When ``brand`` is supplied the lookup is (chat_id, brand) — the bot\npasses the RECEIVING bot's brand so it resolves that brand's space only. When\nomitted the lookup stays chat_id-only (legacy background/group callers); with\ntwo brands present it returns whichever the DB yields first, so callers that\nneed a specific brand must pass one.","operationId":"get_space_by_chat_api_gate_spaces_by_chat__chat_id__get","parameters":[{"name":"chat_id","in":"path","required":true,"schema":{"type":"integer","title":"Chat Id"}},{"name":"brand","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Brand"}},{"name":"X-API-Key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/gate/spaces/resolve/{chat_key}":{"get":{"tags":["gate"],"summary":"Resolve Space","description":"Resolve a bot-facing chat_key to routing metadata (slug, access_tier).\n\nThe bot's container_router consults this to decide host-mode vs\ncontainer-mode and to find the per-container slug.","operationId":"resolve_space_api_gate_spaces_resolve__chat_key__get","parameters":[{"name":"chat_key","in":"path","required":true,"schema":{"type":"string","title":"Chat Key"}},{"name":"X-API-Key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/gate/spaces/{chat_id}/first-sender":{"get":{"tags":["gate"],"summary":"Space First Sender By Chat","description":"Earliest human sender of a Telegram space, resolved by chat_id.","operationId":"space_first_sender_by_chat_api_gate_spaces__chat_id__first_sender_get","parameters":[{"name":"chat_id","in":"path","required":true,"schema":{"type":"integer","title":"Chat Id"}},{"name":"X-API-Key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/gate/spaces/by-slug/{slug}/first-sender":{"get":{"tags":["gate"],"summary":"Space First Sender By Slug","description":"Earliest human sender of a space, resolved by slug (repair tool knows slugs).","operationId":"space_first_sender_by_slug_api_gate_spaces_by_slug__slug__first_sender_get","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","title":"Slug"}},{"name":"X-API-Key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/gate/container/lease":{"post":{"tags":["gate"],"summary":"Container Lease","description":"Mint a container-level lease for a standard-tier space.\n\nWrites /run/ooih-mcp/<slug>.token (read by executor_mcp_server on\nevery tool call) and a container_leases audit row. Returns the slug\nso the bot can stage container directories.","operationId":"container_lease_api_gate_container_lease_post","parameters":[{"name":"X-API-Key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Payload"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/gate/turn/lease":{"post":{"tags":["gate"],"summary":"Turn Lease","description":"Mint a per-turn auth lease.\n\nReturns a JSON string that the bot writes to\n/run/ooih-mcp/<slug>/turns/<turn_id>.turn. The executor validates that\nthe file exists, has typ='turn', matches slug, and matches turn_id.","operationId":"turn_lease_api_gate_turn_lease_post","parameters":[{"name":"X-API-Key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Payload"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/gate/container/queue":{"post":{"tags":["gate"],"summary":"Container Queue","description":"Persist a message queued when no container slot was available.","operationId":"container_queue_api_gate_container_queue_post","parameters":[{"name":"X-API-Key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Payload"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/gate/spaces/provision":{"post":{"tags":["gate"],"summary":"Provision Space","description":"Register a new space (chat) in the gateway.\n\nThe bot calls this when a Telegram chat is first authorized for the\nworkspace. Caller has already created /spaces/<slug>/ on disk and is\nabout to mint a container lease. This endpoint just records the row.","operationId":"provision_space_api_gate_spaces_provision_post","parameters":[{"name":"X-API-Key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Payload"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/gate/spaces/set-owner":{"post":{"tags":["gate"],"summary":"Set Space Owner","description":"Set a space's billing owner (owner-pays, spec 2026-06-12) to the dash\naccount behind a Telegram id. The bot calls this on authorization so the\nauthorizing user owns + pays for the space. `claim_only` (default) writes\nthe owner only when it is currently NULL — re-/authorize and any manual\nadmin reassignment are never clobbered.","operationId":"set_space_owner_api_gate_spaces_set_owner_post","parameters":[{"name":"X-API-Key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetSpaceOwnerRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/gate/bitrix/connection":{"get":{"tags":["gate"],"summary":"Gate Bitrix Connection","description":"Resolve a Bitrix portal to its connection: decrypted creds + is_active +\nthe owner-pays account. This is the env→DB bridge the ingest reads instead of\nits `BITRIX_CONN_*` env vars (cf. the GitHub `/space/{slug}/git-owner` reader).\n\n`is_active` is returned verbatim; the ingest gates on it (reject/queue inbound\nwhen a connection is disabled) — the gate never withholds the row so the\ncaller can log/why.","operationId":"gate_bitrix_connection_api_gate_bitrix_connection_get","parameters":[{"name":"portal","in":"query","required":true,"schema":{"type":"string","title":"Portal"}},{"name":"X-API-Key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/gate/bitrix/stamp-space":{"post":{"tags":["gate"],"summary":"Gate Bitrix Stamp Space","description":"Stamp origin='bitrix' + the routing columns onto an already-provisioned\nspace (by slug). The in-bot ingest calls this right after the generic\n`docker/provision_space` creates the row, so the churning /agent provisioner\nstays untouched while the routing columns become authoritative. Idempotent.","operationId":"gate_bitrix_stamp_space_api_gate_bitrix_stamp_space_post","parameters":[{"name":"X-API-Key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StampBitrixSpace"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/gate/bitrix/space":{"get":{"tags":["gate"],"summary":"Gate Bitrix Space","description":"Resolve (portal, DIALOG_ID) → space via the first-class routing columns.\nReplaces the ingest's crc32-hash-over-chat_id resolution. Returns the slug +\nsynthetic chat_id so the caller can reuse its existing disk/turn paths.","operationId":"gate_bitrix_space_api_gate_bitrix_space_get","parameters":[{"name":"portal","in":"query","required":true,"schema":{"type":"string","title":"Portal"}},{"name":"dialog_id","in":"query","required":true,"schema":{"type":"string","title":"Dialog Id"}},{"name":"X-API-Key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/gate/bitrix/target":{"get":{"tags":["gate"],"summary":"Gate Bitrix Target","description":"The REVERSE of `/bitrix/space`: slug → (portal, dialog_id) from the\nfirst-class routing columns `/bitrix/stamp-space` wrote at provision, so the\nbot's async sub-agent watcher (a different process than the spawning turn)\nreads the reply target from the single source of truth rather than the\nper-space on-disk BITRIX_TARGET.json marker, now a legacy fallback only.\n`ok: false` for an unknown, archived, or not-yet-stamped slug.","operationId":"gate_bitrix_target_api_gate_bitrix_target_get","parameters":[{"name":"slug","in":"query","required":true,"schema":{"type":"string","title":"Slug"}},{"name":"X-API-Key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/gate/bitrix/fetch-connections":{"get":{"tags":["gate"],"summary":"Gate Bitrix Fetch Connections","description":"Enumerate the ACTIVE imbot.v2 fetch connections for the fetch poller.\n\nFetch mode has no inbound webhook — the bot polls its own queue — so the\npoller needs the full list (portal, v2_bot_id, bot_token, fetch_offset,\nwebhook) rather than resolving one portal at a time. Only `event_mode='fetch'`\nAND `is_active` rows are returned; the botToken + webhook are decrypted for the\nbot only, over the gate key. A row whose creds fail to decrypt is skipped (it\ncannot be polled) rather than failing the whole list.","operationId":"gate_bitrix_fetch_connections_api_gate_bitrix_fetch_connections_get","parameters":[{"name":"X-API-Key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/gate/bitrix/fetch-offset":{"post":{"tags":["gate"],"summary":"Gate Bitrix Fetch Offset","description":"Persist the advanced fetch cursor for one connection after a drain.\n\nimbot.v2.Event.get is non-destructive (events are not auto-acked; you advance\nan offset), so the poller stores nextOffset here so a restart resumes where it\nleft off. Monotonic: the offset only moves forward, so a late/duplicate write\nwith a lower value is ignored (guards against an out-of-order retry rewinding\nthe cursor and re-delivering the whole tail).","operationId":"gate_bitrix_fetch_offset_api_gate_bitrix_fetch_offset_post","parameters":[{"name":"X-API-Key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BitrixFetchOffset"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/gate/bitrix/register-v2":{"post":{"tags":["gate"],"summary":"Gate Bitrix Register V2","description":"Write back the imbot.v2 registration onto the portal's connection: the new\nv2 bot id, the caller-invented botToken (folded into the encrypted creds\nbundle), and the event mode. Called once by the ooih register helper right\nafter `imbot.v2.Bot.register` mints the bot RU-side.\n\nAdditive — the v1 columns (bot_id, is_active, the v1 creds) are untouched, so\nthe existing v1 bot keeps working in parallel. Resets fetch_offset to 0 on a\nfresh v2 registration (a new bot's queue starts empty). Requires an existing\nconnection row for the portal (seed it first via seed_bitrix_connection).","operationId":"gate_bitrix_register_v2_api_gate_bitrix_register_v2_post","parameters":[{"name":"X-API-Key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BitrixRegisterV2"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/gate/yandex/connection":{"get":{"tags":["gate"],"summary":"Gate Yandex Connection","description":"Resolve a Yandex org to its connection: decrypted token + is_active + the\nowner-pays account. This is the env→DB bridge the ingest reads instead of an\nenv var (mirrors `/bitrix/connection`).\n\n`is_active` is returned verbatim; the ingest gates on it (reject/queue inbound\nwhen a connection is disabled) — the gate never withholds the row so the caller\ncan log why.","operationId":"gate_yandex_connection_api_gate_yandex_connection_get","parameters":[{"name":"org","in":"query","required":true,"schema":{"type":"string","title":"Org"}},{"name":"X-API-Key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["gate"],"summary":"Gate Yandex Set Connection","description":"Enable / disable the DM user's connection (the bot's 'pause delivery'\ntoggle). Owner-authorized: another user's connection is refused, not\nmutated. The GET on this path is the poller's org→token bridge above — same\npath, different method and different audience.","operationId":"gate_yandex_set_connection_api_gate_yandex_connection_post","parameters":[{"name":"X-API-Key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/YandexDmConnection"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/gate/yandex/fetch-connections":{"get":{"tags":["gate"],"summary":"Gate Yandex Fetch Connections","description":"Enumerate the ACTIVE Yandex connections for the getUpdates poller.\n\nYandex is poll-only — the bot drains its own update queue — so the poller needs\nthe full list (org, token, fetch_offset) rather than resolving one org at a\ntime. Only `is_active` rows are returned; the token is decrypted for the bot\nonly, over the gate key. A row whose creds fail to decrypt is skipped (it\ncannot be polled) rather than failing the whole list.","operationId":"gate_yandex_fetch_connections_api_gate_yandex_fetch_connections_get","parameters":[{"name":"X-API-Key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/gate/yandex/fetch-offset":{"post":{"tags":["gate"],"summary":"Gate Yandex Fetch Offset","description":"Persist the advanced getUpdates cursor for one connection after a drain.\n\ngetUpdates is non-destructive (you advance an offset), so the poller stores\nnextOffset here so a restart resumes where it left off. Monotonic: the offset\nonly moves forward, so a late/duplicate write with a lower value is ignored\n(guards against an out-of-order retry rewinding the cursor and re-delivering\nthe whole tail).","operationId":"gate_yandex_fetch_offset_api_gate_yandex_fetch_offset_post","parameters":[{"name":"X-API-Key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/YandexFetchOffset"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/gate/yandex/stamp-space":{"post":{"tags":["gate"],"summary":"Gate Yandex Stamp Space","description":"Stamp origin='yandex' + the routing columns onto an already-provisioned\nspace (by slug). The in-bot ingest calls this right after the generic\n`docker/provision_space` creates the row (mirrors `/bitrix/stamp-space`). This\nis also how a newly-seen chat_id is recorded for the dashboard to list.\nIdempotent.","operationId":"gate_yandex_stamp_space_api_gate_yandex_stamp_space_post","parameters":[{"name":"X-API-Key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StampYandexSpace"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/gate/yandex/space":{"get":{"tags":["gate"],"summary":"Gate Yandex Space","description":"Resolve (org, chat_id) → space via the first-class routing columns. Returns\nthe slug + chat_id + title so the caller can reuse its existing paths\n(mirrors `/bitrix/space`).","operationId":"gate_yandex_space_api_gate_yandex_space_get","parameters":[{"name":"org","in":"query","required":true,"schema":{"type":"string","title":"Org"}},{"name":"chat_id","in":"query","required":true,"schema":{"type":"string","title":"Chat Id"}},{"name":"X-API-Key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/gate/yandex/target":{"get":{"tags":["gate"],"summary":"Gate Yandex Target","description":"The REVERSE of `/yandex/space`: slug → (org, chat_id) from the first-class\nrouting columns `/yandex/stamp-space` wrote at provision. The bot's async\nsub-agent watcher delivers a finished report from a DIFFERENT process than the\nturn that spawned it, so it must learn the reply target from the single\nsource of truth — this row — not from a per-space on-disk marker\n(YANDEX_TARGET.json), which is now a legacy fallback only. `ok: false` for an\nunknown, archived, or not-yet-stamped slug (mirrors `/bitrix/target`).","operationId":"gate_yandex_target_api_gate_yandex_target_get","parameters":[{"name":"slug","in":"query","required":true,"schema":{"type":"string","title":"Slug"}},{"name":"X-API-Key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/gate/yandex/owner-connection":{"get":{"tags":["gate"],"summary":"Gate Yandex Owner Connection","description":"The Yandex connection owned by this Telegram user, for the DM's status\nview — `{\"connection\": {...}}`, or `{}` when they have none (the bot renders\nthe not-connected prompt on the empty body). Active connection first, newest\notherwise; never returns the token.","operationId":"gate_yandex_owner_connection_api_gate_yandex_owner_connection_get","parameters":[{"name":"owner_telegram_id","in":"query","required":true,"schema":{"type":"string","title":"Owner Telegram Id"}},{"name":"X-API-Key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/gate/yandex/connect":{"post":{"tags":["gate"],"summary":"Gate Yandex Connect","description":"Stand up the DM user's Yandex connection from the token they pasted.\n\nDelegates to the shared connect core, so this writes the same encrypted row\nand books the same flat connect charge (on the same `external_ref`) as the\ndashboard panel. Two differences, both because the caller is a chat:\n\n* `validate=True` — the token is probed against getUpdates first, so a bad\n  token comes back as a reason the bot can print instead of a dead connection.\n* `on_conflict=\"update\"` — re-pasting the same token updates the existing row\n  (the org key is derived from the token) instead of failing on the unique\n  index. Connecting twice yields ONE connection.\n\nEvery refusal is `{\"ok\": false, \"reason\": ..., \"message\": ...}` with a 200 —\nthe bot shows `message` to the user.","operationId":"gate_yandex_connect_api_gate_yandex_connect_post","parameters":[{"name":"X-API-Key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/YandexDmConnect"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/gate/yandex/disconnect":{"post":{"tags":["gate"],"summary":"Gate Yandex Disconnect","description":"Remove the DM user's connection. Owner-authorized; the poller loses the\norg's token on its next enumeration.","operationId":"gate_yandex_disconnect_api_gate_yandex_disconnect_post","parameters":[{"name":"X-API-Key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/YandexDmDisconnect"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/gate/channel-admission/check":{"post":{"tags":["gate"],"summary":"Gate Channel Admission Check","description":"Decide one inbound message: admit, hold, or drop — and say, once per user,\nwhether the newcomer and the admin still need telling.\n\nThe ingest FAILS CLOSED on anything but a 2xx here (it holds the message and\nlogs), so this endpoint must not answer \"admitted\" on a guess: an unknown\nchannel is a 400 rather than a default.","operationId":"gate_channel_admission_check_api_gate_channel_admission_check_post","parameters":[{"name":"X-API-Key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChannelAdmissionCheck"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/gate/channel-admission/replays":{"post":{"tags":["gate"],"summary":"Gate Channel Admission Replays","description":"CLAIM the held questions of this channel's newly-approved users.\n\nA POST, not a GET, because it mutates: each returned row has been stamped\n`replayed_at` in the same transaction, so a second poller (or a re-drain\nafter a restart) gets nothing and the question is answered exactly once.","operationId":"gate_channel_admission_replays_api_gate_channel_admission_replays_post","parameters":[{"name":"X-API-Key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChannelAdmissionReplays"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/gate/channel-admission/decide":{"post":{"tags":["gate"],"summary":"Gate Channel Admission Decide","description":"Apply an approve/block that arrived as a Telegram button tap.\n\nThe gate key proves the BOT is calling; it proves nothing about the person\nwho tapped, so the tapping `actor_telegram_id` is resolved to an account here\nand checked against the connection's owner (or platform admin) — the same\n`may_decide` the dashboard's buttons go through. Settling it here is also what\nmakes the two surfaces agree: both write this one row.","operationId":"gate_channel_admission_decide_api_gate_channel_admission_decide_post","parameters":[{"name":"X-API-Key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChannelAdmissionDecide"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/gate/messages/record":{"post":{"tags":["gate"],"summary":"Record Message","description":"Record one chat message into the unified log. Idempotent on dedup_key so\nthe bot mirror and the one-time .md backfill never double-insert. Best-effort\nfor the caller — resolves space_id from chat_key and sender from telegram_id\nwhen present, but inserts regardless.\n\n``task_ref`` (``<slug>#<n>``) attributes the line to a captured task, which is\nwhat puts a task's MESSAGES on its page next to its spend. Two ways in:\n\n  * the writer sends it (ooih stamps agent/turn lines from the same variable\n    as the usage report) — a malformed value is NULLED, never refused;\n  * for a ``kind='user'`` line that carries none, it is INFERRED from the turn\n    around it (:func:`_task_ref_for_user_message`), because a user message is\n    not a turn and so has nothing to be stamped from at the source.\n\nA dedup collision upgrades a NULL ref to a real one; it never overwrites.","operationId":"record_message_api_gate_messages_record_post","parameters":[{"name":"X-API-Key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RecordMessageRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/gate/messages/{message_id}":{"patch":{"tags":["gate"],"summary":"Edit Message","description":"Edit a mirrored message's text in place (ephemeral sub-agent status line —\nbot/subagent_status). Workspace-scoped: only rows in the caller's workspace are\ntouched, so the gate key can never edit another tenant's message. The web\nTG-mirror view is a full-replace poll, so the UPDATE shows live. Best-effort:\na missing/foreign id returns ok with updated=0 rather than an error.","operationId":"edit_message_api_gate_messages__message_id__patch","parameters":[{"name":"message_id","in":"path","required":true,"schema":{"type":"integer","title":"Message Id"}},{"name":"X-API-Key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MessageEditRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["gate"],"summary":"Delete Message","description":"Delete a mirrored message so it disappears from the web view (ephemeral\nstatus cleanup on finish — bot/subagent_status). Workspace-scoped like the\nedit above. Best-effort: a missing/foreign id returns ok with deleted=0.","operationId":"delete_message_api_gate_messages__message_id__delete","parameters":[{"name":"message_id","in":"path","required":true,"schema":{"type":"integer","title":"Message Id"}},{"name":"X-API-Key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/gate/messages/read":{"post":{"tags":["gate"],"summary":"Read Messages","description":"Recent unified messages for a space (TG + web, one table). The single\nread path for the orch/sub-agent read_messages tool + the web read-only view.","operationId":"read_messages_api_gate_messages_read_post","parameters":[{"name":"X-API-Key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReadMessagesRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/gate/messages/count":{"post":{"tags":["gate"],"summary":"Count Messages","description":"Cheap cursor count for the `chat_new_messages` conditional trigger (bot-side\ntick; messages live only in Postgres). Returns {n, max_id, newest_text} — a\nbounded COUNT/MAX, no rows, no inference.","operationId":"count_messages_api_gate_messages_count_post","parameters":[{"name":"X-API-Key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CountMessagesRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/gate/spaces/{slug}/subagent-journal":{"post":{"tags":["gate"],"summary":"Post Subagent Journal","description":"Append sub-agent lifecycle events for ONE space to the journal (≤500 per\npost), idempotent per `dedup_key`. Accepts either a bare list of events or a\n`{\"events\": [...]}` envelope (see :class:`SubagentJournalBatchIn`). The ooih\nreporter posts here so the status page's Sub-agent journal is fed from real\nevents; the space is named in the path and stamped on every row. Auth is the\nworkspace gate key, exactly like the sibling `/agents/snapshot` and\n`/agents/journal` writers.","operationId":"post_subagent_journal_api_gate_spaces__slug__subagent_journal_post","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","title":"Slug"}},{"name":"X-API-Key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubagentJournalBatchIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/gate/container/event":{"post":{"tags":["gate"],"summary":"Container Event","description":"Record a container lifecycle event (start/stop/evict/exec_failed).","operationId":"container_event_api_gate_container_event_post","parameters":[{"name":"X-API-Key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Payload"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/gate/users/ensure":{"post":{"tags":["gate"],"summary":"Ensure User","description":"Upsert a user and ensure workspace membership.\n\nReplaces direct DB upsert_user + add_board_member for remote bots.","operationId":"ensure_user_api_gate_users_ensure_post","parameters":[{"name":"X-API-Key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnsureUserRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/gate/users/set-role":{"post":{"tags":["gate"],"summary":"Set User Role","description":"Set a user's role. Only admin/manager callers may use this.","operationId":"set_user_role_api_gate_users_set_role_post","parameters":[{"name":"X-API-Key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetRoleRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/gate/workspaces/{workspace_id}/spaces/{slug}/members/grant":{"post":{"tags":["gate"],"summary":"Grant Scoped Space Member","description":"Explicitly grant a registered user to one API-key-scoped Telegram space.","operationId":"grant_scoped_space_member_api_gate_workspaces__workspace_id__spaces__slug__members_grant_post","parameters":[{"name":"workspace_id","in":"path","required":true,"schema":{"type":"string","title":"Workspace Id"}},{"name":"slug","in":"path","required":true,"schema":{"type":"string","title":"Slug"}},{"name":"X-API-Key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GrantScopedSpaceMemberRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/gate/users/grant-chat":{"post":{"tags":["gate"],"summary":"Grant Chat","description":"Grant a user access to a chat_key.","operationId":"grant_chat_api_gate_users_grant_chat_post","parameters":[{"name":"X-API-Key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GrantChatRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/gate/users/revoke-chat":{"post":{"tags":["gate"],"summary":"Revoke Chat","description":"Revoke a user's access to a chat_key.","operationId":"revoke_chat_api_gate_users_revoke_chat_post","parameters":[{"name":"X-API-Key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RevokeChatRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/gate/members/{chat_id}":{"get":{"tags":["gate"],"summary":"List Members","description":"List active members of a board by Telegram chat_id.","operationId":"list_members_api_gate_members__chat_id__get","parameters":[{"name":"chat_id","in":"path","required":true,"schema":{"type":"integer","title":"Chat Id"}},{"name":"X-API-Key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/gate/members/track":{"post":{"tags":["gate"],"summary":"Track Member","description":"Track member join/leave events for a board.","operationId":"track_member_api_gate_members_track_post","parameters":[{"name":"X-API-Key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TrackMemberRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/gate/members/sync":{"post":{"tags":["gate"],"summary":"Sync Members","description":"Bulk sync members for a board (used during /authorize).","operationId":"sync_members_api_gate_members_sync_post","parameters":[{"name":"X-API-Key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SyncMembersRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/gate/invites/consume":{"post":{"tags":["gate"],"summary":"Consume Invite","description":"Validate and consume an invite link: add user to team, create subscription.","operationId":"consume_invite_api_gate_invites_consume_post","parameters":[{"name":"X-API-Key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConsumeInviteRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/gate/workspaces/{workspace_id}":{"put":{"tags":["gate"],"summary":"Update Workspace","description":"Suspend/activate a workspace.","operationId":"update_workspace_api_gate_workspaces__workspace_id__put","parameters":[{"name":"workspace_id","in":"path","required":true,"schema":{"type":"string","title":"Workspace Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/gate/calendars/authorize":{"post":{"tags":["gate"],"summary":"Calendar Authorize","description":"Decide whether a turn's user may act on a calendar.\n\ndecision: owner (theirs) | claimable (unowned — allow, claim after a\nsuccessful read) | denied (another user's) | no_user (unknown telegram_id).\nThe executor fails closed: anything but owner/claimable is refused.","operationId":"calendar_authorize_api_gate_calendars_authorize_post","parameters":[{"name":"X-API-Key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CalendarAuthorizeRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/gate/calendars/claim":{"post":{"tags":["gate"],"summary":"Calendar Claim","description":"Record ownership after a first successful read. Idempotent + race-safe:\nconcurrent claims collapse to one winner via the calendar_id UNIQUE.","operationId":"calendar_claim_api_gate_calendars_claim_post","parameters":[{"name":"X-API-Key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CalendarClaimRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/gate/calendars/release":{"post":{"tags":["gate"],"summary":"Calendar Release","description":"Host/admin recovery: free a calendar (delete the row) or reassign it.\n\nOnly callable with the workspace gate key — never reachable from a turn,\nso the model can't release or reassign anything.","operationId":"calendar_release_api_gate_calendars_release_post","parameters":[{"name":"X-API-Key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CalendarReleaseRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/gate/integrations/google/token":{"post":{"tags":["gate"],"summary":"Gate Google Token","description":"Mint a fresh Google access_token for a workspace user.\n\nBots never see refresh tokens. They call this endpoint each time they\nneed to act on the user's behalf — we look up the encrypted refresh\ntoken, exchange it at Google, and hand back a short-lived access token.","operationId":"gate_google_token_api_gate_integrations_google_token_post","parameters":[{"name":"X-API-Key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GateGoogleTokenRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/gate/referrals/attribute":{"post":{"tags":["gate"],"summary":"Gate Attribute Referral","description":"Bot calls this on /start ref_XXX.\n\nIdempotent: already-referred / self / invalid all return 200 with bound=false\nand a reason, so the bot can show the right onboarding message without\ntreating attribution failure as an error.","operationId":"gate_attribute_referral_api_gate_referrals_attribute_post","parameters":[{"name":"X-API-Key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GateAttributeRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/gate/identities/bind":{"post":{"tags":["gate"],"summary":"Bind Telegram Identity","description":"Resolve a bind token against a verified telegram_id.\n\nOutcomes (all 200 so the bot can message the user appropriately):\n  linked          — telegram was free, attached to the web account\n  already_linked  — this telegram already opens this very account\n  merge_required  — telegram belongs to ANOTHER account; a pending-merge\n                    record is created and the web UI takes over with an\n                    explicit preview+confirm (destructive action gate).","operationId":"bind_telegram_identity_api_gate_identities_bind_post","parameters":[{"name":"X-API-Key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BindTelegramRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/gate/turns/{turn_id}/files":{"post":{"tags":["gate"],"summary":"Gate Register Turn File","description":"Register an agent-produced output file (e.g. a generated/edited image) on a\nturn so the web chat can render + download it. Stored in the file store;\nsurfaced by GET /api/chat/turns/{turn_id}/files and GET /api/chat/files/{id}.","operationId":"gate_register_turn_file_api_gate_turns__turn_id__files_post","parameters":[{"name":"turn_id","in":"path","required":true,"schema":{"type":"string","title":"Turn Id"}},{"name":"X-API-Key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TurnFileRegisterRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/gate/stars/checkout/verify":{"post":{"tags":["gate"],"summary":"Stars Checkout Verify","operationId":"stars_checkout_verify_api_gate_stars_checkout_verify_post","parameters":[{"name":"X-API-Key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StarsCheckoutVerifyRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/gate/stars/packages":{"get":{"tags":["gate"],"summary":"Stars Packages","description":"Active credit packages priced in Stars (XTR) for the bot's invoice menu.","operationId":"stars_packages_api_gate_stars_packages_get","parameters":[{"name":"X-API-Key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/gate/stars/record":{"post":{"tags":["gate"],"summary":"Stars Record","description":"Record a completed Stars payment (idempotent on the charge id).","operationId":"stars_record_api_gate_stars_record_post","parameters":[{"name":"X-API-Key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StarsRecordRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/gate/tg-login/bind":{"post":{"tags":["gate"],"summary":"Tg Login Bind","description":"The bot confirms a web→Telegram login: bind the pending token to the telegram\nuser (resolve/create the account). The web's /api/auth/tg-login/status then issues\nthe session. Gate-authed (X-API-Key) so only the bot can confirm.","operationId":"tg_login_bind_api_gate_tg_login_bind_post","parameters":[{"name":"X-API-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TgLoginBind"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/gate/api-keys/issue":{"post":{"tags":["gate"],"summary":"Gate Api Key Issue","description":"Bot-only: mint an owner-review pointer for a SPACE-scoped public API key.\n\nReturns a `token` the orchestrator turns into the owner-review link (Mini App\n`apikey-<token>` deep link, or the web `/api-keys/<token>` page). No key exists\nyet — the review page mints it only after verifying the opener is the space\nowner. Mirrors /keys/mint: gate-key authenticated, 24h TTL, never returns a key.","operationId":"gate_api_key_issue_api_gate_api_keys_issue_post","parameters":[{"name":"X-API-Key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiKeyIssueReq"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/gate/keys/mint-web":{"post":{"tags":["gate"],"summary":"Gate Keys Mint Web","description":"Mint a browser-native, account-less secret-submission capability.\n\nUnlike /keys/mint (a reuse-safe Telegram Mini App pointer authed by the app\nsession), this returns a plain https link that opens in ANY browser and lets a\nweb/Bitrix/non-registered user add secrets with no Octomatica account. The token\nis single-use, short-TTL (15m), and write-only by construction; it is redeemed at\nPOST /api/space-secrets/cap/{token}. Returns both the raw token and the full URL.","operationId":"gate_keys_mint_web_api_gate_keys_mint_web_post","parameters":[{"name":"X-API-Key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/KeysMintWebReq"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/gate/keys/mint":{"post":{"tags":["gate"],"summary":"Gate Keys Mint","operationId":"gate_keys_mint_api_gate_keys_mint_post","parameters":[{"name":"X-API-Key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/KeysMintReq"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/gate/keys/pending":{"get":{"tags":["gate"],"summary":"Gate Keys Pending","operationId":"gate_keys_pending_api_gate_keys_pending_get","parameters":[{"name":"X-API-Key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/gate/keys/pending/ack":{"post":{"tags":["gate"],"summary":"Gate Keys Ack","operationId":"gate_keys_ack_api_gate_keys_pending_ack_post","parameters":[{"name":"X-API-Key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/KeysAckReq"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/gate/keys/values/{slug}":{"get":{"tags":["gate"],"summary":"Gate Keys Values","description":"Bot-only: decrypt all of a space's secrets to materialize into .env.","operationId":"gate_keys_values_api_gate_keys_values__slug__get","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","title":"Slug"}},{"name":"X-API-Key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/gate/keys/space/{slug}":{"get":{"tags":["gate"],"summary":"Gate Keys Space","description":"Authoritative, workspace-independent per-slug identity for the keys drain.\n\nThe drain resolves a key event's canonical Telegram chat here so it can (a)\nfail closed when the event's chat contradicts the space's real chat and (b)\nrecognise a legitimately chatless space (web/API origin) — one it should still\nmaterialize by slug, with no chat to confirm to. This is deliberately NOT\nworkspace-scoped: key events drain globally, whereas /gate/spaces filters by\nworkspace and omits workspace_id=NULL (web/API) spaces, so scanning that list\nmade every chatless space look \"absent or ambiguous\" and its secret was\nsilently dropped. Still gate-key authenticated; never returns secret material.","operationId":"gate_keys_space_api_gate_keys_space__slug__get","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","title":"Slug"}},{"name":"X-API-Key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/gate/telegram/connect/mint":{"post":{"tags":["gate"],"summary":"Gate Tg Connect Mint","operationId":"gate_tg_connect_mint_api_gate_telegram_connect_mint_post","parameters":[{"name":"X-API-Key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TgConnectMintReq"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/gate/telegram/connect/pending":{"get":{"tags":["gate"],"summary":"Gate Tg Connect Pending","operationId":"gate_tg_connect_pending_api_gate_telegram_connect_pending_get","parameters":[{"name":"X-API-Key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/gate/telegram/connect/result":{"post":{"tags":["gate"],"summary":"Gate Tg Connect Result","operationId":"gate_tg_connect_result_api_gate_telegram_connect_result_post","parameters":[{"name":"X-API-Key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TgConnectResultReq"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/gate/tg/session":{"get":{"tags":["gate"],"summary":"Gate Tg Session","description":"Bot-only: vend the plaintext StringSession for one account of a space.\n\n`account` is an id, a phone, or 'default' (omitted → the space default). The\nsession is decrypted here and returned only over this gate-authed channel;\nit is never logged. A backfilled/legacy row with no session yet returns\n`session: null` so the daemon knows it must (re)provision.","operationId":"gate_tg_session_api_gate_tg_session_get","parameters":[{"name":"space","in":"query","required":true,"schema":{"type":"string","title":"Space"}},{"name":"account","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Account"}},{"name":"X-API-Key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/gate/spaces/{slug}/tg-accounts":{"get":{"tags":["gate"],"summary":"Gate Tg Accounts List","description":"Bot-only: list a space's active Telegram accounts (no secrets).","operationId":"gate_tg_accounts_list_api_gate_spaces__slug__tg_accounts_get","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","title":"Slug"}},{"name":"X-API-Key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/gate/spaces/{slug}/tg-accounts/{account_id}/default":{"post":{"tags":["gate"],"summary":"Gate Tg Account Default","description":"Bot-only: make one account the space default.","operationId":"gate_tg_account_default_api_gate_spaces__slug__tg_accounts__account_id__default_post","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","title":"Slug"}},{"name":"account_id","in":"path","required":true,"schema":{"type":"string","title":"Account Id"}},{"name":"X-API-Key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/gate/spaces/{slug}/tg-accounts/{account_id}/revoke":{"post":{"tags":["gate"],"summary":"Gate Tg Account Revoke","description":"Bot-only: revoke an account — wipe its session and drop it from default.","operationId":"gate_tg_account_revoke_api_gate_spaces__slug__tg_accounts__account_id__revoke_post","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","title":"Slug"}},{"name":"account_id","in":"path","required":true,"schema":{"type":"string","title":"Account Id"}},{"name":"X-API-Key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/gate/spaces/{slug}/integrations":{"get":{"tags":["gate"],"summary":"Gate Space Integrations","description":"Bot-facing integration state + connect links for one space.\n\nThe orchestrator reads this to tell the user, in-chat, what is wired and to\nsurface a connect link it can send:\n  - telegram: `connected` once provisioning reaches `active`; `connect_link`\n    is the live in-progress Mini-App link (call POST /telegram/connect/mint\n    for a fresh one).\n  - google_calendar: the owner's per-user Google grant (with the calendar\n    scope). `connect_link` points at the web /integrations/google page — the OAuth\n    start is session-authed, so the user must open it themselves.\nMirrors the /api/gate/github/space/{slug} + /connect-link shape.","operationId":"gate_space_integrations_api_gate_spaces__slug__integrations_get","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","title":"Slug"}},{"name":"X-API-Key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/gate/support/outbound":{"get":{"tags":["gate"],"summary":"Support Outbound","description":"Undelivered reply turns (admin + space), joined with the ticket origin so\nthe watcher can route each to its chat. Oldest first.","operationId":"support_outbound_api_gate_support_outbound_get","parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","default":50,"title":"Limit"}},{"name":"X-API-Key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/gate/support/outbound/{msg_id}/delivered":{"post":{"tags":["gate"],"summary":"Support Outbound Delivered","description":"Mark one reply turn delivered to its origin chat.","operationId":"support_outbound_delivered_api_gate_support_outbound__msg_id__delivered_post","parameters":[{"name":"msg_id","in":"path","required":true,"schema":{"type":"integer","title":"Msg Id"}},{"name":"X-API-Key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/gate/support/reply":{"post":{"tags":["gate"],"summary":"Support Reply","description":"Author a reply turn from ooih (the identity-aware ``reply_support`` orch\ntool): admin replies from an admin space, or space replies carrying another\nspace's identity. Inserted undelivered so the watcher relays it home.","operationId":"support_reply_api_gate_support_reply_post","parameters":[{"name":"X-API-Key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SupportReplyIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/gate/provider-quota-snapshots":{"post":{"tags":["gate"],"summary":"Provider Quota Snapshots","description":"Append one quota reading per pool member per healthcheck tick (task #49\ncapacity-graph history). Called by ooih's `tools/codex_healthcheck.py` and\n`tools/claude_quota_healthcheck.py` — see ProviderQuotaSnapshot's docstring\nin models.py for why this is fleet-wide (no workspace scoping beyond the\nshared gate key) and append-only (never updates a prior row).","operationId":"provider_quota_snapshots_api_gate_provider_quota_snapshots_post","parameters":[{"name":"X-API-Key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProviderQuotaSnapshotsIn"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/gate/yandex-disk/connect-link":{"post":{"tags":["gate"],"summary":"Gate Disk Connect Link","description":"Mint a one-time link the space's OWNER can click to connect their Disk —\nalready attached to this space when they come back.\n\nThis is what lets the bot say \"connect your Disk here\" in chat instead of\n\"go to the dashboard, find Integrations, connect, then find this space in the\nlist\". The mechanism is the one that already existed: an `oauth_states` row\nis the only carrier of WHICH SPACE the flow is for, and the URL carries an\nopaque ticket and nothing else — no user id, no space slug on the query\nstring, matching the rule the OAuth flow itself follows.\n\nWhat this endpoint does NOT do is grant anything. It records an intent for\nthe space's owner, and every gate below it is checked later:\n\n  * the ticket is minted for the space's OWNER, not for whoever asked in\n    chat — a member cannot cause somebody else's Disk to be connected;\n  * `/start` refuses the ticket unless the AUTHENTICATED caller is that\n    owner, so forwarding the link to someone else gains them nothing;\n  * the callback re-verifies ownership of the named space a second time\n    before attaching, because a URL can be edited in transit;\n  * it expires in 15 minutes and is deleted the first time it is spent.\n\nThe resulting connection is an ORDINARY connection: it appears in the\nowner's connected-disks list like any other, and it simply arrives with this\nspace already attached (marked `auto`, so the card can show which links the\nowner did not make by hand).","operationId":"gate_disk_connect_link_api_gate_yandex_disk_connect_link_post","parameters":[{"name":"X-API-Key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/_DiskLinkOp"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/gate/yandex-disk/status":{"get":{"tags":["gate"],"summary":"Gate Disk Status","description":"Is a Disk attached to this space, and how much of it may the space use?\n\nNo token, ever. `full_access: true` is what the agent should act on: there is\nno folder to stay inside, so a path is just a path on the owner's Disk.","operationId":"gate_disk_status_api_gate_yandex_disk_status_get","parameters":[{"name":"slug","in":"query","required":true,"schema":{"type":"string","title":"Slug"}},{"name":"X-API-Key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/gate/yandex-disk/list":{"post":{"tags":["gate"],"summary":"Gate Disk List","description":"List a directory, anywhere on the attached Disk (`\"\"` = the Disk root).","operationId":"gate_disk_list_api_gate_yandex_disk_list_post","parameters":[{"name":"X-API-Key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/_DiskListOp"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/gate/yandex-disk/stat":{"post":{"tags":["gate"],"summary":"Gate Disk Stat","description":"Metadata for one file/folder.","operationId":"gate_disk_stat_api_gate_yandex_disk_stat_post","parameters":[{"name":"X-API-Key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/_DiskOp"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/gate/yandex-disk/mkdir":{"post":{"tags":["gate"],"summary":"Gate Disk Mkdir","description":"Create a folder on the Disk (idempotent; missing parents are created).","operationId":"gate_disk_mkdir_api_gate_yandex_disk_mkdir_post","parameters":[{"name":"X-API-Key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/_DiskOp"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/gate/yandex-disk/upload":{"post":{"tags":["gate"],"summary":"Gate Disk Upload","description":"Write bytes to the Disk — also the \"write the result\" half of\nprocess-a-file-and-write-a-result (download → the bot transforms → upload).\nMissing parent folders are created.","operationId":"gate_disk_upload_api_gate_yandex_disk_upload_post","parameters":[{"name":"X-API-Key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/_DiskUploadOp"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/gate/yandex-disk/download":{"post":{"tags":["gate"],"summary":"Gate Disk Download","description":"Read a file's bytes. The provider's pre-signed download URL is used inside\nthe service and never logged or returned — the caller gets the content.","operationId":"gate_disk_download_api_gate_yandex_disk_download_post","parameters":[{"name":"X-API-Key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/_DiskOp"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/gate/yandex-disk/move":{"post":{"tags":["gate"],"summary":"Gate Disk Move","description":"Move on the Disk. BOTH ends go through the path validator.","operationId":"gate_disk_move_api_gate_yandex_disk_move_post","parameters":[{"name":"X-API-Key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/_DiskMoveOp"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/gate/yandex-disk/delete":{"post":{"tags":["gate"],"summary":"Gate Disk Delete","description":"Delete on the Disk (to the Disk trash, not permanently). The Disk root\nitself is refused — \"delete everything\" is never what a caller typed.","operationId":"gate_disk_delete_api_gate_yandex_disk_delete_post","parameters":[{"name":"X-API-Key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/_DiskOp"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/gate/yandex-disk/publish":{"post":{"tags":["gate"],"summary":"Gate Disk Publish","description":"Publish a file the attached Disk holds, and answer with the public link.\n\nThis is the operation the agent had no way to perform: it could upload a\nresult and then only name an internal `disk:/...` path, which nobody outside\nthe Disk can open. The grant it needs is `cloud_api:disk.write`, which every\nconnection here already holds, so this was a missing code path rather than a\nmissing permission.\n\nAuthorization is identical to every other Disk operation above: the slug\nresolves to the attachment (`_disk_client`), an unattached, archived or\ndeleted space gets 404, and the path goes through the ONE validator. That\nmatters more here than anywhere else, because this is the only Disk\noperation whose result is reachable by anyone holding a URL.\n\nThe link is returned in the same response as the publish, so the agent can\nsay it in chat without a second call.","operationId":"gate_disk_publish_api_gate_yandex_disk_publish_post","parameters":[{"name":"X-API-Key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/_DiskOp"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/gate/yandex-disk/unpublish":{"post":{"tags":["gate"],"summary":"Gate Disk Unpublish","description":"Withdraw a published link. Same attachment and same validator as publish.\n\nSharing that cannot be taken back is not sharing anyone would choose, so\nthis ships with `publish` rather than after it.","operationId":"gate_disk_unpublish_api_gate_yandex_disk_unpublish_post","parameters":[{"name":"X-API-Key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/_DiskOp"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/gate/yandex-disk/public/stat":{"post":{"tags":["gate"],"summary":"Gate Disk Public Stat","description":"Metadata for a shared link (and, for a shared folder, its listing).\n\nDeliberately does NOT require an attached Disk: there is no Disk involved.","operationId":"gate_disk_public_stat_api_gate_yandex_disk_public_stat_post","parameters":[{"name":"X-API-Key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/_PublicListOp"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/gate/yandex-disk/public/download":{"post":{"tags":["gate"],"summary":"Gate Disk Public Download","description":"Read the bytes behind a shared link. No token is sent to Yandex.","operationId":"gate_disk_public_download_api_gate_yandex_disk_public_download_post","parameters":[{"name":"X-API-Key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/_PublicOp"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/gate/yandex-disk/public/save":{"post":{"tags":["gate"],"summary":"Gate Disk Public Save","description":"Copy a shared resource onto the attached Disk, to work on a copy.\n\nThis one DOES need the Disk (it writes), and the destination goes through the\nsame validator as every other write.","operationId":"gate_disk_public_save_api_gate_yandex_disk_public_save_post","parameters":[{"name":"X-API-Key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/_PublicSaveOp"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/manager/team":{"get":{"tags":["manager"],"summary":"My Team","operationId":"my_team_api_manager_team_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}},"patch":{"tags":["manager"],"summary":"Update Team Settings","description":"Update team-level settings. Today only `dm_allowed` is exposed —\nthe manager toggles whether team members can DM the bot directly\n(cost still goes to the team's billing). When false, new joiners\nvia this team's invite land with users.dm_allowed=false.","operationId":"update_team_settings_api_manager_team_patch","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TeamSettingsUpdate"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/manager/team/members":{"get":{"tags":["manager"],"summary":"Team Members","operationId":"team_members_api_manager_team_members_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/manager/team/invites":{"get":{"tags":["manager"],"summary":"List Invites","operationId":"list_invites_api_manager_team_invites_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}},"post":{"tags":["manager"],"summary":"Create Invite","operationId":"create_invite_api_manager_team_invites_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InviteCreate"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/manager/team/invites/{invite_id}":{"delete":{"tags":["manager"],"summary":"Revoke Invite","operationId":"revoke_invite_api_manager_team_invites__invite_id__delete","parameters":[{"name":"invite_id","in":"path","required":true,"schema":{"type":"integer","title":"Invite Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/billing/plans":{"get":{"tags":["billing"],"summary":"List Plans","operationId":"list_plans_api_billing_plans_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/billing/me":{"get":{"tags":["billing"],"summary":"Billing Me","operationId":"billing_me_api_billing_me_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/billing/payments":{"get":{"tags":["billing"],"summary":"List My Payments","operationId":"list_my_payments_api_billing_payments_get","parameters":[{"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"}}}}}}},"/api/billing/transactions":{"get":{"tags":["billing"],"summary":"List My Transactions","description":"Combined deposit + debit ledger for the current user — what the\n/billing \"Recent activity\" panel renders.","operationId":"list_my_transactions_api_billing_transactions_get","parameters":[{"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"}}}}}}},"/api/billing/apply-promo":{"post":{"tags":["billing"],"summary":"Apply Promo","description":"Validate a promo code and surface the discount.\n\nNo side effects -- binding happens when the user actually calls /renew\nwith the promo_code field set. This avoids spurious attribution from\nabandoned checkouts.","operationId":"apply_promo_api_billing_apply_promo_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApplyPromoRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/billing/renew":{"post":{"tags":["billing"],"summary":"Renew Subscription","description":"Explicit user-initiated renewal: spend balance to extend the Pro sub.\n\nOptional `promo_code` binds an influencer referral before the extension\nruns, so the payout hook activates the referral on the first paid sub.","operationId":"renew_subscription_api_billing_renew_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RenewRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/billing/yookassa/shop-mode":{"get":{"tags":["billing"],"summary":"Yookassa Shop Mode","description":"Admin-only: report whether the configured YooKassa credentials are TEST\nor LIVE (and whether fiscalization is enabled) WITHOUT exposing any secret.\n\nBacks the production go-live check: `test` must be False before real\ncharges are accepted. Never returns the shop_id or secret key.","operationId":"yookassa_shop_mode_api_billing_yookassa_shop_mode_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/billing/topup-quote":{"get":{"tags":["billing"],"summary":"Topup Quote","description":"Server-authoritative price + delivered energy for a slider amount. The\nlinear bulk bonus lands as extra credits (bonus-energy model).\n\nCurrency is brand-aware (see app.brand): Octomatica prices in RUB\n(`price_rub`), Octodus in USD (`price_usd`) at 1 USD = credit_per_usd energy.\nBoth are always present — `currency` says which one the caller's brand uses.\nThe delivered energy is identical either way; only the money side differs.","operationId":"topup_quote_api_billing_topup_quote_get","parameters":[{"name":"energy","in":"query","required":true,"schema":{"type":"integer","title":"Energy"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/billing/credit-packages":{"get":{"tags":["billing"],"summary":"List Credit Packages","description":"List active credit packages with computed credit amounts at current rates.","operationId":"list_credit_packages_api_billing_credit_packages_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/billing/stars-invoice-link":{"post":{"tags":["billing"],"summary":"Stars Invoice Link","description":"Mint a Telegram Stars (XTR) invoice link for a credit package.\n\nThe mini app opens the link with Telegram.WebApp.openInvoice(), so the\nNATIVE Stars payment sheet shows over the app — no chat interaction. The\nbot answers pre_checkout and records the charge at /api/gate/stars/record\n(binding the payer to the checkout owner, idempotent on charge id).","operationId":"stars_invoice_link_api_billing_stars_invoice_link_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StarsInvoiceRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/billing/purchase-credits":{"post":{"tags":["billing"],"summary":"Purchase Credits","description":"Initiate a credit package purchase via YooKassa.\n\nIf `pool_id` is set on the request, the caller must be owner/manager of\nthat pool — the credits land in the pool's balance instead of the\nbuyer's personal balance. Pool routing flows through Yookassa metadata\nso the webhook stays the single source of truth.","operationId":"purchase_credits_api_billing_purchase_credits_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreditPurchaseRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/billing/profile":{"get":{"tags":["checkout"],"summary":"Get Profile","operationId":"get_profile_api_billing_profile_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}},"put":{"tags":["checkout"],"summary":"Put Profile","operationId":"put_profile_api_billing_profile_put","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BillingProfileInput"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/billing/checkout-config":{"get":{"tags":["checkout"],"summary":"Get Checkout Config","operationId":"get_checkout_config_api_billing_checkout_config_get","parameters":[{"name":"route","in":"query","required":true,"schema":{"enum":["yookassa","tochka","stars","paykit","handoff","private-offer","renew","bank-invoice"],"type":"string","title":"Route"}},{"name":"locale","in":"query","required":false,"schema":{"enum":["ru","en","de"],"type":"string","default":"en","title":"Locale"}},{"name":"provider_slug","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Provider Slug"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/billing/bank-invoices":{"get":{"tags":["bank-invoices"],"summary":"List Invoices","operationId":"list_invoices_api_billing_bank_invoices_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}},"post":{"tags":["bank-invoices"],"summary":"Create Invoice","operationId":"create_invoice_api_billing_bank_invoices_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InvoiceInput"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/billing/bank-invoices/{invoice_id}":{"get":{"tags":["bank-invoices"],"summary":"Detail","operationId":"detail_api_billing_bank_invoices__invoice_id__get","parameters":[{"name":"invoice_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Invoice Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/billing/bank-invoices/{invoice_id}/pdf":{"get":{"tags":["bank-invoices"],"summary":"Pdf","operationId":"pdf_api_billing_bank_invoices__invoice_id__pdf_get","parameters":[{"name":"invoice_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Invoice Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/admin/bank-invoices":{"get":{"tags":["bank-invoices-admin"],"summary":"Admin List","operationId":"admin_list_api_admin_bank_invoices_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/admin/bank-invoices/{invoice_id}":{"get":{"tags":["bank-invoices-admin"],"summary":"Admin Detail","operationId":"admin_detail_api_admin_bank_invoices__invoice_id__get","parameters":[{"name":"invoice_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Invoice Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/admin/bank-invoices/{invoice_id}/pdf":{"get":{"tags":["bank-invoices-admin"],"summary":"Admin Pdf","operationId":"admin_pdf_api_admin_bank_invoices__invoice_id__pdf_get","parameters":[{"name":"invoice_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Invoice Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/admin/bank-invoices/{invoice_id}/receipts":{"post":{"tags":["bank-invoices-admin"],"summary":"Record Receipt","operationId":"record_receipt_api_admin_bank_invoices__invoice_id__receipts_post","parameters":[{"name":"invoice_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Invoice Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReceiptInput"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/checkout-legal/{version}":{"get":{"tags":["legal"],"summary":"Public Legal Document","operationId":"public_legal_document_api_checkout_legal__version__get","parameters":[{"name":"version","in":"path","required":true,"schema":{"type":"string","title":"Version"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/payment-providers":{"get":{"tags":["billing"],"summary":"List Payment Providers","operationId":"list_payment_providers_api_payment_providers_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/payments/handoff":{"post":{"tags":["billing"],"summary":"Payments Handoff","operationId":"payments_handoff_api_payments_handoff_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HandoffRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/billing/webhooks/yookassa":{"post":{"tags":["webhooks"],"summary":"Yookassa Webhook","description":"Receive payment + refund notifications from YooKassa.\n\nYooKassa POSTs `{type:\"notification\", event:\"<event>\", object:{...}}`.\nWe validate by re-fetching the underlying resource with our credentials\n(more reliable than IP whitelist and self-healing if YooKassa rotates\nIPs), then update the ledger.\n\nEvents handled:\n  - payment.succeeded  → credit user.balance with USD cents from metadata\n  - refund.succeeded   → debit user.balance proportionally; idempotent on\n                         refund.id (distinct from the credit's payment.id)\n\nAlways 200 on intentional skips (wrong event / replay / status mismatch)\nso YooKassa doesn't retry for 24h on cases we can't action.","operationId":"yookassa_webhook_api_billing_webhooks_yookassa_post","requestBody":{"content":{"application/json":{"schema":{"additionalProperties":true,"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"}}}}}}},"/api/admin/billing/users/{user_id}/credits":{"post":{"tags":["admin-billing"],"summary":"Adjust Credits","operationId":"adjust_credits_api_admin_billing_users__user_id__credits_post","parameters":[{"name":"user_id","in":"path","required":true,"schema":{"type":"integer","title":"User Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreditAdjustment"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/admin/billing/users/{user_id}/adjust-credits":{"post":{"tags":["admin-billing"],"summary":"Adjust Credit Micros","operationId":"adjust_credit_micros_api_admin_billing_users__user_id__adjust_credits_post","parameters":[{"name":"user_id","in":"path","required":true,"schema":{"type":"integer","title":"User Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreditMicrosAdjustment"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/admin/billing/test/state":{"get":{"tags":["admin-billing"],"summary":"Test State","description":"DEBUG-ONLY: high-level config snapshot for the /billing-test page.","operationId":"test_state_api_admin_billing_test_state_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/admin/billing/test/set-plan-price":{"post":{"tags":["admin-billing"],"summary":"Test Set Plan Price","description":"DEBUG-ONLY: flip the Pro plan price between $1 (testing) and $60 (prod).","operationId":"test_set_plan_price_api_admin_billing_test_set_plan_price_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TestSetPlanPrice"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/admin/billing/test/reset-balance/{user_id}":{"post":{"tags":["admin-billing"],"summary":"Test Reset Balance","description":"DEBUG-ONLY: zero out a user's balance via a ledger entry. Subs/payments untouched.","operationId":"test_reset_balance_api_admin_billing_test_reset_balance__user_id__post","parameters":[{"name":"user_id","in":"path","required":true,"schema":{"type":"integer","title":"User Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/admin/billing/payment-providers":{"get":{"tags":["admin-billing"],"summary":"Admin List Providers","operationId":"admin_list_providers_api_admin_billing_payment_providers_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}},"post":{"tags":["admin-billing"],"summary":"Admin Create Provider","operationId":"admin_create_provider_api_admin_billing_payment_providers_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProviderUpsertRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/admin/billing/payment-providers/{provider_id}":{"put":{"tags":["admin-billing"],"summary":"Admin Update Provider","operationId":"admin_update_provider_api_admin_billing_payment_providers__provider_id__put","parameters":[{"name":"provider_id","in":"path","required":true,"schema":{"type":"integer","title":"Provider Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProviderUpsertRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/admin/billing/transactions":{"get":{"tags":["admin-billing"],"summary":"Admin List Transactions","operationId":"admin_list_transactions_api_admin_billing_transactions_get","parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":200,"default":50,"title":"Limit"}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0,"default":0,"title":"Offset"}},{"name":"user_id","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"User Id"}},{"name":"q","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"search by user name/username","title":"Q"},"description":"search by user name/username"},{"name":"reason","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Reason"}},{"name":"date_from","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"ISO date (YYYY-MM-DD)","title":"Date From"},"description":"ISO date (YYYY-MM-DD)"},{"name":"date_to","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"ISO date (YYYY-MM-DD)","title":"Date To"},"description":"ISO date (YYYY-MM-DD)"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/admin/billing/octodus-invoices/{invoice_id}/resend":{"post":{"tags":["admin-billing"],"summary":"Admin Resend Octodus Invoice","description":"Email the stored invoice again now (same number and data).","operationId":"admin_resend_octodus_invoice_api_admin_billing_octodus_invoices__invoice_id__resend_post","parameters":[{"name":"invoice_id","in":"path","required":true,"schema":{"type":"string","title":"Invoice Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/admin/billing/octodus-invoices/{invoice_id}/pdf":{"get":{"tags":["admin-billing"],"summary":"Admin Octodus Invoice Pdf","operationId":"admin_octodus_invoice_pdf_api_admin_billing_octodus_invoices__invoice_id__pdf_get","parameters":[{"name":"invoice_id","in":"path","required":true,"schema":{"type":"string","title":"Invoice Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/admin/billing/transactions/reasons":{"get":{"tags":["admin-billing"],"summary":"Admin List Transaction Reasons","operationId":"admin_list_transaction_reasons_api_admin_billing_transactions_reasons_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/admin/billing/inference-providers":{"get":{"tags":["admin-billing"],"summary":"List Inference Providers","operationId":"list_inference_providers_api_admin_billing_inference_providers_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/admin/billing/inference-providers/{provider_id}":{"patch":{"tags":["admin-billing"],"summary":"Update Inference Provider","operationId":"update_inference_provider_api_admin_billing_inference_providers__provider_id__patch","parameters":[{"name":"provider_id","in":"path","required":true,"schema":{"type":"integer","title":"Provider Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InferenceProviderUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/admin/billing/users/{user_id}/cycle-breakdown":{"get":{"tags":["admin-billing"],"summary":"User Cycle Breakdown","description":"Per-provider raw + billed + overage for the user's current billing cycle.\n\nUsed by the admin UI to show how a user's $60 envelope is being spent.\nReturns an empty breakdown when there's no active subscription / cycle.","operationId":"user_cycle_breakdown_api_admin_billing_users__user_id__cycle_breakdown_get","parameters":[{"name":"user_id","in":"path","required":true,"schema":{"type":"integer","title":"User Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/admin/billing/users/{user_id}/provider-breakdown":{"get":{"tags":["admin-billing"],"summary":"User Provider Breakdown","description":"Lifetime per-provider raw + billed + overage for a user.\n\nCounterpart to /cycle-breakdown but unbounded in time — gives admins a\n\"what was this user actually billed for, ever\" view. Joined against\ninference_providers so a UI label can show whether the slug is still\nregistered (and at what current multiplier — useful for spotting drift\nbetween historically-applied and currently-configured rates).","operationId":"user_provider_breakdown_api_admin_billing_users__user_id__provider_breakdown_get","parameters":[{"name":"user_id","in":"path","required":true,"schema":{"type":"integer","title":"User Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/admin/billing/users/{user_id}/transactions":{"get":{"tags":["admin-billing"],"summary":"User Transactions","description":"Per-user balance ledger — every credit/debit, newest first.\n\nPowers the \"Balance history\" panel on the admin user detail page. Each\nrow is one BalanceTransaction joined to its payment provider (if any)\nand to the admin who created it (for manual adjustments via /credits).\n\nThe `created_by` field lets the UI distinguish:\n  - admin top-up / refund / correction → has created_by, no provider\n  - user self top-up via crypto / yookassa → has provider, no created_by\n  - automatic ledger entry (sub_extend, usage_overage, referral_*) → neither","operationId":"user_transactions_api_admin_billing_users__user_id__transactions_get","parameters":[{"name":"user_id","in":"path","required":true,"schema":{"type":"integer","title":"User Id"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":500,"default":100,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/admin/billing/reconciliation":{"get":{"tags":["admin-billing"],"summary":"Billing Reconciliation","description":"Per-day comparison of money decided vs money moved.\n\nNothing compared those two numbers before, which is why every billing incident\nof 2026-07-31 — leaseless turns charging nothing, web/API spaces running free,\none transcript billed 15 times — was found by hand weeks late.\n\n`findings` is the actionable part: an empty list means the day reconciles.","operationId":"billing_reconciliation_api_admin_billing_reconciliation_get","parameters":[{"name":"days","in":"query","required":false,"schema":{"type":"integer","maximum":60,"minimum":1,"default":7,"title":"Days"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/admin/billing/metrics":{"get":{"tags":["admin-billing"],"summary":"Billing Metrics","description":"Aggregate read-only metrics for the admin billing dashboard.\n\nTreasury balances are fetched live from the crypto provider; if the\nprovider call fails we still return the rest with `treasury.error` set so\nthe page degrades gracefully instead of 500-ing on RPC hiccups.","operationId":"billing_metrics_api_admin_billing_metrics_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/admin/billing/credit-packages":{"get":{"tags":["admin-billing"],"summary":"List Credit Packages","operationId":"list_credit_packages_api_admin_billing_credit_packages_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}},"post":{"tags":["admin-billing"],"summary":"Create Credit Package","operationId":"create_credit_package_api_admin_billing_credit_packages_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PackageCreate"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/admin/billing/credit-packages/{pkg_id}":{"patch":{"tags":["admin-billing"],"summary":"Update Credit Package","operationId":"update_credit_package_api_admin_billing_credit_packages__pkg_id__patch","parameters":[{"name":"pkg_id","in":"path","required":true,"schema":{"type":"integer","title":"Pkg Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PackageUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["admin-billing"],"summary":"Deactivate Credit Package","operationId":"deactivate_credit_package_api_admin_billing_credit_packages__pkg_id__delete","parameters":[{"name":"pkg_id","in":"path","required":true,"schema":{"type":"integer","title":"Pkg Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/internal/credit-balance":{"post":{"tags":["internal"],"summary":"Credit Balance","operationId":"credit_balance_api_internal_credit_balance_post","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreditBalanceRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/billing/paykit/session":{"post":{"tags":["billing"],"summary":"Create Crypto Session","description":"Quote `energy` exactly like the card/Stars rails (same bulk bonus), price\nit in USD at the ledger anchor, open a paykit session with the merchant key\nand remember the token so the webhook can credit the quote.","operationId":"create_crypto_session_api_billing_paykit_session_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CryptoSessionRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/billing/paykit/sessions/latest":{"get":{"tags":["billing"],"summary":"Latest Crypto Session","description":"The return page polls this after the buyer comes back from the pay page:\nthe webhook, not the redirect, is what flips `status` / `credited_micros`.","operationId":"latest_crypto_session_api_billing_paykit_sessions_latest_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/webhooks/paykit":{"post":{"tags":["webhooks"],"summary":"Paykit Webhook","description":"Signed delivery from paykit. Public (no dash auth): the HMAC is the auth.\n\nOrder matters: verify the raw bytes, then claim the delivery id in the SAME\ntransaction as the credit — a duplicate id is a no-op, and a failure after\nthe claim rolls the claim back so paykit's retry is processed, not skipped.","operationId":"paykit_webhook_api_webhooks_paykit_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/billing/receipt-email":{"put":{"tags":["billing"],"summary":"Set Receipt Email","operationId":"set_receipt_email_api_billing_receipt_email_put","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReceiptEmailRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/billing/tochka/payment":{"post":{"tags":["billing"],"summary":"Create Topup","description":"Quote `energy` exactly like the other rails (same bulk bonus), open a\nTochka payment link for the ₽ price and remember the quote by operationId.","operationId":"create_topup_api_billing_tochka_payment_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TopupRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/billing/tochka/payments/latest":{"get":{"tags":["billing"],"summary":"Latest Topup","description":"The energy page polls this after the buyer comes back. The webhook\nnormally credits first; if it hasn't, the payment is re-read from Tochka so\na lost webhook never leaves a paid top-up uncredited.","operationId":"latest_topup_api_billing_tochka_payments_latest_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/billing/plus":{"get":{"tags":["billing"],"summary":"Plus State","operationId":"plus_state_api_billing_plus_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/billing/plus/subscribe":{"post":{"tags":["billing"],"summary":"Plus Subscribe","description":"Open a no-schedule Tochka subscription; its first payment (the link)\nactivates Plus via the webhook, later periods are charged by renew_due.","operationId":"plus_subscribe_api_billing_plus_subscribe_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscribeRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/billing/plus/cancel":{"post":{"tags":["billing"],"summary":"Plus Cancel","description":"Turn off renewal. Nothing is sent to Tochka — in no-schedule mode the bank\nnever charges on its own, we simply stop. Perks last to the period end.","operationId":"plus_cancel_api_billing_plus_cancel_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/webhooks/tochka":{"post":{"tags":["webhooks"],"summary":"Tochka Webhook","description":"`acquiringInternetPayment` from Tochka: a text/plain RS256 JWT, sent only\nfor successful operations and retried 30× every 10 s on anything but 200.\n\nAn unverifiable body is answered 200 and ignored: acting on it is what\nmatters, and Tochka's own registration test must not fail on us.","operationId":"tochka_webhook_api_webhooks_tochka_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/billing/partner/session":{"post":{"tags":["billing"],"summary":"Create Partner Session","description":"Quote `energy` for the SIGNED-IN buyer and return the partner redirect.\n\nThis is the half of the design that makes the webhook safe: the payer and the\nprice are fixed HERE, by us, under the buyer's own browser session. The\npartner never gets to assert either one — it can only confirm this quote.\n\nPricing reuses the existing top-up path (`_topup_config` / `_clamp_energy` /\n`compute_custom_topup`), so the bulk bonus and the brand currency are\nidentical to the card, Stars and crypto rails. Nothing identifying the buyer\ngoes into the redirect URL — only the opaque quote token and the money.","operationId":"create_partner_session_api_billing_partner_session_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PartnerSessionRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/billing/partner/sessions/latest":{"get":{"tags":["billing"],"summary":"Latest Partner Session","description":"The return page polls this: the WEBHOOK, not the redirect back from the\npartner, is what flips `status` / `credited_micros`.","operationId":"latest_partner_session_api_billing_partner_sessions_latest_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/webhooks/partner-settlement":{"post":{"tags":["webhooks"],"summary":"Partner Settlement Webhook","description":"The partner reports a payment it has already taken; we credit it once.\n\nOrder is the security property, not a style choice:\n  1. the bearer key (constant time) and the HMAC over the RAW bytes — a body\n     that parses to the same JSON but signs differently is rejected, which is\n     why the signature is never checked against a re-serialised copy;\n  2. the delivery id is claimed in the SAME transaction as the credit, so a\n     failure after the claim rolls the claim back and the partner's retry is\n     processed rather than silently swallowed;\n  3. the credit itself, guarded by the ledger's unique `external_ref` index.\n\nEvery path here is audited, including the ones that never reach the ledger.","operationId":"partner_settlement_webhook_api_webhooks_partner_settlement_post","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/spaces/usage":{"post":{"tags":["space-billing"],"summary":"Report Space Usage","operationId":"report_space_usage_v1_spaces_usage_post","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SpaceUsageRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/spaces/reserve":{"post":{"tags":["space-billing"],"summary":"Reserve Space Energy","operationId":"reserve_space_energy_v1_spaces_reserve_post","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SpaceReserveRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/spaces/reserve/release":{"post":{"tags":["space-billing"],"summary":"Release Space Reserve","operationId":"release_space_reserve_v1_spaces_reserve_release_post","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SpaceReserveReleaseRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/spaces/usage":{"get":{"tags":["space-billing"],"summary":"Space Usage Summary","description":"Per-app rollup + the owner's current balance for a space. Auth: internal\nBearer (same shared key as the write endpoints).","operationId":"space_usage_summary_api_spaces_usage_get","parameters":[{"name":"space_slug","in":"query","required":true,"schema":{"type":"string","title":"Space Slug"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/spaces/{slug}/proxied-sites":{"post":{"tags":["space-billing"],"summary":"Upsert Proxied Site","description":"Idempotently record that THIS space serves `hostname` via the RU relay.\nIf the hostname is already another space's, refuse (409) — no cross-space steal.","operationId":"upsert_proxied_site_v1_spaces__slug__proxied_sites_post","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","title":"Slug"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProxiedSiteRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"get":{"tags":["space-billing"],"summary":"List Space Proxied Sites","operationId":"list_space_proxied_sites_v1_spaces__slug__proxied_sites_get","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","title":"Slug"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/spaces/{slug}/proxied-sites/{hostname}":{"delete":{"tags":["space-billing"],"summary":"Disable Proxied Site","description":"Mark a site disabled — only if it belongs to THIS space (else 404).","operationId":"disable_proxied_site_v1_spaces__slug__proxied_sites__hostname__delete","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","title":"Slug"}},{"name":"hostname","in":"path","required":true,"schema":{"type":"string","title":"Hostname"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/proxied-sites":{"get":{"tags":["space-billing"],"summary":"List All Proxied Sites","description":"All proxied sites at a status (internal — drives the relay config generator).","operationId":"list_all_proxied_sites_v1_proxied_sites_get","parameters":[{"name":"status","in":"query","required":false,"schema":{"type":"string","default":"active","title":"Status"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/lizard-apps":{"post":{"tags":["space-billing"],"summary":"Sync Lizard Apps","description":"Bulk-upsert deployed-app URLs from the executor (idempotent on project_id).","operationId":"sync_lizard_apps_v1_lizard_apps_post","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LizardAppsSync"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/lizard-apps/clicks":{"post":{"tags":["space-billing"],"summary":"Sync Preview Clicks","description":"Record a batch of preview-link click events and bump each project's lifetime\ncounter. A project_id with no LizardApp row (its deployment was torn down and\npruned by a later sync_lizard_apps reconcile before this batch landed) still gets\nits click events recorded for the historical record — there's just no counter\nrow left to bump for it.","operationId":"sync_preview_clicks_v1_lizard_apps_clicks_post","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LizardAppClicksSync"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/user/referrals/me":{"get":{"tags":["referrals"],"summary":"Get My Referrals","operationId":"get_my_referrals_api_user_referrals_me_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MeResponse"}}}}}}},"/api/user/referrals/referees":{"get":{"tags":["referrals"],"summary":"List Direct Referrals","description":"List direct referrals and aggregate only their non-sensitive activity.","operationId":"list_direct_referrals_api_user_referrals_referees_get","parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":200,"minimum":1,"default":50,"title":"Limit"}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0,"default":0,"title":"Offset"}},{"name":"before_registered_at","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Before Registered At"}},{"name":"before_id","in":"query","required":false,"schema":{"anyOf":[{"type":"integer","minimum":1},{"type":"null"}],"title":"Before Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DirectReferralsResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/user/referrals/apply-influencer":{"post":{"tags":["referrals"],"summary":"Apply Influencer","operationId":"apply_influencer_api_user_referrals_apply_influencer_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApplyInfluencerRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/user/referrals/apply-at-first-purchase":{"post":{"tags":["referrals"],"summary":"Apply At First Purchase","description":"Retroactively bind a referral code entered at first purchase.\n\nA rejection (invalid code, self-referral, already referred, window\nclosed, already granted) is a normal, expected outcome — the frontend\nshows it as a message, not an error page, so this always returns 200.","operationId":"apply_at_first_purchase_api_user_referrals_apply_at_first_purchase_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApplyAtFirstPurchaseRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/user/referrals/payouts":{"get":{"tags":["referrals"],"summary":"List Payouts","operationId":"list_payouts_api_user_referrals_payouts_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"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/user/referrals/set-code":{"post":{"tags":["referrals"],"summary":"Set Custom Code","description":"Change the user's active referral code. Old code becomes an alias.","operationId":"set_custom_code_api_user_referrals_set_code_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetCodeRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/user/referrals/codes":{"get":{"tags":["referrals"],"summary":"List My Codes","description":"List all codes (current + old aliases) with per-code referral counts.","operationId":"list_my_codes_api_user_referrals_codes_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/user/referrals/convert-to-credits":{"post":{"tags":["referrals"],"summary":"Convert Rub To Credits","description":"Convert referral RUB earnings to personal credits at current rate.","operationId":"convert_rub_to_credits_api_user_referrals_convert_to_credits_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConvertRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/user/referrals/withdraw":{"post":{"tags":["referrals"],"summary":"Request Withdrawal","description":"Request withdrawal of referral RUB earnings. Queued for manual processing.","operationId":"request_withdrawal_api_user_referrals_withdraw_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WithdrawRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/user/referrals/my-withdrawals":{"get":{"tags":["referrals"],"summary":"List My Withdrawals","description":"List the current user's own withdrawal requests, newest first.","operationId":"list_my_withdrawals_api_user_referrals_my_withdrawals_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"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/user/referrals/balance":{"get":{"tags":["referrals"],"summary":"Referral Balance","description":"Get referral RUB balance, lifetime earnings, and contact prefill for the\nwithdrawal form (Telegram username off User, email off UserIdentity).","operationId":"referral_balance_api_user_referrals_balance_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/admin/referrals/applications":{"get":{"tags":["admin-referrals"],"summary":"List Applications","operationId":"list_applications_api_admin_referrals_applications_get","parameters":[{"name":"status","in":"query","required":false,"schema":{"type":"string","default":"pending","title":"Status"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/admin/referrals/applications/{user_id}/approve":{"post":{"tags":["admin-referrals"],"summary":"Approve Application","operationId":"approve_application_api_admin_referrals_applications__user_id__approve_post","parameters":[{"name":"user_id","in":"path","required":true,"schema":{"type":"integer","title":"User Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApproveRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/admin/referrals/applications/{user_id}/reject":{"post":{"tags":["admin-referrals"],"summary":"Reject Application","operationId":"reject_application_api_admin_referrals_applications__user_id__reject_post","parameters":[{"name":"user_id","in":"path","required":true,"schema":{"type":"integer","title":"User Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RejectRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/admin/referrals/override/{user_id}":{"post":{"tags":["admin-referrals"],"summary":"Override Referral","operationId":"override_referral_api_admin_referrals_override__user_id__post","parameters":[{"name":"user_id","in":"path","required":true,"schema":{"type":"integer","title":"User Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OverrideRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/admin/referrals/stats":{"get":{"tags":["admin-referrals"],"summary":"Referral Stats","operationId":"referral_stats_api_admin_referrals_stats_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/admin/referrals/flag-fraud/{referral_id}":{"post":{"tags":["admin-referrals"],"summary":"Flag Fraud","description":"Flag a referral as fraud and reverse every reward already paid out.\n\nSpec §5.5: manual fraud flag triggers the same clawback path as auto-churn.\nIdempotent — re-flagging a fraud row writes no duplicate clawbacks.","operationId":"flag_fraud_api_admin_referrals_flag_fraud__referral_id__post","parameters":[{"name":"referral_id","in":"path","required":true,"schema":{"type":"integer","title":"Referral Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RejectRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/admin/referrals/referrers":{"get":{"tags":["admin-referrals"],"summary":"List Referrers","description":"Paginated list of every user with a referral_code, with rollup metrics.\n\nFilters: q (matches username/name/code, case-insensitive), tier,\nhas_paid (≥1 referee with first_paid_at), paused.\nSort keys: earned_desc | signups_desc | recent | name.","operationId":"list_referrers_api_admin_referrals_referrers_get","parameters":[{"name":"q","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Q"}},{"name":"tier","in":"query","required":false,"schema":{"anyOf":[{"type":"string","pattern":"^(regular|influencer)$"},{"type":"null"}],"title":"Tier"}},{"name":"has_paid","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"Has Paid"}},{"name":"paused","in":"query","required":false,"schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Paused"}},{"name":"sort","in":"query","required":false,"schema":{"type":"string","pattern":"^(earned_desc|signups_desc|recent|name)$","default":"earned_desc","title":"Sort"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":200,"minimum":1,"default":50,"title":"Limit"}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0,"default":0,"title":"Offset"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/admin/referrals/referrers/{user_id}":{"get":{"tags":["admin-referrals"],"summary":"Get Referrer Detail","description":"Drill-down: profile, code, aggregates, referrals list, full ledger.","operationId":"get_referrer_detail_api_admin_referrals_referrers__user_id__get","parameters":[{"name":"user_id","in":"path","required":true,"schema":{"type":"integer","title":"User Id"}},{"name":"referrals_limit","in":"query","required":false,"schema":{"type":"integer","maximum":1000,"minimum":1,"default":200,"title":"Referrals Limit"}},{"name":"ledger_limit","in":"query","required":false,"schema":{"type":"integer","maximum":1000,"minimum":1,"default":200,"title":"Ledger Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/admin/referrals/affiliates":{"get":{"tags":["admin-referrals"],"summary":"List Affiliates","description":"Influencer-only view: same rollups as /referrers but constrained to\ntier='influencer' AND surfacing influencer_application metadata so admins\ncan compare claimed audience vs realised signups at a glance.","operationId":"list_affiliates_api_admin_referrals_affiliates_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/admin/referrals/codes/{user_id}/pause":{"post":{"tags":["admin-referrals"],"summary":"Pause Code","operationId":"pause_code_api_admin_referrals_codes__user_id__pause_post","parameters":[{"name":"user_id","in":"path","required":true,"schema":{"type":"integer","title":"User Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/admin/referrals/codes/{user_id}/unpause":{"post":{"tags":["admin-referrals"],"summary":"Unpause Code","operationId":"unpause_code_api_admin_referrals_codes__user_id__unpause_post","parameters":[{"name":"user_id","in":"path","required":true,"schema":{"type":"integer","title":"User Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/admin/referrals/activity":{"get":{"tags":["admin-referrals"],"summary":"Activity Feed","description":"Recent events across attribution + payout lifecycle.\n\nMerges:\n- Referral.attributed_at  → 'attributed'\n- Referral.first_paid_at  → 'first_paid'\n- BalanceTransaction referral_* rows → 'payout' / 'held' / 'signup_bonus' / 'discount' / 'clawback' / 'credit_commission'\nPulls 2× limit from each source then trims to keep the merged list balanced.","operationId":"activity_feed_api_admin_referrals_activity_get","parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":200,"minimum":1,"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"}}}}}}},"/api/admin/referrals/withdrawals":{"get":{"tags":["admin-referrals"],"summary":"List Withdrawals","operationId":"list_withdrawals_api_admin_referrals_withdrawals_get","parameters":[{"name":"status","in":"query","required":false,"schema":{"anyOf":[{"type":"string","pattern":"^(pending|paid|rejected)$"},{"type":"null"}],"title":"Status"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":200,"minimum":1,"default":50,"title":"Limit"}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0,"default":0,"title":"Offset"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/admin/referrals/withdrawals/{withdrawal_id}/mark-paid":{"post":{"tags":["admin-referrals"],"summary":"Mark Withdrawal Paid","description":"Mark a withdrawal as paid. Payout itself happens off-app/manually — this\nonly records that the admin has sent the money.","operationId":"mark_withdrawal_paid_api_admin_referrals_withdrawals__withdrawal_id__mark_paid_post","parameters":[{"name":"withdrawal_id","in":"path","required":true,"schema":{"type":"integer","title":"Withdrawal Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/admin/referrals/withdrawals/{withdrawal_id}/reject":{"post":{"tags":["admin-referrals"],"summary":"Reject Withdrawal","description":"Reject a pending withdrawal and refund the held amount back onto the\nuser's referral balance, with a reversing ledger row for the audit trail.","operationId":"reject_withdrawal_api_admin_referrals_withdrawals__withdrawal_id__reject_post","parameters":[{"name":"withdrawal_id","in":"path","required":true,"schema":{"type":"integer","title":"Withdrawal Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RejectRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/admin/referrals/acquisition":{"get":{"tags":["admin-referrals"],"summary":"Acquisition","description":"Signups, activation, payers, revenue and energy per code / label / UTM value.\n\nThe date range selects accounts by signup day (UTC, inclusive); money is\nthat cohort's lifetime purchases.","operationId":"acquisition_api_admin_referrals_acquisition_get","parameters":[{"name":"dimension","in":"query","required":false,"schema":{"type":"string","pattern":"^(code|label|utm_source|utm_campaign|utm_content)$","default":"code","title":"Dimension"}},{"name":"date_from","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Date From"}},{"name":"date_to","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Date To"}},{"name":"format","in":"query","required":false,"schema":{"type":"string","pattern":"^(json|csv)$","default":"json","title":"Format"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/admin/referrals/acquisition/users":{"get":{"tags":["admin-referrals"],"summary":"Acquisition Drilldown","description":"The accounts behind one acquisition row.","operationId":"acquisition_drilldown_api_admin_referrals_acquisition_users_get","parameters":[{"name":"key","in":"query","required":true,"schema":{"type":"string","minLength":1,"maxLength":120,"title":"Key"}},{"name":"dimension","in":"query","required":false,"schema":{"type":"string","pattern":"^(code|label|utm_source|utm_campaign|utm_content)$","default":"code","title":"Dimension"}},{"name":"date_from","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Date From"}},{"name":"date_to","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Date To"}},{"name":"format","in":"query","required":false,"schema":{"type":"string","pattern":"^(json|csv)$","default":"json","title":"Format"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/admin/referrals/sources":{"post":{"tags":["referral-sources"],"summary":"Create Source","operationId":"create_source_api_admin_referrals_sources_post","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SourceRequest"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"get":{"tags":["referral-sources"],"summary":"List Sources","operationId":"list_sources_api_admin_referrals_sources_get","parameters":[{"name":"q","in":"query","required":false,"schema":{"type":"string","maxLength":120,"default":"","title":"Q"}},{"name":"days","in":"query","required":false,"schema":{"type":"integer","maximum":365,"minimum":0,"default":0,"title":"Days"}},{"name":"state","in":"query","required":false,"schema":{"type":"string","pattern":"^(all|active|paused)$","default":"all","title":"State"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":50,"title":"Limit"}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0,"default":0,"title":"Offset"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/admin/referrals/sources/{source_id}":{"put":{"tags":["referral-sources"],"summary":"Update Source","operationId":"update_source_api_admin_referrals_sources__source_id__put","parameters":[{"name":"source_id","in":"path","required":true,"schema":{"type":"integer","title":"Source Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SourceUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/admin/referrals/sources/{source_id}/signups":{"get":{"tags":["referral-sources"],"summary":"Source Signups","operationId":"source_signups_api_admin_referrals_sources__source_id__signups_get","parameters":[{"name":"source_id","in":"path","required":true,"schema":{"type":"integer","title":"Source Id"}},{"name":"days","in":"query","required":false,"schema":{"type":"integer","maximum":365,"minimum":0,"default":0,"title":"Days"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":50,"title":"Limit"}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0,"default":0,"title":"Offset"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/referral-sources/{code}/visit":{"post":{"tags":["referral-sources"],"summary":"Record Visit","operationId":"record_visit_api_referral_sources__code__visit_post","parameters":[{"name":"code","in":"path","required":true,"schema":{"type":"string","title":"Code"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/VisitRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/pools":{"get":{"tags":["pools"],"summary":"List My Pools","operationId":"list_my_pools_api_pools_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}},"post":{"tags":["pools"],"summary":"Create Pool","operationId":"create_pool_api_pools_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreatePool"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/pools/{pool_id}":{"get":{"tags":["pools"],"summary":"Get Pool","operationId":"get_pool_api_pools__pool_id__get","parameters":[{"name":"pool_id","in":"path","required":true,"schema":{"type":"integer","title":"Pool Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"patch":{"tags":["pools"],"summary":"Update Pool","operationId":"update_pool_api_pools__pool_id__patch","parameters":[{"name":"pool_id","in":"path","required":true,"schema":{"type":"integer","title":"Pool Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdatePool"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/pools/active":{"post":{"tags":["pools"],"summary":"Set Active Pool","operationId":"set_active_pool_api_pools_active_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetActivePool"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/pools/{pool_id}/invites":{"post":{"tags":["pools"],"summary":"Create Invite","operationId":"create_invite_api_pools__pool_id__invites_post","parameters":[{"name":"pool_id","in":"path","required":true,"schema":{"type":"integer","title":"Pool Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateInvite"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/pools/{pool_id}/invites/{invite_id}":{"delete":{"tags":["pools"],"summary":"Deactivate Invite","operationId":"deactivate_invite_api_pools__pool_id__invites__invite_id__delete","parameters":[{"name":"pool_id","in":"path","required":true,"schema":{"type":"integer","title":"Pool Id"}},{"name":"invite_id","in":"path","required":true,"schema":{"type":"integer","title":"Invite Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/pools/join/{code}":{"post":{"tags":["pools"],"summary":"Join Pool","operationId":"join_pool_api_pools_join__code__post","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"}}}}}}},"/api/pools/{pool_id}/members/{target_user_id}/promote":{"post":{"tags":["pools"],"summary":"Promote Member","operationId":"promote_member_api_pools__pool_id__members__target_user_id__promote_post","parameters":[{"name":"pool_id","in":"path","required":true,"schema":{"type":"integer","title":"Pool Id"}},{"name":"target_user_id","in":"path","required":true,"schema":{"type":"integer","title":"Target User Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/pools/{pool_id}/members/{target_user_id}/demote":{"post":{"tags":["pools"],"summary":"Demote Member","operationId":"demote_member_api_pools__pool_id__members__target_user_id__demote_post","parameters":[{"name":"pool_id","in":"path","required":true,"schema":{"type":"integer","title":"Pool Id"}},{"name":"target_user_id","in":"path","required":true,"schema":{"type":"integer","title":"Target User Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/pools/{pool_id}/members/{target_user_id}/remove":{"post":{"tags":["pools"],"summary":"Remove Member","operationId":"remove_member_api_pools__pool_id__members__target_user_id__remove_post","parameters":[{"name":"pool_id","in":"path","required":true,"schema":{"type":"integer","title":"Pool Id"}},{"name":"target_user_id","in":"path","required":true,"schema":{"type":"integer","title":"Target User Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/pools/{pool_id}/leave":{"post":{"tags":["pools"],"summary":"Leave Pool","operationId":"leave_pool_api_pools__pool_id__leave_post","parameters":[{"name":"pool_id","in":"path","required":true,"schema":{"type":"integer","title":"Pool Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/pools/{pool_id}/spaces":{"post":{"tags":["pools"],"summary":"Add Pool Space","operationId":"add_pool_space_api_pools__pool_id__spaces_post","parameters":[{"name":"pool_id","in":"path","required":true,"schema":{"type":"integer","title":"Pool Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddSpace"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/pools/{pool_id}/spaces/{chat_key}":{"delete":{"tags":["pools"],"summary":"Remove Pool Space","operationId":"remove_pool_space_api_pools__pool_id__spaces__chat_key__delete","parameters":[{"name":"pool_id","in":"path","required":true,"schema":{"type":"integer","title":"Pool Id"}},{"name":"chat_key","in":"path","required":true,"schema":{"type":"string","title":"Chat Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/pools/{pool_id}/transactions":{"get":{"tags":["pools"],"summary":"Pool Transactions","operationId":"pool_transactions_api_pools__pool_id__transactions_get","parameters":[{"name":"pool_id","in":"path","required":true,"schema":{"type":"integer","title":"Pool Id"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":200,"default":50,"title":"Limit"}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0,"default":0,"title":"Offset"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/pools/{pool_id}/topup":{"post":{"tags":["pools"],"summary":"Topup Pool From Personal","description":"Transfer energy from the caller's personal balance into one of their pools.\n\nAtomic: row-locks both sides, debits user, credits pool, writes both\nledger rows in a single transaction.","operationId":"topup_pool_from_personal_api_pools__pool_id__topup_post","parameters":[{"name":"pool_id","in":"path","required":true,"schema":{"type":"integer","title":"Pool Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TopupBody"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/pools/{pool_id}/withdraw":{"post":{"tags":["pools"],"summary":"Withdraw Pool To Personal","description":"Transfer energy from a pool back to the caller's personal balance.\n\nManager/owner only — regular members cannot drain the pool. Atomic:\nrow-locks both sides, debits pool, credits user, writes both ledger\nrows in a single transaction.","operationId":"withdraw_pool_to_personal_api_pools__pool_id__withdraw_post","parameters":[{"name":"pool_id","in":"path","required":true,"schema":{"type":"integer","title":"Pool Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TopupBody"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/pools/{pool_id}/analytics":{"get":{"tags":["pools"],"summary":"Pool Analytics","description":"Usage analytics for a pool: spend per space, per member, and daily trend.\n\nOnly usage-attributed debits (ref_usage_id set) are counted. Spend is\nreported as a positive credit-micros amount.","operationId":"pool_analytics_api_pools__pool_id__analytics_get","parameters":[{"name":"pool_id","in":"path","required":true,"schema":{"type":"integer","title":"Pool Id"}},{"name":"days","in":"query","required":false,"schema":{"type":"integer","maximum":365,"minimum":1,"default":30,"title":"Days"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/pools/{pool_id}/member-details":{"get":{"tags":["pools"],"summary":"Pool Member Details","description":"Member roster with per-member personal balance and recent spend.\n\nOwners and managers receive the full B2B view (personal balance, last-N-day\nspend attributed to this pool). Regular members get only the name/role\nroster — same shape, with the sensitive fields omitted.","operationId":"pool_member_details_api_pools__pool_id__member_details_get","parameters":[{"name":"pool_id","in":"path","required":true,"schema":{"type":"integer","title":"Pool Id"}},{"name":"days","in":"query","required":false,"schema":{"type":"integer","maximum":365,"minimum":1,"default":30,"title":"Days"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/pools/transfer":{"post":{"tags":["pools"],"summary":"Transfer Balances","description":"Move energy between any two balances the caller controls.\n\nSource authority: caller must be owner/manager of a pool source, or\nthe source must be the caller's personal balance.\n\nDestination authority: same rules — caller must control the target.\nThis prevents drive-by funding of strangers' pools.\n\nAtomic: row-locks both sides with FOR UPDATE, debits source, credits\ntarget, and writes paired ledger rows in a single commit. Reasons:\n`transfer_out` / `transfer_in` on BalanceTransaction (personal side),\n`transfer_out` / `transfer_in` on PoolTransaction (pool side).","operationId":"transfer_balances_api_pools_transfer_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TransferBody"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/skills":{"get":{"tags":["skills"],"summary":"List Skills","operationId":"list_skills_api_skills_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/skills/pinned":{"get":{"tags":["skills"],"summary":"List Pinned Skills","description":"Home page row — admin-curated short list. Falls back to the first\n`sort_order` page of active skills if no row is pinned yet, so the row is\nnever empty even on a stale seed install.","operationId":"list_pinned_skills_api_skills_pinned_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/skills/processes":{"get":{"tags":["skills"],"summary":"List Space Processes","description":"A space's FLOW TEMPLATES (\"Processes\", #405) — read-only from its knowledge\ntree (``knowledge/wiki/processes/*.md``). Each entry carries its ``name``, the\nordered ``steps`` (+ count) and free-text ``notes``, plus a ``start_deeplink``\n(``startapp=flow-start-<slug>_<name>``) the Skills page turns into a\n\"Start in chat\" button.\n\nMember-authorized, exactly like the per-space tasks read: an unknown space is\n404, a non-member is 403 (an admin session may read any existing space). A\nspace with no processes dir yields an empty list, never an error.","operationId":"list_space_processes_api_skills_processes_get","parameters":[{"name":"space","in":"query","required":true,"schema":{"type":"string","description":"the space slug whose flow templates to list","title":"Space"},"description":"the space slug whose flow templates to list"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/skills/{slug}":{"get":{"tags":["skills"],"summary":"Get Skill","operationId":"get_skill_api_skills__slug__get","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","title":"Slug"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/admin/skills/upload":{"post":{"tags":["admin-skills"],"summary":"Admin Upload Asset","description":"Upload an asset; returns a public URL. Use it in a skill's media list.","operationId":"admin_upload_asset_api_admin_skills_upload_post","requestBody":{"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_admin_upload_asset_api_admin_skills_upload_post"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/admin/skills":{"get":{"tags":["admin-skills"],"summary":"Admin List Skills","operationId":"admin_list_skills_api_admin_skills_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}},"post":{"tags":["admin-skills"],"summary":"Admin Create Skill","operationId":"admin_create_skill_api_admin_skills_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SkillBody"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/admin/skills/{skill_id}":{"patch":{"tags":["admin-skills"],"summary":"Admin Update Skill","operationId":"admin_update_skill_api_admin_skills__skill_id__patch","parameters":[{"name":"skill_id","in":"path","required":true,"schema":{"type":"integer","title":"Skill Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SkillPatch"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["admin-skills"],"summary":"Admin Delete Skill","operationId":"admin_delete_skill_api_admin_skills__skill_id__delete","parameters":[{"name":"skill_id","in":"path","required":true,"schema":{"type":"integer","title":"Skill Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/user/tasks":{"get":{"tags":["user-tasks"],"summary":"List Tasks","description":"A user's tasks + flows across all their spaces, from the DB SSOT.\n\n``scope=space`` (with ``?space=<slug>``) returns EVERY task/flow of one space to\nany of its MEMBERS — the member-visibility path a Mini App task deep-link lands\non. Unknown space → 404, non-member → 403.","operationId":"list_tasks_api_user_tasks_get","parameters":[{"name":"scope","in":"query","required":false,"schema":{"type":"string","pattern":"^(mine|all|space)$","description":"mine = created by / assigned to me; all = every visible task; space = all tasks of one space (members), requires ?space=","default":"mine","title":"Scope"},"description":"mine = created by / assigned to me; all = every visible task; space = all tasks of one space (members), requires ?space="},{"name":"state","in":"query","required":false,"schema":{"type":"string","pattern":"^(open|closed|all)$","default":"open","title":"State"}},{"name":"space","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"the space slug, required when scope=space","title":"Space"},"description":"the space slug, required when scope=space"},{"name":"user_id","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"admins only: view another user's tasks","title":"User Id"},"description":"admins only: view another user's tasks"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/user/tasks/{slug}/flows/{name}":{"get":{"tags":["user-tasks"],"summary":"Flow Detail","description":"One flow of a space, in full, for the «Tasks» nav flow deep-link.\n\nMember-authorized (owner / member / admin). Unknown space → 404, non-member →\n403, unknown flow → 404. Prefers the OPEN flow of a reused name.","operationId":"flow_detail_api_user_tasks__slug__flows__name__get","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","title":"Slug"}},{"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"}}}}}}},"/api/user/tasks/{slug}/{number}":{"get":{"tags":["user-tasks"],"summary":"Task Detail","description":"One task, in full, for the «Tasks» detail panel.\n\nMember-authorized (owner / member / admin). Returns the sanitized rendered body\n(``body_html``, escape-first) alongside ``body_md``, the visible ``tags`` +\n``labels``, the resolved ``creator``/``assignee`` (``{ref, name}``), ``state``,\ntimestamps and ``comments_count`` (the count of ``comment`` events).","operationId":"task_detail_api_user_tasks__slug___number__get","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","title":"Slug"}},{"name":"number","in":"path","required":true,"schema":{"type":"integer","title":"Number"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/user/tasks/{slug}/{number}/artifacts/{artifact_id}/download":{"get":{"tags":["user-tasks"],"summary":"Task Artifact Download","description":"Stream a Telegram-delivered task artifact to a member of the task's space.\n\nThe bytes are pulled live from the bot's own bot-api server by the ``file_id``\nthe gate recorded (dash never stores file content). Member-authorized exactly\nlike the task detail read; an artifact that belongs to a different task is a\n404, never served across tasks.","operationId":"task_artifact_download_api_user_tasks__slug___number__artifacts__artifact_id__download_get","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","title":"Slug"}},{"name":"number","in":"path","required":true,"schema":{"type":"integer","title":"Number"}},{"name":"artifact_id","in":"path","required":true,"schema":{"type":"string","title":"Artifact Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/gate/spaces/{slug}/tasks":{"post":{"tags":["gate-tasks"],"summary":"Gate Create Task","description":"Capture a task. Server-side dedupe by normalized title among OPEN tasks: a\nduplicate returns the EXISTING row with ``deduped:true`` and appends a\n``mentioned`` event (so the repeat is recorded, not lost). A new task gets the\nnext per-space number and a ``created`` event.","operationId":"gate_create_task_api_gate_spaces__slug__tasks_post","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","title":"Slug"}},{"name":"X-API-Key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GateTaskCreate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"get":{"tags":["gate-tasks"],"summary":"Gate List Tasks","description":"A space's flat (non-flow-step) tasks, newest first, bounded — the seed-note\nread. ``state=closed`` means done OR cancelled; ``open`` is the default.","operationId":"gate_list_tasks_api_gate_spaces__slug__tasks_get","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","title":"Slug"}},{"name":"state","in":"query","required":false,"schema":{"type":"string","pattern":"^(open|closed|done|cancelled|all)$","default":"open","title":"State"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":20,"title":"Limit"}},{"name":"X-API-Key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/gate/spaces/{slug}/tasks/{number}":{"patch":{"tags":["gate-tasks"],"summary":"Gate Patch Task","description":"Mutate one task: close | reopen | assign | comment | set_current | delegate.\nEach action appends the matching ``task_events`` row and returns the fresh row.","operationId":"gate_patch_task_api_gate_spaces__slug__tasks__number__patch","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","title":"Slug"}},{"name":"number","in":"path","required":true,"schema":{"type":"integer","title":"Number"}},{"name":"X-API-Key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GateTaskPatch"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/gate/spaces/{slug}/spend":{"get":{"tags":["gate-tasks"],"summary":"Gate Space Spend","description":"Browse the space's spend for the bot — grouped by task | flow | label | kind |\nmodel, with an ``untracked`` bucket for spend not tied to a task. Owner-pays:\nthe summed rows are the space's ``usage`` charges stamped with a ``task_ref``.\n``q`` resolves task titles case-insensitively (so «документация» finds the\ndocumentation tasks).","operationId":"gate_space_spend_api_gate_spaces__slug__spend_get","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","title":"Slug"}},{"name":"group","in":"query","required":false,"schema":{"type":"string","description":"one of ('task', 'flow', 'label', 'kind', 'model')","default":"task","title":"Group"},"description":"one of ('task', 'flow', 'label', 'kind', 'model')"},{"name":"since","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"ISO-8601 lower bound (inclusive)","title":"Since"},"description":"ISO-8601 lower bound (inclusive)"},{"name":"until","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"ISO-8601 upper bound (exclusive)","title":"Until"},"description":"ISO-8601 upper bound (exclusive)"},{"name":"q","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"case-insensitive title/name/label filter","title":"Q"},"description":"case-insensitive title/name/label filter"},{"name":"task","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"restrict to one task number","title":"Task"},"description":"restrict to one task number"},{"name":"flow","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"restrict to one flow name","title":"Flow"},"description":"restrict to one flow name"},{"name":"X-API-Key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/gate/spaces/{slug}/tasks/{number}/stats":{"get":{"tags":["gate-tasks"],"summary":"Gate Task Stats","description":"The full task-detail metrics (§A) for ONE task, for the bot — the same rollup\nthe Mini App shows, plus its artifacts and the share block.","operationId":"gate_task_stats_api_gate_spaces__slug__tasks__number__stats_get","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","title":"Slug"}},{"name":"number","in":"path","required":true,"schema":{"type":"integer","title":"Number"}},{"name":"X-API-Key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/gate/tasks/artifact":{"post":{"tags":["gate-tasks"],"summary":"Gate Record Task Artifact","description":"Record a file the bot delivered for a task as a task artifact (ooih #1308).\n\nResolves ``task_ref`` (``<slug>#<n>``) to the task in a space this workspace may\nwrite (owned or unscoped) — unknown task → 404 ``task_not_found``, malformed ref\n→ 422. Stores only Telegram coordinates + metadata (never message text or file\ncontent). Idempotent on ``(task_id, telegram_file_id, message_id)``: a re-report\nreturns the existing row with ``created:false``.","operationId":"gate_record_task_artifact_api_gate_tasks_artifact_post","parameters":[{"name":"X-API-Key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GateTaskArtifact"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/gate/spaces/{slug}/flows":{"post":{"tags":["gate-tasks"],"summary":"Gate Create Flow","description":"Create a flow + its ordered step tasks (``is_current_step`` on step 1). A\n``created`` event is appended per step task. An existing OPEN flow of the same\nname is returned with ``deduped:true`` (never a second open flow of a name).","operationId":"gate_create_flow_api_gate_spaces__slug__flows_post","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","title":"Slug"}},{"name":"X-API-Key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GateFlowCreate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"get":{"tags":["gate-tasks"],"summary":"Gate List Flows","description":"A space's flows (open first) with assembled step shapes. ``state``\ndefaults to ``open`` — a finished/cancelled flow used to be served on every\ncall even though the bot only ever acts on a live one; pass ``state=all``\nfor the full history (``closed`` is done OR cancelled).","operationId":"gate_list_flows_api_gate_spaces__slug__flows_get","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","title":"Slug"}},{"name":"state","in":"query","required":false,"schema":{"type":"string","pattern":"^(open|closed|all)$","default":"open","title":"State"}},{"name":"X-API-Key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/gate/spaces/{slug}/flows/{name}":{"patch":{"tags":["gate-tasks"],"summary":"Gate Patch Flow","description":"Drive a flow: advance | block | cancel | checkin | delegate | fail. Every\naction appends a ``task_events`` row on the relevant step and returns the\nfresh flow.","operationId":"gate_patch_flow_api_gate_spaces__slug__flows__name__patch","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","title":"Slug"}},{"name":"name","in":"path","required":true,"schema":{"type":"string","title":"Name"}},{"name":"X-API-Key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GateFlowPatch"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/gate/spaces/{slug}/flow-templates":{"get":{"tags":["gate-tasks"],"summary":"Gate List Flow Templates","description":"A space's reusable flow templates.","operationId":"gate_list_flow_templates_api_gate_spaces__slug__flow_templates_get","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","title":"Slug"}},{"name":"X-API-Key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["gate-tasks"],"summary":"Gate Put Flow Template","description":"Upsert one flow template by (space, name). Idempotent.","operationId":"gate_put_flow_template_api_gate_spaces__slug__flow_templates_put","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","title":"Slug"}},{"name":"X-API-Key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GateFlowTemplatePut"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/user/integrations/":{"get":{"tags":["integrations"],"summary":"List Integrations","description":"Return the current user's connected integrations (no secrets).","operationId":"list_integrations_api_user_integrations__get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/user/integrations":{"get":{"tags":["integrations"],"summary":"List Integrations","description":"Return the current user's connected integrations (no secrets).","operationId":"list_integrations_api_user_integrations_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/user/integrations/google/start":{"post":{"tags":["integrations"],"summary":"Start Google Oauth","description":"Begin Google OAuth. Returns {authorize_url} for the client to redirect to.","operationId":"start_google_oauth_api_user_integrations_google_start_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StartOAuthRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/user/integrations/google/callback":{"get":{"tags":["integrations"],"summary":"Google Oauth Callback","description":"Handle Google's redirect after the user grants/denies consent.\n\nOn success: persist tokens, redirect to dash with ok=1.\nOn user denial: redirect to dash with error param.\nOn bad state / token exchange failure: 400 / 500.","operationId":"google_oauth_callback_api_user_integrations_google_callback_get","parameters":[{"name":"code","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Code"}},{"name":"state","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"State"}},{"name":"error","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Error"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/user/integrations/google":{"delete":{"tags":["integrations"],"summary":"Disconnect Google","operationId":"disconnect_google_api_user_integrations_google_delete","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/user/integrations/yandex-disk/":{"get":{"tags":["integrations"],"summary":"Disk Status","description":"The owner's Disk connections, their attached spaces, and the spaces they\ncould attach. No secret — not the token, not its length, not its shape.\n\n`full_access: true` is part of the payload rather than copy in one component:\nwhat an attachment grants is a property of the server's model, and the card\nrenders the warning from it.","operationId":"disk_status_api_user_integrations_yandex_disk__get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/user/integrations/yandex-disk":{"get":{"tags":["integrations"],"summary":"Disk Status","description":"The owner's Disk connections, their attached spaces, and the spaces they\ncould attach. No secret — not the token, not its length, not its shape.\n\n`full_access: true` is part of the payload rather than copy in one component:\nwhat an attachment grants is a property of the server's model, and the card\nrenders the warning from it.","operationId":"disk_status_api_user_integrations_yandex_disk_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/user/integrations/yandex-disk/link/{ticket}":{"get":{"tags":["integrations"],"summary":"Describe Link","description":"What does this bot link name? Read-only — it does NOT spend the ticket.\n\nThe connect page calls this to show the owner which space is about to be\ngranted full use of their Disk BEFORE they press anything. It answers only\nfor the account the ticket was minted for, so a forwarded link does not even\ndisclose the space's name.","operationId":"describe_link_api_user_integrations_yandex_disk_link__ticket__get","parameters":[{"name":"ticket","in":"path","required":true,"schema":{"type":"string","title":"Ticket"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/user/integrations/yandex-disk/start":{"post":{"tags":["integrations"],"summary":"Start Disk Oauth","description":"Begin the Disk grant. Returns {authorize_url} for the client to send the\nbrowser to. PKCE: we keep the verifier, the browser sees only the S256\nchallenge, so an intercepted `code` is worthless without our row.","operationId":"start_disk_oauth_api_user_integrations_yandex_disk_start_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StartDiskOAuth"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/user/integrations/yandex-disk/callback":{"get":{"tags":["integrations"],"summary":"Disk Oauth Callback","description":"Yandex's redirect back. Verifies the one-time state, exchanges the code\nserver-side with the PKCE verifier, and stores the tokens encrypted.\n\nIdempotent on (owner, yandex_uid): a repeated connect of the SAME account\nrefreshes that row — and, if the flow named a space, attaches it to that\nexisting row rather than duplicating the connection. Connecting a DIFFERENT\nYandex account adds a SECOND row and leaves the first intact, with its own\nattachments and its own auto-attach switch. That is what \"enable multiple\ndisks\" means here, and it works because `cloud_api:disk.info` is part of the\ngrant: without the account's uid the two Disks would be indistinguishable and\nthe second connect would silently overwrite the first.","operationId":"disk_oauth_callback_api_user_integrations_yandex_disk_callback_get","parameters":[{"name":"code","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Code"}},{"name":"state","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"State"}},{"name":"error","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Error"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/user/integrations/yandex-disk/{cid}":{"patch":{"tags":["integrations"],"summary":"Patch Connection","description":"Turn auto-attachment on or off for this Disk. Owner-only.","operationId":"patch_connection_api_user_integrations_yandex_disk__cid__patch","parameters":[{"name":"cid","in":"path","required":true,"schema":{"type":"integer","title":"Cid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PatchConnection"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["integrations"],"summary":"Disconnect Disk","description":"Revoke at Yandex and delete the stored tokens.\n\nRevocation is attempted first so this genuinely removes access rather than\nmerely forgetting the credential; the local delete proceeds either way, since\na connection we can no longer use must not be left dangling. Attached links\ngo with it (ON DELETE CASCADE) — nothing keeps reading the Disk afterwards.","operationId":"disconnect_disk_api_user_integrations_yandex_disk__cid__delete","parameters":[{"name":"cid","in":"path","required":true,"schema":{"type":"integer","title":"Cid"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/user/integrations/yandex-disk/{cid}/spaces":{"post":{"tags":["integrations"],"summary":"Attach Space","description":"Attach one of the owner's spaces to this Disk — GRANTING IT FULL USE.\n\nNo Disk call is made: attaching is a row, so it is instant and a Disk outage\ncannot fail the click. What it grants is the whole Disk, which is why the\ncard asks for confirmation naming the space before calling this.\n\nONE Disk per space: a space already on a different connection is refused with\na 409 naming that connection, rather than silently re-homed.","operationId":"attach_space_api_user_integrations_yandex_disk__cid__spaces_post","parameters":[{"name":"cid","in":"path","required":true,"schema":{"type":"integer","title":"Cid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AttachSpace"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/user/integrations/yandex-disk/{cid}/spaces/{space_slug}":{"delete":{"tags":["integrations"],"summary":"Detach Space","description":"Detach a space. The files stay put; the space simply stops reaching them.\n\nImmediate and total: the link row IS the grant, every Disk route resolves\nthrough `connection_for_space`, and nothing caches a client between requests.\nThe next call the space makes gets a 404.","operationId":"detach_space_api_user_integrations_yandex_disk__cid__spaces__space_slug__delete","parameters":[{"name":"cid","in":"path","required":true,"schema":{"type":"integer","title":"Cid"}},{"name":"space_slug","in":"path","required":true,"schema":{"type":"string","title":"Space Slug"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/user/integrations/yandex-disk/spaces/{space_slug}/files":{"get":{"tags":["integrations"],"summary":"Browse Space Files","description":"List a directory on the Disk attached to this space.\n\n`path` is relative to the DISK ROOT — an attached space may browse anywhere,\nwhich is the whole point of the owner's model. `disk:/…` and `/…` spellings\nmean the same thing. What is still refused is a malformed path: `..`, a\nforeign scheme, control characters.","operationId":"browse_space_files_api_user_integrations_yandex_disk_spaces__space_slug__files_get","parameters":[{"name":"space_slug","in":"path","required":true,"schema":{"type":"string","title":"Space Slug"}},{"name":"path","in":"query","required":false,"schema":{"type":"string","description":"path relative to the Disk root","default":"","title":"Path"},"description":"path relative to the Disk root"},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":500,"minimum":1,"default":100,"title":"Limit"}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0,"default":0,"title":"Offset"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/user/integrations/yandex-tracker/":{"get":{"tags":["integrations"],"summary":"Tracker Status","operationId":"tracker_status_api_user_integrations_yandex_tracker__get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/user/integrations/yandex-tracker":{"get":{"tags":["integrations"],"summary":"Tracker Status","operationId":"tracker_status_api_user_integrations_yandex_tracker_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/user/integrations/yandex-tracker/start":{"post":{"tags":["integrations"],"summary":"Start Tracker Oauth","operationId":"start_tracker_oauth_api_user_integrations_yandex_tracker_start_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StartTrackerOAuth"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/user/integrations/yandex-tracker/callback":{"get":{"tags":["integrations"],"summary":"Tracker Oauth Callback","operationId":"tracker_oauth_callback_api_user_integrations_yandex_tracker_callback_get","parameters":[{"name":"code","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Code"}},{"name":"state","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"State"}},{"name":"error","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Error"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/user/integrations/yandex-tracker/{cid}":{"delete":{"tags":["integrations"],"summary":"Disconnect Tracker","description":"Revoke at Yandex (best effort), unlink every space, delete the tokens.","operationId":"disconnect_tracker_api_user_integrations_yandex_tracker__cid__delete","parameters":[{"name":"cid","in":"path","required":true,"schema":{"type":"integer","title":"Cid"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/user/integrations/yandex-tracker/{cid}/spaces":{"post":{"tags":["integrations"],"summary":"Link Space","description":"Let one of the owner's spaces read and change issues through this\nconnection. One Tracker per space: a space linked elsewhere is a 409.","operationId":"link_space_api_user_integrations_yandex_tracker__cid__spaces_post","parameters":[{"name":"cid","in":"path","required":true,"schema":{"type":"integer","title":"Cid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LinkSpace"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/user/integrations/yandex-tracker/{cid}/spaces/{space_slug}":{"delete":{"tags":["integrations"],"summary":"Unlink Space","operationId":"unlink_space_api_user_integrations_yandex_tracker__cid__spaces__space_slug__delete","parameters":[{"name":"cid","in":"path","required":true,"schema":{"type":"integer","title":"Cid"}},{"name":"space_slug","in":"path","required":true,"schema":{"type":"string","title":"Space Slug"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/gate/yandex-tracker/status":{"get":{"tags":["gate"],"summary":"Tracker Status","description":"Is Tracker linked to this space, for which org and account. No token.","operationId":"tracker_status_api_gate_yandex_tracker_status_get","parameters":[{"name":"slug","in":"query","required":true,"schema":{"type":"string","title":"Slug"}},{"name":"X-API-Key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/gate/yandex-tracker/queues":{"post":{"tags":["gate"],"summary":"Tracker Queues","operationId":"tracker_queues_api_gate_yandex_tracker_queues_post","parameters":[{"name":"X-API-Key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/_PageOp"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/gate/yandex-tracker/issues":{"post":{"tags":["gate"],"summary":"Tracker Issues","operationId":"tracker_issues_api_gate_yandex_tracker_issues_post","parameters":[{"name":"X-API-Key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/_SearchOp"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/gate/yandex-tracker/issue":{"post":{"tags":["gate"],"summary":"Tracker Issue","operationId":"tracker_issue_api_gate_yandex_tracker_issue_post","parameters":[{"name":"X-API-Key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/_IssueOp"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/gate/yandex-tracker/create":{"post":{"tags":["gate"],"summary":"Tracker Create","operationId":"tracker_create_api_gate_yandex_tracker_create_post","parameters":[{"name":"X-API-Key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/_CreateOp"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/gate/yandex-tracker/update":{"post":{"tags":["gate"],"summary":"Tracker Update","operationId":"tracker_update_api_gate_yandex_tracker_update_post","parameters":[{"name":"X-API-Key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/_UpdateOp"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/gate/yandex-tracker/transitions":{"post":{"tags":["gate"],"summary":"Tracker Transitions","operationId":"tracker_transitions_api_gate_yandex_tracker_transitions_post","parameters":[{"name":"X-API-Key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/_IssueOp"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/gate/yandex-tracker/transition":{"post":{"tags":["gate"],"summary":"Tracker Transition","operationId":"tracker_transition_api_gate_yandex_tracker_transition_post","parameters":[{"name":"X-API-Key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/_TransitionOp"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/gate/yandex-tracker/comments":{"post":{"tags":["gate"],"summary":"Tracker Comments","operationId":"tracker_comments_api_gate_yandex_tracker_comments_post","parameters":[{"name":"X-API-Key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/_CommentsOp"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/gate/yandex-tracker/comment":{"post":{"tags":["gate"],"summary":"Tracker Comment","operationId":"tracker_comment_api_gate_yandex_tracker_comment_post","parameters":[{"name":"X-API-Key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/_CommentOp"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/user/integrations/yandex-mail/":{"get":{"tags":["integrations"],"summary":"Mail Status","operationId":"mail_status_api_user_integrations_yandex_mail__get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/user/integrations/yandex-mail":{"get":{"tags":["integrations"],"summary":"Mail Status","operationId":"mail_status_api_user_integrations_yandex_mail_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/user/integrations/yandex-mail/start":{"post":{"tags":["integrations"],"summary":"Start Mail Oauth","operationId":"start_mail_oauth_api_user_integrations_yandex_mail_start_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StartMailOAuth"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/user/integrations/yandex-mail/callback":{"get":{"tags":["integrations"],"summary":"Mail Oauth Callback","operationId":"mail_oauth_callback_api_user_integrations_yandex_mail_callback_get","parameters":[{"name":"code","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Code"}},{"name":"state","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"State"}},{"name":"error","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Error"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/user/integrations/yandex-mail/{cid}":{"delete":{"tags":["integrations"],"summary":"Disconnect Mail","description":"Revoke at Yandex (best effort), unlink every space, delete the tokens.\nStored meetings go with the connection.","operationId":"disconnect_mail_api_user_integrations_yandex_mail__cid__delete","parameters":[{"name":"cid","in":"path","required":true,"schema":{"type":"integer","title":"Cid"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/user/integrations/yandex-mail/{cid}/spaces":{"post":{"tags":["integrations"],"summary":"Link Space","description":"Deliver this mailbox's Telemost meetings to one of the owner's spaces.\nOne mailbox per space: a space linked elsewhere is a 409.","operationId":"link_space_api_user_integrations_yandex_mail__cid__spaces_post","parameters":[{"name":"cid","in":"path","required":true,"schema":{"type":"integer","title":"Cid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LinkSpace"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/user/integrations/yandex-mail/{cid}/spaces/{space_slug}":{"delete":{"tags":["integrations"],"summary":"Unlink Space","operationId":"unlink_space_api_user_integrations_yandex_mail__cid__spaces__space_slug__delete","parameters":[{"name":"cid","in":"path","required":true,"schema":{"type":"integer","title":"Cid"}},{"name":"space_slug","in":"path","required":true,"schema":{"type":"string","title":"Space Slug"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/user/integrations/yandex-mail/{cid}/poll":{"post":{"tags":["integrations"],"summary":"Poll Now","description":"Check the mailbox now instead of waiting for the next poll.","operationId":"poll_now_api_user_integrations_yandex_mail__cid__poll_post","parameters":[{"name":"cid","in":"path","required":true,"schema":{"type":"integer","title":"Cid"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/gate/yandex-mail/status":{"get":{"tags":["gate"],"summary":"Gate Mail Status","operationId":"gate_mail_status_api_gate_yandex_mail_status_get","parameters":[{"name":"slug","in":"query","required":true,"schema":{"type":"string","title":"Slug"}},{"name":"X-API-Key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/gate/yandex-mail/meetings":{"get":{"tags":["gate"],"summary":"Gate Meetings","description":"The space's recent meetings with their action items. `tracker_linked`\ntells the orchestrator whether it may propose Tracker issues at all.","operationId":"gate_meetings_api_gate_yandex_mail_meetings_get","parameters":[{"name":"slug","in":"query","required":true,"schema":{"type":"string","title":"Slug"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":20,"title":"Limit"}},{"name":"X-API-Key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/gate/yandex-mail/meeting":{"get":{"tags":["gate"],"summary":"Gate Meeting","description":"One meeting in full: the markdown document to write at `doc_path`.","operationId":"gate_meeting_api_gate_yandex_mail_meeting_get","parameters":[{"name":"slug","in":"query","required":true,"schema":{"type":"string","title":"Slug"}},{"name":"id","in":"query","required":true,"schema":{"type":"integer","title":"Id"}},{"name":"X-API-Key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/gate/yandex-mail/meeting/issue":{"post":{"tags":["gate"],"summary":"Gate Record Issue","description":"Record the Tracker issue the user confirmed for one action item. This\ncreates nothing in Tracker; it only remembers the key.","operationId":"gate_record_issue_api_gate_yandex_mail_meeting_issue_post","parameters":[{"name":"X-API-Key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/_IssueLink"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/user/integrations/bitrix/":{"get":{"tags":["integrations"],"summary":"List Bitrix","description":"List the current owner's Bitrix connections (no secrets).","operationId":"list_bitrix_api_user_integrations_bitrix__get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/user/integrations/bitrix":{"get":{"tags":["integrations"],"summary":"List Bitrix","description":"List the current owner's Bitrix connections (no secrets).","operationId":"list_bitrix_api_user_integrations_bitrix_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}},"post":{"tags":["integrations"],"summary":"Create Bitrix","description":"Stand up a new Bitrix connection for the current owner (v2-fetch-only).\n\nTakes just (webhook, bot_name): the portal host is DERIVED from the webhook\n(the URL already contains it — one field, no way to disagree), the webhook's\nimbot scope is validated, we auto-register a `type:personal`/`eventMode:fetch`\nbot with the user's name, then store the invented botToken + the minted v2 bot\nid + the display name (creds AES-256-GCM-encrypted). The in-bot fetch poller\npicks the connection up on its next enumeration — no relay, no manual register\nstep. Enforces one connection per (owner, portal).","operationId":"create_bitrix_api_user_integrations_bitrix_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BitrixCreate"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/user/integrations/bitrix/{conn_id}":{"patch":{"tags":["integrations"],"summary":"Update Bitrix","description":"Update an owned connection: toggle `is_active` (enable/disable), rotate the\nstored inbound `webhook`, or rename the bot's display `bot_name`. The v2 fetch\nmechanics (botToken, v2 bot id, event mode) are managed by connect and are not\nowner-editable.","operationId":"update_bitrix_api_user_integrations_bitrix__conn_id__patch","parameters":[{"name":"conn_id","in":"path","required":true,"schema":{"type":"integer","title":"Conn Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BitrixUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["integrations"],"summary":"Delete Bitrix","description":"Remove an owned connection. The bot loses the portal's creds on its next\ngate read.","operationId":"delete_bitrix_api_user_integrations_bitrix__conn_id__delete","parameters":[{"name":"conn_id","in":"path","required":true,"schema":{"type":"integer","title":"Conn Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/user/integrations/bitrix/{conn_id}/health":{"post":{"tags":["integrations"],"summary":"Health Bitrix","description":"Validate the connection: call the portal's inbound webhook (imbot.bot.list,\nwhich proves the imbot scope the bot needs) and record connected/error +\nlast_error. Writes `status`/`last_error`/`connected_at` on the row.","operationId":"health_bitrix_api_user_integrations_bitrix__conn_id__health_post","parameters":[{"name":"conn_id","in":"path","required":true,"schema":{"type":"integer","title":"Conn Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/user/integrations/bitrix/{conn_id}/end-users":{"get":{"tags":["integrations"],"summary":"Bitrix End Users","description":"Owner-facing per-user energy for a Bitrix connection: which of the owner's\nBitrix users consumed how much energy across every space (dialog) provisioned\nfor this connection's portal. Carries the real display name/role captured on\ningest, so it reads \"Ivan Petrov: N\" not \"bitrix:123\". Owner-scoped (not\nstaff-only) — the connection must belong to the caller.","operationId":"bitrix_end_users_api_user_integrations_bitrix__conn_id__end_users_get","parameters":[{"name":"conn_id","in":"path","required":true,"schema":{"type":"integer","title":"Conn Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/user/integrations/bitrix/events":{"get":{"tags":["integrations"],"summary":"Bitrix Events","description":"Owner-facing audit log of this owner's Bitrix connect lifecycle — connect,\nconnect_error, health, revoke — so a failed setup (missing scope, unreachable\nportal, insufficient balance) is inspectable by the owner, not just staff.","operationId":"bitrix_events_api_user_integrations_bitrix_events_get","parameters":[{"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"}}}}}}},"/api/user/integrations/yandex/":{"get":{"tags":["integrations"],"summary":"List Yandex","description":"List the current owner's Yandex connections (no secrets).","operationId":"list_yandex_api_user_integrations_yandex__get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/user/integrations/yandex":{"get":{"tags":["integrations"],"summary":"List Yandex","description":"List the current owner's Yandex connections (no secrets).","operationId":"list_yandex_api_user_integrations_yandex_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}},"post":{"tags":["integrations"],"summary":"Create Yandex","description":"Stand up a new Yandex connection for the current owner (poll-only).\n\nThe OAuth token is the only required input (the single secret; stored\nAES-256-GCM-encrypted). `org` is an internal routing key derived from the token\nwhen omitted, and `bot_name` is an optional user label. The in-bot getUpdates\npoller picks the connection up on its next enumeration — no webhook, no register\nstep. Enforces one connection per (owner, org); a re-submit of the same token\nderives the same org and collides. Connect costs a flat 10 energy (owner-pays),\nidempotent via the balance-transaction external_ref.\n\nThe create/encrypt/charge itself lives in `services.yandex_connect` — shared\nverbatim with the Telegram DM onboarding (`/api/gate/yandex/connect`), so both\nfront doors write the same row and charge the same fee exactly once.","operationId":"create_yandex_api_user_integrations_yandex_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/YandexCreate"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/user/integrations/yandex/{conn_id}":{"patch":{"tags":["integrations"],"summary":"Update Yandex","description":"Update an owned connection: toggle `is_active` (enable/disable), rotate the\nstored OAuth `token`, or rename the bot's display `bot_name`.","operationId":"update_yandex_api_user_integrations_yandex__conn_id__patch","parameters":[{"name":"conn_id","in":"path","required":true,"schema":{"type":"integer","title":"Conn Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/YandexUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["integrations"],"summary":"Delete Yandex","description":"Remove an owned connection. The bot loses the org's token on its next gate\nread.","operationId":"delete_yandex_api_user_integrations_yandex__conn_id__delete","parameters":[{"name":"conn_id","in":"path","required":true,"schema":{"type":"integer","title":"Conn Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/user/integrations/yandex/{conn_id}/health":{"post":{"tags":["integrations"],"summary":"Health Yandex","description":"Validate the connection: call the Yandex bot API (getUpdates, which proves\nthe OAuth token is valid) and record connected/error + last_error. Writes\n`status`/`last_error`/`connected_at` on the row.","operationId":"health_yandex_api_user_integrations_yandex__conn_id__health_post","parameters":[{"name":"conn_id","in":"path","required":true,"schema":{"type":"integer","title":"Conn Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/user/integrations/yandex/{conn_id}/end-users":{"get":{"tags":["integrations"],"summary":"Yandex End Users","description":"Owner-facing per-user energy for a Yandex connection: which of the owner's\nYandex users consumed how much energy across every space (chat) provisioned for\nthis connection's org. Mirrors the Bitrix end-users view; owner-scoped (the\nconnection must belong to the caller).","operationId":"yandex_end_users_api_user_integrations_yandex__conn_id__end_users_get","parameters":[{"name":"conn_id","in":"path","required":true,"schema":{"type":"integer","title":"Conn Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/user/integrations/yandex/events":{"get":{"tags":["integrations"],"summary":"Yandex Events","description":"Owner-facing audit log of this owner's Yandex connect lifecycle — connect,\nconnect_error, health, update, revoke — so a failed setup (bad token,\nunreachable API, insufficient balance) is inspectable by the owner.","operationId":"yandex_events_api_user_integrations_yandex_events_get","parameters":[{"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"}}}}}}},"/api/user/integrations/{channel}/{conn_id}/members/":{"get":{"tags":["integrations"],"summary":"List Channel Members","description":"The connection's channel users, pending first, with how many questions\neach waiting person has had held and which account each one is linked to.\n\n`viewer_account_id` is who is asking. The list renders «это вы» on the row\nthe caller has claimed and «это я» on the rest, and it is answered here\nrather than by a second `/auth/me` round trip from the members panel — the\nserver already knows, and a UI that has to fetch its own identity to render a\nrow is a UI that renders it wrong for a moment.","operationId":"list_channel_members_api_user_integrations__channel___conn_id__members__get","parameters":[{"name":"channel","in":"path","required":true,"schema":{"type":"string","title":"Channel"}},{"name":"conn_id","in":"path","required":true,"schema":{"type":"integer","title":"Conn Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/user/integrations/{channel}/{conn_id}/members":{"get":{"tags":["integrations"],"summary":"List Channel Members","description":"The connection's channel users, pending first, with how many questions\neach waiting person has had held and which account each one is linked to.\n\n`viewer_account_id` is who is asking. The list renders «это вы» on the row\nthe caller has claimed and «это я» on the rest, and it is answered here\nrather than by a second `/auth/me` round trip from the members panel — the\nserver already knows, and a UI that has to fetch its own identity to render a\nrow is a UI that renders it wrong for a moment.","operationId":"list_channel_members_api_user_integrations__channel___conn_id__members_get","parameters":[{"name":"channel","in":"path","required":true,"schema":{"type":"string","title":"Channel"}},{"name":"conn_id","in":"path","required":true,"schema":{"type":"integer","title":"Conn Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/user/integrations/{channel}/{conn_id}/members/{admission_id}/link":{"post":{"tags":["integrations"],"summary":"Link Channel Member","description":"«Это я» — claim this channel identity for a platform account.\n\nThe account defaults to the CALLER. A non-admin who names a different one is\nrefused rather than silently corrected, because a request that asked to grant\nsomebody else access is not a typo to be helpful about. A platform admin may\nname any account.\n\nWhat the link buys: the orchestrator's cross-space gate resolves a\n`yandex:<id>` actor through it, so the Yandex-origin space and the linked\naccount's other spaces (a Telegram DM, typically) can call each other with\n`ask_related_orch`. That is privilege, which is why it cannot be granted on\nanyone else's behalf.","operationId":"link_channel_member_api_user_integrations__channel___conn_id__members__admission_id__link_post","parameters":[{"name":"channel","in":"path","required":true,"schema":{"type":"string","title":"Channel"}},{"name":"conn_id","in":"path","required":true,"schema":{"type":"integer","title":"Conn Id"}},{"name":"admission_id","in":"path","required":true,"schema":{"type":"integer","title":"Admission Id"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Body_link_channel_member_api_user_integrations__channel___conn_id__members__admission_id__link_post"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/user/integrations/{channel}/{conn_id}/members/{admission_id}/unlink":{"post":{"tags":["integrations"],"summary":"Unlink Channel Member","description":"Revoke this channel identity's link. Takes effect on the next cross-space\ncall — nothing caches the resolution.\n\nAllowed to the linked account, the connection's owner, or a platform admin:\nwider than linking, and only in the direction that REMOVES privilege. Not\nbehind `_authorized` for that reason — the person who claimed an identity\nmust be able to take it back without being the connection's owner, and a\nrevoke nobody but the owner can perform is a grant with no exit.\n\nAn identity that is not linked is a 404, not a silent success: \"it is already\nhow you want it\" and \"your request did nothing\" look identical to a caller\nwho is trying to cut off access.","operationId":"unlink_channel_member_api_user_integrations__channel___conn_id__members__admission_id__unlink_post","parameters":[{"name":"channel","in":"path","required":true,"schema":{"type":"string","title":"Channel"}},{"name":"conn_id","in":"path","required":true,"schema":{"type":"integer","title":"Conn Id"}},{"name":"admission_id","in":"path","required":true,"schema":{"type":"integer","title":"Admission Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/user/integrations/{channel}/{conn_id}/members/{admission_id}/{action}":{"post":{"tags":["integrations"],"summary":"Decide Channel Member","description":"Approve or block one channel user.\n\nApproving does not merely unlock the future: the ooih ingest claims the\nquestions this person asked while waiting and answers them, so the approval\nfinishes the conversation they started rather than starting a new one.","operationId":"decide_channel_member_api_user_integrations__channel___conn_id__members__admission_id___action__post","parameters":[{"name":"channel","in":"path","required":true,"schema":{"type":"string","title":"Channel"}},{"name":"conn_id","in":"path","required":true,"schema":{"type":"integer","title":"Conn Id"}},{"name":"admission_id","in":"path","required":true,"schema":{"type":"integer","title":"Admission Id"}},{"name":"action","in":"path","required":true,"schema":{"type":"string","title":"Action"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/user/identities/":{"get":{"tags":["identities"],"summary":"List Identities","operationId":"list_identities_api_user_identities__get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/user/identities":{"get":{"tags":["identities"],"summary":"List Identities","operationId":"list_identities_api_user_identities_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/user/identities/{identity_id}":{"delete":{"tags":["identities"],"summary":"Unlink Identity","operationId":"unlink_identity_api_user_identities__identity_id__delete","parameters":[{"name":"identity_id","in":"path","required":true,"schema":{"type":"integer","title":"Identity Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/user/identities/status":{"get":{"tags":["identities"],"summary":"Identity Status","description":"Unified cross-surface account-linkage state.\n\nONE source of truth every surface reads instead of re-deriving \"has the user\nlinked Telegram?\" from the raw identities list. Drives the shell-level\n\"link your account\" affordance so a logged-in-but-unlinked user gets a\nconsistent path everywhere rather than a per-page dead-end.\n\n- has_telegram      — a Telegram login is already attached.\n- can_link_telegram — signed in, no Telegram yet: the bind path is offerable.\n- bind_suggested    — a login-time duplicate was detected (a verified-email\n                      match to another account); prompt the user to unify via\n                      the safe bind+merge flow. Self-heals: once Telegram is\n                      linked the stale nudge is pruned here.","operationId":"identity_status_api_user_identities_status_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/user/identities/suggest/dismiss":{"post":{"tags":["identities"],"summary":"Dismiss Bind Suggestion","description":"Clear the login-time \"you may already have an account\" nudge.\n\nDistinct from /merge/dismiss (which drops a pending destructive merge): this\nonly silences the pre-bind suggestion so a user who really is new isn't\nnagged on every page.","operationId":"dismiss_bind_suggestion_api_user_identities_suggest_dismiss_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/user/identities/telegram/start":{"post":{"tags":["identities"],"summary":"Start Telegram Bind","description":"Mint a one-time bind token and hand back the bot deep-link.","operationId":"start_telegram_bind_api_user_identities_telegram_start_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/user/identities/telegram/pending":{"get":{"tags":["identities"],"summary":"Pending Telegram Merge","description":"The web UI polls this after showing the deep-link: returns the pending\nmerge (with preview) if binding hit an account conflict.","operationId":"pending_telegram_merge_api_user_identities_telegram_pending_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/user/identities/merge/confirm":{"post":{"tags":["identities"],"summary":"Confirm Merge","description":"Execute the account merge. Re-issues the session cookie for the\nsurvivor so the user stays signed in to the unified account.","operationId":"confirm_merge_api_user_identities_merge_confirm_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MergeConfirm"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/user/identities/merge/dismiss":{"post":{"tags":["identities"],"summary":"Dismiss Merge","operationId":"dismiss_merge_api_user_identities_merge_dismiss_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/v1/spaces":{"post":{"tags":["turns"],"summary":"Create Space","description":"Create an isolated API-native space owned by the key's account (no Telegram\nchat). The bot provisions + runs it from this DB record and routes it by the\nfleet POLICY. `engine`/`model` are DEPRECATED: when sent they are validated as\nbefore and become the space's orchestration override (the same record PUT\n/v1/spaces/{slug}/policy writes), and the response carries a `deprecation`.","operationId":"create_space_v1_spaces_post","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateSpaceIn"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"get":{"tags":["turns"],"summary":"List Spaces","description":"List the spaces this key may reach. Workspace-free:\n* A space-bound key (space_slug set) returns EXACTLY its one bound space and\n  nothing else — regardless of that space's origin or legacy workspace.\n* An account-wide key returns the account's API-native spaces; scoped to 'own'\n  it returns only the spaces it created.","operationId":"list_spaces_v1_spaces_get","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/spaces/{slug}":{"patch":{"tags":["turns"],"summary":"Patch Space","description":"Change an existing API space's engine/model. Takes effect on the space's NEXT\nturn — the running orchestrator switches engine inflight (the conversation\ncontinues from the space's memory/CONTEXT). Provide `model_pin` (an id from\nGET /v1/models) OR `engine` (+ optional `model`). Ownership + key-scope guarded.\nDEPRECATED in favour of PUT /v1/spaces/{slug}/policy {\"orchestration\": pin}.","operationId":"patch_space_v1_spaces__slug__patch","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","title":"Slug"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PatchSpaceIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/spaces/{slug}/turns":{"get":{"tags":["turns"],"summary":"List Space Turns","description":"Recent turns for an owned API space — chat history for the console.","operationId":"list_space_turns_v1_spaces__slug__turns_get","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","title":"Slug"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","default":50,"title":"Limit"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/spaces/{slug}/manifest":{"put":{"tags":["turns"],"summary":"Set Manifest","operationId":"set_manifest_v1_spaces__slug__manifest_put","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","title":"Slug"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ManifestIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"get":{"tags":["turns"],"summary":"Get Manifest","operationId":"get_manifest_v1_spaces__slug__manifest_get","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","title":"Slug"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/spaces/{slug}/secret":{"put":{"tags":["turns"],"summary":"Set Secret","description":"Store the space's app credential, encrypted (write-only — never returned in\nplaintext to the client/model; the bot gets it over the gate to inject into .env).","operationId":"set_secret_v1_spaces__slug__secret_put","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","title":"Slug"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SecretIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/spaces/{slug}/secrets":{"post":{"tags":["turns"],"summary":"Set Space Secrets","description":"Set/upsert one or more named secrets for an owned API space — the SAME encrypted\nper-space store (space_secrets) the Mini App / web UI writes. These become env vars\nthe agent's tools read (e.g. OPENAI_API_KEY). Encrypted at rest, write-only (never\nreturned). Names must match [A-Z_][A-Z0-9_]* ; reserved system names are rejected.\nSend `{name, value}` for one, or `{secrets: {NAME: value, …}}` for a batch.","operationId":"set_space_secrets_v1_spaces__slug__secrets_post","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","title":"Slug"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SpaceSecretsIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["turns"],"summary":"Set Space Secrets","description":"Set/upsert one or more named secrets for an owned API space — the SAME encrypted\nper-space store (space_secrets) the Mini App / web UI writes. These become env vars\nthe agent's tools read (e.g. OPENAI_API_KEY). Encrypted at rest, write-only (never\nreturned). Names must match [A-Z_][A-Z0-9_]* ; reserved system names are rejected.\nSend `{name, value}` for one, or `{secrets: {NAME: value, …}}` for a batch.","operationId":"set_space_secrets_v1_spaces__slug__secrets_put","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","title":"Slug"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SpaceSecretsIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"get":{"tags":["turns"],"summary":"List Space Secrets","description":"List the NAMES of a space's secrets — values are never returned (write-only store).\n`system` flags a reserved name managed by the platform.","operationId":"list_space_secrets_v1_spaces__slug__secrets_get","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","title":"Slug"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/spaces/{slug}/secrets/{name}":{"delete":{"tags":["turns"],"summary":"Delete Space Secret","description":"Delete a named secret from an owned API space.","operationId":"delete_space_secret_v1_spaces__slug__secrets__name__delete","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","title":"Slug"}},{"name":"name","in":"path","required":true,"schema":{"type":"string","title":"Name"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/spaces/{slug}/tools":{"put":{"tags":["turns"],"summary":"Set Tools","description":"Set the space's tool config: which built-in capabilities the agent may use\n(allowlist) + the client's own MCP server(s) so it can drive their app via\nstructured tools. The bot materializes this into the per-space engine MCP config.\n\nFull-replace. Use PATCH to flip a single capability without resending the set.","operationId":"set_tools_v1_spaces__slug__tools_put","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","title":"Slug"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ToolsIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"patch":{"tags":["turns"],"summary":"Patch Tools","description":"Merge-update the space's tool config. Unlike PUT (full-replace), only the\nfields present in the request body are changed — the rest are preserved.","operationId":"patch_tools_v1_spaces__slug__tools_patch","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","title":"Slug"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ToolsPatchIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"get":{"tags":["turns"],"summary":"Get Tools","operationId":"get_tools_v1_spaces__slug__tools_get","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","title":"Slug"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/tools/catalog":{"get":{"tags":["turns"],"summary":"Tools Catalog","description":"The built-in capability keys a space may put in `allow` (least-privilege).","operationId":"tools_catalog_v1_tools_catalog_get","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/spaces/{slug}/policy":{"get":{"tags":["turns"],"summary":"Get Space Policy","description":"The space's routing policy: per kind of work, the configured choice, the\nmodel it resolves to right now, the source (fleet_default, space_override,\npin, platform) and, when it is not the first choice, the typed reasons\n(INELIGIBLE, OUT_OF_BUDGET, AT_CAPACITY, UNHEALTHY). A pure read: resolving\nit can never move the space onto another model.","operationId":"get_space_policy_v1_spaces__slug__policy_get","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","title":"Slug"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["turns"],"summary":"Put Space Policy","description":"Set per-kind overrides for this space: {\"<kind>\": \"<model id>\"}. Only the\nkinds in `settable` are writable by the space (today `orchestration`, the\nspace's own default model, written exactly as the Policies tab writes it).\nAn operator-level kind is refused with OPERATOR_ONLY, an unknown kind with\nINVALID_KIND, and a model the space may not use with its typed code. Takes\neffect when the next session starts; a running session keeps its model.","operationId":"put_space_policy_v1_spaces__slug__policy_put","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","title":"Slug"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PolicyIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/spaces/{slug}/policy/{kind}":{"delete":{"tags":["turns"],"summary":"Delete Space Policy","description":"Drop this space's override for one kind, so it returns to the fleet\ndefault. For orchestration that clears the space's own model record, the\nstate a space created without engine/model starts in.","operationId":"delete_space_policy_v1_spaces__slug__policy__kind__delete","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","title":"Slug"}},{"name":"kind","in":"path","required":true,"schema":{"type":"string","title":"Kind"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/models":{"get":{"tags":["turns"],"summary":"Models Catalog","description":"The model catalog for routing policies: each model's id (the value PUT\n/v1/spaces/{slug}/policy takes), label, the kinds it may run, its price tier,\nand the fleet default policy (the table every space routes by until it sets\nan override). `engine`/`model` stay on each entry for the deprecated\nengine/model fields of POST /v1/spaces.","operationId":"models_catalog_v1_models_get","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/usage":{"get":{"tags":["turns"],"summary":"Usage Breakdown","description":"Spend ledger rolled up by end_user | space | key. scope='account' (default) =\nthe whole account (for re-billing across all your keys); scope='key' = only this\nkey's own turns (what the per-key console shows).","operationId":"usage_breakdown_v1_usage_get","parameters":[{"name":"group_by","in":"query","required":false,"schema":{"type":"string","default":"end_user","title":"Group By"}},{"name":"scope","in":"query","required":false,"schema":{"type":"string","default":"account","title":"Scope"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/spaces/{slug}/end-users/{ref}":{"patch":{"tags":["turns"],"summary":"Set End User Limit","description":"Set an end-user's cumulative spend limit (the 'grant credits' lever).","operationId":"set_end_user_limit_v1_spaces__slug__end_users__ref__patch","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","title":"Slug"}},{"name":"ref","in":"path","required":true,"schema":{"type":"string","title":"Ref"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EndUserLimitIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/spaces/{slug}/end-users":{"get":{"tags":["turns"],"summary":"List End Users","description":"List the space's end-users with cumulative spend + limit.","operationId":"list_end_users_v1_spaces__slug__end_users_get","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","title":"Slug"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/turns":{"post":{"tags":["turns"],"summary":"Create Turn","operationId":"create_turn_v1_turns_post","parameters":[{"name":"Idempotency-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Idempotency-Key"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateTurnIn"}}}},"responses":{"202":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/turns/{turn_id}":{"get":{"tags":["turns"],"summary":"Get Turn","operationId":"get_turn_v1_turns__turn_id__get","parameters":[{"name":"turn_id","in":"path","required":true,"schema":{"type":"string","title":"Turn Id"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/turns/{turn_id}/cancel":{"post":{"tags":["turns"],"summary":"Cancel Turn","operationId":"cancel_turn_v1_turns__turn_id__cancel_post","parameters":[{"name":"turn_id","in":"path","required":true,"schema":{"type":"string","title":"Turn Id"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/internal/turns/synthetic":{"post":{"tags":["turns"],"summary":"Create Synthetic Turn","description":"Agent-initiated turn for no-chat (web/api) spaces: sub-agent reports and\nwatchdog wakes become ordinary queued turns so the reply lands in the web\nthread (before this, completion reports for web spaces were DROPPED —\n'No chat_id for space … cannot re-trigger orchestrator').","operationId":"create_synthetic_turn_v1_internal_turns_synthetic_post","parameters":[{"name":"X-API-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SyntheticTurn"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/internal/turns/claim":{"post":{"tags":["turns"],"summary":"Claim Turns","description":"Internal: the bot's api-turn loop claims queued turns to run (gate `X-API-Key`).\n\nAtomically flips queued→running and returns the work (oldest first). The bot\nthen runs each as an ordinary orchestrator turn and reports back via\n/v1/internal/turns/{id}/complete. Single-writer (one bot) — no SKIP LOCKED\nneeded, and kept portable for the sqlite test path. `spaces` optionally scopes\nto the slugs this bot serves.","operationId":"claim_turns_v1_internal_turns_claim_post","parameters":[{"name":"X-API-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ClaimTurnsIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/internal/turns/{turn_id}/complete":{"post":{"tags":["turns"],"summary":"Complete Turn","description":"Internal: the bot reports a turn's result + usage over HTTP (gate `X-API-Key`).\n\nNO lease — usage is reported here at completion; billed_cost = provider_cost ×\nprovider_multiplier (compute_billed) × the key's api_markup_multiplier.","operationId":"complete_turn_v1_internal_turns__turn_id__complete_post","parameters":[{"name":"turn_id","in":"path","required":true,"schema":{"type":"string","title":"Turn Id"}},{"name":"X-API-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CompleteTurnIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/internal/turns/register":{"post":{"tags":["turns"],"summary":"Register Turn","description":"Internal: register an already-running, non-queued turn (gate `X-API-Key`).\n\nThe Bitrix in-bot ingest runs `process_message` INLINE (not via the queued→\nclaim loop), so it inserts its turn as `running` up front — with the owner-pays\n`account_id` and the `end_user_ref` (`bitrix:<user_id>`) — so completion\n(`/complete`) finds the row instead of 404ing and usage attributes per Bitrix\nuser × model for free. Idempotent: a duplicate turn_id returns the existing row\n(mirrors the old psql `ON CONFLICT DO NOTHING`).","operationId":"register_turn_v1_internal_turns_register_post","parameters":[{"name":"X-API-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RegisterTurnIn"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/internal/bitrix/members":{"post":{"tags":["turns"],"summary":"Upsert Bitrix Member","description":"Internal (gate `X-API-Key`): record a Bitrix author as a member of a space.\n\nChannel-aware membership: the ingest calls this for EVERY inbound v2 author\n(not only when the bot is addressed), so a passive participant is a member too.\nPersisted as a SpaceEndUser row — the same store that backs the owner's per-user\nenergy view — so the orchestrator's cross-space gate can check Bitrix membership\nthe way the Telegram path checks getChatMember. Idempotent on (space, ref).","operationId":"upsert_bitrix_member_v1_internal_bitrix_members_post","parameters":[{"name":"X-API-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BitrixMemberIn"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/internal/bitrix/members/{ref}":{"get":{"tags":["turns"],"summary":"Bitrix Member Spaces","description":"Internal (gate `X-API-Key`): every space slug the Bitrix end-user `ref` is a\nmember of. The orchestrator's channel-aware gate calls this for both the caller\nand target space and requires membership in both — the Bitrix analogue of the\ntwo `telegram_user_is_member` checks on the Telegram cross-space path.","operationId":"bitrix_member_spaces_v1_internal_bitrix_members__ref__get","parameters":[{"name":"ref","in":"path","required":true,"schema":{"type":"string","title":"Ref"}},{"name":"X-API-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/internal/yandex/members":{"post":{"tags":["turns"],"summary":"Upsert Yandex Member","description":"Internal (gate `X-API-Key`): record a Yandex author as a member of a space.\n\nMirrors `/internal/bitrix/members`. Channel-aware membership: the ingest calls\nthis for EVERY inbound author (not only when the bot is addressed), so a passive\nparticipant is a member too. Persisted as a SpaceEndUser row — the same store\nthat backs the owner's per-user energy view — so the orchestrator's cross-space\ngate can check Yandex membership. Idempotent on (space, ref).","operationId":"upsert_yandex_member_v1_internal_yandex_members_post","parameters":[{"name":"X-API-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/YandexMemberIn"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/internal/yandex/members/{ref}":{"get":{"tags":["turns"],"summary":"Yandex Member Spaces","description":"Internal (gate `X-API-Key`): every space slug the Yandex end-user `ref` is a\nmember of. Mirrors `/internal/bitrix/members/{ref}` — the orchestrator's\nchannel-aware gate calls this for both the caller and target space and requires\nmembership in both.","operationId":"yandex_member_spaces_v1_internal_yandex_members__ref__get","parameters":[{"name":"ref","in":"path","required":true,"schema":{"type":"string","title":"Ref"}},{"name":"X-API-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/internal/channel-identity/{ref}":{"get":{"tags":["turns"],"summary":"Channel Identity Resolve","description":"Internal (gate `X-API-Key`): who is `yandex:<user_id>` on the platform, and\nwhich spaces would that account reach?\n\nThe orchestrator's cross-space gate calls this beside\n`/internal/yandex/members/{ref}`. That one answers \"which spaces has this\nchannel identity POSTED in\"; this one answers \"which account has claimed this\nidentity as itself, and what can that account reach\" — the two namespaces that\nnever met, which is why a Yandex-origin space could not call its owner's\nTelegram DM and the DM could not call back.\n\nAn unlinked identity, an unparseable ref, or an opaque API `external_ref`\nall return `linked: false` with no spaces, so the gate's behaviour for\neverybody who has not explicitly claimed themselves is exactly what it was.\nThere is no cache on either side: an unlink takes effect on the next call.","operationId":"channel_identity_resolve_v1_internal_channel_identity__ref__get","parameters":[{"name":"ref","in":"path","required":true,"schema":{"type":"string","title":"Ref"}},{"name":"X-API-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/internal/turns/{turn_id}/result":{"get":{"tags":["turns"],"summary":"Internal Turn Result","description":"Internal: read a turn's state + result_text (gate `X-API-Key`).\n\nThe Bitrix ingest polls this after `process_message` returns to get the REAL\nuser-facing reply (result_text) to deliver into the Bitrix dialog — replacing\nthe old `psql SELECT result_text`. Not `_get_owned` (no api key owns these\ninline turns); gate-key scoped like the other internal endpoints.","operationId":"internal_turn_result_v1_internal_turns__turn_id__result_get","parameters":[{"name":"turn_id","in":"path","required":true,"schema":{"type":"string","title":"Turn Id"}},{"name":"X-API-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/internal/turns/{turn_id}/files":{"post":{"tags":["turns"],"summary":"Upload Turn File","description":"Internal: the bot ships an agent-produced file's bytes (gate X-API-Key); the dash\nstores them in the FileStore + records the opaque-id → owner binding. Keeping the\nupload here means the storage creds (Spaces) live only on the dash.","operationId":"upload_turn_file_v1_internal_turns__turn_id__files_post","parameters":[{"name":"turn_id","in":"path","required":true,"schema":{"type":"string","title":"Turn Id"}},{"name":"X-API-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Key"}}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_upload_turn_file_v1_internal_turns__turn_id__files_post"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/turns/{turn_id}/files":{"get":{"tags":["turns"],"summary":"List Turn Files","description":"Files produced by a turn in a space the caller's account owns — the console's\ndownload buttons. Account-level (like history + /v1/files/{id}), so it works\nregardless of which of the account's keys produced the turn.","operationId":"list_turn_files_v1_turns__turn_id__files_get","parameters":[{"name":"turn_id","in":"path","required":true,"schema":{"type":"string","title":"Turn Id"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/files/{file_id}":{"get":{"tags":["turns"],"summary":"Download File","description":"Download by opaque id — Bearer + ownership scoped, bytes proxied from the store.\n404 (not 403) on an unknown/non-owned id so existence isn't even leaked.","operationId":"download_file_v1_files__file_id__get","parameters":[{"name":"file_id","in":"path","required":true,"schema":{"type":"string","title":"File Id"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/spaces/{slug}/files":{"post":{"tags":["turns"],"summary":"Upload Space File","description":"Upload an attachment into a space you own — the bytes land in the FileStore as\nan unbound `upload`. Reference the returned `file_id` in `POST /v1/turns`\n(`file_ids: [...]`) to attach it to a turn; the bot then pulls the bytes into the\nspace before the agent runs (same as a Telegram file download). Key-scoped: a key\nonly reaches spaces it owns (own-scoped → only spaces it created). Max 25 MB.","operationId":"upload_space_file_v1_spaces__slug__files_post","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","title":"Slug"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_upload_space_file_v1_spaces__slug__files_post"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/internal/turns/{turn_id}/events":{"post":{"tags":["turns"],"summary":"Post Turn Events","description":"Internal: the bot's transcript tailer streams humanized activity lines\nfor a RUNNING turn (batched, ~2s cadence). Also refreshes the turn's\none-line current_activity so lightweight pollers stay cheap.","operationId":"post_turn_events_v1_internal_turns__turn_id__events_post","parameters":[{"name":"turn_id","in":"path","required":true,"schema":{"type":"string","title":"Turn Id"}},{"name":"X-API-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TurnEventsIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/internal/files/{file_id}":{"get":{"tags":["turns"],"summary":"Internal Download File","description":"Internal: the bot pulls a user-uploaded attachment's bytes (gate X-API-Key)\nto materialize it inside the space before running the turn. Mirrors the\npublic /v1/files/{id} but workspace-authed instead of key-owner-authed.","operationId":"internal_download_file_v1_internal_files__file_id__get","parameters":[{"name":"file_id","in":"path","required":true,"schema":{"type":"string","title":"File Id"}},{"name":"X-API-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/internal/usage":{"post":{"tags":["turns"],"summary":"Internal Usage","description":"Orch/Telegram usage on the clean /v1 contract — the reliable replacement for the\nfire-and-forget /gate/report. Reuses gate.record_orch_usage (the single charge-math\nentrypoint): lease_id dedup, subscription envelope/overage, balance debit. Writes the\n`usage` ledger (kept SEPARATE from `api_turns`).","operationId":"internal_usage_v1_internal_usage_post","parameters":[{"name":"X-API-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UsageReport"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/chat/conversations":{"get":{"tags":["chat"],"summary":"List Conversations","description":"My web-chat conversations — owned and joined — newest activity first.","operationId":"list_conversations_api_chat_conversations_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}},"post":{"tags":["chat"],"summary":"Create Conversation","description":"Create the backing space for a web-chat conversation.","operationId":"create_conversation_api_chat_conversations_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateConversation"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/chat/knowledge-destinations":{"get":{"tags":["chat"],"summary":"Knowledge Destinations","operationId":"knowledge_destinations_api_chat_knowledge_destinations_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/chat/{slug}/knowledge-imports":{"get":{"tags":["chat"],"summary":"Knowledge Imports","operationId":"knowledge_imports_api_chat__slug__knowledge_imports_get","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","title":"Slug"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/chat/send":{"post":{"tags":["chat"],"summary":"Send Message","description":"Queue a web-turn for the conversation's space (optionally with uploads).","operationId":"send_message_api_chat_send_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SendMessage"}}},"required":true},"responses":{"202":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/chat/turns/{turn_id}":{"get":{"tags":["chat"],"summary":"Get Turn","operationId":"get_turn_api_chat_turns__turn_id__get","parameters":[{"name":"turn_id","in":"path","required":true,"schema":{"type":"string","title":"Turn Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/chat/turns/{turn_id}/events":{"get":{"tags":["chat"],"summary":"List Turn Events","description":"Activity feed of MY turn — what the agent is doing/did, step by step.\nPoll with ?after=<last seen id> for the live tail.","operationId":"list_turn_events_api_chat_turns__turn_id__events_get","parameters":[{"name":"turn_id","in":"path","required":true,"schema":{"type":"string","title":"Turn Id"}},{"name":"after","in":"query","required":false,"schema":{"type":"integer","default":0,"title":"After"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/chat/transcribe":{"post":{"tags":["chat"],"summary":"Transcribe Audio","description":"Transcribe a voice recording to text (OpenAI Whisper). Stateless — voice\nis an input method; the caller edits the text and sends it as a normal\nmessage. No audio is stored.","operationId":"transcribe_audio_api_chat_transcribe_post","requestBody":{"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_transcribe_audio_api_chat_transcribe_post"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/chat/{slug}/files":{"post":{"tags":["chat"],"summary":"Upload Chat File","description":"Upload an attachment into the conversation's space. Unbound until the\nnext send() lists its id — then it rides that turn to the orchestrator.","operationId":"upload_chat_file_api_chat__slug__files_post","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","title":"Slug"}}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_upload_chat_file_api_chat__slug__files_post"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/chat/turns/{turn_id}/files":{"get":{"tags":["chat"],"summary":"List Turn Files","description":"All files of a turn in my chat — uploads and the agent's output.","operationId":"list_turn_files_api_chat_turns__turn_id__files_get","parameters":[{"name":"turn_id","in":"path","required":true,"schema":{"type":"string","title":"Turn Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/chat/{slug}/space-file":{"get":{"tags":["chat"],"summary":"Get Space File","description":"Stream a file the agent saved in the space's folder, addressed by RELATIVE\npath (e.g. downloads/cat.png). No per-file registration — the agent just saves\nto downloads/ and it's linkable by relative path.","operationId":"get_space_file_api_chat__slug__space_file_get","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","title":"Slug"}},{"name":"path","in":"query","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"}}}}}}},"/api/chat/link-preview":{"get":{"tags":["chat"],"summary":"Link Preview","description":"OpenGraph card data for a URL mentioned in a chat message.","operationId":"link_preview_api_chat_link_preview_get","parameters":[{"name":"url","in":"query","required":true,"schema":{"type":"string","title":"Url"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/chat/artifacts":{"get":{"tags":["chat"],"summary":"List Artifacts","description":"Everything produced across my chats, grouped by conversation: uploaded\nfiles, agent-made files, and Google Drive links harvested from the thread.","operationId":"list_artifacts_api_chat_artifacts_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/chat/{slug}/attach/{file_id}":{"post":{"tags":["chat"],"summary":"Attach Existing File","description":"Re-attach a file from another of my chats into this one: a new unbound\nupload row pointing at the same stored bytes (nothing is copied). The next\nsend() lists the returned file_id like any fresh upload.","operationId":"attach_existing_file_api_chat__slug__attach__file_id__post","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","title":"Slug"}},{"name":"file_id","in":"path","required":true,"schema":{"type":"string","title":"File Id"}}],"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/chat/files/{file_id}":{"get":{"tags":["chat"],"summary":"Download Chat File","description":"Stream a file by opaque id — for the owner or any chat member.","operationId":"download_chat_file_api_chat_files__file_id__get","parameters":[{"name":"file_id","in":"path","required":true,"schema":{"type":"string","title":"File Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/chat/{slug}/messages":{"get":{"tags":["chat"],"summary":"Conversation Messages","description":"The shared thread, reconstructed from the space's turns: one user entry\n(sender name + uploads) and one agent entry (reply + generated files +\nsteps key) per turn. Clients poll and diff by turn_id.","operationId":"conversation_messages_api_chat__slug__messages_get","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","title":"Slug"}},{"name":"thread","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Thread"}},{"name":"main_thread","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"Main Thread"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/chat/tg-spaces":{"get":{"tags":["chat"],"summary":"Tg Spaces","description":"The user's Telegram spaces (current board member by telegram_id), with a\nlast-message preview — feeds the read-only TG section of the chat sidebar.","operationId":"tg_spaces_api_chat_tg_spaces_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/chat/{slug}/tg-messages":{"get":{"tags":["chat"],"summary":"Tg Messages","description":"Read-only conversation of a Telegram space from the unified message log.","operationId":"tg_messages_api_chat__slug__tg_messages_get","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","title":"Slug"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/chat/{slug}/invites":{"post":{"tags":["chat"],"summary":"Create Invite","description":"Mint a shareable join link — project-wide or scoped to one chat (thread).\nOnly the owner or a member explicitly granted can_invite may call this; a\nplain member gets 403. NB: scope is visibility-level; the project stays the\nconfidentiality boundary (shared memory spans threads).","operationId":"create_invite_api_chat__slug__invites_post","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","title":"Slug"}}],"requestBody":{"content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/CreateInviteBody"},{"type":"null"}],"title":"Body"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/chat/invites/{token}":{"get":{"tags":["chat"],"summary":"Preview Invite","operationId":"preview_invite_api_chat_invites__token__get","parameters":[{"name":"token","in":"path","required":true,"schema":{"type":"string","title":"Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/chat/invites/{token}/accept":{"post":{"tags":["chat"],"summary":"Accept Invite","operationId":"accept_invite_api_chat_invites__token__accept_post","parameters":[{"name":"token","in":"path","required":true,"schema":{"type":"string","title":"Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/chat/{slug}/members":{"get":{"tags":["chat"],"summary":"List Members","operationId":"list_members_api_chat__slug__members_get","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","title":"Slug"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/chat/{slug}/members/{member_id}":{"delete":{"tags":["chat"],"summary":"Remove Member","description":"Owner removes a member; anyone can remove THEMSELVES (leave).","operationId":"remove_member_api_chat__slug__members__member_id__delete","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","title":"Slug"}},{"name":"member_id","in":"path","required":true,"schema":{"type":"integer","title":"Member Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"patch":{"tags":["chat"],"summary":"Patch Member","description":"Owner grants/revokes a member's invite permission.","operationId":"patch_member_api_chat__slug__members__member_id__patch","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","title":"Slug"}},{"name":"member_id","in":"path","required":true,"schema":{"type":"integer","title":"Member Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PatchMemberBody"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/images/catalog":{"get":{"tags":["images"],"summary":"Catalog","operationId":"catalog_api_images_catalog_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/images":{"get":{"tags":["images"],"summary":"History","operationId":"history_api_images_get","parameters":[{"name":"offset","in":"query","required":false,"schema":{"type":"integer","maximum":10000,"minimum":0,"default":0,"title":"Offset"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":48,"minimum":1,"default":24,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["images"],"summary":"Generate","operationId":"generate_api_images_post","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenerateImage"}}}},"responses":{"202":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/images/{turn_id}":{"get":{"tags":["images"],"summary":"Get Job","operationId":"get_job_api_images__turn_id__get","parameters":[{"name":"turn_id","in":"path","required":true,"schema":{"type":"string","title":"Turn Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/chat/schedules":{"get":{"tags":["schedules"],"summary":"My Schedules","description":"My scheduled tasks grouped by conversation (same shape as artifacts).","operationId":"my_schedules_api_chat_schedules_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/chat/{slug}/schedules":{"get":{"tags":["schedules"],"summary":"Space Schedules","description":"The configured, pending schedules of ONE space — the operational-center\nSchedule panel.\n\nOwner-OR-member scoped and ANY origin, via the same `resolve_space_role`\nresolver the status page (`status.py`) and the keys/secrets pages use: the\ncaller may OWN the space or be a MEMBER of it (web `space_members`, or a\ncurrent Telegram board member). This is the fix for the operational center\nreading `GET /api/chat/schedules` (`my_schedules` → `_my_spaces`), which is\nfenced to `origin='api'` web chats — so a Telegram-origin space's schedules\nnever surfaced there, for owner or member alike. Scoped strictly to this one\n`slug` (no cross-space rows), active|paused only, next-soonest first — the\nsame window `/api/user/status` uses.","operationId":"space_schedules_api_chat__slug__schedules_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"}}}}}},"post":{"tags":["schedules"],"summary":"Create Schedule","operationId":"create_schedule_api_chat__slug__schedules_post","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","title":"Slug"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateSchedule"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/chat/schedules/{schedule_id}":{"patch":{"tags":["schedules"],"summary":"Patch Schedule","operationId":"patch_schedule_api_chat_schedules__schedule_id__patch","parameters":[{"name":"schedule_id","in":"path","required":true,"schema":{"type":"integer","title":"Schedule Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PatchSchedule"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/admin/schedules":{"get":{"tags":["schedules"],"summary":"All Schedules","operationId":"all_schedules_api_admin_schedules_get","parameters":[{"name":"status","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Status"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/internal/schedules":{"get":{"tags":["schedules"],"summary":"Sync Schedules","description":"Active set for the bot (scheduler cache / the agent's schedule-list tool).\nPaused/canceled rows are omitted — absence means «don't fire».\n\nTwo different consumers share this endpoint, and they need different sets:\n\n* the bot's FIRING poller calls it unscoped (`pull_active()` -> run_due_once);\n* the agent's schedule-list tool always names its own space (`?space=<slug>`).\n\nPLAIN api-origin rows are dropped from the UNSCOPED feed only. THIS service fires\nthem (the schedule_fire loop), and they are absent from the bot's Telegram\nregistry by design, so handing them to the firing poller made the two\nschedulers race for the same due slot: the bot logged \"Skipping schedule for\nabsent space\", could not fire, then marked the row fired anyway (run_due_once\nreports unconditionally), consuming the occurrence. Whenever the bot won that\nrace the turn silently never ran — web-e74c8b989a46 was dropped on\n07-19/20/21/22/24/25 and only ran on 07-28/29/30.\n\nCONDITIONAL rows (trigger_config set) are the exception: dash does NOT fire them\n(schedule_fire skips any row with a trigger_config), so there is no race to\navoid. The bot must receive them regardless of origin — it runs the cheap CHECK\neach tick and only wakes a billable turn on a hit. Excluding api-origin\nconditional rows here left web/API-native triggers with no firing path at all,\nso they are carried through below.\n\nA named `?space=` still returns everything, because that is the read path an\nAPI-native space uses to list its OWN schedules; filtering there would trade\nthe race for a blind agent. The bot additionally skips PLAIN api-origin rows\nitself (schedule_sync._is_api_origin_space), so plain-row firing stays guarded\nfrom both ends.","operationId":"sync_schedules_v1_internal_schedules_get","parameters":[{"name":"space","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Space"}},{"name":"X-API-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/internal/schedules/cancel":{"post":{"tags":["schedules"],"summary":"Cancel Schedules","description":"The agent's schedule-remove path.\n\nTwo modes, chosen by whether `schedule_id` is supplied:\n  - with it:    cancel that one row (id + space + active/paused), no matching;\n  - without it: today's behaviour — cancel every active/paused row of the\n                space whose title OR prompt contains the query. The agent's\n                user-facing \"delete my schedule X\" only has a title, so this\n                path has to stay exactly as it was.\n\nCallers holding an id (e.g. the bot's auto-cancel after N failed firings)\nmust send it: the title match alone can take out sibling schedules whose\nnames differ only by a suffix, or whose *prompt* merely mentions another\nschedule's title.\n\nOptionally records WHY, via `reason` (free text) and `actor` (who — the bot\nsends 'auto' for the failure-streak cancel and 'agent' for a user-requested\nremoval). These are the only thing that will ever tell the two apart: both\nevents arrive here with an otherwise identical payload, and until now the\nsole record of which was a line in the bot's log file. Every row the call\ncancels gets the same pair, because one call is one cancelling event.\nOmitting them is exactly the previous behaviour — the columns stay NULL.\nNeither can fail the cancel: an over-long reason is truncated, not rejected.","operationId":"cancel_schedules_v1_internal_schedules_cancel_post","parameters":[{"name":"X-API-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CancelByTitle"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/internal/schedules/{schedule_id}/fired":{"post":{"tags":["schedules"],"summary":"Report Fired","operationId":"report_fired_v1_internal_schedules__schedule_id__fired_post","parameters":[{"name":"schedule_id","in":"path","required":true,"schema":{"type":"integer","title":"Schedule Id"}},{"name":"X-API-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FiredReport"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/internal/schedules/{schedule_id}/checked":{"post":{"tags":["schedules"],"summary":"Report Checked","description":"Persist a conditional schedule's per-tick evaluator state + health. The\ncheap check bills nothing; only a wake (fired=True → reported via the normal\nturn path) enters the owner-pays flow. Advances next_fire_at like /fired so the\ncheck keeps recurring, but only stamps last_fired_at/check_last_wake_at on a wake.","operationId":"report_checked_v1_internal_schedules__schedule_id__checked_post","parameters":[{"name":"schedule_id","in":"path","required":true,"schema":{"type":"integer","title":"Schedule Id"}},{"name":"X-API-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CheckReport"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/internal/schedules/import":{"post":{"tags":["schedules"],"summary":"Import Schedules","description":"Bulk upsert from the bot (legacy SQLite import + TG-created schedules).\nIdempotent on (space_slug, external_ref); created_by keeps the real creator.","operationId":"import_schedules_v1_internal_schedules_import_post","parameters":[{"name":"X-API-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ImportRow"},"title":"Rows"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/admin/agents/active":{"get":{"tags":["agents"],"summary":"Admin Active Agents","operationId":"admin_active_agents_api_admin_agents_active_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/chat/{slug}/agents":{"get":{"tags":["agents"],"summary":"Chat Active Agents","description":"Subagents of one of my chats (member-scoped): live rows + recently\nfinished ones, so the panel shows «работает с …» AND «остановился в …».","operationId":"chat_active_agents_api_chat__slug__agents_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"}}}}}}},"/v1/internal/agents/snapshot":{"post":{"tags":["agents"],"summary":"Post Snapshot","description":"Upsert the bot's current heartbeat set (≤200 rows per post). Old rows\nare purged opportunistically; absence from a snapshot simply ages out.","operationId":"post_snapshot_v1_internal_agents_snapshot_post","parameters":[{"name":"X-API-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/AgentSnapshot"},"title":"Agents"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/internal/agents/journal":{"post":{"tags":["agents"],"summary":"Post Journal","description":"Append sub-agent lifecycle events to the journal (≤500 per post).\n\nIdempotent per `dedup_key`; auth is the workspace gate key, exactly like\n`/agents/snapshot`. See :func:`ingest_journal_events` for the batch semantics.","operationId":"post_journal_v1_internal_agents_journal_post","parameters":[{"name":"X-API-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/JournalEvent"},"title":"Events"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/space-secrets/req/{token}":{"get":{"tags":["space-secrets"],"summary":"Secrets Req","operationId":"secrets_req_api_space_secrets_req__token__get","parameters":[{"name":"token","in":"path","required":true,"schema":{"type":"string","title":"Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/space-secrets/cap/{token}":{"get":{"tags":["space-secrets"],"summary":"Secrets Cap Resolve","description":"Resolve an account-less capability token (peek only — does not consume it).\nReturns which space + which keys the link is for. No existing secret names are\nreturned to an anonymous holder, and never any values.","operationId":"secrets_cap_resolve_api_space_secrets_cap__token__get","parameters":[{"name":"token","in":"path","required":true,"schema":{"type":"string","title":"Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["space-secrets"],"summary":"Secrets Cap Submit","description":"Account-less secret submission. Redeems a single-use capability: writes only\nkeys the token scopes (its need_keys, if any), never overwrites an owner-set key,\nblocks system keys, then consumes the token so it cannot be replayed.","operationId":"secrets_cap_submit_api_space_secrets_cap__token__post","parameters":[{"name":"token","in":"path","required":true,"schema":{"type":"string","title":"Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SecretsSubmit"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/space-secrets/{slug}":{"get":{"tags":["space-secrets"],"summary":"Get Secrets","operationId":"get_secrets_api_space_secrets__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"}}}}}},"post":{"tags":["space-secrets"],"summary":"Post Secrets","operationId":"post_secrets_api_space_secrets__slug__post","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","title":"Slug"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SecretsSubmit"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/space-secrets/{slug}/{name}":{"delete":{"tags":["space-secrets"],"summary":"Delete Secret","operationId":"delete_secret_api_space_secrets__slug___name__delete","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","title":"Slug"}},{"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"}}}}}}},"/api/telegram-connect/req/{token}":{"get":{"tags":["telegram-connect"],"summary":"Connect Req","operationId":"connect_req_api_telegram_connect_req__token__get","parameters":[{"name":"token","in":"path","required":true,"schema":{"type":"string","title":"Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/telegram-connect/{slug}/status":{"get":{"tags":["telegram-connect"],"summary":"Connect Status","operationId":"connect_status_api_telegram_connect__slug__status_get","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","title":"Slug"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/telegram-connect/{slug}/step":{"post":{"tags":["telegram-connect"],"summary":"Connect Step","operationId":"connect_step_api_telegram_connect__slug__step_post","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","title":"Slug"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StepIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/telegram-connect/{slug}/start":{"post":{"tags":["telegram-connect"],"summary":"Connect Start","description":"Owner mints a fresh connect request from the web and gets the Mini-App deep\nlink to open in Telegram. Session-auth counterpart to gate `telegram/connect/mint`\n(which the orchestrator bot uses to send the same link in-chat).\n\nA space can carry several accounts — starting a flow does NOT disturb the\naccounts already connected; it only replaces any in-flight request. `label`\noptionally names the account being added (e.g. \"Reception\").","operationId":"connect_start_api_telegram_connect__slug__start_post","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","title":"Slug"}},{"name":"lang","in":"query","required":false,"schema":{"type":"string","default":"en","title":"Lang"}},{"name":"label","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Label"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/telegram-connect/{slug}/accounts":{"get":{"tags":["telegram-connect"],"summary":"Connect Accounts","description":"Connected Telegram accounts for a space (no secrets). Any member may read.","operationId":"connect_accounts_api_telegram_connect__slug__accounts_get","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","title":"Slug"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/telegram-connect/{slug}/accounts/{account_id}/default":{"post":{"tags":["telegram-connect"],"summary":"Connect Account Default","operationId":"connect_account_default_api_telegram_connect__slug__accounts__account_id__default_post","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","title":"Slug"}},{"name":"account_id","in":"path","required":true,"schema":{"type":"string","title":"Account Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/telegram-connect/{slug}/accounts/{account_id}":{"delete":{"tags":["telegram-connect"],"summary":"Connect Account Disconnect","operationId":"connect_account_disconnect_api_telegram_connect__slug__accounts__account_id__delete","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","title":"Slug"}},{"name":"account_id","in":"path","required":true,"schema":{"type":"string","title":"Account Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/telegram-connect/{slug}/accounts/{account_id}/disconnect":{"post":{"tags":["telegram-connect"],"summary":"Connect Account Disconnect","operationId":"connect_account_disconnect_api_telegram_connect__slug__accounts__account_id__disconnect_post","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","title":"Slug"}},{"name":"account_id","in":"path","required":true,"schema":{"type":"string","title":"Account Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/telegram-connect/{slug}/state":{"get":{"tags":["telegram-connect"],"summary":"Connect State","description":"Space-level Telegram connection state for the settings/secrets panel.\n\n`connected` is durable (a completed request keeps `phase == \"active\"`); a live\nin-progress request also surfaces its `deep_link` so the owner can resume.\nAny member may read it; only the owner may `start`.","operationId":"connect_state_api_telegram_connect__slug__state_get","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","title":"Slug"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/space-api-keys/req/{token}":{"get":{"tags":["space-api-keys"],"summary":"Review Request","description":"Bootstrap the owner-review page: the space it targets, whether the key is still\nmintable (pending) or already issued, and the space's existing keys (management).\nOwner-gated — a member who is not the owner gets 403, never the list.","operationId":"review_request_api_space_api_keys_req__token__get","parameters":[{"name":"token","in":"path","required":true,"schema":{"type":"string","title":"Token"}},{"name":"X-Init-Data","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Init-Data"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/space-api-keys/req/{token}/mint":{"post":{"tags":["space-api-keys"],"summary":"Mint Request","description":"Owner-only, reveal-once: mint the space-bound key and return the plaintext token\nexactly once. A second call after the key exists is a 409 — the secret is gone.","operationId":"mint_request_api_space_api_keys_req__token__mint_post","parameters":[{"name":"token","in":"path","required":true,"schema":{"type":"string","title":"Token"}},{"name":"X-Init-Data","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Init-Data"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/space-api-keys/{slug}/keys":{"get":{"tags":["space-api-keys"],"summary":"List Keys","description":"Owner-only management list of a space's owner-issued keys (no plaintext).","operationId":"list_keys_api_space_api_keys__slug__keys_get","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","title":"Slug"}},{"name":"X-Init-Data","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Init-Data"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["space-api-keys"],"summary":"Issue Key","description":"Owner-only, reveal-once: mint an ADDITIONAL space-bound key (beyond the one from\nthe original review link) so a space can rotate/segment keys. Same binding as the\nreview-link mint — space_slug pinned, account_id the approving owner, issued_via\n'owner_link' — so the membership tie-off and per-key daily cap apply identically.\nThe plaintext is returned exactly once.","operationId":"issue_key_api_space_api_keys__slug__keys_post","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","title":"Slug"}},{"name":"X-Init-Data","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Init-Data"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/IssueKeyIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/space-api-keys/{slug}/keys/{key_id}/revoke":{"post":{"tags":["space-api-keys"],"summary":"Revoke Key","description":"Owner-only soft revoke of one of the space's owner-issued keys. Billing rows\nsurvive; the key stops authenticating immediately (active=False).","operationId":"revoke_key_api_space_api_keys__slug__keys__key_id__revoke_post","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","title":"Slug"}},{"name":"key_id","in":"path","required":true,"schema":{"type":"integer","title":"Key Id"}},{"name":"X-Init-Data","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Init-Data"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/space-api-keys/{slug}/keys/{key_id}/cap":{"post":{"tags":["space-api-keys"],"summary":"Set Cap","description":"Owner-only: change one key's daily spend cap. Enforced on the key's NEXT turn —\nPOST /v1/turns pre-checks today's spend against this cap and returns 429 once it is\nreached (routers/turns.py create_turn), so lowering it here throttles immediately.","operationId":"set_cap_api_space_api_keys__slug__keys__key_id__cap_post","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","title":"Slug"}},{"name":"key_id","in":"path","required":true,"schema":{"type":"integer","title":"Key Id"}},{"name":"X-Init-Data","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Init-Data"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetCapIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/gate/spaces/{slug}/subkeys":{"post":{"tags":["gate"],"summary":"Mint Subkey","operationId":"mint_subkey_api_gate_spaces__slug__subkeys_post","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","title":"Slug"}},{"name":"X-API-Key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MintIn"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"get":{"tags":["gate"],"summary":"List Subkeys Gate","operationId":"list_subkeys_gate_api_gate_spaces__slug__subkeys_get","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","title":"Slug"}},{"name":"X-API-Key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/gate/spaces/{slug}/subkeys/{key_id}":{"delete":{"tags":["gate"],"summary":"Revoke Subkey Gate","operationId":"revoke_subkey_gate_api_gate_spaces__slug__subkeys__key_id__delete","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","title":"Slug"}},{"name":"key_id","in":"path","required":true,"schema":{"type":"integer","title":"Key Id"}},{"name":"archive_subspace","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"Archive Subspace"}},{"name":"X-API-Key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/user/spaces/{slug}/subkeys":{"get":{"tags":["subkeys"],"summary":"List Subkeys","description":"The Operation Center's Sub-spaces section. For a main space: its sub-spaces\nand their keys (prefix only). For a sub-space: the main space it belongs to,\nso the page can link back.","operationId":"list_subkeys_api_user_spaces__slug__subkeys_get","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","title":"Slug"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/user/spaces/{slug}/subkeys/{key_id}/revoke":{"post":{"tags":["subkeys"],"summary":"Revoke Subkey","operationId":"revoke_subkey_api_user_spaces__slug__subkeys__key_id__revoke_post","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","title":"Slug"}},{"name":"key_id","in":"path","required":true,"schema":{"type":"integer","title":"Key Id"}}],"requestBody":{"content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/RevokeIn"},{"type":"null"}],"title":"Body"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/user/feedback":{"post":{"tags":["feedback"],"summary":"Submit Feedback","operationId":"submit_feedback_api_user_feedback_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FeedbackCreate"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/user/feedback/mine":{"get":{"tags":["feedback"],"summary":"My Feedback","operationId":"my_feedback_api_user_feedback_mine_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/user/feedback/{feedback_id}/reply":{"post":{"tags":["feedback"],"summary":"Reply To Feedback","operationId":"reply_to_feedback_api_user_feedback__feedback_id__reply_post","parameters":[{"name":"feedback_id","in":"path","required":true,"schema":{"type":"integer","title":"Feedback Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReplyCreate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/admin/feedback":{"get":{"tags":["admin-feedback"],"summary":"Admin List Feedback","operationId":"admin_list_feedback_api_admin_feedback_get","parameters":[{"name":"status","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Status"}},{"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"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/admin/feedback/unread-count":{"get":{"tags":["admin-feedback"],"summary":"Admin Unread Count","description":"Badge for the console nav: live threads waiting on an admin answer.","operationId":"admin_unread_count_api_admin_feedback_unread_count_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/admin/feedback/{feedback_id}/reply":{"post":{"tags":["admin-feedback"],"summary":"Admin Reply Feedback","operationId":"admin_reply_feedback_api_admin_feedback__feedback_id__reply_post","parameters":[{"name":"feedback_id","in":"path","required":true,"schema":{"type":"integer","title":"Feedback Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReplyCreate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/admin/feedback/{feedback_id}/resolve":{"post":{"tags":["admin-feedback"],"summary":"Resolve Feedback","operationId":"resolve_feedback_api_admin_feedback__feedback_id__resolve_post","parameters":[{"name":"feedback_id","in":"path","required":true,"schema":{"type":"integer","title":"Feedback Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/admin/feedback/{feedback_id}/reopen":{"post":{"tags":["admin-feedback"],"summary":"Reopen Feedback","operationId":"reopen_feedback_api_admin_feedback__feedback_id__reopen_post","parameters":[{"name":"feedback_id","in":"path","required":true,"schema":{"type":"integer","title":"Feedback Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/chat/projects":{"get":{"tags":["projects"],"summary":"My Projects","description":"Default-view payload: my projects (owned or member) with their threads.","operationId":"my_projects_api_chat_projects_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}},"post":{"tags":["projects"],"summary":"Create Project","description":"Create the backing space + project + its first thread. Reuses the\nconversation-space machinery so engine pinning / provisioning stay one path.","operationId":"create_project_api_chat_projects_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateProject"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/chat/projects/{project_id}":{"patch":{"tags":["projects"],"summary":"Rename Project","operationId":"rename_project_api_chat_projects__project_id__patch","parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"integer","title":"Project Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RenameProject"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["projects"],"summary":"Delete Project","description":"Soft-delete a whole space (project + its chats). Owner only — members\nleave instead. Stamps both chat_projects and the backing spaces row so the\nspace drops out of every list while usage/billing history is preserved.","operationId":"delete_project_api_chat_projects__project_id__delete","parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"integer","title":"Project Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/chat/projects/{project_id}/threads/{thread_id}":{"patch":{"tags":["projects"],"summary":"Rename Thread","description":"Rename a thread — also how threads AUTO-NAME: the client derives a title\nfrom the first message sent into a titleless thread.","operationId":"rename_thread_api_chat_projects__project_id__threads__thread_id__patch","parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"integer","title":"Project Id"}},{"name":"thread_id","in":"path","required":true,"schema":{"type":"string","title":"Thread Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RenameThread"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["projects"],"summary":"Delete Thread","description":"Soft-delete a single chat (thread). Any space member may; the last\nremaining chat can't be deleted on its own — delete the space instead.","operationId":"delete_thread_api_chat_projects__project_id__threads__thread_id__delete","parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"integer","title":"Project Id"}},{"name":"thread_id","in":"path","required":true,"schema":{"type":"string","title":"Thread Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/chat/projects/{project_id}/threads":{"post":{"tags":["projects"],"summary":"Create Thread","description":"P2 is live: every thread is an independent orchestrator lineage\n(data/threads/<tid>/) over the project's ONE shared memory.","operationId":"create_thread_api_chat_projects__project_id__threads_post","parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"integer","title":"Project Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateThread"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/user/spaces":{"get":{"tags":["user-spaces"],"summary":"My Spaces","operationId":"my_spaces_api_user_spaces_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/user/spaces/{space_id}/payer":{"post":{"tags":["user-spaces"],"summary":"Change Space Payer","description":"Transfer or renounce the space's shared payer responsibility.\n\nThe current owner row is locked so two concurrent transfers cannot both\nsucceed. Only the current owner may call this. The target may be ANY\ncurrently active member of the space — Telegram role is not a gate.","operationId":"change_space_payer_api_user_spaces__space_id__payer_post","parameters":[{"name":"space_id","in":"path","required":true,"schema":{"type":"integer","title":"Space Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChangeSpacePayer"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/user/spaces/{space_id}":{"patch":{"tags":["user-spaces"],"summary":"Patch My Space","operationId":"patch_my_space_api_user_spaces__space_id__patch","parameters":[{"name":"space_id","in":"path","required":true,"schema":{"type":"integer","title":"Space Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PatchMySpace"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/user/tools/catalog":{"get":{"tags":["user-spaces"],"summary":"My Tools Catalog","description":"The capability catalog (keys + labels + billable/gated flags) the owner\npanel renders as toggles. Same source of truth as GET /v1/tools/catalog.","operationId":"my_tools_catalog_api_user_tools_catalog_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/user/spaces/{space_id}/tools":{"get":{"tags":["user-spaces"],"summary":"My Space Tools","description":"This space's capability policy: `allow` (the ON keys, or null for\nunrestricted). Drives the toggle panel's initial state.","operationId":"my_space_tools_api_user_spaces__space_id__tools_get","parameters":[{"name":"space_id","in":"path","required":true,"schema":{"type":"integer","title":"Space Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"patch":{"tags":["user-spaces"],"summary":"Patch My Space Tools","description":"Flip the space's capability allow-list. Merges into tools_config (preserves\nthe client's mcp_servers) and reconciles the premium *_access gates, so one\nswitch updates both the owner policy and the funding-gate eligibility.","operationId":"patch_my_space_tools_api_user_spaces__space_id__tools_patch","parameters":[{"name":"space_id","in":"path","required":true,"schema":{"type":"integer","title":"Space Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PatchSpaceTools"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/user/spaces/{space_id}/usage-limits":{"get":{"tags":["user-spaces"],"summary":"My Space Usage Limits","description":"This space's windowed usage caps (space-wide + per-end-user). Additional to\nthe monthly `budget_usd`; the owner panel renders these as editable rows.","operationId":"my_space_usage_limits_api_user_spaces__space_id__usage_limits_get","parameters":[{"name":"space_id","in":"path","required":true,"schema":{"type":"integer","title":"Space Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["user-spaces"],"summary":"Put My Space Usage Limit","description":"Upsert (or, with amount=null, delete) one windowed cap for this space.\n\nOne cap per (space, principal, window, metric) — a repeat PUT overwrites the\namount. Enforced BEFORE debit at the gate/turn seams (`app.usage_caps`).","operationId":"put_my_space_usage_limit_api_user_spaces__space_id__usage_limits_put","parameters":[{"name":"space_id","in":"path","required":true,"schema":{"type":"integer","title":"Space Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UsageLimitIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/user/model-catalog":{"get":{"tags":["user-spaces"],"summary":"My Model Catalog","description":"The ENABLED orchestrator engines/models for the owner's picker, in sort\norder — the same set patch_my_space validates a pick against. admin_only pins\nare hidden from non-admins (shown to platform admins).","operationId":"my_model_catalog_api_user_model_catalog_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/user/spaces/{space_id}/members":{"get":{"tags":["user-spaces"],"summary":"My Space Members","description":"Owner view: members with per-member spend (actor attribution) over the\nselected window. Each member carries `can_trigger` — whether the access\npolicy lets them spend the owner's energy (the bot-access toggle).","operationId":"my_space_members_api_user_spaces__space_id__members_get","parameters":[{"name":"space_id","in":"path","required":true,"schema":{"type":"integer","title":"Space Id"}},{"name":"from","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"From"}},{"name":"to","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"To"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/user/spaces/{space_id}/usage":{"get":{"tags":["user-spaces"],"summary":"My Space Usage","description":"Owner view: daily billed spend of ONE space over the window, optionally\nfiltered to a single spender (`actor` = telegram_id for TG / account_id for\nweb). Drives the per-space chart and its by-user filter.","operationId":"my_space_usage_api_user_spaces__space_id__usage_get","parameters":[{"name":"space_id","in":"path","required":true,"schema":{"type":"integer","title":"Space Id"}},{"name":"from","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"From"}},{"name":"to","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"To"}},{"name":"actor","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Actor"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/user/spaces/{space_id}/apps":{"get":{"tags":["user-spaces"],"summary":"My Space Apps","description":"Owner view: the Octo Spaces (Lizard PaaS) apps deployed in ONE owned\nspace, each with its lifetime compute cost + the energy (credit-micros)\ncharged to the owner. Reads the space_usage billing ledger, grouped by\nproject_id; mirrors the admin consumption endpoint but scoped to the\nowner's own space. Empty until the hourly meter records a settled cycle.","operationId":"my_space_apps_api_user_spaces__space_id__apps_get","parameters":[{"name":"space_id","in":"path","required":true,"schema":{"type":"integer","title":"Space Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/user/apps":{"get":{"tags":["user-spaces"],"summary":"My Apps","description":"Owner view: every Octo Spaces (Lizard PaaS) app across ALL the caller's\nowned spaces, rolled up per app instead of the noisy per-hour ledger rows\n(space_usage charges the owner every settled hourly window — see\ntools/lizard_meter.py in the ooih repo). Same columns as GET\n/spaces/{id}/apps (mirrors its query minus the single-space filter), plus\nspace_id/space_slug/space_title so a multi-space owner can tell apps apart.\nPowers the /billing/history \"App maintenance\" tab and the /apps page.\n\n`?space=<slug>` narrows to ONE space, SERVER-side — /apps is grouped per\nspace, and a link from a space's status page or its spaces row lands\npre-filtered without the browser fanning out one request per owned space.\nThe filter can only ever NARROW: it is applied to the already-owner-scoped\nslug set, so an unknown or someone else's slug intersects to nothing and\nreturns empty — never another owner's apps.\n\n`apps` are the BILLED apps (>=1 settled meter cycle). `unmetered` is the\nseparate set of apps that are deployed and running but whose first hourly\ncycle has not settled yet — kept OUT of `apps`/`totals` so the billing\nledger view (/billing/history) is byte-for-byte what it was, and surfaced so\na deploy from minutes ago reads as \"not yet metered\" instead of as \"you have\nno apps\".","operationId":"my_apps_api_user_apps_get","parameters":[{"name":"space","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"narrow to ONE owned space, by slug","title":"Space"},"description":"narrow to ONE owned space, by slug"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/user/spaces/{space_id}/apps/{project_id}/teardown":{"post":{"tags":["user-spaces"],"summary":"Teardown Space App","description":"Tear down ONE deployed app of an owned space — destructive, owner-only.\n\nGuards, in order:\n  * `_owned_space` — the OWNER, never a member-admitting resolver like\n    `_resolve_status_space`. A member must not destroy the owner's app.\n  * the project must be registered to THIS space (`lizard_apps.space_slug`).\n    The Lizard account is shared across every space, so a project_id alone is\n    not authority — this is the same standard the chat path holds itself to\n    for domains (confirm the target is on THIS project's list first). The\n    executor then re-checks it against the slug-keyed registry\n    (policy.TARGETED_VERBS), so two independent fences must both agree.\n  * typed confirmation: `confirm` must equal the app's service name.\n\nIdempotent: an app already gone (no live registration, but this space's own\nledger rows prove it was ours) reports success, not a 500 — a double click\nmust not look like a fault. The teardown itself is NOT reimplemented here; it\nis the bot's own `lizard destroy` verb (services/lizard_ops) — the same verb\nthe chat path uses, which tears the DEPLOYMENT down, KEEPS the git, and hands\nthe repo to this space's owner on the brand-correct Forgejo. The response\ncarries that hand-over so the UI can show the repo link (or, when the owner\nhas no account on that instance yet, the sign-in instruction instead of a\nlink they cannot open). A hand-over that did not apply never makes the\nteardown itself a failure.","operationId":"teardown_space_app_api_user_spaces__space_id__apps__project_id__teardown_post","parameters":[{"name":"space_id","in":"path","required":true,"schema":{"type":"integer","title":"Space Id"}},{"name":"project_id","in":"path","required":true,"schema":{"type":"string","title":"Project Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TeardownApp"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/user/spaces/{space_id}/apps/source/{app_name}":{"get":{"tags":["user-spaces"],"summary":"Download Space App Source","description":"Download a space app's SOURCE as an archive — the second door to a repo\n`destroy` handed over, for the owner who will not use Forgejo directly.\n\nThe org is derived from the OWNED space's slug, never from the request, so\ndash's privileged read token can only ever reach a repo inside this owner's\nown space org — `app_name` picks the repo WITHIN that org and nothing more.\nStreamed, not buffered (services/forgejo_source).","operationId":"download_space_app_source_api_user_spaces__space_id__apps_source__app_name__get","parameters":[{"name":"space_id","in":"path","required":true,"schema":{"type":"integer","title":"Space Id"}},{"name":"app_name","in":"path","required":true,"schema":{"type":"string","title":"App Name"}},{"name":"fmt","in":"query","required":false,"schema":{"type":"string","pattern":"^(zip|tar\\.gz)$","default":"zip","title":"Fmt"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/user/spaces/{space_id}/apps/{project_id}/live":{"get":{"tags":["user-spaces"],"summary":"Space App Live","description":"Owner-only monitoring of ONE deployed app for the Octo Cloud console:\nservice status, CPU/memory metrics, recent deploy events and a log tail, read\nlive from Lizard through the bot's own verbs (services/lizard_ops.live).\n\nSame fences as teardown, minus the confirmation (nothing changes): the\nOWNER's space, and a project registered to THIS space in lizard_apps. The\nservice name comes from that row, never from the browser. `available` is\nfalse when Octo Cloud could not be asked at all; each section is null when\nits own verb failed, so one slow read never blanks the rest.","operationId":"space_app_live_api_user_spaces__space_id__apps__project_id__live_get","parameters":[{"name":"space_id","in":"path","required":true,"schema":{"type":"integer","title":"Space Id"}},{"name":"project_id","in":"path","required":true,"schema":{"type":"string","title":"Project Id"}},{"name":"range","in":"query","required":false,"schema":{"type":"string","default":"1h","title":"Range"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/user/spend":{"get":{"tags":["user-spaces"],"summary":"My Total Spend","description":"Daily billed spend summed across ALL spaces the caller owns (the global\nchart). Members' spend in your spaces is your bill — this is the total.","operationId":"my_total_spend_api_user_spend_get","parameters":[{"name":"from","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"From"}},{"name":"to","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"To"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/user/spenders":{"get":{"tags":["user-spaces"],"summary":"My Spenders","description":"Every spender across ALL the caller's owned spaces, ranked by total\nspend, each with a per-space breakdown — answers 'who spends most' and 'in\nwhich of my spaces does this person spend more'.","operationId":"my_spenders_api_user_spenders_get","parameters":[{"name":"from","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"From"}},{"name":"to","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"To"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/user/task-costs":{"get":{"tags":["user-txns"],"summary":"List Task Costs","description":"Per-TASK consumption: what one thing the user asked for cost, all in.\n\n⚠ \"task\" is a homonym in this product. `/api/user/tasks` aggregates a user's\nForgejo TASK ISSUES across their spaces (the «Tasks» nav) — work items — and\nhas nothing to do with this. Hence `task-costs`: one row per EXECUTION the\nplatform ran on the user's behalf.\n\nA task here is everything `trace_id` binds together — the orchestrator turn, every\nsub-agent it spawned, and (since ooih #447) every individual model call each\nof those made. Until this week there was no such grouping: the list showed a\nturn here and a sub-agent job there with nothing saying they were the same\nrequest, so adding one up meant knowing the job ids by heart.\n\nTHREE COST STATES, AND THE DIFFERENCE BETWEEN THEM IS THE POINT\n\n  settled   every node is terminal and priced. The number is the number.\n  pending   a sub-agent is still running. What is shown is a FLOOR and will\n            grow.\n  unknown   a node finished and no charge was ever recorded for it. The cost\n            is UNKNOWN, which is not zero — asserting $0.00 would claim the\n            work was free, and that plausible-but-wrong value is what this\n            billing programme has spent a week removing (the tid=0 sentinel,\n            the prompt_hash join, \"cost is unknown, not zero\").\n\nCharges with no trace at all are not dropped and not folded into a task that\ndid not incur them: they come back as `unattributed`, because a charge nobody\ncan attribute is a fact worth showing rather than a row to lose.","operationId":"list_task_costs_api_user_task_costs_get","parameters":[{"name":"from","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"From"}},{"name":"to","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"To"}},{"name":"space","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Space"}},{"name":"group","in":"query","required":false,"schema":{"anyOf":[{"type":"string","pattern":"^app$"},{"type":"null"}],"title":"Group"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"default":25,"title":"Limit"}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0,"default":0,"title":"Offset"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/user/txns":{"get":{"tags":["user-txns"],"summary":"List Transactions","description":"Paginated list of the caller's OWN transactions across the spaces they own.\n\nUnion of `usage` (TG turn / sub-agent / tool) and `api_turns` (web/API) rows;\nsub-agent-of-API-turn usage is folded under its parent turn (`has_children`).\n\n``group=task`` (#405) instead rolls the owned usage rows up by their captured\nTASK ISSUE (`usage.task_ref = \"<slug>#<n>\"`) — one group per task with its\ntotal energy + charge count, plus a \"no task\" bucket for the unstamped rows\n(an older bot, or work not tied to a task). The flat list then drills into one\ntask via ``?task_ref=<slug>#<n>`` (api_turns carry no ref, so a task filter\nnaturally yields only its usage charges).","operationId":"list_transactions_api_user_txns_get","parameters":[{"name":"from","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"From"}},{"name":"to","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"To"}},{"name":"space","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Space"}},{"name":"kind","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Kind"}},{"name":"group","in":"query","required":false,"schema":{"anyOf":[{"type":"string","pattern":"^task$"},{"type":"null"}],"description":"group=task rolls the usage rows up by their captured task issue (usage.task_ref)","title":"Group"},"description":"group=task rolls the usage rows up by their captured task issue (usage.task_ref)"},{"name":"task_ref","in":"query","required":false,"schema":{"anyOf":[{"type":"string","maxLength":190},{"type":"null"}],"description":"drill-down: only usage rows stamped this `<slug>#<n>` task ref","title":"Task Ref"},"description":"drill-down: only usage rows stamped this `<slug>#<n>` task ref"},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":200,"default":50,"title":"Limit"}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0,"default":0,"title":"Offset"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/user/txns/{tx_id}":{"get":{"tags":["user-txns"],"summary":"Get Transaction","description":"Detail for one transaction — request, result, and full cost breakdown.\nOwner-guarded: 404 unless the row's space is owned by the caller.","operationId":"get_transaction_api_user_txns__tx_id__get","parameters":[{"name":"tx_id","in":"path","required":true,"schema":{"type":"string","title":"Tx Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/user/txns/{tx_id}/chain":{"get":{"tags":["user-txns"],"summary":"Get Transaction Chain","description":"Async execution TREE rooted at one owned transaction.\n\nOwner-guard on the ROOT (404 unless the caller owns the root's space). The\ntree is reconstructed from the DURABLE lineage on `subagent_activity`\n(trace_id / parent_job_id / depth) grouped by trace, each node priced by\nits `usage` row (prompt_hash == event_id == 'subagent:{job_id}'). Per-node\nSCOPE-A redaction: content only for spaces the caller owns/is a member of.","operationId":"get_transaction_chain_api_user_txns__tx_id__chain_get","parameters":[{"name":"tx_id","in":"path","required":true,"schema":{"type":"string","title":"Tx Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/user/status":{"get":{"tags":["status"],"summary":"Platform Status","description":"Live status across the caller's owned spaces — five read-only panels.\n\nReturns `server_now` so a front-end computes elapsed/age against the API\nclock, not the browser's. `scope=all` is admin-gated; a non-admin asking for\nit is quietly treated as their own scope (never a leak, never a 403 that\nreveals the toggle exists to callers who shouldn't see it).\n\n`period` (default 30d) bounds the summary + turn log: the summary is a full-\nwindow aggregate over that period (not the old ~50-row \"recent window\" that\nshowed a 1-hour slice as the space's spend). The live watchdogs / current-turns\nrail stays \"now\" regardless.\n\nNarrowing to one `space` resolves OWNER-or-MEMBER: a space member sees THAT\nspace's status, scoped strictly to the single space (owner_id=None fences every\naggregate to the one slug — no owner-global numbers, no cross-space leak). An\nowner keeps the full owner-global rollups (owner_id=user.id).","operationId":"platform_status_api_user_status_get","parameters":[{"name":"space","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"narrow to one owned space slug","title":"Space"},"description":"narrow to one owned space slug"},{"name":"scope","in":"query","required":false,"schema":{"anyOf":[{"type":"string","pattern":"^all$"},{"type":"null"}],"description":"admins only: platform-wide","title":"Scope"},"description":"admins only: platform-wide"},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":50,"minimum":1,"default":20,"title":"Limit"}},{"name":"period","in":"query","required":false,"schema":{"type":"string","pattern":"^(24h|7d|30d|all)$","description":"summary + turn-log window: 24h | 7d | 30d | all","default":"30d","title":"Period"},"description":"summary + turn-log window: 24h | 7d | 30d | all"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/user/status/trigger":{"get":{"tags":["status"],"summary":"Status Trigger","description":"The exact trigger prompt behind one cost row.\n\nOwner-OR-member scoped: `space` must be one the caller OWNS or is a MEMBER of,\nelse 404 (never confirm another space or leak its message/dispatch text). Every\ntrigger read is already fenced to this one `slug` (single space, no owner-global\ndata), so a member sees only THIS space's trigger text. Returns the FULL prompt\ntext — the UI truncates the row preview and reveals the full text on demand. A\nmachine/scheduled row with no prompt returns `source='system'` and `text=null`\n(the UI shows the honest trigger, not a blank).","operationId":"status_trigger_api_user_status_trigger_get","parameters":[{"name":"kind","in":"query","required":true,"schema":{"type":"string","description":"row grain: tg_turn | api_turn | subagent","title":"Kind"},"description":"row grain: tg_turn | api_turn | subagent"},{"name":"id","in":"query","required":true,"schema":{"type":"string","description":"row id: trace_id (tg_turn) / turn_id (api_turn) / task_id (subagent)","title":"Id"},"description":"row id: trace_id (tg_turn) / turn_id (api_turn) / task_id (subagent)"},{"name":"space","in":"query","required":true,"schema":{"type":"string","description":"the owned space slug the row belongs to","title":"Space"},"description":"the owned space slug the row belongs to"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/user/spaces/{slug}/ops":{"get":{"tags":["status"],"summary":"Space Ops","description":"Operational-center meta for ONE space: engine/model pick + storage.\n\nOwner-OR-member scoped: 404 for a space the caller neither owns nor is a member\nof, so the endpoint never confirms another space exists. `storage.space_bytes`/\n`file_count` sum THIS space's stored files. `user_total_bytes` is the OWNER's\nGLOBAL footprint across all their spaces — but only the owner sees it; a MEMBER\ngets this single space's bytes (never the owner's cross-space total), so no\nowner-global number leaks to a non-owner.\n\n`space.engine`/`space.model`/`space.model_pin` are the PREFERRED model — what\nthis space PINNED. NULL there is a normal, truthful answer (most spaces never\npinned one), so it must be labelled as a preference, not as \"current\".\n`space.effective` is the separate fact the panel was missing: the model a turn\nwill actually use plus where it came from, resolved bot-side\n(services/effective_model). It is None when that cannot be resolved — rendered\nas \"unavailable\", never silently folded back into \"unset\".","operationId":"space_ops_api_user_spaces__slug__ops_get","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","title":"Slug"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/user/spaces/{slug}/routing":{"get":{"tags":["status"],"summary":"Space Routing","description":"The ROUTING POLICY for ONE space: what runs for each KIND of work, why it\nis not the first choice when it is not, the active engine pin, and what can\nbe changed at which precedence level.\n\nIts own route rather than a field on `/ops`, for the same reason `/dream` is:\nthe answer is resolved bot-side through a subprocess (seconds, not\nmilliseconds), and `/ops` also feeds the Storage tab, which must not wait on\nit. `routing` is None when it cannot be resolved, which the Policies tab\nrenders as \"unavailable\" — never as a space with no policy.\n\nScoped through the SAME `_resolve_status_space` as every other per-space\nstatus read: owner, member or admin, 404 otherwise, so the route never\nconfirms that a space the caller may not see exists. Nothing owner-global is\nreturned.\n\nRead-only end to end. The view resolves with `record=False` bot-side, so\nopening or refreshing the Policies tab can never adopt a pending cap or move\nthe space onto another model.","operationId":"space_routing_api_user_spaces__slug__routing_get","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","title":"Slug"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/user/spaces/{slug}/dream":{"get":{"tags":["status"],"summary":"Space Dream","description":"How far ONE space is from its next dream — the roll that consolidates the\nsession into memory.\n\nIts own route rather than a field on `/ops`: the measurement shells out to the\nbot's venv (seconds, not milliseconds), and `/ops` also feeds the Storage tab,\nwhich must not wait on it.\n\nScoped through the SAME `_resolve_status_space` as every other per-space status\nread — owner, member or admin, 404 otherwise, so the route never confirms that\na space the caller may not see exists. Nothing owner-global is returned (the\npayload is this one space's numbers), so a member/admin needs no extra fence.\n\nRead-only end to end: it reads the space's session pointer, transcript and\ndebt file. It can never trigger a dream.","operationId":"space_dream_api_user_spaces__slug__dream_get","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","title":"Slug"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/user/spaces/{slug}/files":{"get":{"tags":["status"],"summary":"Space Files","description":"Files for ONE space — the operational-center Files tab.\n\nOwner-OR-member scoped, any origin. Every listed file belongs to THIS space\n(`api_turn_files.space_slug == slug` + on-disk /spaces/<slug>/data), so a member\nsees only this space's files — no cross-space leak. Merges the registered ledger\nwith the agent's on-disk outputs under /spaces/<slug>/data (downloads/, output/),\nnewest-first — the on-disk half is what makes a Telegram space's files appear at\nall, since they live on disk, never in the file ledger.","operationId":"space_files_api_user_spaces__slug__files_get","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","title":"Slug"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/user/spaces/{slug}/file":{"get":{"tags":["status"],"summary":"Space File","description":"Stream one on-disk file from a space's agent-output dirs, addressed by\nRELATIVE path. Owner-OR-member scoped + traversal-guarded, any origin (unlike\nthe origin='api'-gated /chat space-file route). The path is fenced to THIS\nspace's /spaces/<slug>/data output dirs, so a member reaches only this space.","operationId":"space_file_api_user_spaces__slug__file_get","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","title":"Slug"}},{"name":"path","in":"query","required":true,"schema":{"type":"string","description":"space-relative path, e.g. downloads/cat.png","title":"Path"},"description":"space-relative path, e.g. downloads/cat.png"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/user/status/share":{"get":{"tags":["status"],"summary":"Get Share Link","description":"The current active share link for an owned space, or null if none.","operationId":"get_share_link_api_user_status_share_get","parameters":[{"name":"space","in":"query","required":true,"schema":{"type":"string","description":"an owned space slug","title":"Space"},"description":"an owned space slug"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["status"],"summary":"Create Share Link","description":"Create (or rotate) the share link for an owned space. Rotating revokes any\nprior active link for that space, so the old URL immediately 404s.","operationId":"create_share_link_api_user_status_share_post","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ShareReq"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["status"],"summary":"Revoke Share Link","description":"Revoke the active share link for an owned space (idempotent).","operationId":"revoke_share_link_api_user_status_share_delete","parameters":[{"name":"space","in":"query","required":true,"schema":{"type":"string","description":"an owned space slug","title":"Space"},"description":"an owned space slug"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/status/shared/{token}":{"get":{"tags":["status"],"summary":"Shared Status","description":"Read-only status for the ONE space a share token authorizes — no login.\n\n404 (never 403) for an unknown/revoked token or an archived space, so the\nendpoint never confirms which tokens exist. Scoped to exactly that space:\n`owner_id=None` + `space=<slug>` means the builder's every query is fenced to\nthe single slug, so a link-holder can reach nothing else.","operationId":"shared_status_api_status_shared__token__get","parameters":[{"name":"token","in":"path","required":true,"schema":{"type":"string","title":"Token"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":50,"minimum":1,"default":20,"title":"Limit"}},{"name":"period","in":"query","required":false,"schema":{"type":"string","pattern":"^(24h|7d|30d|all)$","description":"summary + turn-log window: 24h | 7d | 30d | all","default":"30d","title":"Period"},"description":"summary + turn-log window: 24h | 7d | 30d | all"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/admin/space-view/{slug}/open":{"post":{"tags":["admin-space-view"],"summary":"Open Space View","description":"Open a space's Operations Center as a borrowed viewer — and record the look.\n\nExactly one audit record per viewing session: the polling reads that follow bump\nthat row rather than writing new ones, so the trail names openings, not traffic.\nReturns the header the view's banner renders (space + owner + read-only), never\nany of the space's own data.","operationId":"open_space_view_api_admin_space_view__slug__open_post","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","title":"Slug"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/admin/space-view/log":{"get":{"tags":["admin-space-view"],"summary":"List Space Views","description":"The borrowed-view audit trail, newest first. Read-only, admin-gated — the\nrecord of who looked is worth no less than the record itself.","operationId":"list_space_views_api_admin_space_view_log_get","parameters":[{"name":"space","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"narrow to one space slug","title":"Space"},"description":"narrow to one space slug"},{"name":"admin_user_id","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"narrow to one admin","title":"Admin User Id"},"description":"narrow to one admin"},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":200,"minimum":1,"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"}}}}}}},"/api/admin/space-view/{slug}":{"get":{"tags":["admin-space-view"],"summary":"Read Space View","description":"The space's read-only Operations Center payload — the share view's shape.\n\n`owner_id=None` fences every aggregate to this one slug (no owner-global\nrollups, no other space), `include_raw=False` keeps the operator's raw provider\ncost out of a view that is meant to show what the OWNER sees, and `shared: True`\nmakes the shared renderer drop every control the owner has. Writes nothing —\nthe opening was already recorded by `POST /{slug}/open`.","operationId":"read_space_view_api_admin_space_view__slug__get","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","title":"Slug"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":50,"minimum":1,"default":20,"title":"Limit"}},{"name":"period","in":"query","required":false,"schema":{"type":"string","pattern":"^(24h|7d|30d|all)$","description":"summary + turn-log window: 24h | 7d | 30d | all","default":"30d","title":"Period"},"description":"summary + turn-log window: 24h | 7d | 30d | all"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/admin/fleet":{"get":{"tags":["admin-fleet"],"summary":"Fleet Overview","description":"The fleet command-center payload — everything, across every space.\n\n`status` is the standard status payload built with `admin_all=True` (no owner\nfilter): its `watchdogs` are every live sub-agent, `current_turns` every\norchestrator turn in flight, `spawn_errors`/`queued`/`journal` fleet-wide.\n`energy` is the per-space balance + recent-spend overview. `counts` mirrors the\nstatus counts for the header strip.","operationId":"fleet_overview_api_admin_fleet_get","parameters":[{"name":"days","in":"query","required":false,"schema":{"type":"integer","maximum":90,"minimum":1,"description":"energy spend window","default":7,"title":"Days"},"description":"energy spend window"},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":200,"minimum":1,"description":"turn-log / energy row cap","default":50,"title":"Limit"},"description":"turn-log / energy row cap"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/.well-known/openid-configuration":{"get":{"tags":["oidc"],"summary":"Discovery","operationId":"discovery__well_known_openid_configuration_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/oauth/jwks":{"get":{"tags":["oidc"],"summary":"Jwks","operationId":"jwks_oauth_jwks_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/oauth/authorize":{"get":{"tags":["oidc"],"summary":"Authorize","operationId":"authorize_oauth_authorize_get","parameters":[{"name":"response_type","in":"query","required":false,"schema":{"type":"string","default":"code","title":"Response Type"}},{"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":"scope","in":"query","required":false,"schema":{"type":"string","default":"openid","title":"Scope"}},{"name":"state","in":"query","required":false,"schema":{"type":"string","default":"","title":"State"}},{"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"}}}}}}},"/oauth/token":{"post":{"tags":["oidc"],"summary":"Token","operationId":"token_oauth_token_post","requestBody":{"content":{"application/x-www-form-urlencoded":{"schema":{"$ref":"#/components/schemas/Body_token_oauth_token_post"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/oauth/userinfo":{"get":{"tags":["oidc"],"summary":"Userinfo","operationId":"userinfo_oauth_userinfo_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/admin/context/spaces":{"get":{"tags":["admin-context"],"summary":"List Context Spaces","description":"Every registered (slugged) space with memory-file count, last dream,\nand current context size (chars + ~tokens). The context size is the real\norchestrator seed where computable (see context_analytics.compute_context_size);\ncontext_size_source tells the frontend when it's only an approximation.","operationId":"list_context_spaces_api_admin_context_spaces_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/admin/context/space/{slug}/memory":{"get":{"tags":["admin-context"],"summary":"Get Space Context Memory","description":"MEMORY.md + topic files for one space, plus its context size (computed\nhere rather than reused from the list endpoint — a single seed call is\ncheap; refetching the whole fleet's list just for one row isn't).","operationId":"get_space_context_memory_api_admin_context_space__slug__memory_get","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","title":"Slug"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/admin/context/global-memory":{"get":{"tags":["admin-context"],"summary":"Get Global Context Memory","description":"The global orch memory (~/.claude/projects/-agent/memory/) — cross-space\npatterns, not scoped to any one space.","operationId":"get_global_context_memory_api_admin_context_global_memory_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/admin/context/global-wiki":{"get":{"tags":["admin-context"],"summary":"Get Global Platform Wiki","description":"The global platform wiki (/agent/platform_wiki) — the nested\ncapabilities/tools index every orchestrator loads. Read-only.","operationId":"get_global_platform_wiki_api_admin_context_global_wiki_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/admin/context/space/{slug}/dreams":{"get":{"tags":["admin-context"],"summary":"Get Space Dreams","description":"The space's dream log: git history of its knowledge repo, newest\nfirst. Empty list (not an error) for a space with no knowledge/.git yet.","operationId":"get_space_dreams_api_admin_context_space__slug__dreams_get","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","title":"Slug"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":1000,"default":200,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/admin/support/tickets":{"get":{"tags":["admin-support"],"summary":"List Tickets","description":"List ticket summaries, optionally filtered by status. Plus subscribers'\ntickets (priority support) come first; newest activity first within each.","operationId":"list_tickets_api_admin_support_tickets_get","parameters":[{"name":"status","in":"query","required":false,"schema":{"type":"string","pattern":"^(open|answered|closed|all)$","default":"all","title":"Status"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/admin/support/tickets/{ticket_id}":{"get":{"tags":["admin-support"],"summary":"Get Ticket","description":"Return one full ticket record: the JSON thread merged with the Postgres\nreply turns (console/agent replies), ordered by timestamp.\n\n``ticket_id`` is validated against a strict hex pattern *before* any path is\nbuilt, which rejects traversal like ``../../etc/passwd``. Reading a ticket\nalso mirrors its meta into Postgres so a later reply can be routed home.","operationId":"get_ticket_api_admin_support_tickets__ticket_id__get","parameters":[{"name":"ticket_id","in":"path","required":true,"schema":{"type":"string","title":"Ticket Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/admin/support/tickets/{ticket_id}/reply":{"post":{"tags":["admin-support"],"summary":"Reply Ticket","description":"Author an admin reply to a ticket from the console.\n\nAppends a ``sender_kind='admin'`` row with ``delivered_at`` NULL — the ooih\nwatcher polls the gate for undelivered rows and relays them to the ticket's\norigin chat, then marks them delivered. dash never sends Telegram directly.","operationId":"reply_ticket_api_admin_support_tickets__ticket_id__reply_post","parameters":[{"name":"ticket_id","in":"path","required":true,"schema":{"type":"string","title":"Ticket Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReplyIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/support/tickets/{ticket_id}":{"get":{"tags":["support"],"summary":"Get My Ticket","description":"One full ticket record for its own requester — the JSON thread merged with\nthe Postgres reply turns, ordered by timestamp.\n\nMirrors the admin detail endpoint's parsing and merge (via the shared\n``admin_support`` helpers) but is authorization-scoped to the ticket owner: a\nuser who neither owns the origin space nor is the requesting user gets a\n404, indistinguishable from a ticket that does not exist. ``ticket_id`` is\nvalidated against a strict hex pattern before any path is built, which\nrejects traversal.","operationId":"get_my_ticket_api_support_tickets__ticket_id__get","parameters":[{"name":"ticket_id","in":"path","required":true,"schema":{"type":"string","title":"Ticket Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/admin/offers":{"get":{"tags":["admin-offers"],"summary":"List Offers","operationId":"list_offers_api_admin_offers_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}},"post":{"tags":["admin-offers"],"summary":"Create Offer","operationId":"create_offer_api_admin_offers_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OfferCreate"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/admin/offers/curator-search":{"get":{"tags":["admin-offers"],"summary":"Curator Search","operationId":"curator_search_api_admin_offers_curator_search_get","parameters":[{"name":"q","in":"query","required":true,"schema":{"type":"string","title":"Q"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/admin/offers/{offer_id}":{"get":{"tags":["admin-offers"],"summary":"Get Offer","operationId":"get_offer_api_admin_offers__offer_id__get","parameters":[{"name":"offer_id","in":"path","required":true,"schema":{"type":"integer","title":"Offer Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"patch":{"tags":["admin-offers"],"summary":"Update Offer","operationId":"update_offer_api_admin_offers__offer_id__patch","parameters":[{"name":"offer_id","in":"path","required":true,"schema":{"type":"integer","title":"Offer Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OfferUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/admin/offer-studio/spaces":{"get":{"tags":["admin-offer-studio"],"summary":"List Spaces","description":"List all non-archived spaces for the slug picker.\n\nThe studio space itself is excluded so it never appears as a selectable\nknowledge source.","operationId":"list_spaces_api_admin_offer_studio_spaces_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response List Spaces Api Admin Offer Studio Spaces Get"}}}}}}},"/api/admin/offer-studio/turns":{"post":{"tags":["admin-offer-studio"],"summary":"Create Studio Turn","description":"Queue a new studio generation turn.","operationId":"create_studio_turn_api_admin_offer_studio_turns_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StudioTurnIn"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Create Studio Turn Api Admin Offer Studio Turns Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/admin/offer-studio/turns/{turn_id}":{"get":{"tags":["admin-offer-studio"],"summary":"Get Studio Turn","description":"Poll the state of a studio turn.","operationId":"get_studio_turn_api_admin_offer_studio_turns__turn_id__get","parameters":[{"name":"turn_id","in":"path","required":true,"schema":{"type":"string","title":"Turn Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Get Studio Turn Api Admin Offer Studio Turns  Turn Id  Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/admin/offer-studio/turns/{turn_id}/cancel":{"post":{"tags":["admin-offer-studio"],"summary":"Cancel Studio Turn","description":"Cancel a non-terminal studio turn.","operationId":"cancel_studio_turn_api_admin_offer_studio_turns__turn_id__cancel_post","parameters":[{"name":"turn_id","in":"path","required":true,"schema":{"type":"string","title":"Turn Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Cancel Studio Turn Api Admin Offer Studio Turns  Turn Id  Cancel Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/offers/{code}":{"get":{"tags":["offers"],"summary":"Offer Detail","operationId":"offer_detail_api_offers__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"}}}}}}},"/api/offers/{code}/checkout":{"post":{"tags":["offers"],"summary":"Checkout","operationId":"checkout_api_offers__code__checkout_post","parameters":[{"name":"code","in":"path","required":true,"schema":{"type":"string","title":"Code"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CheckoutBody"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/user/seeding":{"get":{"tags":["user-seeding"],"summary":"Get Seeding","operationId":"get_seeding_api_user_seeding_get","parameters":[{"name":"owner","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Owner"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/user/seeding/content":{"put":{"tags":["user-seeding"],"summary":"Put Content","description":"Edit the working DRAFT directly. Not materialized — approve + attach\nto publish it to a space.","operationId":"put_content_api_user_seeding_content_put","parameters":[{"name":"owner","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Owner"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContentBody"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/user/seeding/consolidate":{"post":{"tags":["user-seeding"],"summary":"Consolidate","description":"On-request: assemble the toggled-on spaces' memory into the DRAFT. The\nowner reviews (and may edit) it, then approves it into a version.","operationId":"consolidate_api_user_seeding_consolidate_post","parameters":[{"name":"owner","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Owner"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/user/seeding/versions":{"post":{"tags":["user-seeding"],"summary":"Approve Version","description":"Approve the current draft → a new immutable version (the active one). An\noptional `name` labels the version for attach management.","operationId":"approve_version_api_user_seeding_versions_post","parameters":[{"name":"owner","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Owner"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApproveBody"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"get":{"tags":["user-seeding"],"summary":"Get Versions","operationId":"get_versions_api_user_seeding_versions_get","parameters":[{"name":"owner","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Owner"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/user/seeding/versions/{version_id}":{"get":{"tags":["user-seeding"],"summary":"Get Version","operationId":"get_version_api_user_seeding_versions__version_id__get","parameters":[{"name":"version_id","in":"path","required":true,"schema":{"type":"integer","title":"Version Id"}},{"name":"owner","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Owner"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/user/seeding/spaces/{space_id}/attach":{"post":{"tags":["user-seeding"],"summary":"Attach Space","description":"Attach a chosen version (or detach with version_id=null) to one of the\nowner's spaces; materializes that space's seed sidecar.","operationId":"attach_space_api_user_seeding_spaces__space_id__attach_post","parameters":[{"name":"space_id","in":"path","required":true,"schema":{"type":"integer","title":"Space Id"}},{"name":"owner","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Owner"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AttachBody"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/user/seeding/attach-all":{"post":{"tags":["user-seeding"],"summary":"Attach All Spaces","description":"Set the \"FOR ALL OWNED\" default version (or clear it with version_id=null):\nattach the chosen version to every owned space that has no explicit per-space\nattachment. Re-materializes each affected space's INDEX sidecar.","operationId":"attach_all_spaces_api_user_seeding_attach_all_post","parameters":[{"name":"owner","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Owner"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AttachBody"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/user/seeding/km-space":{"post":{"tags":["user-seeding"],"summary":"Set Km Space","description":"Designate (or clear) the owner's knowledge-management space. The space must\nbe owned by the caller; only that space's turns may drive the gate KM tools.","operationId":"set_km_space_api_user_seeding_km_space_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/KmSpaceBody"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/user/seeding/kb":{"get":{"tags":["user-seeding"],"summary":"Kb Overview","description":"The visualizer's home read: every named KB (latest version + count), the\nowner's spaces with WHICH KB version each has attached (resolved to its\nkb_name/version_num), and the attach group tokens with live counts.","operationId":"kb_overview_api_user_seeding_kb_get","parameters":[{"name":"owner","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Owner"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/user/seeding/kb/versions":{"get":{"tags":["user-seeding"],"summary":"Kb Versions","description":"One named KB's version history, newest first.","operationId":"kb_versions_api_user_seeding_kb_versions_get","parameters":[{"name":"name","in":"query","required":true,"schema":{"type":"string","title":"Name"}},{"name":"owner","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Owner"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/user/seeding/kb/show":{"get":{"tags":["user-seeding"],"summary":"Kb Show","description":"One named KB version in full (version=0 → latest), plus the owner's spaces\ncurrently attached to THIS exact version (the attachments view).","operationId":"kb_show_api_user_seeding_kb_show_get","parameters":[{"name":"name","in":"query","required":true,"schema":{"type":"string","title":"Name"}},{"name":"version","in":"query","required":false,"schema":{"type":"integer","default":0,"title":"Version"}},{"name":"owner","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Owner"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/user/seeding/kb/source":{"get":{"tags":["user-seeding"],"summary":"Kb Source","description":"Raw consolidation material — the concatenated memory of the owner's spaces\n(all owned by default, or a comma-separated slug list). The owner (or an agent)\nconsolidates this, then commits it via POST /kb/commit.","operationId":"kb_source_api_user_seeding_kb_source_get","parameters":[{"name":"spaces","in":"query","required":false,"schema":{"type":"string","default":"owned","title":"Spaces"}},{"name":"owner","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Owner"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/user/seeding/kb/commit":{"post":{"tags":["user-seeding"],"summary":"Kb Commit","description":"Commit consolidated text as a new immutable version of the named KB `name`.\nThe commit IS the version (no draft/approve for named KBs) — identical to the\norchestrator's kb_commit tool.","operationId":"kb_commit_api_user_seeding_kb_commit_post","parameters":[{"name":"owner","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Owner"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/KbCommitBody"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/user/seeding/kb/attach":{"post":{"tags":["user-seeding"],"summary":"Kb Attach","description":"Attach a named KB version (version=0 → latest) to a flexible set of targets:\ngroup tokens (all, all-bitrix, …) and/or named space slugs. Rolls back to an\nolder version simply by attaching that version. Owner-scoped: resolve_targets\nonly ever returns the owner's own spaces (structural isolation).","operationId":"kb_attach_api_user_seeding_kb_attach_post","parameters":[{"name":"owner","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Owner"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/KbAttachBody"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/user/seeding/kb/detach":{"post":{"tags":["user-seeding"],"summary":"Kb Detach","description":"Detach the owner KB from the resolved targets (same tokens as attach). A\ndetached space falls back to the owner's fleet-wide default if one is set.","operationId":"kb_detach_api_user_seeding_kb_detach_post","parameters":[{"name":"owner","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Owner"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/KbDetachBody"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/user/seeding/kb/chat":{"get":{"tags":["user-seeding"],"summary":"Kb Chat Get","description":"The KB-control chat's full state in one round-trip: the thread (target KB,\npicker selection, persisted draft + uncommitted flag), the controller (KM)\nspace id, the space-picker payload, plus `managing` — every KB the caller can\nact on (own + KBs whose space they joined as an editor) so the Knowledge hub\ncan list and switch between them.","operationId":"kb_chat_get_api_user_seeding_kb_chat_get","parameters":[{"name":"owner","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Owner"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["user-seeding"],"summary":"Kb Chat Bind","description":"Set the chat binding: which named KB it authors, which spaces a committed\nversion attaches to (picker tokens), and (optionally) the controller space.\nDesignating the controller space is an OWNER-only action (you can only point\nyour own KB at your own space); editors may set the KB name / targets.","operationId":"kb_chat_bind_api_user_seeding_kb_chat_put","parameters":[{"name":"owner","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Owner"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/KbChatBindBody"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/user/seeding/kb/chat/space":{"post":{"tags":["user-seeding"],"summary":"Kb Chat Space","description":"The owner's dedicated KB chat space, created on first use; idempotent.\nOwner-only: an editor works in the space they were invited into.","operationId":"kb_chat_space_api_user_seeding_kb_chat_space_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/user/seeding/kb/chat/draft":{"put":{"tags":["user-seeding"],"summary":"Kb Chat Save Draft","description":"Persist the working DRAFT — the uncommitted KB text being edited or the bot\nproduced. Kept across reloads; marked dirty so the UI shows \"not committed\n(draft)\" until it is committed as a version.","operationId":"kb_chat_save_draft_api_user_seeding_kb_chat_draft_put","parameters":[{"name":"owner","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Owner"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/KbChatDraftBody"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/user/seeding/kb/chat/commit":{"post":{"tags":["user-seeding"],"summary":"Kb Chat Commit","description":"Freeze the draft into a new immutable version of the thread's named KB\n(reuse commit_kb_version), attach it to the picker selection (reuse\nresolve_targets/attach_version), then clear the uncommitted flag. Returns the\nnew version and the per-target attach report.","operationId":"kb_chat_commit_api_user_seeding_kb_chat_commit_post","parameters":[{"name":"owner","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Owner"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/KbChatCommitBody"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/user/seeding/kb/proposals":{"get":{"tags":["user-seeding"],"summary":"List Kb Proposals","description":"The proposal inbox for the resolved KB. `status` = pending (default) |\napproved | rejected | all. Always returns the live pending_count for the tab\nbadge.","operationId":"list_kb_proposals_api_user_seeding_kb_proposals_get","parameters":[{"name":"status","in":"query","required":false,"schema":{"type":"string","default":"pending","title":"Status"}},{"name":"owner","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Owner"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/user/seeding/kb/proposals/{proposal_id}":{"get":{"tags":["user-seeding"],"summary":"Get Kb Proposal","description":"One proposal with its full content + the current live version it diffs\nagainst (base_content_md) + the spaces its targets resolve to right now.","operationId":"get_kb_proposal_api_user_seeding_kb_proposals__proposal_id__get","parameters":[{"name":"proposal_id","in":"path","required":true,"schema":{"type":"integer","title":"Proposal Id"}},{"name":"owner","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Owner"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["user-seeding"],"summary":"Edit Kb Proposal","description":"Edit a still-pending proposal before approving it. 409 if already decided.","operationId":"edit_kb_proposal_api_user_seeding_kb_proposals__proposal_id__put","parameters":[{"name":"proposal_id","in":"path","required":true,"schema":{"type":"integer","title":"Proposal Id"}},{"name":"owner","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Owner"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProposalEditBody"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/user/seeding/kb/proposals/{proposal_id}/approve":{"post":{"tags":["user-seeding"],"summary":"Approve Kb Proposal","description":"APPROVE: freeze the proposal into a new KB version and attach it to its\ntargets, in one locked step. 409 if the proposal was already decided (a\ndouble-approve loses the race under the row lock and lands here). Editors of\nthis KB may approve; the ACTOR (`user.id`) is recorded as the approver.","operationId":"approve_kb_proposal_api_user_seeding_kb_proposals__proposal_id__approve_post","parameters":[{"name":"proposal_id","in":"path","required":true,"schema":{"type":"integer","title":"Proposal Id"}},{"name":"owner","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Owner"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/user/seeding/kb/proposals/{proposal_id}/reject":{"post":{"tags":["user-seeding"],"summary":"Reject Kb Proposal","description":"REJECT a pending proposal. 409 if already decided.","operationId":"reject_kb_proposal_api_user_seeding_kb_proposals__proposal_id__reject_post","parameters":[{"name":"proposal_id","in":"path","required":true,"schema":{"type":"integer","title":"Proposal Id"}},{"name":"owner","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Owner"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProposalRejectBody"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/user/seeding/kb/originals/capabilities":{"get":{"tags":["kb-originals"],"summary":"Capabilities","operationId":"capabilities_api_user_seeding_kb_originals_capabilities_get","parameters":[{"name":"owner","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Owner"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/user/seeding/kb/originals/bases":{"post":{"tags":["kb-originals"],"summary":"Create Base","operationId":"create_base_api_user_seeding_kb_originals_bases_post","parameters":[{"name":"owner","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Owner"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateBaseBody"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/user/seeding/kb/originals":{"get":{"tags":["kb-originals"],"summary":"List Originals","operationId":"list_originals_api_user_seeding_kb_originals_get","parameters":[{"name":"name","in":"query","required":true,"schema":{"type":"string","minLength":1,"maxLength":120,"title":"Name"}},{"name":"owner","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Owner"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["kb-originals"],"summary":"Upload Original","operationId":"upload_original_api_user_seeding_kb_originals_post","parameters":[{"name":"name","in":"query","required":true,"schema":{"type":"string","minLength":1,"maxLength":120,"title":"Name"}},{"name":"owner","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Owner"}}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_upload_original_api_user_seeding_kb_originals_post"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/user/seeding/kb/originals/chat-files":{"get":{"tags":["kb-originals"],"summary":"Chat Files","operationId":"chat_files_api_user_seeding_kb_originals_chat_files_get","parameters":[{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0,"default":0,"title":"Offset"}},{"name":"name","in":"query","required":true,"schema":{"type":"string","minLength":1,"maxLength":120,"title":"Name"}},{"name":"owner","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Owner"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/user/seeding/kb/originals/from-chat":{"post":{"tags":["kb-originals"],"summary":"Import Chat File","operationId":"import_chat_file_api_user_seeding_kb_originals_from_chat_post","parameters":[{"name":"name","in":"query","required":true,"schema":{"type":"string","minLength":1,"maxLength":120,"title":"Name"}},{"name":"owner","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Owner"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImportBody"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/user/seeding/kb/originals/{file_id}/retry":{"post":{"tags":["kb-originals"],"summary":"Retry Index","operationId":"retry_index_api_user_seeding_kb_originals__file_id__retry_post","parameters":[{"name":"file_id","in":"path","required":true,"schema":{"type":"string","title":"File Id"}},{"name":"owner","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Owner"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/user/seeding/kb/originals/publication":{"get":{"tags":["kb-originals"],"summary":"Get Publication","operationId":"get_publication_api_user_seeding_kb_originals_publication_get","parameters":[{"name":"version","in":"query","required":false,"schema":{"type":"integer","minimum":0,"default":0,"title":"Version"}},{"name":"name","in":"query","required":true,"schema":{"type":"string","minLength":1,"maxLength":120,"title":"Name"}},{"name":"owner","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Owner"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["kb-originals"],"summary":"Publish Originals","operationId":"publish_originals_api_user_seeding_kb_originals_publication_post","parameters":[{"name":"name","in":"query","required":true,"schema":{"type":"string","minLength":1,"maxLength":120,"title":"Name"}},{"name":"owner","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Owner"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublishBody"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/user/seeding/kb/originals/{file_id}":{"delete":{"tags":["kb-originals"],"summary":"Remove Original","operationId":"remove_original_api_user_seeding_kb_originals__file_id__delete","parameters":[{"name":"file_id","in":"path","required":true,"schema":{"type":"string","title":"File Id"}},{"name":"owner","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Owner"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"get":{"tags":["kb-originals"],"summary":"Download Original","operationId":"download_original_api_user_seeding_kb_originals__file_id__get","parameters":[{"name":"file_id","in":"path","required":true,"schema":{"type":"string","title":"File Id"}},{"name":"owner","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Owner"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/user/seeding/kb/originals/search":{"post":{"tags":["kb-originals"],"summary":"Search Originals","operationId":"search_originals_api_user_seeding_kb_originals_search_post","parameters":[{"name":"name","in":"query","required":true,"schema":{"type":"string","minLength":1,"maxLength":120,"title":"Name"}},{"name":"owner","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Owner"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SearchBody"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/user/seeding/kb/originals/sources/{source_ref}":{"get":{"tags":["kb-originals"],"summary":"Read Source Chunk","operationId":"read_source_chunk_api_user_seeding_kb_originals_sources__source_ref__get","parameters":[{"name":"source_ref","in":"path","required":true,"schema":{"type":"string","title":"Source Ref"}},{"name":"name","in":"query","required":true,"schema":{"type":"string","minLength":1,"maxLength":120,"title":"Name"}},{"name":"owner","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Owner"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/internal/turns/{turn_id}/knowledge/search":{"post":{"tags":["kb-chat-rag"],"summary":"Search","operationId":"search_v1_internal_turns__turn_id__knowledge_search_post","parameters":[{"name":"turn_id","in":"path","required":true,"schema":{"type":"string","title":"Turn Id"}},{"name":"X-API-Key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}},{"name":"X-KB-Token","in":"header","required":true,"schema":{"type":"string","title":"X-Kb-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SearchBody"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/internal/turns/{turn_id}/knowledge/sources/{source_ref}":{"get":{"tags":["kb-chat-rag"],"summary":"Read","operationId":"read_v1_internal_turns__turn_id__knowledge_sources__source_ref__get","parameters":[{"name":"source_ref","in":"path","required":true,"schema":{"type":"string","title":"Source Ref"}},{"name":"turn_id","in":"path","required":true,"schema":{"type":"string","title":"Turn Id"}},{"name":"X-API-Key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}},{"name":"X-KB-Token","in":"header","required":true,"schema":{"type":"string","title":"X-Kb-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/internal/turns/{turn_id}/knowledge/files":{"get":{"tags":["kb-chat-rag"],"summary":"Files","operationId":"files_v1_internal_turns__turn_id__knowledge_files_get","parameters":[{"name":"turn_id","in":"path","required":true,"schema":{"type":"string","title":"Turn Id"}},{"name":"X-API-Key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}},{"name":"X-KB-Token","in":"header","required":true,"schema":{"type":"string","title":"X-Kb-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/internal/turns/{turn_id}/knowledge/files/{file_id}":{"get":{"tags":["kb-chat-rag"],"summary":"File Chunks","operationId":"file_chunks_v1_internal_turns__turn_id__knowledge_files__file_id__get","parameters":[{"name":"file_id","in":"path","required":true,"schema":{"type":"string","title":"File Id"}},{"name":"turn_id","in":"path","required":true,"schema":{"type":"string","title":"Turn Id"}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0,"default":0,"title":"Offset"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":8,"minimum":1,"default":4,"title":"Limit"}},{"name":"X-API-Key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}},{"name":"X-KB-Token","in":"header","required":true,"schema":{"type":"string","title":"X-Kb-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/chat/turns/{turn_id}/knowledge/sources/{source_ref}":{"get":{"tags":["kb-chat-rag"],"summary":"Citation","operationId":"citation_api_chat_turns__turn_id__knowledge_sources__source_ref__get","parameters":[{"name":"turn_id","in":"path","required":true,"schema":{"type":"string","title":"Turn Id"}},{"name":"source_ref","in":"path","required":true,"schema":{"type":"string","title":"Source Ref"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/user/seeding/wiki":{"get":{"tags":["user-wiki"],"summary":"Wiki Tree","description":"The space's nested wiki: group → dimension → topics (title + description +\nupdated). The browsable map the owner visualizes; empty when the space has no\ngathered knowledge yet.","operationId":"wiki_tree_api_user_seeding_wiki_get","parameters":[{"name":"space","in":"query","required":true,"schema":{"type":"string","title":"Space"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/user/seeding/wiki/doc":{"get":{"tags":["user-wiki"],"summary":"Wiki Doc","description":"One topic doc in full: its meta + the markdown body (frontmatter stripped).","operationId":"wiki_doc_api_user_seeding_wiki_doc_get","parameters":[{"name":"space","in":"query","required":true,"schema":{"type":"string","title":"Space"}},{"name":"topic","in":"query","required":true,"schema":{"type":"string","title":"Topic"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["user-wiki"],"summary":"Wiki Doc Save","description":"Edit a topic doc's BODY, preserving its frontmatter, and commit it to the\nspace's knowledge git repo. Owner-scoped; the topic must already exist.","operationId":"wiki_doc_save_api_user_seeding_wiki_doc_put","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WikiDocSave"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/gate/km/spaces":{"get":{"tags":["gate-km"],"summary":"Km Spaces","operationId":"km_spaces_api_gate_km_spaces_get","parameters":[{"name":"caller","in":"query","required":true,"schema":{"type":"string","title":"Caller"}},{"name":"X-API-Key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/gate/km/controller":{"get":{"tags":["gate-km"],"summary":"Km Controller","description":"Quiet probe for the orchestrator's session seed: is `caller` its owner's\ndesignated KM controller space? Unlike the other km/* endpoints this NEVER\n403s for a non-controller (the common case, probed on every space's seed) — it\nreturns `is_controller: false`. When it IS the controller, returns the owner's\nspace roster (same shape as km/spaces) so the KB-control chat can prime the\nassistant to browse the fleet from here.","operationId":"km_controller_api_gate_km_controller_get","parameters":[{"name":"caller","in":"query","required":true,"schema":{"type":"string","title":"Caller"}},{"name":"X-API-Key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/gate/km/space-memory":{"get":{"tags":["gate-km"],"summary":"Km Space Memory","operationId":"km_space_memory_api_gate_km_space_memory_get","parameters":[{"name":"caller","in":"query","required":true,"schema":{"type":"string","title":"Caller"}},{"name":"target","in":"query","required":true,"schema":{"type":"string","title":"Target"}},{"name":"X-API-Key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/gate/km/seeding":{"get":{"tags":["gate-km"],"summary":"Km Get Seeding","description":"Read the owner's working DRAFT + approved version history.","operationId":"km_get_seeding_api_gate_km_seeding_get","parameters":[{"name":"caller","in":"query","required":true,"schema":{"type":"string","title":"Caller"}},{"name":"X-API-Key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["gate-km"],"summary":"Km Write Seeding","description":"The KM orchestrator writes its curated text into the working DRAFT\n(prompt-level: the KM agent assembled/curated it). NOT published — the owner\n(or the agent) then approves it into a version and attaches it.","operationId":"km_write_seeding_api_gate_km_seeding_post","parameters":[{"name":"X-API-Key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/KmWriteBody"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/gate/km/consolidate":{"post":{"tags":["gate-km"],"summary":"Km Consolidate","description":"Mechanical on-request assembly, gate-triggered (same as the dash button) —\nassemble the toggled-on spaces' memory into the working DRAFT.","operationId":"km_consolidate_api_gate_km_consolidate_post","parameters":[{"name":"X-API-Key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/KmCallerBody"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/gate/km/approve":{"post":{"tags":["gate-km"],"summary":"Km Approve","description":"Approve the current draft into a new immutable version (optional name).","operationId":"km_approve_api_gate_km_approve_post","parameters":[{"name":"X-API-Key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/KmApproveBody"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/gate/km/versions":{"get":{"tags":["gate-km"],"summary":"Km Versions","operationId":"km_versions_api_gate_km_versions_get","parameters":[{"name":"caller","in":"query","required":true,"schema":{"type":"string","title":"Caller"}},{"name":"X-API-Key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/gate/km/attach":{"post":{"tags":["gate-km"],"summary":"Km Attach","description":"Attach a version (or detach with version_id=null) to one of the owner's\nspaces, named by slug. Owner-scoped: target must be one of the owner's spaces\nand the version must be the owner's.","operationId":"km_attach_api_gate_km_attach_post","parameters":[{"name":"X-API-Key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/KmAttachBody"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/gate/km/attach-all":{"post":{"tags":["gate-km"],"summary":"Km Attach All","description":"Set/clear the owner's \"FOR ALL OWNED\" default version — attach it to every\nowned space without an explicit per-space attachment.","operationId":"km_attach_all_api_gate_km_attach_all_post","parameters":[{"name":"X-API-Key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/KmAttachAllBody"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/gate/km/kb/source":{"get":{"tags":["gate-km"],"summary":"Kb Source","description":"Raw material for consolidation — the concatenated memory of the owner's\nspaces (all owned by default, or a comma-separated slug list). The orchestrator\nconsolidates this itself, then commits it via kb/commit.","operationId":"kb_source_api_gate_km_kb_source_get","parameters":[{"name":"caller","in":"query","required":true,"schema":{"type":"string","title":"Caller"}},{"name":"spaces","in":"query","required":false,"schema":{"type":"string","default":"owned","title":"Spaces"}},{"name":"X-API-Key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/gate/km/kb/list":{"get":{"tags":["gate-km"],"summary":"Kb List","description":"List the owner's named KBs, each with its latest version + count.","operationId":"kb_list_api_gate_km_kb_list_get","parameters":[{"name":"caller","in":"query","required":true,"schema":{"type":"string","title":"Caller"}},{"name":"X-API-Key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/gate/km/kb/versions":{"get":{"tags":["gate-km"],"summary":"Kb Versions","description":"One named KB's version history, newest first.","operationId":"kb_versions_api_gate_km_kb_versions_get","parameters":[{"name":"caller","in":"query","required":true,"schema":{"type":"string","title":"Caller"}},{"name":"name","in":"query","required":true,"schema":{"type":"string","title":"Name"}},{"name":"X-API-Key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/gate/km/kb/show":{"get":{"tags":["gate-km"],"summary":"Kb Show","description":"One named KB version's full text (version=0 → latest).","operationId":"kb_show_api_gate_km_kb_show_get","parameters":[{"name":"caller","in":"query","required":true,"schema":{"type":"string","title":"Caller"}},{"name":"name","in":"query","required":true,"schema":{"type":"string","title":"Name"}},{"name":"version","in":"query","required":false,"schema":{"type":"integer","default":0,"title":"Version"}},{"name":"X-API-Key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/gate/km/kb/propose":{"post":{"tags":["gate-km"],"summary":"Kb Propose","description":"The agent's ONLY KB write: file a PROPOSAL for the owner to review, edit and\napprove in the dashboard. Never commits or attaches — approval does that. Queues\na new pending row (proposals pile up; they do not clobber) and notifies the\nowner (DM + in-app badge). Owner-scoped via the KM caller.","operationId":"kb_propose_api_gate_km_kb_propose_post","parameters":[{"name":"X-API-Key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/KbProposeBody"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/gate/km/kb/commit":{"post":{"tags":["gate-km"],"summary":"Kb Commit Closed","description":"CLOSED — the agent proposes, it does not publish. See /kb/propose.","operationId":"kb_commit_closed_api_gate_km_kb_commit_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/gate/km/kb/attach":{"post":{"tags":["gate-km"],"summary":"Kb Attach Closed","description":"CLOSED — the agent proposes, it does not publish. See /kb/propose.","operationId":"kb_attach_closed_api_gate_km_kb_attach_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/gate/km/kb/detach":{"post":{"tags":["gate-km"],"summary":"Kb Detach Closed","description":"CLOSED — the agent proposes, it does not publish. See /kb/propose.","operationId":"kb_detach_closed_api_gate_km_kb_detach_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/gate/km/kb/draft":{"put":{"tags":["gate-km"],"summary":"Kb Draft","description":"Persist the orchestrator's consolidated text as the owner's KB-control chat\nDRAFT — uncommitted, kept across reloads, shown in the dashboard as\n\"not committed (draft)\" until the human previews and commits it as a version.\nThe seam that lets the bot author into the draft (preview-before-commit)\ninstead of freezing a version outright. Owner-scoped via the KM caller.","operationId":"kb_draft_api_gate_km_kb_draft_put","parameters":[{"name":"X-API-Key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/KbDraftBody"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/gate/kb":{"get":{"tags":["gate-kb"],"summary":"Kb Index Read","description":"The INDEX of the caller space's effective attached version — entry titles +\none-line previews, no bodies. `attached:false` when nothing is attached.","operationId":"kb_index_read_api_gate_kb_get","parameters":[{"name":"caller","in":"query","required":true,"schema":{"type":"string","title":"Caller"}},{"name":"X-API-Key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/gate/kb/entry":{"get":{"tags":["gate-kb"],"summary":"Kb Entry Read","description":"One entry (a \"fact\") in full from the caller space's effective attached\nversion, looked up by title or anchor. 404 when nothing is attached or no\nentry matches.","operationId":"kb_entry_read_api_gate_kb_entry_get","parameters":[{"name":"caller","in":"query","required":true,"schema":{"type":"string","title":"Caller"}},{"name":"entry","in":"query","required":true,"schema":{"type":"string","title":"Entry"}},{"name":"X-API-Key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/webhooks":{"post":{"tags":["webhooks"],"summary":"Create Webhook","description":"Register a webhook for this key. The signing `secret` is returned in THIS\nresponse only (never on GET); omit it to have one generated.","operationId":"create_webhook_v1_webhooks_post","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookIn"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"get":{"tags":["webhooks"],"summary":"List Webhooks","operationId":"list_webhooks_v1_webhooks_get","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/webhooks/{webhook_id}":{"get":{"tags":["webhooks"],"summary":"Get Webhook","operationId":"get_webhook_v1_webhooks__webhook_id__get","parameters":[{"name":"webhook_id","in":"path","required":true,"schema":{"type":"integer","title":"Webhook Id"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"patch":{"tags":["webhooks"],"summary":"Patch Webhook","description":"Edit url / events / space / active, or rotate the secret (`secret` to set\nyour own, `rotate_secret: true` to have one generated). A rotated secret is\nreturned once in this response. Re-activating a webhook the platform disabled\n(410 Gone) clears `disabled_reason`.","operationId":"patch_webhook_v1_webhooks__webhook_id__patch","parameters":[{"name":"webhook_id","in":"path","required":true,"schema":{"type":"integer","title":"Webhook Id"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookPatchIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["webhooks"],"summary":"Delete Webhook","description":"Remove the webhook. Pending deliveries to it are dropped; delivered/failed\nrows stay for the log (their webhook_id becomes null).","operationId":"delete_webhook_v1_webhooks__webhook_id__delete","parameters":[{"name":"webhook_id","in":"path","required":true,"schema":{"type":"integer","title":"Webhook Id"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/webhooks/{webhook_id}/deliveries":{"get":{"tags":["webhooks"],"summary":"List Deliveries","description":"Most recent deliveries to this webhook: status, code, attempts, timestamps.","operationId":"list_deliveries_v1_webhooks__webhook_id__deliveries_get","parameters":[{"name":"webhook_id","in":"path","required":true,"schema":{"type":"integer","title":"Webhook Id"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","default":50,"title":"Limit"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/turns/{turn_id}/deliveries":{"get":{"tags":["webhooks"],"summary":"List Turn Deliveries","description":"Every delivery for one of this key's turns — including one-off per-turn\n`webhook_url` targets, which have no webhook row to list them under.","operationId":"list_turn_deliveries_v1_turns__turn_id__deliveries_get","parameters":[{"name":"turn_id","in":"path","required":true,"schema":{"type":"string","title":"Turn Id"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","default":50,"title":"Limit"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/webhooks/{webhook_id}/deliveries/{delivery_id}/redeliver":{"post":{"tags":["webhooks"],"summary":"Redeliver","description":"Replay a delivery: a new pending row with the same event id + payload.","operationId":"redeliver_v1_webhooks__webhook_id__deliveries__delivery_id__redeliver_post","parameters":[{"name":"webhook_id","in":"path","required":true,"schema":{"type":"integer","title":"Webhook Id"}},{"name":"delivery_id","in":"path","required":true,"schema":{"type":"string","title":"Delivery Id"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"responses":{"202":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/commander/space":{"post":{"tags":["commander"],"summary":"Open Commander Space","description":"The caller's Commander space, provisioned on first open.\n\n`created` says whether THIS call minted it, so a double open reports the\nsecond call as a plain resolve rather than a second provisioning.","operationId":"open_commander_space_api_commander_space_post","requestBody":{"content":{"application/json":{"schema":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Body"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/commander/links":{"post":{"tags":["commander"],"summary":"Mint Link","description":"A dashboard link for the caller: their keys page for a space, the energy\ntop-up page, a space's status page, or its Policies tab.\n\nA link grants nothing by itself: every page behind it runs its own session\ncheck. Minting still requires the caller to be the owner or a member of the\nspace it names, the same bar the page itself applies, so a link is never\nhanded out for a space the caller cannot open.","operationId":"mint_link_api_commander_links_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LinkIn"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/commander/actions":{"get":{"tags":["commander"],"summary":"Commander Actions","description":"What the caller's Commander did on their behalf, newest first: every\nrequest its delegation token authenticated (services/commander_audit.py).","operationId":"commander_actions_api_commander_actions_get","parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":500,"minimum":1,"default":100,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/commander/openapi":{"get":{"tags":["commander"],"summary":"Commander Openapi","description":"The API schema filtered to what the caller may call, so the Commander can\ndiscover its surface: paths, methods, summaries, parameters and bodies.","operationId":"commander_openapi_api_commander_openapi_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/gate/commander/delegation":{"post":{"tags":["commander"],"summary":"Mint Delegation","description":"A short-lived token that lets the bot call the dashboard AS\n`sender_account_id`, with exactly that user's login access (see\nauth.get_current_user).\n\nMinted only for the Commander's own owner speaking in their own Commander:\nthe slug must be the one derived from the sender's account AND the space\nunder it must be owned by that account (the derivation alone is not proof,\nsee services/commander.py COLLISIONS). Everything else is a 403, with one\nmessage, so the endpoint answers no questions about other accounts.","operationId":"mint_delegation_api_gate_commander_delegation_post","parameters":[{"name":"X-API-Key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DelegationIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/internal/metrics":{"get":{"tags":["internal-metrics"],"summary":"Metrics","operationId":"metrics_api_internal_metrics_get","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/health":{"get":{"summary":"Health","operationId":"health_api_health_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}}},"components":{"schemas":{"AddProviderRequest":{"properties":{"sub_id":{"type":"string","title":"Sub Id"},"name":{"type":"string","title":"Name"}},"type":"object","required":["sub_id","name"],"title":"AddProviderRequest"},"AddSpace":{"properties":{"chat_key":{"type":"string","title":"Chat Key"}},"type":"object","required":["chat_key"],"title":"AddSpace"},"AddWorkspaceMember":{"properties":{"user_id":{"type":"integer","title":"User Id"},"role":{"type":"string","title":"Role","default":"user"},"dm_allowed":{"type":"boolean","title":"Dm Allowed","default":false}},"type":"object","required":["user_id"],"title":"AddWorkspaceMember"},"AdminEditKeyIn":{"properties":{"daily_cap_usd":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Daily Cap Usd"},"api_markup_multiplier":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Api Markup Multiplier"}},"type":"object","title":"AdminEditKeyIn"},"AdminMintKeyIn":{"properties":{"account_id":{"type":"integer","title":"Account Id"},"label":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Label"},"space":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Space"},"space_scope":{"type":"string","title":"Space Scope","default":"account"},"daily_cap_usd":{"type":"number","title":"Daily Cap Usd","default":5},"api_markup_multiplier":{"type":"number","title":"Api Markup Multiplier","default":1},"live":{"type":"boolean","title":"Live","default":false}},"type":"object","required":["account_id"],"title":"AdminMintKeyIn"},"AdminTeamInviteCreate":{"properties":{"expires_days":{"type":"integer","title":"Expires Days","default":7}},"type":"object","title":"AdminTeamInviteCreate"},"AgentSnapshot":{"properties":{"space_slug":{"type":"string","title":"Space Slug"},"topic":{"type":"string","title":"Topic"},"task_id":{"type":"string","title":"Task Id"},"engine":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Engine"},"status":{"type":"string","title":"Status"},"task":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Task"},"started_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Started At"},"last_event_ts":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Last Event Ts"},"parent_job_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Parent Job Id"},"trace_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Trace Id"},"origin_kind":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Origin Kind"},"depth":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Depth"},"event_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Event Id"},"job_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Job Id"},"result":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Result"}},"type":"object","required":["space_slug","topic","task_id","status"],"title":"AgentSnapshot"},"ApiKeyIssueReq":{"properties":{"slug":{"type":"string","title":"Slug"},"chat_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Chat Id"},"lang":{"type":"string","title":"Lang","default":"en"},"label":{"anyOf":[{"type":"string","maxLength":120},{"type":"null"}],"title":"Label"},"daily_cap_usd":{"type":"number","maximum":1000.0,"exclusiveMinimum":0.0,"title":"Daily Cap Usd","default":5}},"type":"object","required":["slug"],"title":"ApiKeyIssueReq"},"ApplyAtFirstPurchaseRequest":{"properties":{"code":{"type":"string","maxLength":64,"minLength":1,"title":"Code"}},"type":"object","required":["code"],"title":"ApplyAtFirstPurchaseRequest"},"ApplyInfluencerRequest":{"properties":{"audience_size":{"type":"integer","minimum":0.0,"title":"Audience Size"},"channels":{"items":{"$ref":"#/components/schemas/ChannelEntry"},"type":"array","title":"Channels"},"desired_code":{"type":"string","maxLength":24,"minLength":2,"title":"Desired Code"},"pitch":{"type":"string","maxLength":2000,"title":"Pitch"}},"type":"object","required":["audience_size","channels","desired_code","pitch"],"title":"ApplyInfluencerRequest"},"ApplyPromoRequest":{"properties":{"code":{"type":"string","maxLength":24,"minLength":2,"title":"Code"}},"type":"object","required":["code"],"title":"ApplyPromoRequest"},"ApproveBody":{"properties":{"note":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Note"},"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name"}},"type":"object","title":"ApproveBody"},"ApproveRequest":{"properties":{"code":{"type":"string","maxLength":24,"minLength":2,"title":"Code"},"commission_pct":{"type":"integer","maximum":100.0,"minimum":0.0,"title":"Commission Pct","default":30},"audience_discount_pct":{"type":"integer","maximum":100.0,"minimum":0.0,"title":"Audience Discount Pct","default":15},"notes":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Notes"}},"type":"object","required":["code"],"title":"ApproveRequest"},"AttachBody":{"properties":{"version_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Version Id"}},"type":"object","title":"AttachBody"},"AttachSpace":{"properties":{"space_slug":{"type":"string","title":"Space Slug"}},"type":"object","required":["space_slug"],"title":"AttachSpace"},"AuthCodeRequest":{"properties":{"sub_id":{"type":"string","title":"Sub Id"},"name":{"type":"string","title":"Name"},"code":{"type":"string","title":"Code"}},"type":"object","required":["sub_id","name","code"],"title":"AuthCodeRequest"},"BillingProfileInput":{"properties":{"type":{"type":"string","enum":["individual","company"],"title":"Type"},"given_name":{"anyOf":[{"type":"string","maxLength":100,"minLength":1},{"type":"null"}],"title":"Given Name"},"family_name":{"anyOf":[{"type":"string","maxLength":100,"minLength":1},{"type":"null"}],"title":"Family Name"},"company_name":{"anyOf":[{"type":"string","maxLength":200,"minLength":1},{"type":"null"}],"title":"Company Name"},"invoice_email":{"type":"string","maxLength":254,"format":"email","title":"Invoice Email"},"country":{"type":"string","title":"Country"},"city":{"type":"string","maxLength":100,"minLength":1,"title":"City"},"address_line1":{"type":"string","maxLength":200,"minLength":1,"title":"Address Line1"},"address_line2":{"anyOf":[{"type":"string","maxLength":200,"minLength":1},{"type":"null"}],"title":"Address Line2"},"region":{"anyOf":[{"type":"string","maxLength":100,"minLength":1},{"type":"null"}],"title":"Region"},"postal_code":{"anyOf":[{"type":"string","maxLength":32,"minLength":1},{"type":"null"}],"title":"Postal Code"},"tax_id":{"anyOf":[{"type":"string","maxLength":64,"minLength":1},{"type":"null"}],"title":"Tax Id"}},"additionalProperties":false,"type":"object","required":["type","invoice_email","country","city","address_line1"],"title":"BillingProfileInput"},"BindTelegramRequest":{"properties":{"token":{"type":"string","title":"Token"},"telegram_id":{"type":"integer","title":"Telegram Id"},"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name"},"username":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Username"},"language_code":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Language Code"}},"type":"object","required":["token","telegram_id"],"title":"BindTelegramRequest"},"BitrixCreate":{"properties":{"webhook":{"type":"string","title":"Webhook"},"bot_name":{"type":"string","title":"Bot Name"},"portal":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Portal"}},"type":"object","required":["webhook","bot_name"],"title":"BitrixCreate","description":"A NEW connection is v2-fetch-only: the owner supplies just the inbound\nwebhook (carrying the imbot scope) and a display name for the bot. The portal\nhost is DERIVED from the webhook — the URL already contains it — so there is no\nseparate portal field. We invent the botToken and register the personal-fetch\nbot server-side. (`portal` is accepted-but-ignored for older clients; the\nderived host always wins so the two can never disagree.)"},"BitrixFetchOffset":{"properties":{"id":{"type":"integer","title":"Id"},"offset":{"type":"integer","title":"Offset"}},"type":"object","required":["id","offset"],"title":"BitrixFetchOffset"},"BitrixMemberIn":{"properties":{"space_slug":{"type":"string","title":"Space Slug"},"end_user_ref":{"type":"string","title":"End User Ref"},"display_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Display Name"},"role":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Role"},"account_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Account Id"}},"type":"object","required":["space_slug","end_user_ref"],"title":"BitrixMemberIn"},"BitrixRegisterV2":{"properties":{"portal":{"type":"string","title":"Portal"},"v2_bot_id":{"type":"string","title":"V2 Bot Id"},"bot_token":{"type":"string","title":"Bot Token"},"event_mode":{"type":"string","title":"Event Mode","default":"fetch"},"owner_telegram_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Owner Telegram Id"}},"type":"object","required":["portal","v2_bot_id","bot_token"],"title":"BitrixRegisterV2"},"BitrixUpdate":{"properties":{"webhook":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Webhook"},"bot_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Bot Name"},"is_active":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Is Active"}},"type":"object","title":"BitrixUpdate"},"Body_admin_upload_asset_api_admin_skills_upload_post":{"properties":{"file":{"type":"string","format":"binary","title":"File"}},"type":"object","required":["file"],"title":"Body_admin_upload_asset_api_admin_skills_upload_post"},"Body_link_channel_member_api_user_integrations__channel___conn_id__members__admission_id__link_post":{"properties":{"account_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Account Id"}},"type":"object","title":"Body_link_channel_member_api_user_integrations__channel___conn_id__members__admission_id__link_post"},"Body_token_oauth_token_post":{"properties":{"grant_type":{"type":"string","title":"Grant Type"},"code":{"type":"string","title":"Code","default":""},"redirect_uri":{"type":"string","title":"Redirect Uri","default":""},"client_id":{"type":"string","title":"Client Id","default":""},"client_secret":{"type":"string","title":"Client Secret","default":""}},"type":"object","required":["grant_type"],"title":"Body_token_oauth_token_post"},"Body_transcribe_audio_api_chat_transcribe_post":{"properties":{"file":{"type":"string","format":"binary","title":"File"}},"type":"object","required":["file"],"title":"Body_transcribe_audio_api_chat_transcribe_post"},"Body_upload_chat_file_api_chat__slug__files_post":{"properties":{"file":{"type":"string","format":"binary","title":"File"}},"type":"object","required":["file"],"title":"Body_upload_chat_file_api_chat__slug__files_post"},"Body_upload_original_api_user_seeding_kb_originals_post":{"properties":{"file":{"type":"string","format":"binary","title":"File"}},"type":"object","required":["file"],"title":"Body_upload_original_api_user_seeding_kb_originals_post"},"Body_upload_space_file_v1_spaces__slug__files_post":{"properties":{"file":{"type":"string","format":"binary","title":"File"}},"type":"object","required":["file"],"title":"Body_upload_space_file_v1_spaces__slug__files_post"},"Body_upload_turn_file_v1_internal_turns__turn_id__files_post":{"properties":{"file":{"type":"string","format":"binary","title":"File"}},"type":"object","required":["file"],"title":"Body_upload_turn_file_v1_internal_turns__turn_id__files_post"},"BriefRequest":{"properties":{"lang":{"type":"string","enum":["en","ru"],"title":"Lang","default":"en"},"request_id":{"type":"string","format":"uuid","title":"Request Id"}},"type":"object","title":"BriefRequest"},"CalendarAuthorizeRequest":{"properties":{"telegram_id":{"type":"integer","title":"Telegram Id"},"calendar_id":{"type":"string","title":"Calendar Id"}},"type":"object","required":["telegram_id","calendar_id"],"title":"CalendarAuthorizeRequest"},"CalendarClaimRequest":{"properties":{"telegram_id":{"type":"integer","title":"Telegram Id"},"calendar_id":{"type":"string","title":"Calendar Id"},"space_slug":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Space Slug"}},"type":"object","required":["telegram_id","calendar_id"],"title":"CalendarClaimRequest"},"CalendarReleaseRequest":{"properties":{"calendar_id":{"type":"string","title":"Calendar Id"},"reassign_to_telegram_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Reassign To Telegram Id"}},"type":"object","required":["calendar_id"],"title":"CalendarReleaseRequest"},"CancelByTitle":{"properties":{"space_slug":{"type":"string","title":"Space Slug"},"title":{"type":"string","title":"Title"},"schedule_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Schedule Id"},"reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Reason"},"actor":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Actor"}},"type":"object","required":["space_slug","title"],"title":"CancelByTitle"},"ChangeSpacePayer":{"properties":{"actor_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Actor Id"}},"type":"object","required":["actor_id"],"title":"ChangeSpacePayer"},"ChannelAdmissionCheck":{"properties":{"channel":{"type":"string","title":"Channel"},"connection_id":{"type":"integer","title":"Connection Id"},"external_user_id":{"type":"string","title":"External User Id"},"display_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Display Name"},"chat_ref":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Chat Ref"},"space_slug":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Space Slug"},"addressed":{"type":"boolean","title":"Addressed","default":false},"message":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Message"}},"type":"object","required":["channel","connection_id","external_user_id"],"title":"ChannelAdmissionCheck"},"ChannelAdmissionDecide":{"properties":{"channel":{"type":"string","title":"Channel"},"admission_id":{"type":"integer","title":"Admission Id"},"action":{"type":"string","title":"Action"},"actor_telegram_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Actor Telegram Id"}},"type":"object","required":["channel","admission_id","action"],"title":"ChannelAdmissionDecide"},"ChannelAdmissionReplays":{"properties":{"channel":{"type":"string","title":"Channel"},"connection_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Connection Id"},"limit":{"type":"integer","title":"Limit","default":20}},"type":"object","required":["channel"],"title":"ChannelAdmissionReplays"},"ChannelEntry":{"properties":{"platform":{"type":"string","title":"Platform"},"url":{"type":"string","title":"Url"}},"type":"object","required":["platform","url"],"title":"ChannelEntry"},"CheckReport":{"properties":{"checked_at":{"type":"string","format":"date-time","title":"Checked At"},"next_fire_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Next Fire At"},"fired":{"type":"boolean","title":"Fired","default":false},"trigger_state":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Trigger State"},"check_fail_count":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Check Fail Count"},"check_next_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Check Next At"}},"type":"object","required":["checked_at"],"title":"CheckReport","description":"A conditional schedule's cheap-check outcome for one tick — persisted whether\nor not it woke a turn, so 'changed' always means 'since the last observation'."},"CheckoutBody":{"properties":{"checkout":{"anyOf":[{"$ref":"#/components/schemas/CheckoutInput"},{"type":"null"}]},"method":{"type":"string","title":"Method","default":"yookassa"}},"type":"object","title":"CheckoutBody"},"CheckoutInput":{"properties":{"profile":{"$ref":"#/components/schemas/BillingProfileInput"},"terms_accepted":{"type":"boolean","title":"Terms Accepted"},"privacy_acknowledged":{"type":"boolean","title":"Privacy Acknowledged"},"terms_version":{"type":"string","maxLength":120,"minLength":1,"title":"Terms Version"},"privacy_version":{"type":"string","maxLength":120,"minLength":1,"title":"Privacy Version"},"locale":{"type":"string","enum":["ru","en","de"],"title":"Locale"}},"additionalProperties":false,"type":"object","required":["profile","terms_accepted","privacy_acknowledged","terms_version","privacy_version","locale"],"title":"CheckoutInput"},"ClaimTurnsIn":{"properties":{"limit":{"type":"integer","title":"Limit","default":10},"spaces":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Spaces"}},"type":"object","title":"ClaimTurnsIn"},"CompleteTurnIn":{"properties":{"knowledge_source_refs":{"anyOf":[{"items":{"type":"string"},"type":"array","maxItems":256},{"type":"null"}],"title":"Knowledge Source Refs"},"state":{"type":"string","title":"State"},"result_text":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Result Text"},"current_activity":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Current Activity"},"error_code":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Error Code"},"error_message":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Error Message"},"provider":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Provider"},"model":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Model"},"model_context_window":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Model Context Window"},"provider_cost_usd":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Provider Cost Usd"},"usage":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Usage"}},"type":"object","required":["state"],"title":"CompleteTurnIn"},"ConcurrencyConfig":{"properties":{"max_orch":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Max Orch"},"max_orch_per_chat":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Max Orch Per Chat"},"max_subagents":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Max Subagents"},"max_subagents_per_chat":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Max Subagents Per Chat"}},"type":"object","title":"ConcurrencyConfig"},"ConsumeInviteRequest":{"properties":{"token":{"type":"string","title":"Token"},"telegram_id":{"type":"integer","title":"Telegram Id"},"name":{"type":"string","title":"Name"},"username":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Username"},"language_code":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Language Code"}},"type":"object","required":["token","telegram_id","name"],"title":"ConsumeInviteRequest"},"ContentBody":{"properties":{"content_md":{"type":"string","title":"Content Md"}},"type":"object","required":["content_md"],"title":"ContentBody"},"ConvertRequest":{"properties":{"amount_rub_cents":{"type":"integer","exclusiveMinimum":0.0,"title":"Amount Rub Cents"}},"type":"object","required":["amount_rub_cents"],"title":"ConvertRequest"},"CountMessagesRequest":{"properties":{"chat_key":{"type":"string","title":"Chat Key"},"last_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Last Id"},"thread_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Thread Id"},"kinds":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Kinds"}},"type":"object","required":["chat_key"],"title":"CountMessagesRequest"},"CreateBaseBody":{"properties":{"name":{"type":"string","maxLength":120,"minLength":1,"title":"Name"}},"type":"object","required":["name"],"title":"CreateBaseBody"},"CreateConversation":{"properties":{"title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Title"},"model":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Model"}},"type":"object","title":"CreateConversation"},"CreateInvite":{"properties":{"max_uses":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Max Uses"}},"type":"object","title":"CreateInvite"},"CreateInviteBody":{"properties":{"thread_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Thread Id"}},"type":"object","title":"CreateInviteBody"},"CreatePool":{"properties":{"name":{"type":"string","title":"Name"}},"type":"object","required":["name"],"title":"CreatePool"},"CreateProject":{"properties":{"name":{"type":"string","title":"Name"},"model":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Model"}},"type":"object","required":["name"],"title":"CreateProject"},"CreateSchedule":{"properties":{"prompt":{"type":"string","title":"Prompt"},"due_at":{"type":"string","format":"date-time","title":"Due At"},"title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Title"},"recurrence":{"type":"string","title":"Recurrence","default":""},"active_days":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Active Days"},"timezone":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Timezone"},"reply_optional":{"type":"boolean","title":"Reply Optional","default":false}},"type":"object","required":["prompt","due_at"],"title":"CreateSchedule"},"CreateSpaceIn":{"properties":{"engine":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Engine"},"model":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Model"},"title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Title"},"external_ref":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"External Ref"}},"type":"object","title":"CreateSpaceIn"},"CreateThread":{"properties":{"title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Title"}},"type":"object","title":"CreateThread"},"CreateTurnIn":{"properties":{"space":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Space"},"text":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Text"},"end_user_ref":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"End User Ref"},"metadata":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Metadata"},"file_ids":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"File Ids"},"webhook_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Webhook Url"},"webhook_secret":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Webhook Secret"}},"type":"object","title":"CreateTurnIn"},"CreateUser":{"properties":{"name":{"type":"string","title":"Name"},"telegram_id":{"type":"integer","title":"Telegram Id","default":0},"username":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Username"},"role":{"type":"string","title":"Role","default":"user"},"login":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Login"},"password":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Password"},"energy_limit_usd":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Energy Limit Usd"},"duration_days":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Duration Days"}},"type":"object","required":["name"],"title":"CreateUser"},"CreateWorkspace":{"properties":{"id":{"type":"string","title":"Id"},"name":{"type":"string","title":"Name"},"admin_telegram_id":{"type":"integer","title":"Admin Telegram Id"},"budget_monthly_usd":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Budget Monthly Usd"}},"type":"object","required":["id","name","admin_telegram_id"],"title":"CreateWorkspace"},"CreditAdjustment":{"properties":{"amount_cents":{"type":"integer","title":"Amount Cents"},"reason":{"type":"string","title":"Reason"},"notes":{"type":"string","title":"Notes"}},"type":"object","required":["amount_cents","reason","notes"],"title":"CreditAdjustment"},"CreditBalanceRequest":{"properties":{"provider_slug":{"type":"string","title":"Provider Slug"},"user_external_id":{"type":"integer","title":"User External Id"},"amount_usd_cents":{"type":"integer","exclusiveMinimum":0.0,"title":"Amount Usd Cents"},"external_ref":{"type":"string","title":"External Ref"},"idempotency_key":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Idempotency Key"}},"type":"object","required":["provider_slug","user_external_id","amount_usd_cents","external_ref"],"title":"CreditBalanceRequest"},"CreditMicrosAdjustment":{"properties":{"amount_credits":{"type":"number","title":"Amount Credits"},"reason":{"type":"string","title":"Reason"},"notes":{"type":"string","title":"Notes","default":""}},"type":"object","required":["amount_credits","reason"],"title":"CreditMicrosAdjustment"},"CreditPurchaseRequest":{"properties":{"checkout":{"anyOf":[{"$ref":"#/components/schemas/CheckoutInput"},{"type":"null"}]},"package_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Package Id"},"energy":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Energy"},"return_url":{"type":"string","title":"Return Url"},"pool_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Pool Id"},"embedded":{"type":"boolean","title":"Embedded","default":false},"octomatica_checkout":{"anyOf":[{"$ref":"#/components/schemas/OctomaticaCheckoutInput"},{"type":"null"}]}},"type":"object","required":["return_url"],"title":"CreditPurchaseRequest"},"CryptoSessionRequest":{"properties":{"checkout":{"anyOf":[{"$ref":"#/components/schemas/CheckoutInput"},{"type":"null"}]},"energy":{"type":"integer","title":"Energy"},"return_url":{"type":"string","title":"Return Url"},"octodus_checkout":{"anyOf":[{"$ref":"#/components/schemas/OctodusCheckoutInput"},{"type":"null"}]}},"type":"object","required":["energy","return_url"],"title":"CryptoSessionRequest"},"DelegationIn":{"properties":{"slug":{"type":"string","title":"Slug"},"sender_account_id":{"type":"integer","title":"Sender Account Id"}},"type":"object","required":["slug","sender_account_id"],"title":"DelegationIn"},"DeleteAccountBody":{"properties":{"confirm":{"type":"string","title":"Confirm","default":""}},"type":"object","title":"DeleteAccountBody"},"DeviceBody":{"properties":{"token":{"type":"string","title":"Token","default":""},"platform":{"type":"string","title":"Platform","default":""}},"type":"object","title":"DeviceBody"},"DirectReferralEntry":{"properties":{"id":{"type":"integer","title":"Id"},"display_name":{"type":"string","title":"Display Name"},"registered_at":{"type":"string","format":"date-time","title":"Registered At"},"first_paid_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"First Paid At"},"paid_rub_cents":{"type":"integer","title":"Paid Rub Cents"},"paid_usd_cents":{"type":"integer","title":"Paid Usd Cents"},"payment_amount_complete":{"type":"boolean","title":"Payment Amount Complete"},"energy_spent_micros":{"type":"integer","title":"Energy Spent Micros"},"activity_status":{"type":"string","title":"Activity Status"}},"type":"object","required":["id","display_name","registered_at","first_paid_at","paid_rub_cents","paid_usd_cents","payment_amount_complete","energy_spent_micros","activity_status"],"title":"DirectReferralEntry"},"DirectReferralsResponse":{"properties":{"items":{"items":{"$ref":"#/components/schemas/DirectReferralEntry"},"type":"array","title":"Items"},"total":{"type":"integer","title":"Total"},"limit":{"type":"integer","title":"Limit"},"offset":{"type":"integer","title":"Offset"},"has_more":{"type":"boolean","title":"Has More"}},"type":"object","required":["items","total","limit","offset","has_more"],"title":"DirectReferralsResponse"},"DisableProviderRequest":{"properties":{"reason":{"type":"string","title":"Reason","default":""}},"type":"object","title":"DisableProviderRequest"},"EditKeyIn":{"properties":{"daily_cap_usd":{"type":"number","maximum":1000.0,"exclusiveMinimum":0.0,"title":"Daily Cap Usd"}},"type":"object","required":["daily_cap_usd"],"title":"EditKeyIn"},"ElevenlabsAccessRequest":{"properties":{"chat_key":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Chat Key"},"telegram_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Telegram Id"}},"type":"object","title":"ElevenlabsAccessRequest"},"EndUserLimitIn":{"properties":{"total_limit_usd":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Total Limit Usd"}},"type":"object","title":"EndUserLimitIn"},"EnsureUserRequest":{"properties":{"telegram_id":{"type":"integer","title":"Telegram Id"},"name":{"type":"string","title":"Name"},"username":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Username"},"language_code":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Language Code"},"ref_code":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Ref Code"},"attribution_label":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Attribution Label"},"utm_source":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Utm Source"},"utm_campaign":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Utm Campaign"},"utm_content":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Utm Content"},"telegram_update_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Telegram Update Id"},"chat_key":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Chat Key"}},"type":"object","required":["telegram_id","name"],"title":"EnsureUserRequest"},"FeedbackCreate":{"properties":{"topic":{"type":"string","enum":["bug","billing","idea","other"],"title":"Topic"},"message":{"type":"string","maxLength":4000,"minLength":3,"title":"Message"},"contact":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}],"title":"Contact"}},"type":"object","required":["topic","message"],"title":"FeedbackCreate"},"FiredReport":{"properties":{"fired_at":{"type":"string","format":"date-time","title":"Fired At"},"next_fire_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Next Fire At"}},"type":"object","required":["fired_at"],"title":"FiredReport"},"FleetCapsUpdate":{"properties":{"effort_cap":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Effort Cap"},"model_cap":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Model Cap"},"model_caps":{"anyOf":[{"additionalProperties":{"anyOf":[{"type":"string"},{"type":"null"}]},"type":"object"},{"type":"null"}],"title":"Model Caps"},"model_cap_mode":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Model Cap Mode"}},"type":"object","title":"FleetCapsUpdate"},"GateAttributeRequest":{"properties":{"telegram_id":{"type":"integer","title":"Telegram Id"},"code":{"type":"string","title":"Code"},"attribution_label":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Attribution Label"},"utm_source":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Utm Source"},"utm_campaign":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Utm Campaign"},"utm_content":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Utm Content"}},"type":"object","required":["telegram_id","code"],"title":"GateAttributeRequest"},"GateFlowCreate":{"properties":{"name":{"type":"string","title":"Name"},"steps":{"items":{},"type":"array","title":"Steps","default":[]},"template_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Template Name"},"created_by_ref":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Created By Ref"}},"type":"object","required":["name"],"title":"GateFlowCreate"},"GateFlowPatch":{"properties":{"action":{"type":"string","title":"Action"},"note":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Note"},"job_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Job Id"},"schedule":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Schedule"},"actor_ref":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Actor Ref"}},"type":"object","required":["action"],"title":"GateFlowPatch"},"GateFlowTemplatePut":{"properties":{"name":{"type":"string","title":"Name"},"steps":{"items":{},"type":"array","title":"Steps"},"notes":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Notes"},"source_path":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Source Path"}},"type":"object","required":["name","steps"],"title":"GateFlowTemplatePut"},"GateGoogleTokenRequest":{"properties":{"telegram_id":{"type":"integer","title":"Telegram Id"},"required_scopes":{"items":{"type":"string"},"type":"array","title":"Required Scopes"}},"type":"object","required":["telegram_id"],"title":"GateGoogleTokenRequest"},"GateTaskArtifact":{"properties":{"task_ref":{"type":"string","title":"Task Ref"},"kind":{"type":"string","title":"Kind","default":"file"},"title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Title"},"mime":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Mime"},"size":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Size"},"telegram_file_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Telegram File Id"},"chat_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Chat Id"},"message_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Message Id"},"turn_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Turn Id"},"created_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Created At"}},"type":"object","required":["task_ref"],"title":"GateTaskArtifact"},"GateTaskCreate":{"properties":{"title":{"type":"string","title":"Title"},"body_md":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Body Md"},"user_words":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"User Words"},"creator_ref":{"type":"string","title":"Creator Ref"},"assignee_ref":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Assignee Ref"},"tags":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Tags"},"source":{"type":"string","title":"Source","default":"manual"}},"type":"object","required":["title","creator_ref"],"title":"GateTaskCreate"},"GateTaskPatch":{"properties":{"action":{"type":"string","title":"Action"},"assignee_ref":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Assignee Ref"},"note":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Note"},"reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Reason"},"actor_ref":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Actor Ref"},"job_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Job Id"}},"type":"object","required":["action"],"title":"GateTaskPatch"},"GenerateImage":{"properties":{"request_id":{"type":"string","format":"uuid","title":"Request Id"},"slug":{"type":"string","maxLength":200,"minLength":1,"title":"Slug"},"prompt":{"type":"string","maxLength":8000,"minLength":1,"title":"Prompt"},"model":{"type":"string","title":"Model"},"aspect_ratio":{"type":"string","enum":["auto","1:1","3:2","2:3","16:9","9:16"],"title":"Aspect Ratio","default":"auto"},"file_ids":{"items":{"type":"string"},"type":"array","maxItems":4,"title":"File Ids"}},"type":"object","required":["request_id","slug","prompt","model"],"title":"GenerateImage"},"GrantChatRequest":{"properties":{"telegram_id":{"type":"integer","title":"Telegram Id"},"chat_key":{"type":"string","title":"Chat Key"}},"type":"object","required":["telegram_id","chat_key"],"title":"GrantChatRequest"},"GrantScopedSpaceMemberRequest":{"properties":{"telegram_id":{"type":"integer","title":"Telegram Id"},"actor_telegram_id":{"type":"integer","title":"Actor Telegram Id"}},"type":"object","required":["telegram_id","actor_telegram_id"],"title":"GrantScopedSpaceMemberRequest"},"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"HandoffRequest":{"properties":{"checkout":{"$ref":"#/components/schemas/CheckoutInput"},"provider_slug":{"type":"string","title":"Provider Slug"},"return_url":{"type":"string","title":"Return Url"},"amount_usd_cents":{"type":"integer","maximum":1000000.0,"minimum":100.0,"title":"Amount Usd Cents"}},"type":"object","required":["checkout","provider_slug","return_url","amount_usd_cents"],"title":"HandoffRequest"},"HiggsfieldAccessRequest":{"properties":{"chat_key":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Chat Key"},"telegram_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Telegram Id"}},"type":"object","title":"HiggsfieldAccessRequest"},"HiggsfieldCompleteRequest":{"properties":{"callback_url":{"type":"string","title":"Callback Url"}},"type":"object","required":["callback_url"],"title":"HiggsfieldCompleteRequest"},"ImportBody":{"properties":{"file_id":{"type":"string","maxLength":128,"minLength":1,"title":"File Id"}},"type":"object","required":["file_id"],"title":"ImportBody"},"ImportRow":{"properties":{"space_slug":{"type":"string","title":"Space Slug"},"prompt":{"type":"string","title":"Prompt","default":""},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"due_at":{"type":"string","format":"date-time","title":"Due At"},"title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Title"},"recurrence":{"type":"string","title":"Recurrence","default":""},"active_days":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Active Days"},"active_hours":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Active Hours"},"report_mode":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Report Mode"},"created_by":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Created By"},"external_ref":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"External Ref"},"origin":{"type":"string","title":"Origin","default":"tg"},"timezone":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Timezone"},"trigger_config":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Trigger Config"},"reply_optional":{"type":"boolean","title":"Reply Optional","default":false}},"type":"object","required":["space_slug","due_at"],"title":"ImportRow","description":"One schedule as the BOT spells it. The whole of the bot's vocabulary is\naccepted here — a word the bot has and this contract lacks is not a safe\nno-op, it is a 422 the user reads as \"schedule add is broken\" (ticket\n95df03ada641: every add carrying active_hours / report_mode / a description\ncame back \"422 Unprocessable Content\" and only the minimal four fields\nworked)."},"InferenceProviderUpdate":{"properties":{"cost_multiplier":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Cost Multiplier"},"is_active":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Is Active"},"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name"},"notes":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Notes"},"sort_order":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Sort Order"}},"type":"object","title":"InferenceProviderUpdate"},"InfluencerApplicationStatus":{"properties":{"status":{"type":"string","title":"Status"},"applied_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Applied At"},"approved_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Approved At"},"notes":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Notes"}},"type":"object","required":["status","applied_at","approved_at","notes"],"title":"InfluencerApplicationStatus"},"InviteCreate":{"properties":{"expires_days":{"type":"integer","title":"Expires Days","default":7}},"type":"object","title":"InviteCreate"},"InvoiceInput":{"properties":{"amount_rub_cents":{"type":"integer","maximum":100000000.0,"exclusiveMinimum":0.0,"title":"Amount Rub Cents"},"checkout":{"$ref":"#/components/schemas/CheckoutInput"},"idempotency_key":{"type":"string","format":"uuid","title":"Idempotency Key"}},"additionalProperties":false,"type":"object","required":["amount_rub_cents","checkout","idempotency_key"],"title":"InvoiceInput"},"IssueKeyIn":{"properties":{"label":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Label"},"daily_cap_usd":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Daily Cap Usd"}},"type":"object","title":"IssueKeyIn"},"JournalEvent":{"properties":{"space_slug":{"type":"string","title":"Space Slug"},"task_id":{"type":"string","title":"Task Id"},"kind":{"type":"string","title":"Kind"},"topic":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Topic"},"status":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Status"},"engine":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Engine"},"message":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Message"},"event_ts":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Event Ts"},"queued_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Queued At"},"started_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Started At"},"ended_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Ended At"},"report_count":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Report Count"},"queue_position":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Queue Position"},"admission_state":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Admission State"},"blocked_by":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Blocked By"},"host_occupied":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Host Occupied"},"host_cap":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Host Cap"},"space_occupied":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Space Occupied"},"space_cap":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Space Cap"},"dedup_key":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Dedup Key"},"parent_job_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Parent Job Id"},"trace_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Trace Id"},"origin_kind":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Origin Kind"},"depth":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Depth"}},"type":"object","required":["space_slug","task_id","kind"],"title":"JournalEvent"},"KbAttachBody":{"properties":{"name":{"type":"string","title":"Name"},"version":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Version","default":0},"targets":{"items":{"type":"string"},"type":"array","title":"Targets"}},"type":"object","required":["name","targets"],"title":"KbAttachBody"},"KbChatBindBody":{"properties":{"kb_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Kb Name"},"target_tokens":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Target Tokens"},"km_space_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Km Space Id"},"set_km_space":{"type":"boolean","title":"Set Km Space","default":false}},"type":"object","title":"KbChatBindBody"},"KbChatCommitBody":{"properties":{"note":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Note"},"base_version_num":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Base Version Num"},"content_md":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Content Md"}},"type":"object","title":"KbChatCommitBody"},"KbChatDraftBody":{"properties":{"content_md":{"type":"string","title":"Content Md"}},"type":"object","required":["content_md"],"title":"KbChatDraftBody"},"KbCommitBody":{"properties":{"name":{"type":"string","title":"Name"},"content_md":{"type":"string","title":"Content Md"},"base_version_num":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Base Version Num"},"note":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Note"}},"type":"object","required":["name","content_md"],"title":"KbCommitBody"},"KbDetachBody":{"properties":{"targets":{"items":{"type":"string"},"type":"array","title":"Targets"}},"type":"object","required":["targets"],"title":"KbDetachBody"},"KbDraftBody":{"properties":{"caller":{"type":"string","title":"Caller"},"content_md":{"type":"string","title":"Content Md"}},"type":"object","required":["caller","content_md"],"title":"KbDraftBody"},"KbImportTarget":{"properties":{"owner":{"type":"integer","exclusiveMinimum":0.0,"title":"Owner"},"name":{"type":"string","maxLength":120,"minLength":1,"title":"Name"}},"type":"object","required":["owner","name"],"title":"KbImportTarget"},"KbProposeBody":{"properties":{"caller":{"type":"string","title":"Caller"},"name":{"type":"string","title":"Name"},"content_md":{"type":"string","title":"Content Md"},"targets":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Targets"},"base_version_num":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Base Version Num"},"note":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Note"},"source_slugs":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Source Slugs"}},"type":"object","required":["caller","name","content_md"],"title":"KbProposeBody"},"KeysAckReq":{"properties":{"ids":{"items":{"type":"integer"},"type":"array","title":"Ids"}},"type":"object","title":"KeysAckReq"},"KeysMintReq":{"properties":{"slug":{"type":"string","title":"Slug"},"chat_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Chat Id"},"lang":{"type":"string","title":"Lang","default":"en"},"need_keys":{"items":{"type":"string"},"type":"array","title":"Need Keys"}},"type":"object","required":["slug"],"title":"KeysMintReq"},"KeysMintWebReq":{"properties":{"slug":{"type":"string","title":"Slug"},"chat_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Chat Id"},"lang":{"type":"string","title":"Lang","default":"en"},"need_keys":{"items":{"type":"string"},"type":"array","title":"Need Keys"},"sender_ref":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Sender Ref"}},"type":"object","required":["slug"],"title":"KeysMintWebReq"},"KmApproveBody":{"properties":{"caller":{"type":"string","title":"Caller"},"note":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Note"},"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name"}},"type":"object","required":["caller"],"title":"KmApproveBody"},"KmAttachAllBody":{"properties":{"caller":{"type":"string","title":"Caller"},"version_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Version Id"}},"type":"object","required":["caller"],"title":"KmAttachAllBody"},"KmAttachBody":{"properties":{"caller":{"type":"string","title":"Caller"},"target":{"type":"string","title":"Target"},"version_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Version Id"}},"type":"object","required":["caller","target"],"title":"KmAttachBody"},"KmCallerBody":{"properties":{"caller":{"type":"string","title":"Caller"}},"type":"object","required":["caller"],"title":"KmCallerBody"},"KmSpaceBody":{"properties":{"space_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Space Id"}},"type":"object","title":"KmSpaceBody"},"KmWriteBody":{"properties":{"caller":{"type":"string","title":"Caller"},"content_md":{"type":"string","title":"Content Md"},"source_slugs":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Source Slugs"}},"type":"object","required":["caller","content_md"],"title":"KmWriteBody"},"LeaseRequest":{"properties":{"telegram_id":{"type":"integer","title":"Telegram Id"},"chat_key":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Chat Key"},"provider":{"type":"string","title":"Provider","default":"claude"},"route":{"type":"string","title":"Route","default":"basic_response"},"billing_chat_key":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Billing Chat Key"}},"type":"object","required":["telegram_id"],"title":"LeaseRequest"},"LinkIn":{"properties":{"kind":{"type":"string","enum":["keys","energy","status","policies"],"title":"Kind"},"slug":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Slug"}},"type":"object","required":["kind"],"title":"LinkIn"},"LinkSpace":{"properties":{"space_slug":{"type":"string","title":"Space Slug"}},"type":"object","required":["space_slug"],"title":"LinkSpace"},"LizardAppClickEvent":{"properties":{"project_id":{"type":"string","title":"Project Id"},"path":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Path"},"status":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Status"},"utm_source":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Utm Source"},"utm_medium":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Utm Medium"},"utm_campaign":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Utm Campaign"},"utm_term":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Utm Term"},"utm_content":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Utm Content"}},"type":"object","required":["project_id"],"title":"LizardAppClickEvent"},"LizardAppClicksSync":{"properties":{"events":{"items":{"$ref":"#/components/schemas/LizardAppClickEvent"},"type":"array","title":"Events"}},"type":"object","required":["events"],"title":"LizardAppClicksSync"},"LizardAppRow":{"properties":{"project_id":{"type":"string","title":"Project Id"},"space_slug":{"type":"string","title":"Space Slug"},"service_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Service Name"},"domain":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Domain"},"preview_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Preview Url"}},"type":"object","required":["project_id","space_slug"],"title":"LizardAppRow"},"LizardAppsSync":{"properties":{"apps":{"items":{"$ref":"#/components/schemas/LizardAppRow"},"type":"array","title":"Apps"}},"type":"object","required":["apps"],"title":"LizardAppsSync"},"LoginRequest":{"properties":{"login":{"type":"string","title":"Login"},"password":{"type":"string","title":"Password"}},"type":"object","required":["login","password"],"title":"LoginRequest"},"LogtoSessionRequest":{"properties":{"sub":{"type":"string","title":"Sub"},"email":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Email"},"email_verified":{"type":"boolean","title":"Email Verified","default":false},"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name"}},"type":"object","required":["sub"],"title":"LogtoSessionRequest"},"MagicExchange":{"properties":{"token":{"type":"string","title":"Token"}},"type":"object","required":["token"],"title":"MagicExchange"},"MagicLinkRequest":{"properties":{"telegram_id":{"type":"integer","title":"Telegram Id"},"ttl_minutes":{"type":"integer","title":"Ttl Minutes","default":60}},"type":"object","required":["telegram_id"],"title":"MagicLinkRequest"},"ManifestIn":{"properties":{"manifest":{"type":"string","title":"Manifest"}},"type":"object","required":["manifest"],"title":"ManifestIn"},"MappingUpsert":{"properties":{"container_name":{"type":"string","title":"Container Name"},"user_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"User Id"},"space_key":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Space Key"}},"type":"object","required":["container_name"],"title":"MappingUpsert"},"MeResponse":{"properties":{"code":{"type":"string","title":"Code"},"tier":{"type":"string","title":"Tier"},"commission_pct":{"type":"integer","title":"Commission Pct"},"audience_discount_pct":{"type":"integer","title":"Audience Discount Pct"},"deeplink":{"type":"string","title":"Deeplink"},"short_link":{"type":"string","title":"Short Link"},"referee_bonus_energy":{"type":"number","title":"Referee Bonus Energy"},"stats":{"$ref":"#/components/schemas/ReferralStats"},"influencer_application":{"anyOf":[{"$ref":"#/components/schemas/InfluencerApplicationStatus"},{"type":"null"}]}},"type":"object","required":["code","tier","commission_pct","audience_discount_pct","deeplink","short_link","referee_bonus_energy","stats","influencer_application"],"title":"MeResponse"},"MediaItem":{"properties":{"url":{"type":"string","title":"Url"},"type":{"type":"string","title":"Type","default":"image"},"caption":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Caption"}},"type":"object","required":["url"],"title":"MediaItem"},"MergeConfirm":{"properties":{"merge_token":{"type":"string","title":"Merge Token"}},"type":"object","required":["merge_token"],"title":"MergeConfirm"},"MessageEditRequest":{"properties":{"text":{"type":"string","title":"Text"}},"type":"object","required":["text"],"title":"MessageEditRequest"},"MintIn":{"properties":{"label":{"type":"string","title":"Label"},"purpose":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Purpose"},"daily_cap_usd":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Daily Cap Usd"},"monthly_cap_usd":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Monthly Cap Usd"},"store_as":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Store As"}},"type":"object","required":["label"],"title":"MintIn"},"MintKeyIn":{"properties":{"label":{"anyOf":[{"type":"string","maxLength":120},{"type":"null"}],"title":"Label"},"space":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Space"},"space_scope":{"type":"string","title":"Space Scope","default":"own"},"daily_cap_usd":{"type":"number","maximum":1000.0,"exclusiveMinimum":0.0,"title":"Daily Cap Usd","default":5}},"type":"object","title":"MintKeyIn"},"ModelCatalogPatch":{"properties":{"enabled":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Enabled"},"admin_only":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Admin Only"},"label":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Label"},"sort_order":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Sort Order"},"min_balance_energy":{"anyOf":[{"type":"number","minimum":0.0},{"type":"null"}],"title":"Min Balance Energy"},"min_spent_energy":{"anyOf":[{"type":"number","minimum":0.0},{"type":"null"}],"title":"Min Spent Energy"}},"type":"object","title":"ModelCatalogPatch"},"OctodusAddress":{"properties":{"name":{"type":"string","maxLength":200,"minLength":2,"title":"Name"},"street":{"type":"string","maxLength":200,"minLength":3,"title":"Street"},"postal_code":{"type":"string","maxLength":16,"title":"Postal Code","default":""},"city":{"type":"string","maxLength":100,"minLength":1,"title":"City"},"country":{"type":"string","maxLength":2,"minLength":2,"title":"Country"},"country_name":{"type":"string","maxLength":80,"title":"Country Name","default":""}},"additionalProperties":false,"type":"object","required":["name","street","city","country"],"title":"OctodusAddress"},"OctodusCheckoutInput":{"properties":{"terms_accepted":{"type":"boolean","title":"Terms Accepted"},"terms_version":{"type":"string","maxLength":40,"minLength":1,"title":"Terms Version"},"email":{"type":"string","maxLength":254,"format":"email","title":"Email"},"buyer_type":{"type":"string","const":"business","title":"Buyer Type","default":"business"},"country_group":{"type":"string","enum":["de","eu","non_eu"],"title":"Country Group"},"address":{"$ref":"#/components/schemas/OctodusAddress"},"business_declaration":{"type":"boolean","title":"Business Declaration","default":false},"withdrawal_waiver":{"type":"boolean","const":false,"title":"Withdrawal Waiver","default":false}},"additionalProperties":false,"type":"object","required":["terms_accepted","terms_version","email","country_group","address"],"title":"OctodusCheckoutInput","description":"Sent by the energy page's order form with an Octodus payment request."},"OctomaticaCheckoutInput":{"properties":{"edition":{"type":"string","maxLength":40,"minLength":1,"title":"Edition"},"locale":{"type":"string","enum":["ru","en"],"title":"Locale"},"offer_accepted":{"type":"boolean","title":"Offer Accepted"},"business_declaration":{"type":"boolean","title":"Business Declaration"},"personal_data_consent":{"type":"boolean","title":"Personal Data Consent","default":false}},"additionalProperties":false,"type":"object","required":["edition","locale","offer_accepted","business_declaration"],"title":"OctomaticaCheckoutInput","description":"Sent by the checkout with a Tochka, Plus or YooKassa payment request."},"OfferCreate":{"properties":{"name":{"type":"string","title":"Name"},"fields":{"items":{"type":"string"},"type":"array","title":"Fields"},"price_rub":{"type":"integer","title":"Price Rub"},"energy_credits":{"type":"integer","title":"Energy Credits"},"stars_price":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Stars Price"},"curator_user_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Curator User Id"},"commission_pct":{"type":"integer","title":"Commission Pct","default":0},"allowed_methods":{"items":{"type":"string"},"type":"array","title":"Allowed Methods"},"body_html":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Body Html"},"terms":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Terms"}},"type":"object","required":["name","price_rub","energy_credits"],"title":"OfferCreate"},"OfferUpdate":{"properties":{"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name"},"fields":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Fields"},"price_rub":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Price Rub"},"energy_credits":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Energy Credits"},"stars_price":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Stars Price"},"curator_user_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Curator User Id"},"commission_pct":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Commission Pct"},"allowed_methods":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Allowed Methods"},"body_html":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Body Html"},"terms":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Terms"},"status":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Status"}},"type":"object","title":"OfferUpdate"},"OverrideRequest":{"properties":{"code":{"anyOf":[{"type":"string","maxLength":24,"minLength":2},{"type":"null"}],"title":"Code"},"tier":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Tier"},"commission_pct":{"anyOf":[{"type":"integer","maximum":100.0,"minimum":0.0},{"type":"null"}],"title":"Commission Pct"},"audience_discount_pct":{"anyOf":[{"type":"integer","maximum":100.0,"minimum":0.0},{"type":"null"}],"title":"Audience Discount Pct"},"notes":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Notes"}},"type":"object","title":"OverrideRequest"},"PackageCreate":{"properties":{"name":{"type":"string","title":"Name"},"price_rub":{"type":"integer","title":"Price Rub"},"discount_pct":{"type":"integer","title":"Discount Pct","default":0},"sort_order":{"type":"integer","title":"Sort Order","default":0}},"type":"object","required":["name","price_rub"],"title":"PackageCreate"},"PackageUpdate":{"properties":{"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name"},"price_rub":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Price Rub"},"discount_pct":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Discount Pct"},"is_active":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Is Active"},"sort_order":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Sort Order"}},"type":"object","title":"PackageUpdate"},"PartnerSessionRequest":{"properties":{"energy":{"type":"integer","title":"Energy"},"return_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Return Url"}},"type":"object","required":["energy"],"title":"PartnerSessionRequest"},"PatchConnection":{"properties":{"auto_attach":{"type":"boolean","title":"Auto Attach","description":"attach this Disk to new integration spaces"}},"type":"object","required":["auto_attach"],"title":"PatchConnection"},"PatchMemberBody":{"properties":{"can_invite":{"type":"boolean","title":"Can Invite"}},"type":"object","required":["can_invite"],"title":"PatchMemberBody"},"PatchMySpace":{"properties":{"access_policy":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Access Policy"},"budget_usd":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Budget Usd"},"clear_budget":{"type":"boolean","title":"Clear Budget","default":false},"owner_hidden":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Owner Hidden"},"seed_included":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Seed Included"},"model_pin":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Model Pin"},"allowed_engines":{"anyOf":[{"items":{},"type":"array"},{"type":"null"}],"title":"Allowed Engines"}},"type":"object","title":"PatchMySpace"},"PatchSchedule":{"properties":{"status":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Status"},"title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Title"},"prompt":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Prompt"},"due_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Due At"},"recurrence":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Recurrence"},"active_days":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Active Days"},"timezone":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Timezone"},"trigger_config":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Trigger Config"},"reply_optional":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Reply Optional"}},"type":"object","title":"PatchSchedule","description":"Reconfigure a schedule — every field optional; only sent fields change.\nMirrors the bot's full vocabulary (recurrence incl. minute:N, active_days)."},"PatchSpaceIn":{"properties":{"model_pin":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Model Pin"},"engine":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Engine"},"model":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Model"}},"type":"object","title":"PatchSpaceIn"},"PatchSpaceTools":{"properties":{"allow":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Allow"}},"type":"object","title":"PatchSpaceTools"},"PolicyIn":{"properties":{"orchestration":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Orchestration"}},"additionalProperties":true,"type":"object","title":"PolicyIn"},"ProposalEditBody":{"properties":{"content_md":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Content Md"},"target_tokens":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Target Tokens"},"note":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Note"}},"type":"object","title":"ProposalEditBody"},"ProposalRejectBody":{"properties":{"note":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Note"}},"type":"object","title":"ProposalRejectBody"},"ProviderQuotaSnapshotIn":{"properties":{"provider":{"type":"string","title":"Provider"},"subscription_id":{"type":"string","title":"Subscription Id"},"window":{"type":"string","title":"Window"},"used_pct":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Used Pct"},"reset_at":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Reset At"}},"type":"object","required":["provider","subscription_id","window"],"title":"ProviderQuotaSnapshotIn"},"ProviderQuotaSnapshotsIn":{"properties":{"snapshots":{"items":{"$ref":"#/components/schemas/ProviderQuotaSnapshotIn"},"type":"array","title":"Snapshots"}},"type":"object","required":["snapshots"],"title":"ProviderQuotaSnapshotsIn"},"ProviderUpsertRequest":{"properties":{"slug":{"type":"string","title":"Slug"},"name":{"type":"string","title":"Name"},"icon_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Icon Url"},"currencies":{"items":{"type":"string"},"type":"array","title":"Currencies"},"rails":{"items":{"type":"string"},"type":"array","title":"Rails"},"payment_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Payment Url"},"sessions_api_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Sessions Api Url"},"is_active":{"type":"boolean","title":"Is Active","default":true},"is_user_facing":{"type":"boolean","title":"Is User Facing","default":true},"sort_order":{"type":"integer","title":"Sort Order","default":0}},"type":"object","required":["slug","name","currencies","rails"],"title":"ProviderUpsertRequest"},"ProxiedSiteRequest":{"properties":{"hostname":{"type":"string","title":"Hostname"},"lizard_edge":{"type":"string","title":"Lizard Edge","default":"eu.cname.onlizard.com"},"service":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Service"},"project_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Project Id"}},"type":"object","required":["hostname"],"title":"ProxiedSiteRequest"},"PublishBody":{"properties":{"base_version":{"type":"integer","minimum":1.0,"title":"Base Version"},"file_ids":{"items":{"type":"string"},"type":"array","maxItems":100,"title":"File Ids"},"targets":{"items":{"type":"string"},"type":"array","maxItems":100,"title":"Targets"}},"type":"object","required":["base_version","file_ids"],"title":"PublishBody"},"ReadMessagesRequest":{"properties":{"chat_key":{"type":"string","title":"Chat Key"},"limit":{"type":"integer","title":"Limit","default":50},"since_ts":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Since Ts"},"oldest_first":{"type":"boolean","title":"Oldest First","default":false},"thread_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Thread Id"},"main_thread":{"type":"boolean","title":"Main Thread","default":false},"query":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Query"}},"type":"object","required":["chat_key"],"title":"ReadMessagesRequest"},"ReceiptEmailRequest":{"properties":{"email":{"type":"string","maxLength":254,"format":"email","title":"Email"}},"type":"object","required":["email"],"title":"ReceiptEmailRequest"},"ReceiptInput":{"properties":{"amount_rub_cents":{"type":"integer","maximum":100000000.0,"exclusiveMinimum":0.0,"title":"Amount Rub Cents"},"bank_reference":{"type":"string","maxLength":200,"minLength":1,"title":"Bank Reference"},"received_at":{"type":"string","format":"date-time","title":"Received At"},"note":{"anyOf":[{"type":"string","maxLength":1000},{"type":"null"}],"title":"Note"}},"additionalProperties":false,"type":"object","required":["amount_rub_cents","bank_reference","received_at"],"title":"ReceiptInput"},"RecordMessageRequest":{"properties":{"chat_key":{"type":"string","title":"Chat Key"},"text":{"type":"string","title":"Text"},"origin":{"type":"string","title":"Origin","default":"telegram"},"kind":{"type":"string","title":"Kind","default":"user"},"ts":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Ts"},"sender_telegram_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Sender Telegram Id"},"sender_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Sender Name"},"telegram_message_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Telegram Message Id"},"chat_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Chat Id"},"thread_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Thread Id"},"trace_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Trace Id"},"run_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Run Id"},"task_ref":{"anyOf":[{"type":"string","maxLength":190},{"type":"null"}],"title":"Task Ref"}},"additionalProperties":true,"type":"object","required":["chat_key","text"],"title":"RecordMessageRequest"},"ReferralStats":{"properties":{"referred_signups":{"type":"integer","title":"Referred Signups"},"paid_referees":{"type":"integer","title":"Paid Referees"},"active_in_window":{"type":"integer","title":"Active In Window"},"earned_total_cents":{"type":"integer","title":"Earned Total Cents"},"earned_held_cents":{"type":"integer","title":"Earned Held Cents"},"earned_released_cents":{"type":"integer","title":"Earned Released Cents"}},"type":"object","required":["referred_signups","paid_referees","active_in_window","earned_total_cents","earned_held_cents","earned_released_cents"],"title":"ReferralStats"},"RegisterTurnIn":{"properties":{"turn_id":{"type":"string","title":"Turn Id"},"space_slug":{"type":"string","title":"Space Slug"},"input_text":{"type":"string","title":"Input Text"},"state":{"type":"string","title":"State","default":"running"},"end_user_ref":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"End User Ref"},"account_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Account Id"},"end_user_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"End User Name"},"end_user_role":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"End User Role"}},"type":"object","required":["turn_id","space_slug","input_text"],"title":"RegisterTurnIn"},"RejectRequest":{"properties":{"notes":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Notes"}},"type":"object","title":"RejectRequest"},"RenameProject":{"properties":{"name":{"type":"string","title":"Name"}},"type":"object","required":["name"],"title":"RenameProject"},"RenameThread":{"properties":{"title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Title"}},"type":"object","title":"RenameThread"},"RenewRequest":{"properties":{"checkout":{"$ref":"#/components/schemas/CheckoutInput"},"promo_code":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Promo Code"}},"type":"object","required":["checkout"],"title":"RenewRequest"},"ReplyCreate":{"properties":{"message":{"type":"string","maxLength":4000,"minLength":1,"title":"Message"}},"type":"object","required":["message"],"title":"ReplyCreate"},"ReplyIn":{"properties":{"content":{"type":"string","maxLength":4000,"minLength":1,"title":"Content"}},"type":"object","required":["content"],"title":"ReplyIn"},"RevokeChatRequest":{"properties":{"telegram_id":{"type":"integer","title":"Telegram Id"},"chat_key":{"type":"string","title":"Chat Key"}},"type":"object","required":["telegram_id","chat_key"],"title":"RevokeChatRequest"},"RevokeIn":{"properties":{"archive_subspace":{"type":"boolean","title":"Archive Subspace","default":false}},"type":"object","title":"RevokeIn"},"SearchBody":{"properties":{"query":{"type":"string","maxLength":500,"minLength":1,"title":"Query"}},"type":"object","required":["query"],"title":"SearchBody"},"SecretIn":{"properties":{"secret":{"type":"string","title":"Secret"}},"type":"object","required":["secret"],"title":"SecretIn"},"SecretsSubmit":{"properties":{"keys":{"additionalProperties":{"type":"string"},"type":"object","title":"Keys"}},"type":"object","title":"SecretsSubmit"},"SendMessage":{"properties":{"slug":{"type":"string","title":"Slug"},"text":{"type":"string","title":"Text","default":""},"file_ids":{"items":{"type":"string"},"type":"array","title":"File Ids","default":[]},"kb_import":{"anyOf":[{"$ref":"#/components/schemas/KbImportTarget"},{"type":"null"}]},"image_model":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Image Model"},"silent":{"type":"boolean","title":"Silent","default":false},"thread_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Thread Id"}},"type":"object","required":["slug"],"title":"SendMessage"},"SetActivePool":{"properties":{"pool_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Pool Id"}},"type":"object","title":"SetActivePool"},"SetCapIn":{"properties":{"daily_cap_usd":{"type":"number","title":"Daily Cap Usd"}},"type":"object","required":["daily_cap_usd"],"title":"SetCapIn"},"SetCodeRequest":{"properties":{"code":{"type":"string","maxLength":24,"minLength":2,"title":"Code"}},"type":"object","required":["code"],"title":"SetCodeRequest"},"SetCredentials":{"properties":{"login":{"type":"string","title":"Login"},"password":{"type":"string","title":"Password"}},"type":"object","required":["login","password"],"title":"SetCredentials"},"SetRoleRequest":{"properties":{"telegram_id":{"type":"integer","title":"Telegram Id"},"role":{"type":"string","title":"Role"},"caller_telegram_id":{"type":"integer","title":"Caller Telegram Id"}},"type":"object","required":["telegram_id","role","caller_telegram_id"],"title":"SetRoleRequest"},"SetSpaceOwnerRequest":{"properties":{"chat_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Chat Id"},"slug":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Slug"},"owner_telegram_id":{"type":"integer","title":"Owner Telegram Id"},"claim_only":{"type":"boolean","title":"Claim Only","default":true}},"type":"object","required":["owner_telegram_id"],"title":"SetSpaceOwnerRequest"},"SettingUpdate":{"properties":{"key":{"type":"string","title":"Key"},"value":{"type":"string","title":"Value"}},"type":"object","required":["key","value"],"title":"SettingUpdate"},"ShareReq":{"properties":{"space":{"type":"string","title":"Space"}},"type":"object","required":["space"],"title":"ShareReq"},"SkillBody":{"properties":{"slug":{"type":"string","title":"Slug"},"title":{"type":"string","title":"Title"},"title_ru":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Title Ru"},"description":{"type":"string","title":"Description","default":""},"description_ru":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description Ru"},"category":{"type":"string","title":"Category","default":"general"},"emoji":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Emoji"},"examples":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Examples"},"examples_ru":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Examples Ru"},"launch_text":{"type":"string","title":"Launch Text"},"launch_text_ru":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Launch Text Ru"},"is_active":{"type":"boolean","title":"Is Active","default":true},"is_pinned":{"type":"boolean","title":"Is Pinned","default":false},"sort_order":{"type":"integer","title":"Sort Order","default":0},"media":{"items":{"$ref":"#/components/schemas/MediaItem"},"type":"array","title":"Media","default":[]}},"type":"object","required":["slug","title","launch_text"],"title":"SkillBody"},"SkillPatch":{"properties":{"slug":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Slug"},"title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Title"},"title_ru":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Title Ru"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"description_ru":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description Ru"},"category":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Category"},"emoji":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Emoji"},"examples":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Examples"},"examples_ru":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Examples Ru"},"launch_text":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Launch Text"},"launch_text_ru":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Launch Text Ru"},"is_active":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Is Active"},"is_pinned":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Is Pinned"},"sort_order":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Sort Order"},"media":{"anyOf":[{"items":{"$ref":"#/components/schemas/MediaItem"},"type":"array"},{"type":"null"}],"title":"Media"}},"type":"object","title":"SkillPatch"},"SourceRequest":{"properties":{"name":{"type":"string","maxLength":120,"minLength":1,"title":"Name"},"source":{"type":"string","maxLength":80,"minLength":1,"title":"Source"},"notes":{"anyOf":[{"type":"string","maxLength":2000},{"type":"null"}],"title":"Notes"}},"additionalProperties":false,"type":"object","required":["name","source"],"title":"SourceRequest"},"SourceUpdate":{"properties":{"name":{"type":"string","maxLength":120,"minLength":1,"title":"Name"},"source":{"type":"string","maxLength":80,"minLength":1,"title":"Source"},"notes":{"anyOf":[{"type":"string","maxLength":2000},{"type":"null"}],"title":"Notes"},"is_paused":{"type":"boolean","title":"Is Paused"}},"additionalProperties":false,"type":"object","required":["name","source","is_paused"],"title":"SourceUpdate"},"SpaceBrandRequest":{"properties":{"brand":{"type":"string","title":"Brand"}},"type":"object","required":["brand"],"title":"SpaceBrandRequest"},"SpaceDeleteRequest":{"properties":{"chat_key":{"type":"string","title":"Chat Key"}},"type":"object","required":["chat_key"],"title":"SpaceDeleteRequest"},"SpaceLangRequest":{"properties":{"language":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Language"},"lang":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Lang"}},"type":"object","title":"SpaceLangRequest"},"SpaceMigrateChatIdRequest":{"properties":{"old_chat_id":{"type":"integer","title":"Old Chat Id"},"new_chat_id":{"type":"integer","title":"New Chat Id"}},"type":"object","required":["old_chat_id","new_chat_id"],"title":"SpaceMigrateChatIdRequest"},"SpaceReserveReleaseRequest":{"properties":{"project_id":{"type":"string","title":"Project Id"}},"type":"object","required":["project_id"],"title":"SpaceReserveReleaseRequest"},"SpaceReserveRequest":{"properties":{"space_slug":{"type":"string","title":"Space Slug"},"project_id":{"type":"string","title":"Project Id"},"energy_micros":{"type":"integer","title":"Energy Micros"}},"type":"object","required":["space_slug","project_id","energy_micros"],"title":"SpaceReserveRequest"},"SpaceSecretsIn":{"properties":{"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name"},"value":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Value"},"secrets":{"anyOf":[{"additionalProperties":{"type":"string"},"type":"object"},{"type":"null"}],"title":"Secrets"}},"type":"object","title":"SpaceSecretsIn"},"SpaceTimezoneRequest":{"properties":{"timezone":{"type":"string","title":"Timezone"}},"additionalProperties":false,"type":"object","required":["timezone"],"title":"SpaceTimezoneRequest"},"SpaceUpsertRequest":{"properties":{"chat_key":{"type":"string","title":"Chat Key"},"chat_id":{"type":"integer","title":"Chat Id"},"title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Title"},"timezone":{"type":"string","title":"Timezone","default":"Europe/Berlin"},"group_key":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Group Key"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"brand":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Brand"}},"type":"object","required":["chat_key","chat_id"],"title":"SpaceUpsertRequest"},"SpaceUsageRequest":{"properties":{"space_slug":{"type":"string","title":"Space Slug"},"project_id":{"type":"string","title":"Project Id"},"cost_usd":{"type":"number","title":"Cost Usd"},"period_start":{"type":"string","format":"date-time","title":"Period Start"},"period_end":{"type":"string","format":"date-time","title":"Period End"},"target":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Target"},"topic":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Topic"},"event_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Event Id"},"cost_source":{"anyOf":[{"type":"string","enum":["vendor_reported","computed_from_tokens","computed_from_units","recovered_estimate"]},{"type":"null"}],"title":"Cost Source"}},"type":"object","required":["space_slug","project_id","cost_usd","period_start","period_end"],"title":"SpaceUsageRequest"},"StampBitrixSpace":{"properties":{"slug":{"type":"string","title":"Slug"},"portal":{"type":"string","title":"Portal"},"dialog_id":{"type":"string","title":"Dialog Id"}},"type":"object","required":["slug","portal","dialog_id"],"title":"StampBitrixSpace"},"StampYandexSpace":{"properties":{"slug":{"type":"string","title":"Slug"},"org":{"type":"string","title":"Org"},"chat_id":{"type":"string","title":"Chat Id"}},"type":"object","required":["slug","org","chat_id"],"title":"StampYandexSpace"},"StarsCheckoutVerifyRequest":{"properties":{"checkout_id":{"type":"string","title":"Checkout Id"},"telegram_id":{"type":"integer","exclusiveMinimum":0.0,"title":"Telegram Id"},"stars_paid":{"type":"integer","exclusiveMinimum":0.0,"title":"Stars Paid"},"pre_checkout_query_id":{"type":"string","maxLength":255,"minLength":1,"title":"Pre Checkout Query Id"}},"type":"object","required":["checkout_id","telegram_id","stars_paid","pre_checkout_query_id"],"title":"StarsCheckoutVerifyRequest"},"StarsInvoiceRequest":{"properties":{"checkout":{"anyOf":[{"$ref":"#/components/schemas/CheckoutInput"},{"type":"null"}]},"package_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Package Id"},"energy":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Energy"},"octodus_checkout":{"anyOf":[{"$ref":"#/components/schemas/OctodusCheckoutInput"},{"type":"null"}]}},"type":"object","title":"StarsInvoiceRequest"},"StarsRecordRequest":{"properties":{"checkout_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Checkout Id"},"telegram_id":{"type":"integer","title":"Telegram Id"},"package_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Package Id"},"base_energy":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Base Energy"},"telegram_payment_charge_id":{"type":"string","title":"Telegram Payment Charge Id"},"stars_paid":{"type":"integer","title":"Stars Paid"}},"type":"object","required":["telegram_id","telegram_payment_charge_id","stars_paid"],"title":"StarsRecordRequest"},"StartDiskOAuth":{"properties":{"space_slug":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Space Slug"},"ticket":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Ticket"},"redirect_to":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Redirect To"}},"type":"object","title":"StartDiskOAuth"},"StartMailOAuth":{"properties":{"space_slug":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Space Slug"},"redirect_to":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Redirect To"}},"type":"object","title":"StartMailOAuth"},"StartOAuthRequest":{"properties":{"feature_groups":{"items":{"type":"string"},"type":"array","title":"Feature Groups"},"redirect_to":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Redirect To"}},"type":"object","title":"StartOAuthRequest"},"StartTrackerOAuth":{"properties":{"org_id":{"type":"string","title":"Org Id"},"org_type":{"type":"string","title":"Org Type"},"space_slug":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Space Slug"},"redirect_to":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Redirect To"}},"type":"object","required":["org_id","org_type"],"title":"StartTrackerOAuth"},"StepIn":{"properties":{"value":{"type":"string","title":"Value"}},"type":"object","required":["value"],"title":"StepIn"},"StudioTurnIn":{"properties":{"offer_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Offer Id"},"thread_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Thread Id"},"source_slugs":{"items":{"type":"string"},"type":"array","title":"Source Slugs","default":[]},"prompt":{"type":"string","title":"Prompt","default":""},"current_html":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Current Html"},"facts":{"additionalProperties":true,"type":"object","title":"Facts","default":{}}},"type":"object","title":"StudioTurnIn"},"SubagentJournalBatchIn":{"properties":{"events":{"items":{"$ref":"#/components/schemas/SubagentJournalEventIn"},"type":"array","title":"Events"}},"type":"object","title":"SubagentJournalBatchIn","description":"The batch body for the gate journal writer. Accepts BOTH wire shapes: a\nbare list of events (dash #430's original contract) AND `{\"events\": [...]}`\n(the shape the ooih journal writer, #1239, actually posts). The pre-validator\nnormalizes a bare list into the wrapped form so one endpoint takes either."},"SubagentJournalEventIn":{"properties":{"task_id":{"type":"string","title":"Task Id"},"kind":{"type":"string","title":"Kind"},"topic":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Topic"},"status":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Status"},"engine":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Engine"},"message":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Message"},"event_ts":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Event Ts"},"queued_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Queued At"},"started_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Started At"},"ended_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Ended At"},"report_count":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Report Count"},"queue_position":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Queue Position"},"admission_state":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Admission State"},"blocked_by":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Blocked By"},"host_occupied":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Host Occupied"},"host_cap":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Host Cap"},"space_occupied":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Space Occupied"},"space_cap":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Space Cap"},"dedup_key":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Dedup Key"},"parent_job_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Parent Job Id"},"trace_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Trace Id"},"origin_kind":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Origin Kind"},"depth":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Depth"}},"type":"object","required":["task_id","kind"],"title":"SubagentJournalEventIn","description":"One sub-agent lifecycle event for the batch journal write. Mirrors the\n`subagent_journal` table (the gate path names the space, so `space_slug` is\nNOT carried here). `kind` is one of spawn|progress|report|error|queued; a\n`cancelled` STATUS on a report/error is a drain/deploy cancellation (neutral,\nresumes automatically) and never renders as a failure on the status page."},"SubscribeRequest":{"properties":{"return_url":{"type":"string","title":"Return Url"},"octomatica_checkout":{"anyOf":[{"$ref":"#/components/schemas/OctomaticaCheckoutInput"},{"type":"null"}]}},"type":"object","required":["return_url"],"title":"SubscribeRequest"},"SubscriptionCreate":{"properties":{"user_id":{"type":"integer","title":"User Id"},"status":{"type":"string","title":"Status","default":"active"},"starts_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Starts At"},"expires_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Expires At"},"energy_limit_usd":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Energy Limit Usd","default":10.0},"notes":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Notes"}},"type":"object","required":["user_id"],"title":"SubscriptionCreate"},"SubscriptionUpdate":{"properties":{"status":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Status"},"starts_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Starts At"},"expires_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Expires At"},"energy_limit_usd":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Energy Limit Usd"},"notes":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Notes"}},"type":"object","title":"SubscriptionUpdate","description":"Partial update — sub_id comes from the URL, user_id never changes,\nand any field omitted from the body is left as-is. Plan is fixed to 'pro'\npost-unification and is no longer client-controllable."},"SupportReplyIn":{"properties":{"ticket_id":{"type":"string","maxLength":32,"minLength":8,"title":"Ticket Id"},"sender_kind":{"type":"string","pattern":"^(admin|space)$","title":"Sender Kind"},"content":{"type":"string","maxLength":8000,"minLength":1,"title":"Content"},"sender_space_slug":{"anyOf":[{"type":"string","maxLength":120},{"type":"null"}],"title":"Sender Space Slug"},"sender_actor":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}],"title":"Sender Actor"},"origin_space_slug":{"anyOf":[{"type":"string","maxLength":120},{"type":"null"}],"title":"Origin Space Slug"},"origin_space_key":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}],"title":"Origin Space Key"},"origin_chat_id":{"anyOf":[{"type":"string","maxLength":64},{"type":"null"}],"title":"Origin Chat Id"},"origin_user_id":{"anyOf":[{"type":"string","maxLength":64},{"type":"null"}],"title":"Origin User Id"},"origin_user_name":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}],"title":"Origin User Name"}},"type":"object","required":["ticket_id","sender_kind","content"],"title":"SupportReplyIn"},"SyncMembersRequest":{"properties":{"chat_id":{"type":"integer","title":"Chat Id"},"members":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Members"},"telegram_update_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Telegram Update Id"}},"type":"object","required":["chat_id","members"],"title":"SyncMembersRequest"},"SyntheticTurn":{"properties":{"space_slug":{"type":"string","title":"Space Slug"},"input_text":{"type":"string","title":"Input Text"},"thread_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Thread Id"},"kind":{"type":"string","title":"Kind","default":"subagent_report"}},"type":"object","required":["space_slug","input_text"],"title":"SyntheticTurn"},"TeamCreate":{"properties":{"manager_user_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Manager User Id"},"manager_user_ids":{"anyOf":[{"items":{"type":"integer"},"type":"array"},{"type":"null"}],"title":"Manager User Ids"},"manager_telegram_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Manager Telegram Id"},"manager_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Manager Name"},"manager_username":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Manager Username"},"name":{"type":"string","title":"Name"},"total_seats":{"type":"integer","title":"Total Seats","default":5},"energy_limit_usd":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Energy Limit Usd"},"duration_days":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Duration Days"}},"type":"object","required":["name"],"title":"TeamCreate"},"TeamSettingsUpdate":{"properties":{"dm_allowed":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Dm Allowed"}},"type":"object","title":"TeamSettingsUpdate"},"TeamUpdate":{"properties":{"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name"},"total_seats":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Total Seats"}},"type":"object","title":"TeamUpdate"},"TeardownApp":{"properties":{"confirm":{"type":"string","title":"Confirm"}},"type":"object","required":["confirm"],"title":"TeardownApp","description":"The owner types the app's own name to confirm. A bare \"are you sure\" is\nnot enough for a verb that stops a running customer application."},"TelegramWebAppAuth":{"properties":{"init_data":{"type":"string","title":"Init Data"},"ref_code":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Ref Code"},"lang":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Lang"}},"type":"object","required":["init_data"],"title":"TelegramWebAppAuth"},"TestSetPlanPrice":{"properties":{"cents":{"type":"integer","title":"Cents"}},"type":"object","required":["cents"],"title":"TestSetPlanPrice"},"TgConnectMintReq":{"properties":{"slug":{"type":"string","title":"Slug"},"requested_by_user_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Requested By User Id"},"lang":{"type":"string","title":"Lang","default":"en"},"label":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Label"}},"type":"object","required":["slug"],"title":"TgConnectMintReq"},"TgConnectResultReq":{"properties":{"token":{"type":"string","title":"Token"},"phase":{"type":"string","title":"Phase"},"status_message":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Status Message"},"tg_user_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Tg User Id"},"username":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Username"},"phone":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Phone"},"label":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Label"},"session":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Session"}},"type":"object","required":["token","phase"],"title":"TgConnectResultReq"},"TgLoginBind":{"properties":{"token":{"type":"string","title":"Token"},"telegram_id":{"type":"integer","title":"Telegram Id"},"first_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"First Name"},"username":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Username"}},"type":"object","required":["token","telegram_id"],"title":"TgLoginBind"},"ToolsIn":{"properties":{"allow":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Allow"},"mcp_servers":{"anyOf":[{"items":{"additionalProperties":true,"type":"object"},"type":"array"},{"type":"null"}],"title":"Mcp Servers"}},"type":"object","title":"ToolsIn"},"ToolsPatchIn":{"properties":{"allow":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Allow"},"mcp_servers":{"anyOf":[{"items":{"additionalProperties":true,"type":"object"},"type":"array"},{"type":"null"}],"title":"Mcp Servers"}},"type":"object","title":"ToolsPatchIn"},"TopupBody":{"properties":{"amount_energy":{"type":"number","title":"Amount Energy"}},"type":"object","required":["amount_energy"],"title":"TopupBody"},"TopupRequest":{"properties":{"checkout":{"anyOf":[{"$ref":"#/components/schemas/CheckoutInput"},{"type":"null"}]},"energy":{"type":"integer","title":"Energy"},"return_url":{"type":"string","title":"Return Url"},"octomatica_checkout":{"anyOf":[{"$ref":"#/components/schemas/OctomaticaCheckoutInput"},{"type":"null"}]}},"type":"object","required":["energy","return_url"],"title":"TopupRequest"},"TrackMemberRequest":{"properties":{"chat_id":{"type":"integer","title":"Chat Id"},"telegram_id":{"type":"integer","title":"Telegram Id"},"username":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Username"},"first_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"First Name"},"action":{"type":"string","title":"Action"},"role":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Role"},"telegram_update_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Telegram Update Id"}},"type":"object","required":["chat_id","telegram_id","action"],"title":"TrackMemberRequest"},"TransferBody":{"properties":{"from_source":{"type":"string","title":"From Source"},"to_target":{"type":"string","title":"To Target"},"amount_energy":{"type":"number","title":"Amount Energy"}},"type":"object","required":["from_source","to_target","amount_energy"],"title":"TransferBody"},"TurnEventIn":{"properties":{"kind":{"type":"string","title":"Kind","default":"info"},"text":{"type":"string","title":"Text"}},"type":"object","required":["text"],"title":"TurnEventIn"},"TurnEventsIn":{"properties":{"events":{"items":{"$ref":"#/components/schemas/TurnEventIn"},"type":"array","title":"Events"},"current_activity":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Current Activity"}},"type":"object","required":["events"],"title":"TurnEventsIn"},"TurnFileRegisterRequest":{"properties":{"space_slug":{"type":"string","title":"Space Slug"},"name":{"type":"string","title":"Name"},"content_type":{"type":"string","title":"Content Type","default":"image/png"},"data_b64":{"type":"string","title":"Data B64"}},"type":"object","required":["space_slug","name","data_b64"],"title":"TurnFileRegisterRequest"},"UpdateApiKeyRequest":{"properties":{"key_value":{"type":"string","title":"Key Value"}},"type":"object","required":["key_value"],"title":"UpdateApiKeyRequest"},"UpdatePool":{"properties":{"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name"},"dm_allowed":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Dm Allowed"},"status":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Status"}},"type":"object","title":"UpdatePool"},"UpdateUser":{"properties":{"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name"},"role":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Role"},"username":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Username"},"telegram_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Telegram Id"},"dm_allowed":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Dm Allowed"}},"type":"object","title":"UpdateUser"},"UsageLimitIn":{"properties":{"end_user_ref":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"End User Ref"},"window":{"type":"string","title":"Window"},"metric":{"type":"string","title":"Metric"},"amount":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Amount"}},"type":"object","required":["window","metric"],"title":"UsageLimitIn"},"UsageReport":{"properties":{"telegram_id":{"type":"integer","title":"Telegram Id","default":0},"chat_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Chat Id"},"chat_key":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Chat Key"},"billing_chat_key":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Billing Chat Key"},"provider":{"type":"string","title":"Provider","default":"claude"},"model":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Model"},"tokens_input":{"type":"integer","minimum":0.0,"title":"Tokens Input","default":0},"tokens_cached":{"type":"integer","minimum":0.0,"title":"Tokens Cached","default":0},"tokens_cache_read":{"anyOf":[{"type":"integer","minimum":0.0},{"type":"null"}],"title":"Tokens Cache Read"},"tokens_cache_write":{"anyOf":[{"type":"integer","minimum":0.0},{"type":"null"}],"title":"Tokens Cache Write"},"tokens_output":{"type":"integer","minimum":0.0,"title":"Tokens Output","default":0},"cost_usd":{"type":"number","minimum":0.0,"title":"Cost Usd","default":0},"duration_sec":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Duration Sec"},"session_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Session Id"},"prompt_hash":{"anyOf":[{"type":"string","maxLength":64},{"type":"null"}],"title":"Prompt Hash"},"subagent_task_id":{"anyOf":[{"type":"string","maxLength":128},{"type":"null"}],"title":"Subagent Task Id"},"subscription_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Subscription Id"},"lease_token":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Lease Token"},"api_turn_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Api Turn Id"},"event_id":{"anyOf":[{"type":"string","maxLength":64,"minLength":1},{"type":"null"}],"title":"Event Id"},"turns_counted":{"anyOf":[{"type":"integer","minimum":0.0},{"type":"null"}],"title":"Turns Counted"},"turns_digest":{"anyOf":[{"type":"string","maxLength":64},{"type":"null"}],"title":"Turns Digest"},"trace_id":{"anyOf":[{"type":"string","maxLength":128},{"type":"null"}],"title":"Trace Id"},"run_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Run Id"},"task_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Task Id"},"cost_source":{"anyOf":[{"type":"string","enum":["vendor_reported","computed_from_tokens","computed_from_units","recovered_estimate"]},{"type":"null"}],"title":"Cost Source"},"turn_role":{"anyOf":[{"type":"string","enum":["origin","no_send_retry","failover_retry"]},{"type":"null"}],"title":"Turn Role"},"turn_outcome":{"anyOf":[{"type":"string","enum":["delivered","failed","timeout"]},{"type":"null"}],"title":"Turn Outcome"},"cost_factor":{"anyOf":[{"type":"number","minimum":0.0},{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$"},{"type":"null"}],"title":"Cost Factor"},"metering_unit":{"anyOf":[{"type":"string","enum":["tokens","call","asset","character","second"]},{"type":"null"}],"title":"Metering Unit"},"task_ref":{"anyOf":[{"type":"string","maxLength":190},{"type":"null"}],"title":"Task Ref"}},"type":"object","title":"UsageReport"},"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"},"VerifyRequest":{"properties":{"telegram_id":{"type":"integer","title":"Telegram Id"},"chat_key":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Chat Key"}},"type":"object","required":["telegram_id"],"title":"VerifyRequest"},"VisitRequest":{"properties":{"event_id":{"type":"string","format":"uuid","title":"Event Id"}},"type":"object","required":["event_id"],"title":"VisitRequest"},"WebhookIn":{"properties":{"url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Url"},"events":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Events"},"space":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Space"},"secret":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Secret"},"active":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Active"}},"type":"object","title":"WebhookIn"},"WebhookPatchIn":{"properties":{"url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Url"},"events":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Events"},"space":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Space"},"secret":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Secret"},"active":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Active"},"rotate_secret":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Rotate Secret"}},"type":"object","title":"WebhookPatchIn"},"WikiDocSave":{"properties":{"space":{"type":"string","title":"Space"},"topic":{"type":"string","title":"Topic"},"body_md":{"type":"string","title":"Body Md"}},"type":"object","required":["space","topic","body_md"],"title":"WikiDocSave"},"WithdrawRequest":{"properties":{"amount_rub_cents":{"type":"integer","minimum":500000.0,"title":"Amount Rub Cents"},"contact_username":{"anyOf":[{"type":"string","maxLength":120},{"type":"null"}],"title":"Contact Username"},"contact_email":{"anyOf":[{"type":"string","maxLength":190},{"type":"null"}],"title":"Contact Email"}},"type":"object","required":["amount_rub_cents"],"title":"WithdrawRequest"},"YandexCreate":{"properties":{"token":{"type":"string","title":"Token"},"org":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Org"},"bot_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Bot Name"}},"type":"object","required":["token"],"title":"YandexCreate","description":"A NEW connection. The only thing the owner must supply is the OAuth token —\nthe single secret a poll-only bot needs; it is already bound to a bot created\nin Yandex 360, so there is no webhook and no registration step. `org` is an\nINTERNAL routing key, derived from the token when omitted (the token implies\nthe org — it is never sent to Yandex). `bot_name` is an optional user label."},"YandexDmConnect":{"properties":{"token":{"type":"string","title":"Token"},"owner_telegram_id":{"anyOf":[{"type":"integer"},{"type":"string"}],"title":"Owner Telegram Id"},"label":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Label"}},"type":"object","required":["token","owner_telegram_id"],"title":"YandexDmConnect"},"YandexDmConnection":{"properties":{"id":{"type":"integer","title":"Id"},"owner_telegram_id":{"anyOf":[{"type":"integer"},{"type":"string"}],"title":"Owner Telegram Id"},"is_active":{"type":"boolean","title":"Is Active"}},"type":"object","required":["id","owner_telegram_id","is_active"],"title":"YandexDmConnection"},"YandexDmDisconnect":{"properties":{"id":{"type":"integer","title":"Id"},"owner_telegram_id":{"anyOf":[{"type":"integer"},{"type":"string"}],"title":"Owner Telegram Id"}},"type":"object","required":["id","owner_telegram_id"],"title":"YandexDmDisconnect"},"YandexFetchOffset":{"properties":{"id":{"type":"integer","title":"Id"},"offset":{"type":"integer","title":"Offset"}},"type":"object","required":["id","offset"],"title":"YandexFetchOffset"},"YandexMemberIn":{"properties":{"space_slug":{"type":"string","title":"Space Slug"},"end_user_ref":{"type":"string","title":"End User Ref"},"display_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Display Name"},"role":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Role"},"account_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Account Id"}},"type":"object","required":["space_slug","end_user_ref"],"title":"YandexMemberIn"},"YandexUpdate":{"properties":{"token":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Token"},"bot_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Bot Name"},"is_active":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Is Active"}},"type":"object","title":"YandexUpdate"},"_CommentOp":{"properties":{"slug":{"type":"string","title":"Slug"},"key":{"type":"string","title":"Key"},"text":{"type":"string","title":"Text"}},"type":"object","required":["slug","key","text"],"title":"_CommentOp"},"_CommentsOp":{"properties":{"slug":{"type":"string","title":"Slug"},"key":{"type":"string","title":"Key"},"per_page":{"type":"integer","title":"Per Page","default":50},"after_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"After Id"}},"type":"object","required":["slug","key"],"title":"_CommentsOp"},"_CreateOp":{"properties":{"slug":{"type":"string","title":"Slug"},"fields":{"additionalProperties":true,"type":"object","title":"Fields"}},"type":"object","required":["slug","fields"],"title":"_CreateOp"},"_DiskLinkOp":{"properties":{"slug":{"type":"string","title":"Slug"},"requested_by":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Requested By"}},"type":"object","required":["slug"],"title":"_DiskLinkOp","description":"\"Give me a link the owner can click to connect their Disk to THIS space."},"_DiskListOp":{"properties":{"slug":{"type":"string","title":"Slug"},"path":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Path"},"limit":{"type":"integer","title":"Limit","default":100},"offset":{"type":"integer","title":"Offset","default":0}},"type":"object","required":["slug"],"title":"_DiskListOp"},"_DiskMoveOp":{"properties":{"slug":{"type":"string","title":"Slug"},"src":{"type":"string","title":"Src"},"dst":{"type":"string","title":"Dst"}},"type":"object","required":["slug","src","dst"],"title":"_DiskMoveOp"},"_DiskOp":{"properties":{"slug":{"type":"string","title":"Slug"},"path":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Path"}},"type":"object","required":["slug"],"title":"_DiskOp"},"_DiskUploadOp":{"properties":{"slug":{"type":"string","title":"Slug"},"path":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Path"},"content_b64":{"type":"string","title":"Content B64"},"overwrite":{"type":"boolean","title":"Overwrite","default":true}},"type":"object","required":["slug","content_b64"],"title":"_DiskUploadOp"},"_IssueLink":{"properties":{"slug":{"type":"string","title":"Slug"},"meeting_id":{"type":"integer","title":"Meeting Id"},"item":{"type":"integer","title":"Item"},"issue_key":{"type":"string","title":"Issue Key"}},"type":"object","required":["slug","meeting_id","item","issue_key"],"title":"_IssueLink"},"_IssueOp":{"properties":{"slug":{"type":"string","title":"Slug"},"key":{"type":"string","title":"Key"}},"type":"object","required":["slug","key"],"title":"_IssueOp"},"_PageOp":{"properties":{"slug":{"type":"string","title":"Slug"},"page":{"type":"integer","title":"Page","default":1},"per_page":{"type":"integer","title":"Per Page","default":50}},"type":"object","required":["slug"],"title":"_PageOp"},"_PublicListOp":{"properties":{"public_key":{"type":"string","title":"Public Key"},"path":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Path"},"limit":{"type":"integer","title":"Limit","default":100},"offset":{"type":"integer","title":"Offset","default":0}},"type":"object","required":["public_key"],"title":"_PublicListOp"},"_PublicOp":{"properties":{"public_key":{"type":"string","title":"Public Key"},"path":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Path"}},"type":"object","required":["public_key"],"title":"_PublicOp","description":"A publicly-shared resource. No space and no Disk connection needed —\nreading one of these uses no credential of ours whatsoever."},"_PublicSaveOp":{"properties":{"public_key":{"type":"string","title":"Public Key"},"path":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Path"},"slug":{"type":"string","title":"Slug"},"dest":{"type":"string","title":"Dest"},"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name"}},"type":"object","required":["public_key","slug","dest"],"title":"_PublicSaveOp"},"_SearchOp":{"properties":{"slug":{"type":"string","title":"Slug"},"page":{"type":"integer","title":"Page","default":1},"per_page":{"type":"integer","title":"Per Page","default":50},"query":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Query"},"filter":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Filter"},"queue":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Queue"},"keys":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Keys"},"order":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Order"}},"type":"object","required":["slug"],"title":"_SearchOp"},"_SetSpaceOwner":{"properties":{"owner_account_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Owner Account Id"}},"type":"object","title":"_SetSpaceOwner"},"_TransitionOp":{"properties":{"slug":{"type":"string","title":"Slug"},"key":{"type":"string","title":"Key"},"transition_id":{"type":"string","title":"Transition Id"},"comment":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Comment"},"fields":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Fields"}},"type":"object","required":["slug","key","transition_id"],"title":"_TransitionOp"},"_UpdateOp":{"properties":{"slug":{"type":"string","title":"Slug"},"key":{"type":"string","title":"Key"},"fields":{"additionalProperties":true,"type":"object","title":"Fields"},"version":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Version"}},"type":"object","required":["slug","key","fields"],"title":"_UpdateOp"}}}}