{"openapi":"3.1.0","info":{"title":"App Manager API","version":"0.1.0"},"paths":{"/api/auth/me":{"get":{"tags":["auth"],"summary":"Me","operationId":"me_api_auth_me_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserInfo"}}}}}}},"/api/auth/me/locale":{"put":{"tags":["auth"],"summary":"Set My Locale","description":"Record the language the user runs the platform in.\n\nCalled by the frontend only when it differs from what /me returned, and\nwritten only when it actually changes — never from the per-request user\nupsert, which would turn every API call into a write.","operationId":"set_my_locale_api_auth_me_locale_put","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LocaleIn"}}},"required":true},"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/users/signup-sources":{"get":{"tags":["users"],"summary":"Signup Sources","description":"Where the accounts came from — the whole point of the capture.\n\nAggregated in Python rather than in SQL because `signup_attribution` is\nJSON on SQLite and JSONB on Postgres, and the two disagree about how you\nreach into it. The row count here is accounts, not events; this stays cheap\nfor far longer than a `->>` expression would be worth.","operationId":"signup_sources_api_users_signup_sources_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SignupSourcesOut"}}}}}}},"/api/users":{"get":{"tags":["users"],"summary":"List Users","operationId":"list_users_api_users_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/UserOut"},"type":"array","title":"Response List Users Api Users Get"}}}}}}},"/api/users/{user_id}":{"delete":{"tags":["users"],"summary":"Delete User","operationId":"delete_user_api_users__user_id__delete","parameters":[{"name":"user_id","in":"path","required":true,"schema":{"type":"string","title":"User Id"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/users/invite":{"post":{"tags":["users"],"summary":"Invite User","operationId":"invite_user_api_users_invite_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserInviteRequest"}}},"required":true},"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/admin/announcements/config":{"get":{"tags":["announcements"],"summary":"Announcement Config","description":"What this deployment can send, so the composer does not have to guess.","operationId":"announcement_config_api_admin_announcements_config_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/admin/announcements":{"get":{"tags":["announcements"],"summary":"List Announcements","operationId":"list_announcements_api_admin_announcements_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/admin/announcements/recipients":{"get":{"tags":["announcements"],"summary":"Search Recipients","description":"Accounts whose email contains ``q``, for picking specific recipients.","operationId":"search_recipients_api_admin_announcements_recipients_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/announcements/{announcement_id}":{"get":{"tags":["announcements"],"summary":"Get Announcement","operationId":"get_announcement_api_admin_announcements__announcement_id__get","parameters":[{"name":"announcement_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Announcement Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/admin/announcements/audience-preview":{"post":{"tags":["announcements"],"summary":"Audience Preview","operationId":"audience_preview_api_admin_announcements_audience_preview_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AudiencePreviewIn"}}},"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/announcements/preview":{"post":{"tags":["announcements"],"summary":"Preview","operationId":"preview_api_admin_announcements_preview_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PreviewIn"}}},"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/announcements/test":{"post":{"tags":["announcements"],"summary":"Send Test","description":"Send every written language to the caller, and only to the caller.","operationId":"send_test_api_admin_announcements_test_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TestIn"}}},"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/announcements/send":{"post":{"tags":["announcements"],"summary":"Send","operationId":"send_api_admin_announcements_send_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SendIn"}}},"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/announcements/images":{"post":{"tags":["announcements"],"summary":"Upload Announcement Image","description":"Store an image and return the link to put in the body.","operationId":"upload_announcement_image_api_admin_announcements_images_post","requestBody":{"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_upload_announcement_image_api_admin_announcements_images_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/public/announcement-images/{image_id}":{"get":{"tags":["announcements"],"summary":"Serve Announcement Image","operationId":"serve_announcement_image_api_public_announcement_images__image_id__get","parameters":[{"name":"image_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Image Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/public/email/preferences":{"get":{"tags":["email-preferences"],"summary":"Preferences","operationId":"preferences_api_public_email_preferences_get","parameters":[{"name":"token","in":"query","required":false,"schema":{"type":"string","default":"","title":"Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/public/email/unsubscribe":{"post":{"tags":["email-preferences"],"summary":"Unsubscribe","operationId":"unsubscribe_api_public_email_unsubscribe_post","parameters":[{"name":"token","in":"query","required":false,"schema":{"type":"string","default":"","title":"Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/public/email/resubscribe":{"post":{"tags":["email-preferences"],"summary":"Resubscribe","operationId":"resubscribe_api_public_email_resubscribe_post","parameters":[{"name":"token","in":"query","required":false,"schema":{"type":"string","default":"","title":"Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/orgs":{"get":{"tags":["orgs"],"summary":"List Orgs","description":"Orgs this user belongs to. Everyone has at least their personal org.","operationId":"list_orgs_api_orgs_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/OrgOut"},"type":"array","title":"Response List Orgs Api Orgs Get"}}}}}},"post":{"tags":["orgs"],"summary":"Create Org","description":"Create a team org. Open to anyone.\n\nSafe precisely because a team org has no free-trial path: minting orgs\ngains an abuser nothing, since a team org with no payment method cannot\ncreate apps at all.","operationId":"create_org_api_orgs_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateOrgRequest"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/orgs/{slug}":{"get":{"tags":["orgs"],"summary":"Get Org","operationId":"get_org_api_orgs__slug__get","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","title":"Slug"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"patch":{"tags":["orgs"],"summary":"Update Org","operationId":"update_org_api_orgs__slug__patch","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","title":"Slug"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateOrgRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["orgs"],"summary":"Delete Org","description":"Delete an organization. Owner only, and only once it holds no apps.\n\nThis is the way OUT of an organization for its owner. An owner cannot\nsimply leave — that would strand the org with nobody able to pay for it,\nmanage its apps, or even receive its billing mail — so the choice is to\nhand ownership to someone else or to delete the organization outright.","operationId":"delete_org_api_orgs__slug__delete","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","title":"Slug"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/orgs/{slug}/members":{"get":{"tags":["orgs"],"summary":"List Members","operationId":"list_members_api_orgs__slug__members_get","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","title":"Slug"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/OrgMemberOut"},"title":"Response List Members Api Orgs  Slug  Members Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["orgs"],"summary":"Invite Member","description":"Invite someone into the org. Owner/admin only — the sole way in.","operationId":"invite_member_api_orgs__slug__members_post","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","title":"Slug"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InviteMemberRequest"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InviteResult"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/orgs/{slug}/apps":{"get":{"tags":["orgs"],"summary":"List Org Apps","description":"The org's own apps, for the invite dialog's picker.\n\nAdmin-only, and scoped to this org: `GET /apps` is every app the CALLER can\nsee across all their orgs, so filling an org invite's picker from it would\noffer apps from a different organization and grant them on submit.","operationId":"list_org_apps_api_orgs__slug__apps_get","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","title":"Slug"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/OrgAppOut"},"title":"Response List Org Apps Api Orgs  Slug  Apps Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/orgs/{slug}/members/{user_id}":{"patch":{"tags":["orgs"],"summary":"Set Member Role","operationId":"set_member_role_api_orgs__slug__members__user_id__patch","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","title":"Slug"}},{"name":"user_id","in":"path","required":true,"schema":{"type":"string","title":"User Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetRoleRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgMemberOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["orgs"],"summary":"Remove Member","description":"Remove a member — and every per-app grant they hold in this org.\n\nThe cascade lives in `orgs_engine.remove_member`. Without it, revoking\nmembership would leave `user_apps` rows intact and the person would keep\nfull access to the apps they were on: the removal would look like it\nworked and would have done nothing.","operationId":"remove_member_api_orgs__slug__members__user_id__delete","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","title":"Slug"}},{"name":"user_id","in":"path","required":true,"schema":{"type":"string","title":"User Id"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/orgs/{slug}/transfer-owner":{"post":{"tags":["orgs"],"summary":"Transfer Owner","operationId":"transfer_owner_api_orgs__slug__transfer_owner_post","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","title":"Slug"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TransferOwnerRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgMemberOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/apps/templates":{"get":{"tags":["apps"],"summary":"List Templates","operationId":"list_templates_api_apps_templates_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/apps":{"get":{"tags":["apps"],"summary":"List Apps","operationId":"list_apps_api_apps_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/AppOut"},"type":"array","title":"Response List Apps Api Apps Get"}}}}}},"post":{"tags":["apps"],"summary":"Create App","operationId":"create_app_api_apps_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateAppRequest"}}},"required":true},"responses":{"202":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateAppJobOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/apps/status":{"get":{"tags":["apps"],"summary":"Get Bulk Status","operationId":"get_bulk_status_api_apps_status_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BulkStatusResponse"}}}}}}},"/api/apps/health":{"get":{"tags":["apps"],"summary":"Get Bulk Health","description":"Per-app health snapshot for the app list: uptime, backups, security, privacy.\n\nAll three are computed from data already in our DB (uptime samples, backup\nruns, the persisted security-scan snapshot) — no Railway/customer round\ntrips — so a client can see at a glance whether each app is online, backed\nup, and clean. Registered before GET /{name} so the literal path wins.","operationId":"get_bulk_health_api_apps_health_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BulkHealthResponse"}}}}}}},"/api/apps/jobs":{"get":{"tags":["apps"],"summary":"List Jobs","operationId":"list_jobs_api_apps_jobs_get","parameters":[{"name":"active_only","in":"query","required":false,"schema":{"type":"boolean","default":true,"title":"Active Only"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/JobOut"},"title":"Response List Jobs Api Apps Jobs Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/apps/name-available":{"get":{"tags":["apps"],"summary":"Name Available","description":"Pre-flight for create_app: is this app name free? Use before create_app\n(the UI checks it on the name field). When taken, `existing` carries the\napp_id + provisioning_status — a failed/incomplete app can be recovered via\nPOST /apps/{app_id}/resume instead of being recreated under a new name.\n\nRegistered before GET /{name} so the static path isn't shadowed by the\n{name} param.","operationId":"name_available_api_apps_name_available_get","parameters":[{"name":"name","in":"query","required":true,"schema":{"type":"string","title":"Name"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NameAvailableOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/apps/{name}":{"get":{"tags":["apps"],"summary":"Get App","operationId":"get_app_api_apps__name__get","parameters":[{"name":"name","in":"path","required":true,"schema":{"type":"string","title":"Name"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"patch":{"tags":["apps"],"summary":"Update App","description":"Update an app's editable metadata. Only display_name (the UI-facing name)\nis mutable; the slug/handle is fixed. App admins/owners and global admins.","operationId":"update_app_api_apps__name__patch","parameters":[{"name":"name","in":"path","required":true,"schema":{"type":"string","title":"Name"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateAppRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["apps"],"summary":"Delete App","operationId":"delete_app_api_apps__name__delete","parameters":[{"name":"name","in":"path","required":true,"schema":{"type":"string","title":"Name"}},{"name":"delete_repo","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"Delete Repo"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/apps/{ident}/resume":{"post":{"tags":["apps"],"summary":"Resume App","description":"Resume a failed or incomplete app creation. ``ident`` is the app_id (the\nstable handle returned by create_app, preferred) or the app name. Re-runs\nonly the steps that haven't completed yet — safe to call repeatedly.","operationId":"resume_app_api_apps__ident__resume_post","parameters":[{"name":"ident","in":"path","required":true,"schema":{"type":"string","title":"Ident"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateAppJobOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/apps/jobs/{job_id}":{"get":{"tags":["apps"],"summary":"Get Job","operationId":"get_job_api_apps_jobs__job_id__get","parameters":[{"name":"job_id","in":"path","required":true,"schema":{"type":"string","title":"Job Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/JobOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/apps/{name}/users":{"get":{"tags":["apps"],"summary":"List App Users","operationId":"list_app_users_api_apps__name__users_get","parameters":[{"name":"name","in":"path","required":true,"schema":{"type":"string","title":"Name"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/AppUserOut"},"title":"Response List App Users Api Apps  Name  Users Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["apps"],"summary":"Add App User","operationId":"add_app_user_api_apps__name__users_post","parameters":[{"name":"name","in":"path","required":true,"schema":{"type":"string","title":"Name"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddAppUserRequest"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppUserOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/apps/{name}/users/candidates":{"get":{"tags":["apps"],"summary":"List App User Candidates","description":"Who this app's admin may still grant access to: the app's ORG members.\n\nExactly the set `add_app_user` below accepts, minus whoever already holds a\ngrant — so every name the picker offers is one the POST will take.\n\nThe UI used to build this list from `GET /users`, which is platform-admin\nonly and returns every user on the platform. For an ordinary org owner that\ncall 403s and the dropdown rendered empty with no error, so nobody outside\nplatform staff could add a user to an app at all; for platform staff it\nlisted every customer's address on the platform and most of them would have\nbeen refused on submit. Neither half was right.","operationId":"list_app_user_candidates_api_apps__name__users_candidates_get","parameters":[{"name":"name","in":"path","required":true,"schema":{"type":"string","title":"Name"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppUserCandidatesOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/apps/{name}/users/invite":{"post":{"tags":["apps"],"summary":"Invite App User","description":"Bring someone NEW into the org and give them this app, in one step.\n\n`add_app_user` can only shuffle access within the org's existing\npopulation, so adding a colleague meant leaving the app entirely, finding\nthe organization page, inviting them there, coming back, and granting the\napp. This is that round trip collapsed.\n\nIt is org-owner/admin only, deliberately. An app admin who is a plain org\nmember must not be able to widen the org — that containment property is\nwhat makes a per-app grant a real boundary, and it is asserted by\n`test_an_app_admin_cannot_add_a_non_member_to_their_app`. Such a caller\nkeeps the picker and gets 403 here.\n\n`require_team` runs before any row is written, exactly as `invite_member`\ndoes: a refused invite must not leave a pending user squatting the address.","operationId":"invite_app_user_api_apps__name__users_invite_post","parameters":[{"name":"name","in":"path","required":true,"schema":{"type":"string","title":"Name"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InviteAppUserRequest"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InviteAppUserResult"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/apps/{name}/users/{user_id}":{"delete":{"tags":["apps"],"summary":"Remove App User","operationId":"remove_app_user_api_apps__name__users__user_id__delete","parameters":[{"name":"name","in":"path","required":true,"schema":{"type":"string","title":"Name"}},{"name":"user_id","in":"path","required":true,"schema":{"type":"string","title":"User Id"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/apps/{name}/transfer-owner":{"post":{"tags":["apps"],"summary":"Transfer Owner","operationId":"transfer_owner_api_apps__name__transfer_owner_post","parameters":[{"name":"name","in":"path","required":true,"schema":{"type":"string","title":"Name"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TransferOwnerRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppUserOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/apps/{name}/downtime-alerts":{"get":{"tags":["apps"],"summary":"Get Downtime Alerts","description":"Whether the app's admins are mailed when its prod address goes down.","operationId":"get_downtime_alerts_api_apps__name__downtime_alerts_get","parameters":[{"name":"name","in":"path","required":true,"schema":{"type":"string","title":"Name"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DowntimeAlertsOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["apps"],"summary":"Set Downtime Alerts","description":"Switch downtime alerts on or off. App admins/owners and global admins.","operationId":"set_downtime_alerts_api_apps__name__downtime_alerts_put","parameters":[{"name":"name","in":"path","required":true,"schema":{"type":"string","title":"Name"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DowntimeAlertsIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DowntimeAlertsOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/apps/{name}/volume":{"get":{"tags":["apps"],"summary":"Get App Volume","operationId":"get_app_volume_api_apps__name__volume_get","parameters":[{"name":"name","in":"path","required":true,"schema":{"type":"string","title":"Name"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/VolumeInfoResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/apps/{name}/usage":{"get":{"tags":["apps"],"summary":"Get App Usage","description":"Daily resource usage for the current month. Usage only — no costs; the\nbilling endpoints own the money view.","operationId":"get_app_usage_api_apps__name__usage_get","parameters":[{"name":"name","in":"path","required":true,"schema":{"type":"string","title":"Name"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppUsageResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/apps/{name}/backups/settings":{"get":{"tags":["backups"],"summary":"Get Backup Settings","operationId":"get_backup_settings_api_apps__name__backups_settings_get","parameters":[{"name":"name","in":"path","required":true,"schema":{"type":"string","title":"Name"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BackupSettingsOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["backups"],"summary":"Update Backup Settings","operationId":"update_backup_settings_api_apps__name__backups_settings_put","parameters":[{"name":"name","in":"path","required":true,"schema":{"type":"string","title":"Name"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateBackupSettingsRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BackupSettingsOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/apps/{name}/backups/health":{"get":{"tags":["backups"],"summary":"Get Backup Health","operationId":"get_backup_health_api_apps__name__backups_health_get","parameters":[{"name":"name","in":"path","required":true,"schema":{"type":"string","title":"Name"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BackupHealthOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/apps/{name}/backups/secret-check":{"get":{"tags":["backups"],"summary":"Get Secret Check","operationId":"get_secret_check_api_apps__name__backups_secret_check_get","parameters":[{"name":"name","in":"path","required":true,"schema":{"type":"string","title":"Name"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SecretCheckOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/apps/{name}/backups/rotate-secret":{"post":{"tags":["backups"],"summary":"Post Rotate Secret","operationId":"post_rotate_secret_api_apps__name__backups_rotate_secret_post","parameters":[{"name":"name","in":"path","required":true,"schema":{"type":"string","title":"Name"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RotateSecretOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/apps/{name}/backups":{"get":{"tags":["backups"],"summary":"List Backups","operationId":"list_backups_api_apps__name__backups_get","parameters":[{"name":"name","in":"path","required":true,"schema":{"type":"string","title":"Name"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","default":100,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/BackupRunOut"},"title":"Response List Backups Api Apps  Name  Backups Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["backups"],"summary":"Create Backup","operationId":"create_backup_api_apps__name__backups_post","parameters":[{"name":"name","in":"path","required":true,"schema":{"type":"string","title":"Name"}}],"responses":{"202":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BackupRunOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["backups"],"summary":"Delete Failed Backups","description":"Bulk-delete every backup_run for the app whose status == 'failed'.\n\nConvenience for clearing noise rows produced while a service was broken.\nFailed rows almost never have S3 objects, but we still go through\ndelete_backup_run so any stragglers get cleaned up.","operationId":"delete_failed_backups_api_apps__name__backups_delete","parameters":[{"name":"name","in":"path","required":true,"schema":{"type":"string","title":"Name"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/apps/{name}/backups/{run_id}/download":{"get":{"tags":["backups"],"summary":"Download Backup","operationId":"download_backup_api_apps__name__backups__run_id__download_get","parameters":[{"name":"name","in":"path","required":true,"schema":{"type":"string","title":"Name"}},{"name":"run_id","in":"path","required":true,"schema":{"type":"string","title":"Run Id"}},{"name":"file","in":"query","required":false,"schema":{"type":"string","default":"db.dump","title":"File"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/apps/{name}/backups/{run_id}":{"delete":{"tags":["backups"],"summary":"Delete Backup","operationId":"delete_backup_api_apps__name__backups__run_id__delete","parameters":[{"name":"name","in":"path","required":true,"schema":{"type":"string","title":"Name"}},{"name":"run_id","in":"path","required":true,"schema":{"type":"string","title":"Run Id"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/apps/{name}/restore":{"post":{"tags":["backups"],"summary":"Restore Backup","operationId":"restore_backup_api_apps__name__restore_post","parameters":[{"name":"name","in":"path","required":true,"schema":{"type":"string","title":"Name"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RestoreRequest"}}}},"responses":{"202":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BackupRunOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/apps/{name}/board":{"get":{"tags":["board"],"summary":"Get Board","operationId":"get_board_api_apps__name__board_get","parameters":[{"name":"name","in":"path","required":true,"schema":{"type":"string","title":"Name"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/apps/{name}/board/assignees":{"get":{"tags":["board"],"summary":"List Assignees","operationId":"list_assignees_api_apps__name__board_assignees_get","parameters":[{"name":"name","in":"path","required":true,"schema":{"type":"string","title":"Name"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/AssigneeOut"},"title":"Response List Assignees Api Apps  Name  Board Assignees Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/apps/{name}/board/sync":{"post":{"tags":["board"],"summary":"Sync Board","description":"Apply commits no board hook saw (pushed directly, merged on GitHub).\n\n`auto` is the board opening: at most every couple of minutes. The Refresh\nbutton forces one, with a short floor so a burst of clicks is one read.","operationId":"sync_board_api_apps__name__board_sync_post","parameters":[{"name":"name","in":"path","required":true,"schema":{"type":"string","title":"Name"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SyncIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/apps/{name}/board/attachments":{"post":{"tags":["board"],"summary":"Upload Attachment","description":"An image for a ticket description: returns a link the editor can show now.\n\nThe link expires; saving the description folds it back to a stable reference\n(engine/board_attachments.py). Read one byte past the limit so an oversized\nfile is refused without buffering all of it.","operationId":"upload_attachment_api_apps__name__board_attachments_post","parameters":[{"name":"name","in":"path","required":true,"schema":{"type":"string","title":"Name"}}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_upload_attachment_api_apps__name__board_attachments_post"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/apps/{name}/board/settings":{"patch":{"tags":["board"],"summary":"Update Settings","description":"Board name, ticket prefix and new-ticket defaults: an app admin's.\n\nRenaming the prefix changes every ticket's key, and commits must use the new\none from then on.","operationId":"update_settings_api_apps__name__board_settings_patch","parameters":[{"name":"name","in":"path","required":true,"schema":{"type":"string","title":"Name"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BoardSettingsIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/apps/{name}/board/columns":{"post":{"tags":["board"],"summary":"Create Column","operationId":"create_column_api_apps__name__board_columns_post","parameters":[{"name":"name","in":"path","required":true,"schema":{"type":"string","title":"Name"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ColumnIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/apps/{name}/board/columns/order":{"put":{"tags":["board"],"summary":"Reorder Columns","operationId":"reorder_columns_api_apps__name__board_columns_order_put","parameters":[{"name":"name","in":"path","required":true,"schema":{"type":"string","title":"Name"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ColumnOrderIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/apps/{name}/board/columns/{column_id}":{"patch":{"tags":["board"],"summary":"Rename Column","operationId":"rename_column_api_apps__name__board_columns__column_id__patch","parameters":[{"name":"name","in":"path","required":true,"schema":{"type":"string","title":"Name"}},{"name":"column_id","in":"path","required":true,"schema":{"type":"string","title":"Column Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ColumnIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["board"],"summary":"Delete Column","operationId":"delete_column_api_apps__name__board_columns__column_id__delete","parameters":[{"name":"name","in":"path","required":true,"schema":{"type":"string","title":"Name"}},{"name":"column_id","in":"path","required":true,"schema":{"type":"string","title":"Column Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/apps/{name}/board/versions":{"post":{"tags":["board"],"summary":"Create Version","description":"Release versions: any member of the app manages them, like columns.","operationId":"create_version_api_apps__name__board_versions_post","parameters":[{"name":"name","in":"path","required":true,"schema":{"type":"string","title":"Name"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/VersionCreateIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/apps/{name}/board/versions/{version_id}":{"patch":{"tags":["board"],"summary":"Update Version","operationId":"update_version_api_apps__name__board_versions__version_id__patch","parameters":[{"name":"name","in":"path","required":true,"schema":{"type":"string","title":"Name"}},{"name":"version_id","in":"path","required":true,"schema":{"type":"string","title":"Version Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/VersionUpdateIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["board"],"summary":"Delete Version","description":"Its tickets stay on the board, with no version — unless `delete_tickets`,\nwhich deletes them too, under the rules for deleting a ticket.","operationId":"delete_version_api_apps__name__board_versions__version_id__delete","parameters":[{"name":"name","in":"path","required":true,"schema":{"type":"string","title":"Name"}},{"name":"version_id","in":"path","required":true,"schema":{"type":"string","title":"Version Id"}},{"name":"delete_tickets","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"Delete Tickets"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/apps/{name}/board/tickets":{"post":{"tags":["board"],"summary":"Create Ticket","operationId":"create_ticket_api_apps__name__board_tickets_post","parameters":[{"name":"name","in":"path","required":true,"schema":{"type":"string","title":"Name"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TicketCreateIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/apps/{name}/board/tickets/{number}":{"patch":{"tags":["board"],"summary":"Update Ticket","operationId":"update_ticket_api_apps__name__board_tickets__number__patch","parameters":[{"name":"name","in":"path","required":true,"schema":{"type":"string","title":"Name"}},{"name":"number","in":"path","required":true,"schema":{"type":"integer","title":"Number"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TicketUpdateIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["board"],"summary":"Delete Ticket","operationId":"delete_ticket_api_apps__name__board_tickets__number__delete","parameters":[{"name":"name","in":"path","required":true,"schema":{"type":"string","title":"Name"}},{"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/apps/{name}/board/tickets/{number}/move":{"post":{"tags":["board"],"summary":"Move Ticket","operationId":"move_ticket_api_apps__name__board_tickets__number__move_post","parameters":[{"name":"name","in":"path","required":true,"schema":{"type":"string","title":"Name"}},{"name":"number","in":"path","required":true,"schema":{"type":"integer","title":"Number"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TicketMoveIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/apps/{name}/board/agent":{"post":{"tags":["board"],"summary":"Set Board Agent","description":"Switch the platform's own agent on or off for this app. An app admin's.\n\nTurning an autonomous committer on for someone's repository should be a\ndecision somebody made, not a side effect of opening the board — which is\nwhy the agent is not granted access anywhere else, and why this is gated the\nsame way the ticket prefix is.\n\nDeliberately HTTP only, with no MCP twin. The rule that a gate needs both\nsurfaces is about a gate being BYPASSABLE on the one that lacks it; a\ncapability that simply is not exposed over MCP cannot be reached from there\nat all. It also costs nothing against `TOTAL_DESCRIPTION_CEILING`, which has\nsingle-digit headroom.","operationId":"set_board_agent_api_apps__name__board_agent_post","parameters":[{"name":"name","in":"path","required":true,"schema":{"type":"string","title":"Name"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/apps/{name}/board/tickets/{number}/run/cancel":{"post":{"tags":["board"],"summary":"Cancel Ticket Run","description":"Stop the agent on this ticket and unassign it.\n\nA queued or waiting run stops on the spot. A running one is a request rather\nthan a kill: the runner reads it at the next step boundary and lets go of the\nticket there, so nothing is left half-applied.","operationId":"cancel_ticket_run_api_apps__name__board_tickets__number__run_cancel_post","parameters":[{"name":"name","in":"path","required":true,"schema":{"type":"string","title":"Name"}},{"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/apps/{name}/board/tickets/{number}/run/retry":{"post":{"tags":["board"],"summary":"Retry Ticket Run","description":"Start a failed run again, from the top.\n\nFrom the top because the throwaway checkout went with the process that died;\nresuming where it stopped would resume into an empty directory.","operationId":"retry_ticket_run_api_apps__name__board_tickets__number__run_retry_post","parameters":[{"name":"name","in":"path","required":true,"schema":{"type":"string","title":"Name"}},{"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/apps/{name}/board/tickets/{number}/messages":{"get":{"tags":["board"],"summary":"List Ticket Messages","description":"The ticket's thread: the agent's questions, the answers, its spec and verdicts.\n\nAny member of the app may read it, the same rule as the rest of the board.","operationId":"list_ticket_messages_api_apps__name__board_tickets__number__messages_get","parameters":[{"name":"name","in":"path","required":true,"schema":{"type":"string","title":"Name"}},{"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"}}}}}},"post":{"tags":["board"],"summary":"Add Ticket Message","description":"Reply on a ticket. Answers the agent's outstanding question when there is one.\n\nAn answer (which resumes the run) only while a run is waiting for one;\notherwise a comment — see `ticket_runs.reply`. Returns the whole thread, the\nway every board write returns the whole board — the caller replaces its state\nwith the server's view rather than patching its own guess.","operationId":"add_ticket_message_api_apps__name__board_tickets__number__messages_post","parameters":[{"name":"name","in":"path","required":true,"schema":{"type":"string","title":"Name"}},{"name":"number","in":"path","required":true,"schema":{"type":"integer","title":"Number"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TicketMessageIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/apps/{name}/roadmap":{"get":{"tags":["roadmap"],"summary":"Get Roadmap","operationId":"get_roadmap_api_apps__name__roadmap_get","parameters":[{"name":"name","in":"path","required":true,"schema":{"type":"string","title":"Name"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/apps/{name}/roadmap/sessions":{"post":{"tags":["roadmap"],"summary":"Start Session","operationId":"start_session_api_apps__name__roadmap_sessions_post","parameters":[{"name":"name","in":"path","required":true,"schema":{"type":"string","title":"Name"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SessionStartIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/apps/{name}/roadmap/sessions/{session_id}":{"get":{"tags":["roadmap"],"summary":"Get Session","description":"Any session of the app, finished ones too — the transcript behind a version.","operationId":"get_session_api_apps__name__roadmap_sessions__session_id__get","parameters":[{"name":"name","in":"path","required":true,"schema":{"type":"string","title":"Name"}},{"name":"session_id","in":"path","required":true,"schema":{"type":"string","title":"Session Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/apps/{name}/roadmap/sessions/{session_id}/messages":{"post":{"tags":["roadmap"],"summary":"Post Message","operationId":"post_message_api_apps__name__roadmap_sessions__session_id__messages_post","parameters":[{"name":"name","in":"path","required":true,"schema":{"type":"string","title":"Name"}},{"name":"session_id","in":"path","required":true,"schema":{"type":"string","title":"Session Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MessageIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/apps/{name}/roadmap/sessions/{session_id}/retry":{"post":{"tags":["roadmap"],"summary":"Retry","operationId":"retry_api_apps__name__roadmap_sessions__session_id__retry_post","parameters":[{"name":"name","in":"path","required":true,"schema":{"type":"string","title":"Name"}},{"name":"session_id","in":"path","required":true,"schema":{"type":"string","title":"Session Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/apps/{name}/roadmap/sessions/{session_id}/close":{"post":{"tags":["roadmap"],"summary":"Close Session","operationId":"close_session_api_apps__name__roadmap_sessions__session_id__close_post","parameters":[{"name":"name","in":"path","required":true,"schema":{"type":"string","title":"Name"}},{"name":"session_id","in":"path","required":true,"schema":{"type":"string","title":"Session Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/apps/{name}/roadmap/sessions/{session_id}/confirm":{"post":{"tags":["roadmap"],"summary":"Confirm","description":"Create the version and its tickets. Safe to send twice — see engine/roadmap.confirm.","operationId":"confirm_api_apps__name__roadmap_sessions__session_id__confirm_post","parameters":[{"name":"name","in":"path","required":true,"schema":{"type":"string","title":"Name"}},{"name":"session_id","in":"path","required":true,"schema":{"type":"string","title":"Session Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConfirmIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/roadmap/draft":{"get":{"tags":["roadmap"],"summary":"Get Live Draft","description":"The person's draft still being planned, or null.","operationId":"get_live_draft_api_roadmap_draft_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/roadmap/drafts":{"post":{"tags":["roadmap"],"summary":"Start Draft","operationId":"start_draft_api_roadmap_drafts_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DraftStartIn"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/roadmap/drafts/{session_id}":{"get":{"tags":["roadmap"],"summary":"Get Draft","operationId":"get_draft_api_roadmap_drafts__session_id__get","parameters":[{"name":"session_id","in":"path","required":true,"schema":{"type":"string","title":"Session Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/roadmap/drafts/{session_id}/messages":{"post":{"tags":["roadmap"],"summary":"Post Draft Message","operationId":"post_draft_message_api_roadmap_drafts__session_id__messages_post","parameters":[{"name":"session_id","in":"path","required":true,"schema":{"type":"string","title":"Session Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MessageIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/roadmap/drafts/{session_id}/retry":{"post":{"tags":["roadmap"],"summary":"Retry Draft","operationId":"retry_draft_api_roadmap_drafts__session_id__retry_post","parameters":[{"name":"session_id","in":"path","required":true,"schema":{"type":"string","title":"Session Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/roadmap/drafts/{session_id}/close":{"post":{"tags":["roadmap"],"summary":"Close Draft","operationId":"close_draft_api_roadmap_drafts__session_id__close_post","parameters":[{"name":"session_id","in":"path","required":true,"schema":{"type":"string","title":"Session Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/billing/summary":{"get":{"tags":["billing"],"summary":"Billing Summary","operationId":"billing_summary_api_billing_summary_get","parameters":[{"name":"org","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Org"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/billing/apps/{name}":{"get":{"tags":["billing"],"summary":"App Billing","operationId":"app_billing_api_billing_apps__name__get","parameters":[{"name":"name","in":"path","required":true,"schema":{"type":"string","title":"Name"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/billing/apps/{name}/retry-subscription":{"post":{"tags":["billing"],"summary":"Retry Subscription","description":"Re-attempt a subscription that failed to be created in Stripe.\n\nOpen to the app's billing owner (a trial user with no card must be able to\nself-serve) and to super-admins. Any remaining trial days are preserved.","operationId":"retry_subscription_api_billing_apps__name__retry_subscription_post","parameters":[{"name":"name","in":"path","required":true,"schema":{"type":"string","title":"Name"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/billing/checkout/setup":{"post":{"tags":["billing"],"summary":"Checkout Setup","operationId":"checkout_setup_api_billing_checkout_setup_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CheckoutRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/billing/portal":{"post":{"tags":["billing"],"summary":"Billing Portal","operationId":"billing_portal_api_billing_portal_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CheckoutRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/billing/invoices":{"get":{"tags":["billing"],"summary":"Invoices","operationId":"invoices_api_billing_invoices_get","parameters":[{"name":"org","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Org"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/billing/apps/{name}/billing-exempt":{"put":{"tags":["billing"],"summary":"Set Billing Exempt","operationId":"set_billing_exempt_api_billing_apps__name__billing_exempt_put","parameters":[{"name":"name","in":"path","required":true,"schema":{"type":"string","title":"Name"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExemptRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/billing/apps/{name}/billing-hold":{"put":{"tags":["billing"],"summary":"Set Billing Hold","description":"Super-admin \"treat as no payment\" switch. Setting it true disconnects the\napp immediately (and emails the owner the first time); clearing it restores\nthe app if it's otherwise paid up. The daily sweep enforces the same rule\ngoing forward.\n\nSetting it on an app that is already suspended re-asserts the disconnect\nrather than doing nothing — the only manual way to take a paused app down\nwithout waiting for the sweep. It does not restart the deletion clock.","operationId":"set_billing_hold_api_billing_apps__name__billing_hold_put","parameters":[{"name":"name","in":"path","required":true,"schema":{"type":"string","title":"Name"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HoldRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/billing/ai-balance":{"get":{"tags":["billing"],"summary":"Get Ai Balance","description":"This organization's AI credit pool.\n\n`available_microcents` is the number that matters: `balance - reserved`. Requests\nin flight hold against the balance until they settle, so `balance_microcents`\nalone would overstate what can actually be spent right now.","operationId":"get_ai_balance_api_billing_ai_balance_get","parameters":[{"name":"org","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Org"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AiBalanceOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/billing/ai-usage":{"get":{"tags":["billing"],"summary":"Get Ai Usage","description":"What this organization's AI credit went on over the last 30 days, per\nday, product and use. Who can see the balance can see this.","operationId":"get_ai_usage_api_billing_ai_usage_get","parameters":[{"name":"org","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Org"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AiUsageOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/billing/ai-balance/topup":{"post":{"tags":["billing"],"summary":"Topup Ai Balance","description":"Buy AI credit now. Org owner/admin.\n\nReturns the invoice status rather than a success flag, because \"charged\" and\n\"credited\" are different moments: the balance goes up when the webhook\nconfirms payment, never here. A caller that renders this response as\n\"credit added\" would be showing money that can still be reversed.","operationId":"topup_ai_balance_api_billing_ai_balance_topup_post","parameters":[{"name":"org","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Org"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TopupRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TopupOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/billing/ai-balance/auto-refill":{"put":{"tags":["billing"],"summary":"Set Auto Refill","description":"Turn automatic refill on or off and set its amount and trigger point.\n\nThe threshold is a floor on AVAILABLE credit, not on the balance, and it is\nwhat keeps a customer's app from ever seeing a 402: the refill fires while\nthere is still credit left to spend rather than after it has run out.","operationId":"set_auto_refill_api_billing_ai_balance_auto_refill_put","parameters":[{"name":"org","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Org"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AutoRefillRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AiBalanceOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/billing/ai-balance/grant":{"post":{"tags":["billing"],"summary":"Grant Ai Credit","description":"Comp an organization AI credit. Platform admin only.\n\nNot reachable by an org's own admins, and not exposed over MCP at all. Now\nthat customers can buy credit themselves, this is the *comp* path: credit\nnobody paid for, which is why it stays deliberate and attributable rather\nthan merely privileged. Every call writes an `ai_credit_grants` row naming\nthe granting user.\n\n`LogtoAdminUser` and not `AdminUser`: the in-app `admin` role can be set in\nthe database independently of the Logto scope, and minting money is not\nsomething a row in a table should be able to authorize.","operationId":"grant_ai_credit_api_billing_ai_balance_grant_post","parameters":[{"name":"org","in":"query","required":true,"schema":{"type":"string","title":"Org"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GrantCreditRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AiBalanceOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/billing/apps/{name}/tier":{"put":{"tags":["billing"],"summary":"Set App Tier","description":"Move an app between Hobby and Pro. App admin, or platform admin.\n\n`enterprise` is refused here even for a platform admin: it has no configured\nprice, so \"setting\" it self-serve would leave an app entitled at the top of\nthe ladder on a $15 subscription. It is set through the admin endpoint\nbelow, as part of a deal someone has actually made.","operationId":"set_app_tier_api_billing_apps__name__tier_put","parameters":[{"name":"name","in":"path","required":true,"schema":{"type":"string","title":"Name"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TierRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/billing/orgs/{slug}/plan":{"put":{"tags":["billing"],"summary":"Set Organization Plan","description":"Move an org between Solo and Team. Org owner/admin, or platform admin.\n\nEnterprise is refused for the same reason as the app tier above.","operationId":"set_organization_plan_api_billing_orgs__slug__plan_put","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","title":"Slug"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PlanRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/billing/admin/apps/{name}/tier":{"put":{"tags":["billing"],"summary":"Admin Set App Tier","description":"Set an app's PAID tier, Enterprise included. Platform admin only.\n\nThis is the money endpoint — it goes through the same Stripe path a\ncustomer's own upgrade does. To give an app a capability WITHOUT changing\nwhat it is billed, use `/admin/apps/{name}/entitlement` instead.","operationId":"admin_set_app_tier_api_billing_admin_apps__name__tier_put","parameters":[{"name":"name","in":"path","required":true,"schema":{"type":"string","title":"Name"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TierRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/billing/admin/orgs/{slug}/plan":{"put":{"tags":["billing"],"summary":"Admin Set Org Plan","description":"Set an org's PAID plan, Enterprise included. Platform admin only.","operationId":"admin_set_org_plan_api_billing_admin_orgs__slug__plan_put","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","title":"Slug"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PlanRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/billing/admin/apps/{name}/entitlement":{"put":{"tags":["billing"],"summary":"Admin Set App Entitlement","description":"Comp an app a tier it is not paying for, or revoke the comp.\n\nTouches no Stripe object and does not move the usage allowance: the customer\nkeeps the invoice and the included usage they have, and gains the\ncapability. `billing_exempt` is NOT the tool for this — it means \"no billing\nat all\", so using it to do someone a favour would stop charging them.\n\n`LogtoAdminUser`, not `AdminUser`, for the same reason `grant_ai_credit` is:\nthe in-app `admin` role is a row in a table, and giving away revenue is not\nsomething a row should be able to authorize.","operationId":"admin_set_app_entitlement_api_billing_admin_apps__name__entitlement_put","parameters":[{"name":"name","in":"path","required":true,"schema":{"type":"string","title":"Name"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EntitlementRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/billing/admin/orgs/{slug}/entitlement":{"put":{"tags":["billing"],"summary":"Admin Set Org Entitlement","description":"The org-axis twin of the endpoint above. Platform admin only.","operationId":"admin_set_org_entitlement_api_billing_admin_orgs__slug__entitlement_put","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","title":"Slug"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EntitlementRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/billing/admin/entitlement-grants":{"get":{"tags":["billing"],"summary":"List Entitlement Grants","description":"Every comp, newest first — so one granted six months ago is findable by\nsomebody who did not grant it.","operationId":"list_entitlement_grants_api_billing_admin_entitlement_grants_get","parameters":[{"name":"include_revoked","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"Include Revoked"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/billing/admin/orgs":{"get":{"tags":["billing"],"summary":"List All Organizations","description":"Every organization on the platform, with its plan and its apps' tiers.\n\n`GET /api/orgs` deliberately returns only orgs the caller BELONGS to, even\nfor a super admin — membership is how that endpoint authorizes, and widening\nit would change what it means for everyone. So the admin view is its own\nendpoint rather than a flag on that one, and this is the list the admin\nscreens pick an organization from instead of asking someone to type a slug.","operationId":"list_all_organizations_api_billing_admin_orgs_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/apps/{name}/promote":{"post":{"tags":["deploy"],"summary":"Promote App","operationId":"promote_app_api_apps__name__promote_post","parameters":[{"name":"name","in":"path","required":true,"schema":{"type":"string","title":"Name"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PromoteRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PromoteResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/apps/{name}/promote/cancel":{"post":{"tags":["deploy"],"summary":"Cancel Release","description":"Withdraw a release scheduled to merge when CI passes.","operationId":"cancel_release_api_apps__name__promote_cancel_post","parameters":[{"name":"name","in":"path","required":true,"schema":{"type":"string","title":"Name"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/apps/{name}/discard":{"post":{"tags":["deploy"],"summary":"Discard App","operationId":"discard_app_api_apps__name__discard_post","parameters":[{"name":"name","in":"path","required":true,"schema":{"type":"string","title":"Name"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/apps/{name}/logs":{"get":{"tags":["deploy"],"summary":"Get Logs","operationId":"get_logs_api_apps__name__logs_get","parameters":[{"name":"name","in":"path","required":true,"schema":{"type":"string","title":"Name"}},{"name":"env","in":"query","required":false,"schema":{"type":"string","default":"dev","title":"Env"}},{"name":"type","in":"query","required":false,"schema":{"type":"string","default":"runtime","title":"Type"}},{"name":"lines","in":"query","required":false,"schema":{"type":"integer","default":50,"title":"Lines"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LogsResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/apps/{name}/status":{"get":{"tags":["deploy"],"summary":"Get Status","operationId":"get_status_api_apps__name__status_get","parameters":[{"name":"name","in":"path","required":true,"schema":{"type":"string","title":"Name"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatusResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/apps/{name}/dev/replicas":{"post":{"tags":["deploy"],"summary":"Set Dev Replicas","operationId":"set_dev_replicas_api_apps__name__dev_replicas_post","parameters":[{"name":"name","in":"path","required":true,"schema":{"type":"string","title":"Name"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetReplicasRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/apps/{name}/domains":{"get":{"tags":["deploy"],"summary":"Get Domains","operationId":"get_domains_api_apps__name__domains_get","parameters":[{"name":"name","in":"path","required":true,"schema":{"type":"string","title":"Name"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["deploy"],"summary":"Add Domain","operationId":"add_domain_api_apps__name__domains_post","parameters":[{"name":"name","in":"path","required":true,"schema":{"type":"string","title":"Name"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddDomainRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["deploy"],"summary":"Delete Domain","operationId":"delete_domain_api_apps__name__domains_delete","parameters":[{"name":"name","in":"path","required":true,"schema":{"type":"string","title":"Name"}},{"name":"domain","in":"query","required":true,"schema":{"type":"string","title":"Domain"}},{"name":"env","in":"query","required":false,"schema":{"enum":["prod","dev"],"type":"string","default":"prod","title":"Env"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/apps/{name}/domains/primary":{"post":{"tags":["deploy"],"summary":"Set Primary Domain","description":"Promote a verified custom domain to be the env's primary.\n\nFor prod, this also swings the status subdomain: tear down\n``status.<old_primary>`` and provision ``status.<new_primary>`` on the\napp-manager Railway service. Both steps are best-effort — DB primary swap\ncommits regardless so the UI isn't blocked by a Railway/Cloudflare flake.","operationId":"set_primary_domain_api_apps__name__domains_primary_post","parameters":[{"name":"name","in":"path","required":true,"schema":{"type":"string","title":"Name"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetPrimaryDomainRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/apps/{name}/status-page-dns":{"get":{"tags":["deploy"],"summary":"Get Status Page Dns","description":"Return the DNS records Railway requires for `status.<prod_domain>`.\n\nThe frontend uses this to surface a manual-DNS instruction box on the\nStatus card when the customer's zone isn't on our Cloudflare account —\nRailway's CNAME + ACME-challenge TXT need to be added by hand for the\ncert to issue. When `verified` is True the box can be hidden; everything\nis already wired up.","operationId":"get_status_page_dns_api_apps__name__status_page_dns_get","parameters":[{"name":"name","in":"path","required":true,"schema":{"type":"string","title":"Name"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/apps/{name}/provision-status":{"post":{"tags":["deploy"],"summary":"Provision Status","description":"Backfill `status.<prod_domain>` for an app whose prod domain was added\nbefore the status-page feature shipped. Idempotent — calling on an\nalready-provisioned app just re-syncs Cloudflare DNS.","operationId":"provision_status_api_apps__name__provision_status_post","parameters":[{"name":"name","in":"path","required":true,"schema":{"type":"string","title":"Name"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/apps/{name}/variables":{"get":{"tags":["deploy"],"summary":"Get Variables","description":"List env vars, with the values of the caller's own vars.\n\nThe browser gets its values here, not one reveal at a time: this page is the\nonly interface a human has for setting a secret now that MCP can't, so it has\nto be usable. The masking is client-side again, as it was before.\n\nFiltering is still server-side: Railway-injected vars never leave the backend,\nand platform-managed ones (DATABASE_URL, BACKUP_HMAC_SECRET, ...) are listed\nonly to super-admins — and even for them, only as metadata. Their values stay\non /variables/reveal, one key at a time.","operationId":"get_variables_api_apps__name__variables_get","parameters":[{"name":"name","in":"path","required":true,"schema":{"type":"string","title":"Name"}},{"name":"env","in":"query","required":false,"schema":{"type":"string","default":"prod","title":"Env"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["deploy"],"summary":"Update Variables","description":"Upsert and delete env vars. The human path — no agent allow-list here.\n\nDeliberately not gated by the agent allow-list: this is an authenticated\nperson in a browser, which is precisely where secrets are supposed to be\nentered. Platform-managed keys stay super-admin only.","operationId":"update_variables_api_apps__name__variables_put","parameters":[{"name":"name","in":"path","required":true,"schema":{"type":"string","title":"Name"}},{"name":"env","in":"query","required":false,"schema":{"type":"string","default":"prod","title":"Env"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateVariablesRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/apps/{name}/variables/reveal":{"post":{"tags":["deploy"],"summary":"Reveal Variables","description":"Return the values of specific keys. The only path to a *platform* value.\n\nA caller's own vars come with the list; this endpoint is what remains for the\nones that never do. Browser-only by construction — the MCP tools have no\nequivalent, so a secret never reaches an AI context. Platform-managed vars are\nsuper-admin only, and BACKUP_HMAC_SECRET is never disclosed at all: it is\nours, the customer has no use for the value, and its fingerprint is already\non the backups page.","operationId":"reveal_variables_api_apps__name__variables_reveal_post","parameters":[{"name":"name","in":"path","required":true,"schema":{"type":"string","title":"Name"}},{"name":"env","in":"query","required":false,"schema":{"type":"string","default":"prod","title":"Env"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RevealVariablesRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/apps/{name}/allowlist":{"get":{"tags":["deploy"],"summary":"List Allowlist","description":"List the app's secret-scan allow-list entries (values redacted).","operationId":"list_allowlist_api_apps__name__allowlist_get","parameters":[{"name":"name","in":"path","required":true,"schema":{"type":"string","title":"Name"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["deploy"],"summary":"Add Allowlist Entry","description":"Allow a specific value to pass the secret-scan gate for this app.\n\nThe value is hashed here and discarded — only the fingerprint and a\nredacted form are stored. This path exists for a value that has never been\nreported as a finding; when it has, prefer the finding-based action, which\nneeds no value at all.","operationId":"add_allowlist_entry_api_apps__name__allowlist_post","parameters":[{"name":"name","in":"path","required":true,"schema":{"type":"string","title":"Name"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddAllowlistRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/apps/{name}/allowlist/{entry_id}":{"delete":{"tags":["deploy"],"summary":"Remove Allowlist Entry","description":"Remove a secret-scan allow-list entry by id.","operationId":"remove_allowlist_entry_api_apps__name__allowlist__entry_id__delete","parameters":[{"name":"name","in":"path","required":true,"schema":{"type":"string","title":"Name"}},{"name":"entry_id","in":"path","required":true,"schema":{"type":"string","title":"Entry Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/apps/{name}/security/findings":{"get":{"tags":["deploy"],"summary":"List Security Findings","description":"What the last full-history security scan found in this app's repo.","operationId":"list_security_findings_api_apps__name__security_findings_get","parameters":[{"name":"name","in":"path","required":true,"schema":{"type":"string","title":"Name"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/apps/{name}/security/findings/{finding_id}/allowlist":{"post":{"tags":["deploy"],"summary":"Allowlist Security Finding","description":"Mark one finding as safe to publish.\n\nThe finding's stored fingerprint is copied into the allow-list server-side.\nNo value is read, sent, or stored anywhere along this path — which is the\npoint: the alternative is a human digging the secret out of the repo and\npasting it into a form.","operationId":"allowlist_security_finding_api_apps__name__security_findings__finding_id__allowlist_post","parameters":[{"name":"name","in":"path","required":true,"schema":{"type":"string","title":"Name"}},{"name":"finding_id","in":"path","required":true,"schema":{"type":"string","title":"Finding Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AllowlistFindingRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/apps/{name}/security/scan":{"post":{"tags":["deploy"],"summary":"Run Security Scan","description":"Start a full-history security scan now. Returns a job to poll.\n\nMinutes, not seconds — hence a job. This is how a fix or an allow-list\nchange is reflected without waiting for the nightly sweep.","operationId":"run_security_scan_api_apps__name__security_scan_post","parameters":[{"name":"name","in":"path","required":true,"schema":{"type":"string","title":"Name"}}],"responses":{"202":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/apps/{name}/env-allowlist":{"get":{"tags":["deploy"],"summary":"List Env Allowlist","description":"List the keys an agent may write for this app (plus the server defaults).","operationId":"list_env_allowlist_api_apps__name__env_allowlist_get","parameters":[{"name":"name","in":"path","required":true,"schema":{"type":"string","title":"Name"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["deploy"],"summary":"Add Env Allowlist Entry","description":"Let an agent write this key. Only for keys that hold no secret.","operationId":"add_env_allowlist_entry_api_apps__name__env_allowlist_post","parameters":[{"name":"name","in":"path","required":true,"schema":{"type":"string","title":"Name"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddEnvAllowlistRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/apps/{name}/env-allowlist/{entry_id}":{"delete":{"tags":["deploy"],"summary":"Remove Env Allowlist Entry","description":"Stop an agent from being able to write this key.","operationId":"remove_env_allowlist_entry_api_apps__name__env_allowlist__entry_id__delete","parameters":[{"name":"name","in":"path","required":true,"schema":{"type":"string","title":"Name"}},{"name":"entry_id","in":"path","required":true,"schema":{"type":"string","title":"Entry Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/apps/{name}/auth":{"get":{"tags":["deploy"],"summary":"Get Auth","operationId":"get_auth_api_apps__name__auth_get","parameters":[{"name":"name","in":"path","required":true,"schema":{"type":"string","title":"Name"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthStatusOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["deploy"],"summary":"Set Auth","operationId":"set_auth_api_apps__name__auth_put","parameters":[{"name":"name","in":"path","required":true,"schema":{"type":"string","title":"Name"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetAuthRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthStatusOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/apps/{name}/ai":{"get":{"tags":["deploy"],"summary":"Get Ai","operationId":"get_ai_api_apps__name__ai_get","parameters":[{"name":"name","in":"path","required":true,"schema":{"type":"string","title":"Name"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AiStatusOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["deploy"],"summary":"Set Ai","description":"Toggle managed AI, and set this app's spend cap.","operationId":"set_ai_api_apps__name__ai_put","parameters":[{"name":"name","in":"path","required":true,"schema":{"type":"string","title":"Name"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetAiRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AiStatusOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/apps/{name}/ai/concurrency":{"put":{"tags":["deploy"],"summary":"Set Agent Concurrency","description":"Set how many of this app's ticket runs may execute at once. Platform admin only.\n\n`LogtoAdminUser`, not the app's own admins: concurrency is capacity the\nplatform pays for, and is to be sold as an add-on — an app admin raising\ntheir own would be giving it away.","operationId":"set_agent_concurrency_api_apps__name__ai_concurrency_put","parameters":[{"name":"name","in":"path","required":true,"schema":{"type":"string","title":"Name"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetConcurrencyRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AiStatusOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/apps/{name}/ai/rotate-key":{"post":{"tags":["deploy"],"summary":"Rotate Ai Key","description":"Issue a new key for one environment. The value is shown to nobody.\n\nPer environment on purpose: a leaked dev key should not force a prod\nredeploy, and prod and dev never share a key.","operationId":"rotate_ai_key_api_apps__name__ai_rotate_key_post","parameters":[{"name":"name","in":"path","required":true,"schema":{"type":"string","title":"Name"}},{"name":"env","in":"query","required":false,"schema":{"enum":["prod","dev"],"type":"string","default":"prod","title":"Env"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AiStatusOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/apps/{name}/auth/users":{"get":{"tags":["deploy"],"summary":"List Auth Users","operationId":"list_auth_users_api_apps__name__auth_users_get","parameters":[{"name":"name","in":"path","required":true,"schema":{"type":"string","title":"Name"}},{"name":"search","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Search"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/TenantUserOut"},"title":"Response List Auth Users Api Apps  Name  Auth Users Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/apps/{name}/auth/users/{user_id}":{"patch":{"tags":["deploy"],"summary":"Set Auth User Suspended","operationId":"set_auth_user_suspended_api_apps__name__auth_users__user_id__patch","parameters":[{"name":"name","in":"path","required":true,"schema":{"type":"string","title":"Name"}},{"name":"user_id","in":"path","required":true,"schema":{"type":"string","title":"User Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetSuspendedRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TenantUserOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["deploy"],"summary":"Delete Auth User","operationId":"delete_auth_user_api_apps__name__auth_users__user_id__delete","parameters":[{"name":"name","in":"path","required":true,"schema":{"type":"string","title":"Name"}},{"name":"user_id","in":"path","required":true,"schema":{"type":"string","title":"User Id"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/apps/{name}/auth/signup":{"get":{"tags":["deploy"],"summary":"Get Auth Signup","operationId":"get_auth_signup_api_apps__name__auth_signup_get","parameters":[{"name":"name","in":"path","required":true,"schema":{"type":"string","title":"Name"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SignupOptionsOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["deploy"],"summary":"Set Auth Signup","operationId":"set_auth_signup_api_apps__name__auth_signup_put","parameters":[{"name":"name","in":"path","required":true,"schema":{"type":"string","title":"Name"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetSignupOptionsRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SignupOptionsOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/apps/{name}/auth/settings":{"get":{"tags":["deploy"],"summary":"Get Auth Settings","operationId":"get_auth_settings_api_apps__name__auth_settings_get","parameters":[{"name":"name","in":"path","required":true,"schema":{"type":"string","title":"Name"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthSettingsOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/apps/{name}/auth/users/{user_id}/sessions":{"get":{"tags":["deploy"],"summary":"List Auth User Sessions","operationId":"list_auth_user_sessions_api_apps__name__auth_users__user_id__sessions_get","parameters":[{"name":"name","in":"path","required":true,"schema":{"type":"string","title":"Name"}},{"name":"user_id","in":"path","required":true,"schema":{"type":"string","title":"User Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/UserSessionOut"},"title":"Response List Auth User Sessions Api Apps  Name  Auth Users  User Id  Sessions Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/apps/{name}/auth/users/{user_id}/sessions/{session_id}":{"delete":{"tags":["deploy"],"summary":"Revoke Auth User Session","operationId":"revoke_auth_user_session_api_apps__name__auth_users__user_id__sessions__session_id__delete","parameters":[{"name":"name","in":"path","required":true,"schema":{"type":"string","title":"Name"}},{"name":"user_id","in":"path","required":true,"schema":{"type":"string","title":"User Id"}},{"name":"session_id","in":"path","required":true,"schema":{"type":"string","title":"Session Id"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/settings/railway-health":{"get":{"tags":["settings"],"summary":"Get Railway Health","operationId":"get_railway_health_api_settings_railway_health_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RailwayHealth"}}}}}}},"/api/settings/railway-webhooks/{app_name}":{"post":{"tags":["settings"],"summary":"Register Railway Webhook","operationId":"register_railway_webhook_api_settings_railway_webhooks__app_name__post","parameters":[{"name":"app_name","in":"path","required":true,"schema":{"type":"string","title":"App Name"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookResult"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["settings"],"summary":"Unregister Railway Webhook","operationId":"unregister_railway_webhook_api_settings_railway_webhooks__app_name__delete","parameters":[{"name":"app_name","in":"path","required":true,"schema":{"type":"string","title":"App Name"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookResult"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/settings/railway-webhooks":{"post":{"tags":["settings"],"summary":"Backfill Railway Webhooks","description":"Register ready apps' webhooks, up to `limit` per call.\n\nDefault: only apps with no webhook yet — call again for the next batch.\n\n`include_registered=true` is the repair after RAILWAY_WEBHOOK_SECRET or\nAPP_MANAGER_PUBLIC_URL changes. Every existing registration then points at\na URL that 404s, and nothing else re-registers an app that already has a\nwebhook id. It walks every ready app, replacing stale registrations and\nadopting current ones; page through with `offset`.\n\nSequential and capped, because it runs inside a request: ~3 Railway calls\nper app, and a whole fleet in one call would outlast the proxy's timeout.","operationId":"backfill_railway_webhooks_api_settings_railway_webhooks_post","parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","default":20,"title":"Limit"}},{"name":"include_registered","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"Include Registered"}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","default":0,"title":"Offset"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/WebhookResult"},"title":"Response Backfill Railway Webhooks Api Settings Railway Webhooks Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/internal/backup-runs/{run_id}/complete":{"post":{"tags":["internal"],"summary":"Backup Complete","operationId":"backup_complete_api_internal_backup_runs__run_id__complete_post","parameters":[{"name":"run_id","in":"path","required":true,"schema":{"type":"string","title":"Run Id"}},{"name":"x-backup-signature","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Backup-Signature"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/internal/uploads/init":{"post":{"tags":["internal"],"summary":"Uploads Init","description":"Open an S3 multipart upload for one (run, kind) and persist the\nUploadId so subsequent sign-part / complete calls can find it.","operationId":"uploads_init_api_internal_uploads_init_post","parameters":[{"name":"x-backup-signature","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Backup-Signature"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/internal/uploads/sign-part":{"post":{"tags":["internal"],"summary":"Uploads Sign Part","description":"Generate a presigned PUT URL for one part of an in-flight multipart upload.","operationId":"uploads_sign_part_api_internal_uploads_sign_part_post","parameters":[{"name":"x-backup-signature","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Backup-Signature"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/internal/uploads/complete":{"post":{"tags":["internal"],"summary":"Uploads Complete","description":"Finalize an in-flight multipart upload with the collected ETags.","operationId":"uploads_complete_api_internal_uploads_complete_post","parameters":[{"name":"x-backup-signature","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Backup-Signature"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/internal/uploads/abort":{"post":{"tags":["internal"],"summary":"Uploads Abort","description":"Release an in-flight multipart upload (S3 won't bill for the parts).","operationId":"uploads_abort_api_internal_uploads_abort_post","parameters":[{"name":"x-backup-signature","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Backup-Signature"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/internal/tenant-users":{"get":{"tags":["tenant-users"],"summary":"List Users","description":"List the app's end-users (id + email).","operationId":"list_users_api_internal_tenant_users_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":{"type":"array","items":{"type":"object","additionalProperties":true},"title":"Response List Users Api Internal Tenant Users Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/internal/tenant-users/{user_id}/email":{"patch":{"tags":["tenant-users"],"summary":"Update Email","description":"Change one user's primary email.","operationId":"update_email_api_internal_tenant_users__user_id__email_patch","parameters":[{"name":"user_id","in":"path","required":true,"schema":{"type":"string","title":"User 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/UpdateEmailBody"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Update Email Api Internal Tenant Users  User Id  Email Patch"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/internal/tenant-users/{user_id}/password":{"post":{"tags":["tenant-users"],"summary":"Reset Password","description":"Set one user's password (admin reset). The password is never logged.","operationId":"reset_password_api_internal_tenant_users__user_id__password_post","parameters":[{"name":"user_id","in":"path","required":true,"schema":{"type":"string","title":"User 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/ResetPasswordBody"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Reset Password Api Internal Tenant Users  User Id  Password Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/apps/{name}/snapshot.tar.gz":{"get":{"tags":["snapshots"],"summary":"Download Snapshot","description":"Stream the workspace ``.tar.gz`` that MCP built and stashed on the ticket.\n\nThe ``ticket`` query param must be a valid one-shot ticket minted by\nMCP for this exact app (its tarball was built at mint time from a fresh\nclone of ``develop``). Treated as the sole auth: ticket invalid /\nexpired / consumed / app-mismatch all return 404 so a leaked URL\ncan't be probed for app existence.","operationId":"download_snapshot_api_apps__name__snapshot_tar_gz_get","parameters":[{"name":"name","in":"path","required":true,"schema":{"type":"string","title":"Name"}},{"name":"ticket","in":"query","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/apps/{name}/images":{"post":{"tags":["uploads"],"summary":"Upload Image","description":"Upload a binary image and commit it to ``develop``.\n\nMirrors the snapshot flow: the image is written into a fresh isolated clone\nof ``develop`` and committed+pushed in one atomic step — it never touches the\nshared per-app workspace, so concurrent uploads/edits can't collide and the\ntree can't be left on the wrong branch. Path comes from the ticket (ticket\nflow) or the ``path`` form field (bearer flow); the commit message comes from\nthe ticket or the ``message`` form field, defaulting to ``\"Add image\n<path>\"``. Rejects non-image extensions and images over 5 MiB. Path safety\n(no ``..`` / ``.git/`` / absolute) is enforced by the workspace writer.","operationId":"upload_image_api_apps__name__images_post","parameters":[{"name":"name","in":"path","required":true,"schema":{"type":"string","title":"Name"}},{"name":"ticket","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Ticket"}}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_upload_image_api_apps__name__images_post"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"get":{"tags":["uploads"],"summary":"Download Image","description":"Download a binary image from the app's ``develop`` branch.\n\nPath comes from the ticket (ticket flow) or the ``path`` query param (bearer\nflow). Reads the committed develop content from a fresh isolated clone (the\nsame isolation as upload — no shared workspace). 404 if the file isn't present.","operationId":"download_image_api_apps__name__images_get","parameters":[{"name":"name","in":"path","required":true,"schema":{"type":"string","title":"Name"}},{"name":"path","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Path"}},{"name":"ticket","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Ticket"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/status/{app_name}":{"get":{"tags":["status"],"summary":"Status Json","operationId":"status_json_api_status__app_name__get","parameters":[{"name":"app_name","in":"path","required":true,"schema":{"type":"string","title":"App Name"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/status":{"get":{"tags":["status"],"summary":"Status Page","operationId":"status_page_status_get","parameters":[{"name":"app","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"App"}}],"responses":{"200":{"description":"Successful Response","content":{"text/html":{"schema":{"type":"string"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/internal/railway/deploy/{app_id}/{secret}":{"post":{"tags":["railway-webhooks"],"summary":"Railway Deploy Webhook","operationId":"railway_deploy_webhook_api_internal_railway_deploy__app_id___secret__post","parameters":[{"name":"app_id","in":"path","required":true,"schema":{"type":"string","title":"App Id"}},{"name":"secret","in":"path","required":true,"schema":{"type":"string","title":"Secret"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/internal/stripe/webhooks":{"post":{"tags":["stripe-webhooks"],"summary":"Stripe Webhook","operationId":"stripe_webhook_api_internal_stripe_webhooks_post","parameters":[{"name":"Stripe-Signature","in":"header","required":false,"schema":{"type":"string","title":"Stripe-Signature"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/public/legal/subprocessors":{"get":{"tags":["legal"],"summary":"Public Subprocessors","description":"Vendor-neutral subprocessor disclosure.\n\nServes engine.legal.public_view(), which is an allow-list projection — a\nfield added to the registry stays private until someone deliberately adds it\nto PUBLIC_FIELDS. Do not \"enrich\" this response from named_view().","operationId":"public_subprocessors_api_public_legal_subprocessors_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/public/legal/{kind}":{"get":{"tags":["legal"],"summary":"Public Document","description":"A legal document as a prospect reads it, before there is a controller.\n\nThe DPA gets its annexes filled with placeholders and the vendor-neutral\nsubprocessor table, never the named one.","operationId":"public_document_api_public_legal__kind__get","parameters":[{"name":"kind","in":"path","required":true,"schema":{"type":"string","title":"Kind"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/public/privacy":{"get":{"tags":["privacy"],"summary":"Public Privacy Policy","operationId":"public_privacy_policy_api_public_privacy_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/public/terms":{"get":{"tags":["terms"],"summary":"Public Terms Of Service","operationId":"public_terms_of_service_api_public_terms_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/legal/entity":{"get":{"tags":["legal"],"summary":"Get Entity","operationId":"get_entity_api_legal_entity_get","parameters":[{"name":"org","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Org"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["legal"],"summary":"Put Entity","description":"Save the controller's legal identity.\n\nDeliberately does not touch existing acceptances: those carry their own\nfrozen annex snapshot, and rewriting the party on a concluded agreement\nwould falsify the record.","operationId":"put_entity_api_legal_entity_put","parameters":[{"name":"org","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Org"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LegalEntityRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/legal/data-locations":{"get":{"tags":["legal"],"summary":"Data Locations","description":"Where this controller's data is processed.\n\nRegions are platform-wide settings, so they are reported once rather than\nper app; the app list is what varies, and it drives which areas apply.","operationId":"data_locations_api_legal_data_locations_get","parameters":[{"name":"org","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Org"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/legal/dpa":{"get":{"tags":["legal"],"summary":"Get Dpa","description":"The DPA as this controller would conclude it, plus their acceptance state.","operationId":"get_dpa_api_legal_dpa_get","parameters":[{"name":"org","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Org"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/legal/dpa/accept":{"post":{"tags":["legal"],"summary":"Accept Dpa","description":"Conclude the DPA in electronic form (Art. 28(9)).\n\nRecords the hash of the exact text and a frozen snapshot of the annex data,\nso the agreement stays reconstructable after the registry and the customer's\napp estate have both moved on.","operationId":"accept_dpa_api_legal_dpa_accept_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AcceptRequest"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/legal/acceptances/{acceptance_id}":{"get":{"tags":["legal"],"summary":"Get Acceptance","description":"Re-render a concluded agreement from its frozen snapshot.\n\nReads the snapshot, never the live registry — the whole point of freezing it\nis that this stays byte-identical after subprocessors change. The hash is\nreturned alongside so the customer can verify that for themselves.","operationId":"get_acceptance_api_legal_acceptances__acceptance_id__get","parameters":[{"name":"acceptance_id","in":"path","required":true,"schema":{"type":"string","title":"Acceptance Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/legal/processing-record":{"get":{"tags":["legal"],"summary":"Processing Record","description":"Art. 30(1) scaffold: the recipient, transfer and retention facts a\ncontroller needs for their own record, pre-filled from what we know.","operationId":"processing_record_api_legal_processing_record_get","parameters":[{"name":"org","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Org"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/legal/health":{"get":{"tags":["legal"],"summary":"Legal Health","description":"Cheap probe that the registry parses and the documents are present.","operationId":"legal_health_api_legal_health_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/admin/backup":{"post":{"tags":["backup"],"summary":"Trigger Backup","operationId":"trigger_backup_admin_backup_post","parameters":[{"name":"x-backup-signature","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Backup-Signature"}}],"responses":{"202":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/restore":{"post":{"tags":["backup"],"summary":"Trigger Restore","operationId":"trigger_restore_admin_restore_post","parameters":[{"name":"x-backup-signature","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Backup-Signature"}}],"responses":{"202":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/backup/fingerprint":{"get":{"tags":["backup"],"summary":"Backup Fingerprint","operationId":"backup_fingerprint_admin_backup_fingerprint_get","parameters":[{"name":"x-backup-signature","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Backup-Signature"}}],"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":{}}}}}}},"/{full_path}":{"get":{"summary":"Serve Spa","operationId":"serve_spa__full_path__get","parameters":[{"name":"full_path","in":"path","required":true,"schema":{"type":"string","title":"Full Path"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}}},"components":{"schemas":{"AcceptRequest":{"properties":{"document_kind":{"type":"string","const":"dpa","title":"Document Kind","default":"dpa"},"document_version":{"anyOf":[{"type":"string","pattern":"^v\\d+\\.\\d+$"},{"type":"null"}],"title":"Document Version"},"locale":{"type":"string","title":"Locale","default":"en"},"signer_name":{"type":"string","maxLength":200,"minLength":1,"title":"Signer Name"},"org":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Org"}},"type":"object","required":["signer_name"],"title":"AcceptRequest"},"AddAllowlistRequest":{"properties":{"value":{"type":"string","title":"Value"},"reason":{"type":"string","title":"Reason"}},"type":"object","required":["value","reason"],"title":"AddAllowlistRequest"},"AddAppUserRequest":{"properties":{"email":{"type":"string","title":"Email"},"role":{"type":"string","title":"Role","default":"client"}},"type":"object","required":["email"],"title":"AddAppUserRequest"},"AddDomainRequest":{"properties":{"domain":{"type":"string","title":"Domain"},"env":{"type":"string","enum":["prod","dev"],"title":"Env","default":"prod"},"allow_platform_zone":{"type":"boolean","title":"Allow Platform Zone","default":false}},"type":"object","required":["domain"],"title":"AddDomainRequest"},"AddEnvAllowlistRequest":{"properties":{"key":{"type":"string","title":"Key"},"reason":{"type":"string","title":"Reason"}},"type":"object","required":["key","reason"],"title":"AddEnvAllowlistRequest"},"AgentIn":{"properties":{"enabled":{"type":"boolean","title":"Enabled"}},"type":"object","required":["enabled"],"title":"AgentIn"},"AiBalanceOut":{"properties":{"balance_microcents":{"type":"integer","title":"Balance Microcents"},"reserved_microcents":{"type":"integer","title":"Reserved Microcents"},"available_microcents":{"type":"integer","title":"Available Microcents"},"auto_refill_enabled":{"type":"boolean","title":"Auto Refill Enabled"},"low_balance_threshold_microcents":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Low Balance Threshold Microcents"},"auto_refill_amount_microcents":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Auto Refill Amount Microcents"},"has_payment_method":{"type":"boolean","title":"Has Payment Method"}},"type":"object","required":["balance_microcents","reserved_microcents","available_microcents","auto_refill_enabled","low_balance_threshold_microcents","auto_refill_amount_microcents","has_payment_method"],"title":"AiBalanceOut"},"AiStatusOut":{"properties":{"enabled":{"type":"boolean","title":"Enabled"},"configured":{"type":"boolean","title":"Configured"},"available_models":{"items":{"type":"string"},"type":"array","title":"Available Models"},"max_completion_tokens_cap":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Max Completion Tokens Cap"},"period_cap_microcents":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Period Cap Microcents"},"org_available_microcents":{"type":"integer","title":"Org Available Microcents"},"agent_offered":{"type":"boolean","title":"Agent Offered"},"max_concurrent_runs":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Max Concurrent Runs"},"default_concurrent_runs":{"type":"integer","title":"Default Concurrent Runs"}},"type":"object","required":["enabled","configured","available_models","max_completion_tokens_cap","period_cap_microcents","org_available_microcents","agent_offered","max_concurrent_runs","default_concurrent_runs"],"title":"AiStatusOut"},"AiUsageOut":{"properties":{"days":{"type":"integer","title":"Days"},"rows":{"items":{"$ref":"#/components/schemas/AiUsageRow"},"type":"array","title":"Rows"}},"type":"object","required":["days","rows"],"title":"AiUsageOut"},"AiUsageRow":{"properties":{"date":{"type":"string","title":"Date"},"product":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Product"},"deleted":{"type":"boolean","title":"Deleted"},"kind":{"type":"string","title":"Kind"},"ticket":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Ticket"},"cost_microcents":{"type":"integer","title":"Cost Microcents"}},"type":"object","required":["date","product","deleted","kind","ticket","cost_microcents"],"title":"AiUsageRow"},"AllowlistFindingRequest":{"properties":{"reason":{"type":"string","title":"Reason"}},"type":"object","required":["reason"],"title":"AllowlistFindingRequest"},"AppBillingState":{"properties":{"status":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Status"},"stripe_status":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Stripe Status"},"suspended":{"type":"boolean","title":"Suspended"},"deletion_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Deletion At"},"payment_failed_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Payment Failed At"},"disconnect_by":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Disconnect By"},"deletion_by":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Deletion By"},"trial_ends_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Trial Ends At"},"on_trial":{"type":"boolean","title":"On Trial"},"exempt":{"type":"boolean","title":"Exempt"},"hold":{"type":"boolean","title":"Hold"}},"type":"object","required":["status","stripe_status","suspended","deletion_at","trial_ends_at","on_trial","exempt","hold"],"title":"AppBillingState","description":"Compact billing snapshot for at-a-glance dashboard badges. None on AppOut\nwhen billing is disabled or the app has no subscription."},"AppHealth":{"properties":{"is_up":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Is Up"},"uptime_today_pct":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Uptime Today Pct"},"backup_status":{"type":"string","title":"Backup Status"},"security_status":{"type":"string","title":"Security Status"},"security_findings":{"type":"integer","title":"Security Findings","default":0},"privacy_status":{"type":"string","title":"Privacy Status","default":"never"},"privacy_findings":{"type":"integer","title":"Privacy Findings","default":0}},"type":"object","required":["backup_status","security_status"],"title":"AppHealth"},"AppOut":{"properties":{"id":{"type":"string","title":"Id"},"name":{"type":"string","title":"Name"},"display_name":{"type":"string","title":"Display Name"},"repo":{"type":"string","title":"Repo"},"project_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Project Id"},"service_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Service Id"},"prod_env_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Prod Env Id"},"dev_env_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Dev Env Id"},"prod_domain":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Prod Domain"},"dev_domain":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Dev Domain"},"has_postgres":{"type":"boolean","title":"Has Postgres"},"has_volume":{"type":"boolean","title":"Has Volume"},"created_at":{"type":"string","title":"Created At"},"template":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Template"},"is_owner":{"type":"boolean","title":"Is Owner","default":false},"provisioning_status":{"type":"string","title":"Provisioning Status"},"provisioning_current_step":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Provisioning Current Step"},"provisioning_error":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Provisioning Error"},"provisioning_steps":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Provisioning Steps"},"provisioning_interrupted":{"type":"boolean","title":"Provisioning Interrupted","default":false},"billing":{"anyOf":[{"$ref":"#/components/schemas/AppBillingState"},{"type":"null"}]},"ticket_prefix":{"type":"string","title":"Ticket Prefix"}},"type":"object","required":["id","name","display_name","repo","project_id","service_id","prod_env_id","dev_env_id","prod_domain","dev_domain","has_postgres","has_volume","created_at","provisioning_status","ticket_prefix"],"title":"AppOut"},"AppStatus":{"properties":{"prod_status":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Prod Status"},"dev_status":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Dev Status"},"dev_replicas":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Dev Replicas"}},"type":"object","required":["prod_status","dev_status"],"title":"AppStatus"},"AppUsageResponse":{"properties":{"app":{"type":"string","title":"App"},"period_start":{"type":"string","title":"Period Start"},"period_end":{"type":"string","title":"Period End"},"resources":{"items":{"$ref":"#/components/schemas/UsageResourceInfo"},"type":"array","title":"Resources"},"series":{"items":{"$ref":"#/components/schemas/UsageDay"},"type":"array","title":"Series"}},"type":"object","required":["app","period_start","period_end","resources","series"],"title":"AppUsageResponse"},"AppUserCandidateOut":{"properties":{"id":{"type":"string","title":"Id"},"email":{"type":"string","title":"Email"},"pending":{"type":"boolean","title":"Pending","default":false}},"type":"object","required":["id","email"],"title":"AppUserCandidateOut"},"AppUserCandidatesOut":{"properties":{"candidates":{"items":{"$ref":"#/components/schemas/AppUserCandidateOut"},"type":"array","title":"Candidates"},"can_invite":{"type":"boolean","title":"Can Invite"},"org_plan":{"type":"string","title":"Org Plan"},"org_slug":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Org Slug"}},"type":"object","required":["candidates","can_invite","org_plan"],"title":"AppUserCandidatesOut","description":"The picker's whole state, so the UI never has to guess at the org.\n\n`AppOut` carries no organization at all, which is why the dropdown was\nfilled from the platform-wide `/users` in the first place. Everything the\nsection needs to decide what to offer comes back here instead."},"AppUserOut":{"properties":{"id":{"type":"string","title":"Id"},"email":{"type":"string","title":"Email"},"role":{"type":"string","title":"Role"}},"type":"object","required":["id","email","role"],"title":"AppUserOut"},"AssigneeOut":{"properties":{"id":{"type":"string","title":"Id"},"email":{"type":"string","title":"Email"},"display_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Display Name"}},"type":"object","required":["id","email"],"title":"AssigneeOut"},"AudiencePreviewIn":{"properties":{"category":{"type":"string","enum":["service","product_update"],"title":"Category"},"audience":{"$ref":"#/components/schemas/AudienceSpec"}},"additionalProperties":false,"type":"object","required":["category","audience"],"title":"AudiencePreviewIn"},"AudienceSpec":{"properties":{"kind":{"type":"string","enum":["all","users","orgs"],"title":"Kind"},"user_ids":{"items":{"type":"string","format":"uuid"},"type":"array","title":"User Ids"},"org_roles":{"items":{"type":"string","enum":["owner","admin","user"]},"type":"array","title":"Org Roles"},"app_tiers":{"items":{"type":"string","enum":["hobby","pro","enterprise"]},"type":"array","title":"App Tiers"},"org_plans":{"items":{"type":"string","enum":["solo","team","enterprise"]},"type":"array","title":"Org Plans"}},"additionalProperties":false,"type":"object","required":["kind"],"title":"AudienceSpec","description":"Who an announcement is for.\n\n* ``all`` — every account that has signed in at least once.\n* ``users`` — the accounts in ``user_ids``.\n* ``orgs`` — members holding one of ``org_roles`` in orgs matching the\n  filters. No filters means every org, which with the default roles is\n  \"everyone who manages an org\". ``org_plans`` and ``app_tiers`` both have to\n  match when both are given; an org matches a tier when any of its apps has it."},"AuthSettingsOut":{"properties":{"access_token_ttl_seconds":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Access Token Ttl Seconds"},"access_token_ttl_source":{"type":"string","title":"Access Token Ttl Source"},"session_ttl_seconds":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Session Ttl Seconds"},"session_ttl_source":{"type":"string","title":"Session Ttl Source"},"refresh_token_ttl_days":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Refresh Token Ttl Days"},"refresh_token_ttl_source":{"type":"string","title":"Refresh Token Ttl Source"},"rotate_refresh_token":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Rotate Refresh Token"},"rotate_refresh_token_source":{"type":"string","title":"Rotate Refresh Token Source"},"refresh_token_sliding":{"type":"boolean","title":"Refresh Token Sliding"},"grant_ttl_days":{"type":"integer","title":"Grant Ttl Days"},"rotation_cap_days":{"type":"integer","title":"Rotation Cap Days"}},"type":"object","required":["access_token_ttl_source","session_ttl_source","refresh_token_ttl_source","rotate_refresh_token_source","refresh_token_sliding","grant_ttl_days","rotation_cap_days"],"title":"AuthSettingsOut","description":"Token and session lifetimes, read live from the auth provider.\n\nEach `_source` is \"default\" (inherited from the platform), \"app\" (set for this\napp alone) or \"unknown\"; a value is null only when its source is \"unknown\",\nwhich means the setting could not be read rather than that it is unset. The\ntrailing fields are fixed ceilings, not per-app settings."},"AuthStatusOut":{"properties":{"enabled":{"type":"boolean","title":"Enabled"},"tenant_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Tenant Id"},"app_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"App Id"},"api_resource":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Api Resource"},"tenant_endpoint":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Tenant Endpoint"}},"type":"object","required":["enabled"],"title":"AuthStatusOut"},"AutoRefillRequest":{"properties":{"enabled":{"type":"boolean","title":"Enabled"},"amount_microcents":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Amount Microcents"},"threshold_microcents":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Threshold Microcents"}},"type":"object","required":["enabled"],"title":"AutoRefillRequest"},"BackupHealthOut":{"properties":{"enabled":{"type":"boolean","title":"Enabled"},"schedule":{"type":"string","title":"Schedule"},"min_keep":{"type":"integer","title":"Min Keep"},"retention_days":{"type":"integer","title":"Retention Days"},"successful_runs_count":{"type":"integer","title":"Successful Runs Count"},"last_successful_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Last Successful At"},"last_attempt_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Last Attempt At"},"last_attempt_status":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Last Attempt Status"},"status":{"type":"string","title":"Status"}},"type":"object","required":["enabled","schedule","min_keep","retention_days","successful_runs_count","last_successful_at","last_attempt_at","last_attempt_status","status"],"title":"BackupHealthOut"},"BackupRunOut":{"properties":{"id":{"type":"string","title":"Id"},"kind":{"type":"string","title":"Kind"},"status":{"type":"string","title":"Status"},"triggered_by":{"type":"string","title":"Triggered By"},"s3_key":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"S3 Key"},"db_size_bytes":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Db Size Bytes"},"volume_size_bytes":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Volume Size Bytes"},"error":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Error"},"started_at":{"type":"string","title":"Started At"},"finished_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Finished At"}},"type":"object","required":["id","kind","status","triggered_by","s3_key","db_size_bytes","volume_size_bytes","error","started_at","finished_at"],"title":"BackupRunOut"},"BackupSettingsOut":{"properties":{"enabled":{"type":"boolean","title":"Enabled"},"schedule":{"type":"string","title":"Schedule"},"retention_days":{"type":"integer","title":"Retention Days"},"min_keep":{"type":"integer","title":"Min Keep"}},"type":"object","required":["enabled","schedule","retention_days","min_keep"],"title":"BackupSettingsOut"},"BoardSettingsIn":{"properties":{"title":{"anyOf":[{"type":"string","maxLength":60},{"type":"null"}],"title":"Title"},"ticket_prefix":{"anyOf":[{"type":"string","maxLength":3,"minLength":3},{"type":"null"}],"title":"Ticket Prefix"},"default_assignee_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Default Assignee Id"},"default_type":{"anyOf":[{"type":"string","enum":["feat","bug","story"]},{"type":"null"}],"title":"Default Type"}},"type":"object","title":"BoardSettingsIn","description":"Only the fields sent change. `title: null` restores \"Board\";\n`default_assignee_id: null` clears the default."},"Body_upload_announcement_image_api_admin_announcements_images_post":{"properties":{"file":{"type":"string","contentMediaType":"application/octet-stream","title":"File"}},"type":"object","required":["file"],"title":"Body_upload_announcement_image_api_admin_announcements_images_post"},"Body_upload_attachment_api_apps__name__board_attachments_post":{"properties":{"file":{"type":"string","contentMediaType":"application/octet-stream","title":"File"}},"type":"object","required":["file"],"title":"Body_upload_attachment_api_apps__name__board_attachments_post"},"Body_upload_image_api_apps__name__images_post":{"properties":{"file":{"type":"string","contentMediaType":"application/octet-stream","title":"File"},"path":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Path"},"message":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Message"}},"type":"object","required":["file"],"title":"Body_upload_image_api_apps__name__images_post"},"BulkHealthResponse":{"properties":{"health":{"additionalProperties":{"$ref":"#/components/schemas/AppHealth"},"type":"object","title":"Health"}},"type":"object","required":["health"],"title":"BulkHealthResponse"},"BulkStatusResponse":{"properties":{"statuses":{"additionalProperties":{"$ref":"#/components/schemas/AppStatus"},"type":"object","title":"Statuses"},"source":{"type":"string","title":"Source","default":"railway"}},"type":"object","required":["statuses"],"title":"BulkStatusResponse"},"CheckoutRequest":{"properties":{"return_path":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Return Path"},"org":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Org"}},"type":"object","title":"CheckoutRequest"},"ColumnIn":{"properties":{"name":{"type":"string","maxLength":60,"minLength":1,"title":"Name"}},"type":"object","required":["name"],"title":"ColumnIn"},"ColumnOrderIn":{"properties":{"column_ids":{"items":{"type":"string"},"type":"array","title":"Column Ids"}},"type":"object","required":["column_ids"],"title":"ColumnOrderIn"},"ConfirmIn":{"properties":{"proposal":{"additionalProperties":true,"type":"object","title":"Proposal"},"queue":{"type":"boolean","title":"Queue","default":true}},"additionalProperties":false,"type":"object","required":["proposal"],"title":"ConfirmIn","description":"The proposal as the person edited it, and how to file its tickets.\n\n`queue`: true puts the tickets in TO DO, false parks them. Each ticket's\n`assignee` is \"agent\" or null."},"CreateAppJobOut":{"properties":{"job_id":{"type":"string","title":"Job Id"},"app_id":{"type":"string","title":"App Id"},"name":{"type":"string","title":"Name"},"status":{"type":"string","title":"Status"},"step":{"type":"string","title":"Step"}},"type":"object","required":["job_id","app_id","name","status","step"],"title":"CreateAppJobOut"},"CreateAppRequest":{"properties":{"name":{"type":"string","title":"Name"},"template":{"type":"string","title":"Template","default":"webapp"},"repo":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Repo"},"postgres":{"type":"boolean","title":"Postgres","default":false},"volume":{"type":"boolean","title":"Volume","default":false},"mcp":{"type":"boolean","title":"Mcp","default":false},"env_vars":{"anyOf":[{"additionalProperties":{"type":"string"},"type":"object"},{"type":"null"}],"title":"Env Vars"},"billing_exempt":{"type":"boolean","title":"Billing Exempt","default":false},"tier":{"type":"string","title":"Tier","default":"hobby"},"start_trial":{"type":"boolean","title":"Start Trial","default":false},"org_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Org Id"},"roadmap_session_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Roadmap Session Id"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"auth":{"type":"boolean","title":"Auth","default":false},"ai":{"type":"boolean","title":"Ai","default":false}},"type":"object","required":["name"],"title":"CreateAppRequest"},"CreateOrgRequest":{"properties":{"name":{"type":"string","title":"Name"}},"type":"object","required":["name"],"title":"CreateOrgRequest"},"DowntimeAlertsIn":{"properties":{"enabled":{"type":"boolean","title":"Enabled"}},"type":"object","required":["enabled"],"title":"DowntimeAlertsIn"},"DowntimeAlertsOut":{"properties":{"enabled":{"type":"boolean","title":"Enabled"}},"type":"object","required":["enabled"],"title":"DowntimeAlertsOut"},"DraftStartIn":{"properties":{"content":{"type":"string","maxLength":8000,"minLength":1,"title":"Content"},"org":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Org"}},"additionalProperties":false,"type":"object","required":["content"],"title":"DraftStartIn"},"EntitlementRequest":{"properties":{"tier":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Tier"},"reason":{"type":"string","title":"Reason"},"expires_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Expires At"}},"type":"object","required":["reason"],"title":"EntitlementRequest"},"ExemptRequest":{"properties":{"exempt":{"type":"boolean","title":"Exempt"}},"type":"object","required":["exempt"],"title":"ExemptRequest"},"GrantCreditRequest":{"properties":{"amount_usd":{"type":"number","title":"Amount Usd"},"reason":{"type":"string","title":"Reason","default":"manual grant"}},"type":"object","required":["amount_usd"],"title":"GrantCreditRequest"},"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"HoldRequest":{"properties":{"hold":{"type":"boolean","title":"Hold"}},"type":"object","required":["hold"],"title":"HoldRequest"},"InviteAppUserRequest":{"properties":{"email":{"type":"string","title":"Email"},"role":{"type":"string","title":"Role","default":"client"}},"type":"object","required":["email"],"title":"InviteAppUserRequest"},"InviteAppUserResult":{"properties":{"member":{"$ref":"#/components/schemas/AppUserOut"},"converted_to_team":{"type":"boolean","title":"Converted To Team"}},"type":"object","required":["member","converted_to_team"],"title":"InviteAppUserResult"},"InviteMemberRequest":{"properties":{"email":{"type":"string","title":"Email"},"role":{"type":"string","title":"Role","default":"user"},"app_ids":{"items":{"type":"string"},"type":"array","title":"App Ids","default":[]}},"type":"object","required":["email"],"title":"InviteMemberRequest"},"InviteResult":{"properties":{"member":{"$ref":"#/components/schemas/OrgMemberOut"},"converted_to_team":{"type":"boolean","title":"Converted To Team"}},"type":"object","required":["member","converted_to_team"],"title":"InviteResult"},"JobOut":{"properties":{"id":{"type":"string","title":"Id"},"kind":{"type":"string","title":"Kind"},"name":{"type":"string","title":"Name"},"status":{"type":"string","title":"Status"},"step":{"type":"string","title":"Step"},"error":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Error"},"detail":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Detail"},"result":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Result"}},"type":"object","required":["id","kind","name","status","step"],"title":"JobOut"},"LegalEntityRequest":{"properties":{"legal_name":{"type":"string","maxLength":200,"minLength":1,"title":"Legal Name"},"org_number":{"anyOf":[{"type":"string","maxLength":64},{"type":"null"}],"title":"Org Number"},"address":{"type":"string","maxLength":500,"minLength":1,"title":"Address"},"country":{"type":"string","maxLength":64,"minLength":2,"title":"Country"},"privacy_contact_email":{"anyOf":[{"type":"string","maxLength":320,"pattern":"^[^@\\s]+@[^@\\s]+\\.[^@\\s]+$"},{"type":"null"}],"title":"Privacy Contact Email"}},"type":"object","required":["legal_name","address","country"],"title":"LegalEntityRequest"},"LocaleContent":{"properties":{"subject":{"type":"string","title":"Subject","default":""},"body":{"type":"string","title":"Body","default":""}},"additionalProperties":false,"type":"object","title":"LocaleContent"},"LocaleIn":{"properties":{"locale":{"type":"string","title":"Locale"}},"type":"object","required":["locale"],"title":"LocaleIn"},"LogsResponse":{"properties":{"logs":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Logs"}},"type":"object","required":["logs"],"title":"LogsResponse"},"MessageIn":{"properties":{"content":{"type":"string","maxLength":8000,"minLength":1,"title":"Content"}},"type":"object","required":["content"],"title":"MessageIn"},"NameAvailableOut":{"properties":{"name":{"type":"string","title":"Name"},"slug":{"type":"string","title":"Slug"},"available":{"type":"boolean","title":"Available"},"existing":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Existing"},"reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Reason"}},"type":"object","required":["name","slug","available"],"title":"NameAvailableOut"},"OrgAppOut":{"properties":{"id":{"type":"string","title":"Id"},"name":{"type":"string","title":"Name"}},"type":"object","required":["id","name"],"title":"OrgAppOut"},"OrgMemberOut":{"properties":{"user_id":{"type":"string","title":"User Id"},"email":{"type":"string","title":"Email"},"role":{"type":"string","title":"Role"},"pending":{"type":"boolean","title":"Pending"}},"type":"object","required":["user_id","email","role","pending"],"title":"OrgMemberOut"},"OrgOut":{"properties":{"id":{"type":"string","title":"Id"},"slug":{"type":"string","title":"Slug"},"name":{"type":"string","title":"Name"},"is_personal":{"type":"boolean","title":"Is Personal"},"is_mine":{"type":"boolean","title":"Is Mine"},"my_role":{"type":"string","title":"My Role"},"member_count":{"type":"integer","title":"Member Count"},"app_count":{"type":"integer","title":"App Count"},"has_payment_method":{"type":"boolean","title":"Has Payment Method"},"plan":{"type":"string","title":"Plan"},"entitled_plan":{"type":"string","title":"Entitled Plan"}},"type":"object","required":["id","slug","name","is_personal","is_mine","my_role","member_count","app_count","has_payment_method","plan","entitled_plan"],"title":"OrgOut"},"PlanRequest":{"properties":{"plan":{"type":"string","title":"Plan"}},"type":"object","required":["plan"],"title":"PlanRequest"},"PreviewIn":{"properties":{"category":{"type":"string","enum":["service","product_update"],"title":"Category"},"locale":{"type":"string","title":"Locale"},"subject":{"type":"string","title":"Subject","default":""},"body":{"type":"string","title":"Body","default":""}},"additionalProperties":false,"type":"object","required":["category","locale"],"title":"PreviewIn"},"PromoteRequest":{"properties":{"merge":{"type":"boolean","title":"Merge","default":false}},"type":"object","title":"PromoteRequest"},"PromoteResponse":{"properties":{"status":{"type":"string","title":"Status","default":"open"},"pr_url":{"type":"string","title":"Pr Url"},"pr_number":{"type":"integer","title":"Pr Number"},"merged":{"type":"boolean","title":"Merged"},"jobs":{"anyOf":[{"items":{"additionalProperties":true,"type":"object"},"type":"array"},{"type":"null"}],"title":"Jobs"},"scan":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Scan"},"versions":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Versions","default":[]},"released_versions":{"items":{"type":"string"},"type":"array","title":"Released Versions","default":[]}},"type":"object","required":["pr_url","pr_number","merged"],"title":"PromoteResponse"},"RailwayHealth":{"properties":{"rate_limit":{"additionalProperties":{"type":"string"},"type":"object","title":"Rate Limit"},"workspace_id":{"type":"string","title":"Workspace Id"},"credential_problem":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Credential Problem"},"webhooks_backed":{"type":"integer","title":"Webhooks Backed","default":0},"webhooks_provisioned":{"type":"integer","title":"Webhooks Provisioned","default":0},"webhook_registration_problem":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Webhook Registration Problem"},"reconcile":{"additionalProperties":{"type":"integer"},"type":"object","title":"Reconcile","default":{}}},"type":"object","required":["rate_limit","workspace_id"],"title":"RailwayHealth"},"ResetPasswordBody":{"properties":{"password":{"type":"string","maxLength":256,"minLength":1,"title":"Password"}},"type":"object","required":["password"],"title":"ResetPasswordBody"},"RestoreRequest":{"properties":{"run_id":{"type":"string","title":"Run Id"},"confirm_name":{"type":"string","title":"Confirm Name"}},"type":"object","required":["run_id","confirm_name"],"title":"RestoreRequest"},"RevealVariablesRequest":{"properties":{"keys":{"items":{"type":"string"},"type":"array","title":"Keys"}},"type":"object","required":["keys"],"title":"RevealVariablesRequest"},"RotateSecretOut":{"properties":{"fingerprint":{"type":"string","title":"Fingerprint"}},"type":"object","required":["fingerprint"],"title":"RotateSecretOut"},"SecretCheckOut":{"properties":{"status":{"type":"string","title":"Status"},"expected_fp":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Expected Fp"},"customer_fp":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Customer Fp"},"error":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Error"}},"type":"object","required":["status","expected_fp","customer_fp","error"],"title":"SecretCheckOut"},"SendIn":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"category":{"type":"string","enum":["service","product_update"],"title":"Category"},"content":{"additionalProperties":{"$ref":"#/components/schemas/LocaleContent"},"type":"object","title":"Content"},"audience":{"$ref":"#/components/schemas/AudienceSpec"}},"additionalProperties":false,"type":"object","required":["id","category","content","audience"],"title":"SendIn"},"SessionStartIn":{"properties":{"content":{"type":"string","maxLength":8000,"minLength":1,"title":"Content"},"version_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Version Id"}},"additionalProperties":false,"type":"object","required":["content"],"title":"SessionStartIn"},"SetAiRequest":{"properties":{"enabled":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Enabled"},"period_cap_microcents":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Period Cap Microcents"}},"type":"object","title":"SetAiRequest"},"SetAuthRequest":{"properties":{"enabled":{"type":"boolean","title":"Enabled"}},"type":"object","required":["enabled"],"title":"SetAuthRequest"},"SetConcurrencyRequest":{"properties":{"max_concurrent_runs":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Max Concurrent Runs"}},"additionalProperties":false,"type":"object","required":["max_concurrent_runs"],"title":"SetConcurrencyRequest"},"SetPrimaryDomainRequest":{"properties":{"domain":{"type":"string","title":"Domain"},"env":{"type":"string","enum":["prod","dev"],"title":"Env","default":"prod"}},"type":"object","required":["domain"],"title":"SetPrimaryDomainRequest"},"SetReplicasRequest":{"properties":{"num_replicas":{"type":"integer","title":"Num Replicas"}},"type":"object","required":["num_replicas"],"title":"SetReplicasRequest"},"SetRoleRequest":{"properties":{"role":{"type":"string","title":"Role"}},"type":"object","required":["role"],"title":"SetRoleRequest"},"SetSignupOptionsRequest":{"properties":{"allow_registration":{"type":"boolean","title":"Allow Registration"}},"type":"object","required":["allow_registration"],"title":"SetSignupOptionsRequest"},"SetSuspendedRequest":{"properties":{"is_suspended":{"type":"boolean","title":"Is Suspended"}},"type":"object","required":["is_suspended"],"title":"SetSuspendedRequest"},"SignupOptionsOut":{"properties":{"allow_registration":{"type":"boolean","title":"Allow Registration"},"identifiers":{"items":{"type":"string"},"type":"array","title":"Identifiers","default":[]}},"type":"object","required":["allow_registration"],"title":"SignupOptionsOut"},"SignupSourceGroupOut":{"properties":{"group":{"type":"string","title":"Group"},"accounts":{"type":"integer","title":"Accounts"},"sources":{"items":{"type":"string"},"type":"array","title":"Sources"}},"type":"object","required":["group","accounts","sources"],"title":"SignupSourceGroupOut"},"SignupSourceOut":{"properties":{"source":{"type":"string","title":"Source"},"accounts":{"type":"integer","title":"Accounts"},"campaigns":{"items":{"type":"string"},"type":"array","title":"Campaigns"},"group":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Group"},"first_account_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"First Account At"},"last_account_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Last Account At"}},"type":"object","required":["source","accounts","campaigns","group","first_account_at","last_account_at"],"title":"SignupSourceOut"},"SignupSourcesOut":{"properties":{"total_accounts":{"type":"integer","title":"Total Accounts"},"unattributed":{"type":"integer","title":"Unattributed"},"sources":{"items":{"$ref":"#/components/schemas/SignupSourceOut"},"type":"array","title":"Sources"},"groups":{"items":{"$ref":"#/components/schemas/SignupSourceGroupOut"},"type":"array","title":"Groups"}},"type":"object","required":["total_accounts","unattributed","sources","groups"],"title":"SignupSourcesOut"},"StatusResponse":{"properties":{"name":{"type":"string","title":"Name"},"prod_status":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Prod Status"},"dev_status":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Dev Status"},"dev_replicas":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Dev Replicas"},"source":{"type":"string","title":"Source","default":"railway"}},"type":"object","required":["name","prod_status","dev_status"],"title":"StatusResponse"},"SyncIn":{"properties":{"auto":{"type":"boolean","title":"Auto","default":false}},"type":"object","title":"SyncIn"},"TenantUserOut":{"properties":{"id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Id"},"email":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Email"},"username":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Username"},"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name"},"sign_in_methods":{"items":{"type":"string"},"type":"array","title":"Sign In Methods","default":[]},"created_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Created At"},"last_sign_in_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Last Sign In At"},"is_suspended":{"type":"boolean","title":"Is Suspended","default":false},"application_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Application Id"}},"type":"object","title":"TenantUserOut"},"TestIn":{"properties":{"category":{"type":"string","enum":["service","product_update"],"title":"Category"},"content":{"additionalProperties":{"$ref":"#/components/schemas/LocaleContent"},"type":"object","title":"Content"}},"additionalProperties":false,"type":"object","required":["category","content"],"title":"TestIn"},"TicketCreateIn":{"properties":{"title":{"type":"string","maxLength":200,"minLength":1,"title":"Title"},"type":{"type":"string","enum":["feat","bug","story","setup"],"title":"Type","default":"feat"},"description":{"type":"string","maxLength":20000,"title":"Description","default":""},"assignee_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Assignee Id"},"column_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Column Id"},"version_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Version Id"},"depends_on":{"items":{"type":"integer"},"type":"array","maxItems":20,"title":"Depends On"}},"type":"object","required":["title"],"title":"TicketCreateIn"},"TicketMessageIn":{"properties":{"content":{"type":"string","maxLength":20000,"minLength":1,"title":"Content"},"ask_agent":{"type":"boolean","title":"Ask Agent","default":true}},"type":"object","required":["content"],"title":"TicketMessageIn"},"TicketMoveIn":{"properties":{"column_id":{"type":"string","title":"Column Id"},"index":{"type":"integer","minimum":0.0,"title":"Index"}},"type":"object","required":["column_id","index"],"title":"TicketMoveIn"},"TicketUpdateIn":{"properties":{"title":{"anyOf":[{"type":"string","maxLength":200,"minLength":1},{"type":"null"}],"title":"Title"},"type":{"anyOf":[{"type":"string","enum":["feat","bug","story","setup"]},{"type":"null"}],"title":"Type"},"description":{"anyOf":[{"type":"string","maxLength":20000},{"type":"null"}],"title":"Description"},"assignee_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Assignee Id"},"version_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Version Id"},"depends_on":{"anyOf":[{"items":{"type":"integer"},"type":"array","maxItems":20},{"type":"null"}],"title":"Depends On"}},"type":"object","title":"TicketUpdateIn","description":"Only the fields present are changed; `assignee_id: null` unassigns,\n`version_id: null` takes the ticket out of its version, `depends_on`\nreplaces the ticket's dependencies (`[]` clears them)."},"TierRequest":{"properties":{"tier":{"type":"string","title":"Tier"}},"type":"object","required":["tier"],"title":"TierRequest"},"TopupOut":{"properties":{"status":{"type":"string","title":"Status"},"hosted_invoice_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Hosted Invoice Url"},"balance":{"$ref":"#/components/schemas/AiBalanceOut"}},"type":"object","required":["status","hosted_invoice_url","balance"],"title":"TopupOut"},"TopupRequest":{"properties":{"amount_microcents":{"type":"integer","title":"Amount Microcents"}},"type":"object","required":["amount_microcents"],"title":"TopupRequest"},"TransferOwnerRequest":{"properties":{"user_id":{"type":"string","title":"User Id"}},"type":"object","required":["user_id"],"title":"TransferOwnerRequest"},"UpdateAppRequest":{"properties":{"display_name":{"type":"string","title":"Display Name"}},"type":"object","required":["display_name"],"title":"UpdateAppRequest"},"UpdateBackupSettingsRequest":{"properties":{"enabled":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Enabled"},"schedule":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Schedule"},"retention_days":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Retention Days"},"min_keep":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Min Keep"}},"type":"object","title":"UpdateBackupSettingsRequest"},"UpdateEmailBody":{"properties":{"email":{"type":"string","maxLength":320,"minLength":3,"title":"Email"}},"type":"object","required":["email"],"title":"UpdateEmailBody"},"UpdateOrgRequest":{"properties":{"name":{"type":"string","title":"Name"}},"type":"object","required":["name"],"title":"UpdateOrgRequest"},"UpdateVariablesRequest":{"properties":{"set":{"additionalProperties":{"type":"string"},"type":"object","title":"Set","default":{}},"delete":{"items":{"type":"string"},"type":"array","title":"Delete","default":[]}},"type":"object","title":"UpdateVariablesRequest"},"UsageDay":{"properties":{"day":{"type":"string","title":"Day"},"resources":{"additionalProperties":{"type":"number"},"type":"object","title":"Resources"}},"type":"object","required":["day","resources"],"title":"UsageDay"},"UsageResourceInfo":{"properties":{"resource":{"type":"string","title":"Resource"},"unit":{"type":"string","title":"Unit"},"latest":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Latest"},"peak":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Peak"}},"type":"object","required":["resource","unit","latest","peak"],"title":"UsageResourceInfo"},"UserAppInfo":{"properties":{"name":{"type":"string","title":"Name"},"role":{"type":"string","title":"Role"}},"type":"object","required":["name","role"],"title":"UserAppInfo"},"UserInfo":{"properties":{"id":{"type":"string","title":"Id"},"email":{"type":"string","title":"Email"},"role":{"type":"string","title":"Role"},"apps":{"items":{"$ref":"#/components/schemas/UserAppInfo"},"type":"array","title":"Apps"},"is_platform_admin":{"type":"boolean","title":"Is Platform Admin"},"locale":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Locale"}},"type":"object","required":["id","email","role","apps","is_platform_admin"],"title":"UserInfo"},"UserInviteRequest":{"properties":{"email":{"type":"string","title":"Email"},"app_ids":{"items":{"type":"string"},"type":"array","title":"App Ids","default":[]}},"type":"object","required":["email"],"title":"UserInviteRequest"},"UserOut":{"properties":{"id":{"type":"string","title":"Id"},"email":{"type":"string","title":"Email"},"role":{"type":"string","title":"Role"},"apps":{"items":{"$ref":"#/components/schemas/UserAppInfo"},"type":"array","title":"Apps"},"pending":{"type":"boolean","title":"Pending"}},"type":"object","required":["id","email","role","apps","pending"],"title":"UserOut"},"UserSessionOut":{"properties":{"id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Id"},"client_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Client Id"},"signed_in_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Signed In At"},"expires_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Expires At"},"ip":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Ip"},"user_agent":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"User Agent"},"location":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Location"}},"type":"object","title":"UserSessionOut"},"ValidationError":{"properties":{"loc":{"items":{"anyOf":[{"type":"string"},{"type":"integer"}]},"type":"array","title":"Location"},"msg":{"type":"string","title":"Message"},"type":{"type":"string","title":"Error Type"},"input":{"title":"Input"},"ctx":{"type":"object","title":"Context"}},"type":"object","required":["loc","msg","type"],"title":"ValidationError"},"VersionCreateIn":{"properties":{"name":{"type":"string","maxLength":60,"minLength":1,"title":"Name"},"description":{"type":"string","maxLength":2000,"title":"Description","default":""},"target_date":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Target Date"}},"type":"object","required":["name"],"title":"VersionCreateIn"},"VersionUpdateIn":{"properties":{"name":{"anyOf":[{"type":"string","maxLength":60,"minLength":1},{"type":"null"}],"title":"Name"},"description":{"anyOf":[{"type":"string","maxLength":2000},{"type":"null"}],"title":"Description"},"target_date":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Target Date"},"status":{"anyOf":[{"type":"string","enum":["planned","released"]},{"type":"null"}],"title":"Status"}},"type":"object","title":"VersionUpdateIn","description":"Only the fields sent change. `target_date: null` clears it; `status`\n`released` stamps `released_at`, and `planned` clears it again."},"VolumeInfoResponse":{"properties":{"production":{"anyOf":[{"$ref":"#/components/schemas/VolumeMetrics"},{"type":"null"}]},"development":{"anyOf":[{"$ref":"#/components/schemas/VolumeMetrics"},{"type":"null"}]}},"type":"object","required":["production","development"],"title":"VolumeInfoResponse"},"VolumeMetrics":{"properties":{"size_mb":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Size Mb"},"current_size_mb":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Current Size Mb"},"mount_path":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Mount Path"},"state":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"State"}},"type":"object","required":["size_mb","current_size_mb","mount_path","state"],"title":"VolumeMetrics"},"WebhookResult":{"properties":{"app":{"type":"string","title":"App"},"result":{"type":"string","title":"Result"},"leftover":{"items":{"type":"string"},"type":"array","title":"Leftover","default":[]},"detail":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Detail"}},"type":"object","required":["app","result"],"title":"WebhookResult"}}}}