{"openapi":"3.1.0","info":{"title":"Hands API","version":"0.1.0","description":"Interactive API reference for Hands. Generated from modular Hono/Zod route definitions."},"servers":[{"url":"https://hands.build","description":"Current request origin"},{"url":"http://localhost:8787","description":"Local wrangler dev"}],"tags":[{"name":"System","description":"Operational health and public metadata."},{"name":"Auth","description":"Login with Raft, Agent Login, and current session endpoints."},{"name":"Public update","description":"Client-facing release resolution endpoints."},{"name":"Public feedback","description":"Client-facing feedback and crash submission endpoints."},{"name":"Public pages","description":"Unauthenticated share, history, and icon pages."},{"name":"Public downloads","description":"Unauthenticated signed artifact download endpoints."},{"name":"Apps","description":"App lifecycle and app-level public client configuration."},{"name":"Analytics","description":"Authenticated app usage, device, and version metrics."},{"name":"Builds","description":"Create, inspect, and download build artifacts."},{"name":"Releases","description":"Draft, publish, scope, and operate releases."},{"name":"Release shares","description":"Create and manage revocable public release share pages."},{"name":"Feedback","description":"Triage feedback and crash tickets."},{"name":"Organizations","description":"Organization membership and access management."},{"name":"Invites","description":"Invite-link creation, refresh, revoke, and acceptance."},{"name":"Webhooks","description":"Webhook subscriptions and delivery history."},{"name":"Channels","description":"Per-app release channels."},{"name":"Product types","description":"Per-app artifact product families."},{"name":"Release types","description":"Per-app release-type configuration."},{"name":"App access","description":"App members, server grants, and scoped automation credentials."},{"name":"Audit","description":"Organization, app, and user audit trails."},{"name":"Operations","description":"Long-running app operation log and retry endpoints."}],"components":{"schemas":{"GenericObject":{"type":"object","properties":{},"additionalProperties":{}},"ErrorResponse":{"type":"object","properties":{"error":{"type":"string"},"detail":{"type":"string"}},"required":["error"],"additionalProperties":{}},"OkResponse":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]}},"required":["ok"],"additionalProperties":{}},"PublicLatestResponse":{"type":"object","properties":{"app":{"$ref":"#/components/schemas/PublicApp"},"channel":{"type":"string"},"build":{"type":"object","properties":{"id":{"type":"string"},"version":{"type":"string"},"version_code":{"type":"integer"},"release_type":{"type":"string"},"changelog":{"type":["string","null"]},"release_notes":{"$ref":"#/components/schemas/ReleaseNotes"},"force_update":{"type":"boolean"},"released_at":{"type":"integer"}},"required":["id","version","version_code","released_at"]},"assets":{"type":"array","items":{"$ref":"#/components/schemas/PublicAsset"}},"scoped":{"$ref":"#/components/schemas/PublicScope"},"fallback_release":{"type":["object","null"],"additionalProperties":{}},"expires_in":{"type":"integer"}},"required":["app","channel","build","assets","scoped","fallback_release","expires_in"]},"PublicApp":{"type":"object","properties":{"slug":{"type":"string"},"platform":{"type":"string"}},"required":["slug","platform"]},"ReleaseNotes":{"type":["object","null"],"additionalProperties":{"type":"string"}},"PublicAsset":{"type":"object","properties":{"platform":{"type":"string"},"arch":{"type":["string","null"]},"variant":{"type":["string","null"]},"filetype":{"type":"string"},"size_bytes":{"type":"integer"},"signature":{"type":["string","null"]},"download_url":{"type":"string","format":"uri"}},"required":["platform","filetype","size_bytes","download_url"]},"PublicScope":{"type":"object","properties":{"scope_type":{"type":"string","enum":["full","platform","user_cohort","ip_range"]},"scope_value":{"type":"string"},"release_id":{"type":"string"},"rollout_cohort_count":{"type":["integer","null"]}},"required":["scope_type","scope_value","release_id"]},"PublicUpdateCheckResponse":{"anyOf":[{"$ref":"#/components/schemas/PublicUpdateAvailableResponse"},{"$ref":"#/components/schemas/PublicNoUpdateResponse"}]},"PublicUpdateAvailableResponse":{"type":"object","properties":{"update_available":{"type":"boolean","enum":[true]},"app":{"$ref":"#/components/schemas/PublicApp"},"channel":{"type":"string"},"current_version_code":{"type":"integer"},"latest":{"type":"object","properties":{"build_id":{"type":"string"},"version":{"type":"string"},"version_code":{"type":"integer"},"changelog":{"type":["string","null"]},"release_notes":{"$ref":"#/components/schemas/ReleaseNotes"},"force_update":{"type":"boolean"},"released_at":{"type":"integer"}},"required":["build_id","version","version_code","force_update","released_at"]},"asset":{"$ref":"#/components/schemas/PublicAsset"},"scoped":{"$ref":"#/components/schemas/PublicScope"},"expires_in":{"type":"integer"}},"required":["update_available","app","channel","current_version_code","latest","asset","scoped","expires_in"]},"PublicNoUpdateResponse":{"type":"object","properties":{"update_available":{"type":"boolean","enum":[false]},"app":{"$ref":"#/components/schemas/PublicApp"},"channel":{"type":"string"},"current_version_code":{"type":"integer"},"latest_version_code":{"type":"integer"},"scoped":{"$ref":"#/components/schemas/PublicScope"},"checked_at":{"type":"integer"}},"required":["update_available","app","channel","current_version_code","latest_version_code","scoped","checked_at"]},"PublicReleaseNotesResponse":{"type":"object","properties":{"app":{"type":"object","properties":{"slug":{"type":"string"},"name":{"type":"string"},"platform":{"type":"string"}},"required":["slug","name","platform"]},"requested_version_code":{"type":["integer","null"]},"lang":{"type":["string","null"]},"releases":{"type":"array","items":{"type":"object","properties":{"release_id":{"type":"string"},"status":{"type":"string"},"channel":{"type":"string"},"version":{"type":"string"},"version_code":{"type":"integer"},"released_at":{"type":"integer"},"changelog":{"type":["string","null"]},"release_notes":{"$ref":"#/components/schemas/ReleaseNotes"}},"required":["release_id","status","channel","version","version_code","released_at","changelog","release_notes"]}}},"required":["app","requested_version_code","lang","releases"]},"PublicChannelsResponse":{"type":"object","properties":{"app":{"$ref":"#/components/schemas/PublicApp"},"channels":{"type":"array","items":{"$ref":"#/components/schemas/GenericObject"}}},"required":["app","channels"]},"MetricsIngestResponse":{"type":"object","properties":{"ok":{"type":"boolean"}},"required":["ok"]},"MetricsIngestRequest":{"type":"object","properties":{"version_name":{"type":"string"},"version_code":{"type":"integer"},"channel":{"type":"string"},"platform":{"type":"string"},"arch":{"type":"string"},"os_version":{"type":"string"},"device_model":{"type":"string"},"locale":{"type":"string"}},"additionalProperties":{}},"FeedbackSubmitResponse":{"type":"object","properties":{"id":{"type":"string"},"status":{"type":"string"},"attachments":{"type":"integer"},"reference":{"type":"string"},"ticket_url":{"type":["string","null"]}},"required":["id","status"]},"InviteResponse":{"type":"object","properties":{},"additionalProperties":{}},"AppInput":{"type":"object","properties":{"slug":{"type":"string","minLength":1},"name":{"type":"string","minLength":1},"platform":{"type":"string"},"description":{"type":["string","null"]},"public_history_enabled":{"type":"boolean"}},"additionalProperties":{}},"VersionMetricsResponse":{"type":"object","properties":{"window_start":{"type":"integer"},"window_days":{"type":"integer"},"window_minutes":{"type":"integer"},"versions":{"type":"array","items":{"type":"object","properties":{"release_id":{"type":["string","null"]},"build_id":{"type":["string","null"]},"channel":{"type":"string"},"product_type":{"type":["string","null"]},"release_type":{"type":["string","null"]},"release_status":{"type":["string","null"]},"rollout_cohort_count":{"type":["integer","null"]},"version_name":{"type":"string"},"version_code":{"type":["integer","null"]},"released_at":{"type":["integer","null"]},"release_updated_at":{"type":["integer","null"]},"active_devices":{"type":"integer"},"total_devices":{"type":"integer"},"update_current_count":{"type":"integer"},"update_offered_count":{"type":"integer"},"last_checked_at":{"type":["integer","null"]},"feedback_count":{"type":"integer"},"crash_count":{"type":"integer"},"download_count":{"type":"integer"},"telemetry_only":{"type":"boolean"}},"required":["release_id","build_id","channel","product_type","release_type","release_status","rollout_cohort_count","version_name","version_code","released_at","release_updated_at","active_devices","total_devices","update_current_count","update_offered_count","last_checked_at","feedback_count","crash_count","download_count","telemetry_only"]}}},"required":["window_start","window_days","window_minutes","versions"]},"ClientKeyResponse":{"type":"object","properties":{"client_key":{"type":["string","null"]}},"required":["client_key"],"additionalProperties":{}},"BuildInput":{"type":"object","properties":{"channel_id":{"type":"string"},"product_type":{"type":"string"},"release_type":{"type":"string"},"version_name":{"type":"string"},"version_code":{"type":"integer"},"changelog":{"type":["string","null"]},"source_commit":{"type":["string","null"]},"source_branch":{"type":["string","null"]},"ci_provider":{"type":["string","null"]},"ci_run_id":{"type":["string","null"]},"ci_url":{"type":["string","null"]},"metadata_json":{"type":"object","additionalProperties":{}}},"additionalProperties":{}},"BuildAssetInput":{"type":"object","properties":{"artifact_kind":{"type":"string","default":"installable"},"platform":{"type":"string"},"arch":{"type":["string","null"]},"variant":{"type":["string","null"]},"filetype":{"type":"string"},"r2_key":{"type":"string"},"file_hash":{"type":"string"},"size_bytes":{"type":"integer"},"signature":{"type":["string","null"]},"metadata_json":{"type":"object","additionalProperties":{}}},"required":["platform","filetype"],"additionalProperties":{}},"ReleaseInput":{"type":"object","properties":{"build_id":{"type":"string"},"channel_id":{"type":"string"},"product_type":{"type":"string"},"release_type":{"type":"string"},"status":{"type":"string","enum":["draft","active"]},"changelog":{"type":["string","null"]},"release_notes":{"type":["object","null"],"additionalProperties":{"type":"string"}},"rollout_cohort_count":{"type":["integer","null"]},"should_force_update":{"type":"boolean"},"scopes":{"type":"array","items":{"$ref":"#/components/schemas/GenericObject"}}},"additionalProperties":{}},"ReleaseShare":{"type":"object","properties":{"id":{"type":"string"},"token_hash":{"type":"string","description":"Hash of the public share token. The raw token is not returned."},"created_at":{"type":"integer"},"expires_at":{"type":"integer"},"revoked_at":{"type":["integer","null"]},"view_count":{"type":"integer"},"unique_view_count":{"type":"integer"},"download_count":{"type":"integer"},"unique_download_count":{"type":"integer"}},"required":["id","token_hash","created_at","expires_at","revoked_at","view_count","unique_view_count","download_count","unique_download_count"]},"CreateReleaseShareResponse":{"type":"object","properties":{"id":{"type":"string"},"release_id":{"type":"string"},"share_url":{"type":"string","format":"uri"},"expires_at":{"type":"integer"},"revoked_at":{"type":["integer","null"]},"has_password":{"type":"boolean"}},"required":["id","release_id","share_url","expires_at"]},"ReleaseShareRequest":{"type":"object","properties":{"ttl_seconds":{"type":"integer","minimum":60,"maximum":2592000,"description":"Time-to-live in seconds. Defaults to 7 days."},"expires_at":{"type":"integer","description":"Absolute expiry as unix timestamp in milliseconds."},"password":{"type":["string","null"]}}},"UpdateReleaseShareResponse":{"type":"object","properties":{"id":{"type":"string"},"release_id":{"type":"string"},"expires_at":{"type":"integer"},"revoked_at":{"type":["integer","null"]},"has_password":{"type":"boolean"}},"required":["id","expires_at"],"additionalProperties":{}},"RevokeResponse":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"id":{"type":"string"},"revoked_at":{"type":"integer"}},"required":["ok","id"],"additionalProperties":{}},"AppServerGrant":{"type":"object","properties":{"id":{"type":"string"},"app_id":{"type":"string"},"server_id":{"type":["string","null"]},"server_slug":{"type":["string","null"]},"app_role":{"type":"string","enum":["viewer","publisher","admin"],"description":"Backend compatibility role. The admin UI currently presents server grants as visibility grants."},"granted_by":{"type":["string","null"]},"created_at":{"type":"integer"},"updated_at":{"type":"integer"}},"required":["id","app_id","server_id","server_slug","app_role","granted_by","created_at","updated_at"]},"UpsertAppServerGrantRequest":{"type":"object","properties":{"server_id":{"type":"string"},"server_slug":{"type":"string"},"app_role":{"type":"string","enum":["viewer","publisher","admin"],"default":"viewer"}}},"AppDeployToken":{"type":"object","properties":{"id":{"type":"string"},"app_id":{"type":"string"},"name":{"type":"string"},"token_prefix":{"type":"string"},"app_role":{"type":"string","enum":["viewer","publisher"]},"created_by":{"type":["string","null"]},"created_by_actor":{"type":"string"},"created_at":{"type":"integer"},"expires_at":{"type":["integer","null"]},"last_used_at":{"type":["integer","null"]},"revoked_at":{"type":["integer","null"]}},"required":["id","app_id","name","token_prefix","app_role","created_by_actor","created_at","expires_at","last_used_at","revoked_at"]},"CreateAppDeployTokenResponse":{"type":"object","properties":{"token":{"type":"string","description":"Raw bearer token. It is returned only once and should be stored directly in a secret manager."},"deploy_token":{"$ref":"#/components/schemas/AppDeployToken"}},"required":["token","deploy_token"]},"CreateAppDeployTokenRequest":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":80},"app_role":{"type":"string","enum":["viewer","publisher"]},"expires_at":{"type":["integer","null"],"description":"Optional absolute expiry as unix timestamp in milliseconds. Must be at least 60 seconds in the future."}},"required":["name","app_role"]},"FeedbackUpdateInput":{"type":"object","properties":{"status":{"type":"string"},"assignee":{"type":["string","null"]}},"additionalProperties":{}},"FeedbackCommentInput":{"type":"object","properties":{"message":{"type":"string","minLength":1}},"required":["message"]},"InviteInput":{"type":"object","properties":{"email":{"type":"string","format":"email"},"role":{"type":"string"},"app_id":{"type":["string","null"]},"message":{"type":["string","null"]}},"required":["email"]},"WebhookInput":{"type":"object","properties":{"url":{"type":"string","format":"uri"},"secret":{"type":"string"},"events":{"type":"array","items":{"type":"string"}},"enabled":{"type":"boolean"}},"additionalProperties":{}},"ChannelInput":{"type":"object","properties":{},"additionalProperties":{}},"ProductTypeInput":{"type":"object","properties":{},"additionalProperties":{}},"ReleaseTypeInput":{"type":"object","properties":{},"additionalProperties":{}}},"parameters":{},"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT","description":"Hands JWT from Login with Raft, or an app deploy token for scoped CI/agent access."}}},"paths":{"/health":{"get":{"tags":["System"],"summary":"Worker health check","responses":{"200":{"description":"Health status.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]}},"required":["ok"],"additionalProperties":{}}}}}}}},"/.well-known/raft-agent-manifest.json":{"get":{"tags":["Auth"],"summary":"Raft Agent Login manifest","responses":{"200":{"description":"Agent manifest.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}}}}}},"/api/auth/config":{"get":{"tags":["Auth"],"summary":"Read public auth configuration","responses":{"200":{"description":"Auth config.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}}}}}},"/api/auth/login":{"get":{"tags":["Auth"],"summary":"Start Login with Raft","parameters":[{"schema":{"type":"string"},"required":false,"name":"return_to","in":"query"}],"responses":{"302":{"description":"Redirects to Raft OAuth."},"500":{"description":"Auth configuration is incomplete.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}}}}}},"/login/raft/callback":{"get":{"tags":["Auth"],"summary":"Login with Raft callback","parameters":[{"schema":{"type":"string"},"required":false,"name":"code","in":"query"},{"schema":{"type":"string"},"required":false,"name":"state","in":"query"}],"responses":{"200":{"description":"Agent token response when called by Raft Agent Login.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}}},"302":{"description":"Browser login success redirect."},"400":{"description":"Invalid callback.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Server or principal is not allowed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/auth/me":{"get":{"tags":["Auth"],"summary":"Read current authenticated principal","responses":{"200":{"description":"Current account context.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}}}}}},"/api/auth/logout":{"post":{"tags":["Auth"],"summary":"Logout current browser session","responses":{"200":{"description":"Logged out.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OkResponse"}}}}}}},"/public/v2/apps/{slug}/latest":{"get":{"tags":["Public update"],"summary":"Check latest release for an app","description":"Resolves the best active release for a client on a channel, optionally filtered by product type and scoped by platform/cohort/IP.","parameters":[{"schema":{"type":"string","example":"raft-android"},"required":true,"name":"slug","in":"path"},{"schema":{"type":"string","default":"main"},"required":false,"name":"channel","in":"query"},{"schema":{"type":"string"},"required":false,"name":"product_type","in":"query"},{"schema":{"type":"string"},"required":false,"name":"lang","in":"query"},{"schema":{"type":"string"},"required":false,"name":"device_id","in":"query"},{"schema":{"type":"string"},"required":false,"name":"X-Hands-Client-Platform","in":"header"},{"schema":{"type":"string"},"required":false,"name":"X-Hands-Cohort","in":"header"},{"schema":{"type":"string"},"required":false,"name":"X-Hands-Lang","in":"header"},{"schema":{"type":"string"},"required":false,"name":"X-Hands-Device-Id","in":"header"}],"responses":{"200":{"description":"Resolved release and downloadable assets.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicLatestResponse"}}}},"404":{"description":"App, channel, active release, or matching scoped release was not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Matched release data is inconsistent or signing failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/public/apps/{slug}/latest":{"get":{"tags":["Public update"],"summary":"Legacy latest endpoint backed by the release resolver","parameters":[{"schema":{"type":"string","example":"raft-android"},"required":true,"name":"slug","in":"path"},{"schema":{"type":"string","default":"main"},"required":false,"name":"channel","in":"query"},{"schema":{"type":"string"},"required":false,"name":"product_type","in":"query"}],"responses":{"200":{"description":"Resolved release and downloadable assets.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicLatestResponse"}}}},"404":{"description":"No matching release was found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/public/v2/apps/{slug}/updates/check":{"get":{"tags":["Public update"],"summary":"Check whether a client should update","description":"SDK-friendly update check. Resolves the active release, compares version code, chooses one compatible asset, and returns update/no-update.","parameters":[{"schema":{"type":"string","example":"raft-android"},"required":true,"name":"slug","in":"path"},{"schema":{"type":["integer","null"],"minimum":0},"required":false,"name":"current_version_code","in":"query"},{"schema":{"type":"string","default":"main"},"required":false,"name":"channel","in":"query"},{"schema":{"type":"string","default":"android-apk"},"required":false,"name":"product_type","in":"query"},{"schema":{"type":"string"},"required":false,"name":"platform","in":"query"},{"schema":{"type":"string"},"required":false,"name":"arch","in":"query"},{"schema":{"type":"string","default":"apk"},"required":false,"name":"filetype","in":"query"},{"schema":{"type":"string"},"required":false,"name":"lang","in":"query"},{"schema":{"type":"string"},"required":false,"name":"device_id","in":"query"},{"schema":{"type":"string"},"required":false,"name":"X-Hands-Client-Platform","in":"header"},{"schema":{"type":"string"},"required":false,"name":"X-Hands-Client-Arch","in":"header"},{"schema":{"type":"string"},"required":false,"name":"X-Hands-Cohort","in":"header"},{"schema":{"type":"string"},"required":false,"name":"X-Hands-Lang","in":"header"},{"schema":{"type":"string"},"required":false,"name":"X-Hands-Device-Id","in":"header"}],"responses":{"200":{"description":"Update decision.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicUpdateCheckResponse"}}}},"400":{"description":"current_version_code is missing or invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"No matching app, channel, release, or compatible asset was found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Matched release data is inconsistent or signing failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/public/v2/apps/{slug}/release-notes":{"get":{"tags":["Public update"],"summary":"Get structured public release notes","description":"Returns public release notes as structured per-language objects for consumers that need JSON instead of the HTML /notes page.","parameters":[{"schema":{"type":"string","example":"raft-android"},"required":true,"name":"slug","in":"path"},{"schema":{"type":"integer"},"required":false,"name":"version_code","in":"query"},{"schema":{"type":"string"},"required":false,"name":"lang","in":"query"},{"schema":{"type":"string"},"required":false,"name":"Accept-Language","in":"header"}],"responses":{"200":{"description":"Structured release notes.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicReleaseNotesResponse"}}}},"404":{"description":"App was not found or public history/release notes are disabled.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/public/apps/{slug}/channels":{"get":{"tags":["Public update"],"summary":"List public channels for an app","parameters":[{"schema":{"type":"string","example":"raft-android"},"required":true,"name":"slug","in":"path"}],"responses":{"200":{"description":"Channel list.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicChannelsResponse"}}}},"404":{"description":"App was not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/public/v2/apps/{slug}/metrics":{"post":{"tags":["Public metrics"],"summary":"Report SDK runtime metrics","description":"Canonical SDK metrics ingest endpoint. Clients send a throttled launch/install ping with a stable per-install X-Hands-Device-Id and build/runtime metadata. This powers active-device and version-distribution analytics; it is not an unthrottled online heartbeat.","parameters":[{"schema":{"type":"string","example":"raft-android"},"required":true,"name":"slug","in":"path"},{"schema":{"type":"string"},"required":false,"name":"client_key","in":"query"},{"schema":{"type":"string"},"required":false,"name":"device_id","in":"query"},{"schema":{"type":"string"},"required":false,"name":"X-Hands-Client-Key","in":"header"},{"schema":{"type":"string"},"required":false,"name":"X-Hands-Device-Id","in":"header"}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MetricsIngestRequest"}}}},"responses":{"202":{"description":"Metrics accepted.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MetricsIngestResponse"}}}},"400":{"description":"Device id is missing or invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing or invalid client key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"App was not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/public/v2/apps/{slug}/devices":{"post":{"tags":["Public metrics"],"summary":"Compatibility alias for SDK runtime metrics","description":"Legacy alias for /public/v2/apps/{slug}/metrics. New SDKs should use /metrics.","parameters":[{"schema":{"type":"string","example":"raft-android"},"required":true,"name":"slug","in":"path"},{"schema":{"type":"string"},"required":false,"name":"client_key","in":"query"},{"schema":{"type":"string"},"required":false,"name":"device_id","in":"query"},{"schema":{"type":"string"},"required":false,"name":"X-Hands-Client-Key","in":"header"},{"schema":{"type":"string"},"required":false,"name":"X-Hands-Device-Id","in":"header"}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MetricsIngestRequest"}}}},"responses":{"202":{"description":"Metrics accepted.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MetricsIngestResponse"}}}},"400":{"description":"Device id is missing or invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing or invalid client key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"App was not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/public/v2/apps/{slug}/feedback":{"post":{"tags":["Public feedback"],"summary":"Submit feedback or crash report","description":"Accepts SDK/client feedback, bug reports, and crash reports. Requires the app client key in X-Hands-Client-Key or client_key.","parameters":[{"schema":{"type":"string","example":"raft-android"},"required":true,"name":"slug","in":"path"},{"schema":{"type":"string"},"required":false,"name":"client_key","in":"query"},{"schema":{"type":"string"},"required":false,"name":"X-Hands-Client-Key","in":"header"}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/GenericObject"}}}},"responses":{"201":{"description":"Created feedback ticket.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FeedbackSubmitResponse"}}}},"400":{"description":"Invalid feedback payload.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing or invalid client key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Attachment is too large.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/public/apps/{slug}/icon":{"get":{"tags":["Public pages"],"summary":"Download app icon","parameters":[{"schema":{"type":"string","example":"raft-android"},"required":true,"name":"slug","in":"path"}],"responses":{"200":{"description":"Icon image.","content":{"application/octet-stream":{"schema":{"type":"string","format":"binary"}}}},"404":{"description":"App or icon was not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/electron/{slug}/{channel}/{file}":{"get":{"tags":["Public update"],"summary":"Serve Electron generic-provider update metadata or artifacts","description":"Hosts electron-builder generated files as-is for electron-updater's generic provider. Store latest*.yml, installers, and .blockmap files as build assets on an active electron-installer release.","parameters":[{"schema":{"type":"string"},"required":true,"name":"slug","in":"path"},{"schema":{"type":"string"},"required":true,"name":"channel","in":"path"},{"schema":{"type":"string","example":"latest.yml"},"required":true,"name":"file","in":"path"},{"schema":{"type":"string","default":"electron-installer"},"required":false,"name":"product_type","in":"query"}],"responses":{"200":{"description":"Electron updater metadata or binary artifact.","content":{"application/octet-stream":{"schema":{"type":"string","format":"binary"}}}},"404":{"description":"No active Electron release or matching asset was found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/public/r2/{key}":{"get":{"tags":["Public downloads"],"summary":"Download a signed public release artifact","parameters":[{"schema":{"type":"string","example":"apps%2Fapp_123%2Fbuilds%2Fbuild_123%2Fapp.apk"},"required":true,"name":"key","in":"path"},{"schema":{"type":["integer","null"]},"required":false,"name":"expires","in":"query"},{"schema":{"type":"string"},"required":true,"name":"sig","in":"query"}],"responses":{"200":{"description":"Artifact stream.","content":{"application/octet-stream":{"schema":{"type":"string","format":"binary"}}}},"302":{"description":"Redirect to presigned object storage URL."},"400":{"description":"Invalid signature parameters.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Signature expired or invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Artifact is not attached to an active release.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/share/{token}":{"get":{"tags":["Public pages"],"summary":"Render a public release share page","parameters":[{"schema":{"type":"string","example":"invite_token"},"required":true,"name":"token","in":"path"}],"responses":{"200":{"description":"Share page HTML.","content":{"text/html":{"schema":{"type":"string"}}}},"404":{"description":"Share link is expired, revoked, or unavailable.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/share/{token}/unlock":{"post":{"tags":["Public pages"],"summary":"Unlock a password-protected share page","parameters":[{"schema":{"type":"string","example":"invite_token"},"required":true,"name":"token","in":"path"}],"requestBody":{"required":true,"content":{"application/x-www-form-urlencoded":{"schema":{"type":"object","properties":{"password":{"type":"string"}},"required":["password"]}}}},"responses":{"302":{"description":"Redirects back to the share page after successful unlock."},"401":{"description":"Password is invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Share link is expired, revoked, or unavailable.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/share/{token}/download":{"get":{"tags":["Public downloads"],"summary":"Download a release share artifact","parameters":[{"schema":{"type":"string","example":"invite_token"},"required":true,"name":"token","in":"path"}],"responses":{"302":{"description":"Redirects to a signed artifact URL."},"401":{"description":"Password unlock is required.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Share link is expired, revoked, or unavailable.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/share/{token}/icon":{"get":{"tags":["Public pages"],"summary":"Download icon for a share page","parameters":[{"schema":{"type":"string","example":"invite_token"},"required":true,"name":"token","in":"path"}],"responses":{"200":{"description":"Icon image.","content":{"application/octet-stream":{"schema":{"type":"string","format":"binary"}}}},"404":{"description":"Share or icon was not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/apps/{slug}/history":{"get":{"tags":["Public pages"],"summary":"Render public version history","parameters":[{"schema":{"type":"string","example":"raft-android"},"required":true,"name":"slug","in":"path"}],"responses":{"200":{"description":"Version history HTML.","content":{"text/html":{"schema":{"type":"string"}}}},"404":{"description":"App history is disabled or unavailable.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/apps/{slug}/history/{releaseId}/download":{"get":{"tags":["Public downloads"],"summary":"Download a version history release artifact","parameters":[{"schema":{"type":"string","example":"raft-android"},"required":true,"name":"slug","in":"path"},{"schema":{"type":"string","example":"rel_123"},"required":true,"name":"releaseId","in":"path"}],"responses":{"302":{"description":"Redirects to a signed artifact URL."},"404":{"description":"Release or public history page was not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/invites/{token}":{"get":{"tags":["Invites"],"summary":"Read invite details before accepting","parameters":[{"schema":{"type":"string","example":"invite_token"},"required":true,"name":"token","in":"path"}],"responses":{"200":{"description":"Invite details.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InviteResponse"}}}},"404":{"description":"Invite was not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/apps":{"get":{"tags":["Apps"],"summary":"List apps visible to the current principal","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"App list.","content":{"application/json":{"schema":{"type":"object","properties":{"apps":{"type":"array","items":{"$ref":"#/components/schemas/GenericObject"}}},"required":["apps"]}}}},"401":{"description":"Missing or invalid authentication.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"post":{"tags":["Apps"],"summary":"Create an app","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppInput"}}}},"responses":{"201":{"description":"Created app.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}}},"400":{"description":"Invalid app payload.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Current principal cannot create apps.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"App slug already exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/apps/{appId}":{"get":{"tags":["Apps"],"summary":"Get app details","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","example":"app_123"},"required":true,"name":"appId","in":"path"}],"responses":{"200":{"description":"App details.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}}},"403":{"description":"Current principal cannot view the app.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"App was not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"patch":{"tags":["Apps"],"summary":"Update app details","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","example":"app_123"},"required":true,"name":"appId","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppInput"}}}},"responses":{"200":{"description":"Updated app.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}}},"400":{"description":"Invalid app payload.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Current principal cannot update the app.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"App was not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/apps/{appId}/archive":{"post":{"tags":["Apps"],"summary":"Archive or restore an app","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","example":"app_123"},"required":true,"name":"appId","in":"path"}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"archived":{"type":"boolean"}},"additionalProperties":{}}}}},"responses":{"200":{"description":"Archive state updated.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}}},"403":{"description":"Current principal cannot archive the app.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"App was not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/apps/{appId}/purge":{"post":{"tags":["Apps"],"summary":"Permanently purge an archived app","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","example":"app_123"},"required":true,"name":"appId","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"confirm_slug":{"type":"string"}},"additionalProperties":{}}}}},"responses":{"200":{"description":"App purged.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OkResponse"}}}},"400":{"description":"App must be archived and confirmed before purge.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Current principal cannot purge the app.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"App was not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/apps/{appId}/icon":{"put":{"tags":["Apps"],"summary":"Upload app-level fallback icon","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","example":"app_123"},"required":true,"name":"appId","in":"path"}],"requestBody":{"required":true,"content":{"application/octet-stream":{"schema":{"type":"string","format":"binary"}}}},"responses":{"200":{"description":"Icon uploaded.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}}},"400":{"description":"Icon upload failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Current principal cannot upload app icon.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/apps/{appId}/analytics/versions":{"get":{"tags":["Analytics"],"summary":"List per-version usage metrics","description":"Aggregates release update-check counters, active device pings, feedback/crash volume, and artifact download counts by app version.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","example":"app_123"},"required":true,"name":"appId","in":"path"},{"schema":{"type":"integer","exclusiveMinimum":0,"maximum":365,"example":30},"required":false,"name":"window_days","in":"query"},{"schema":{"type":"integer","exclusiveMinimum":0,"maximum":525600,"example":15},"required":false,"name":"window_minutes","in":"query"}],"responses":{"200":{"description":"Version metrics.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/VersionMetricsResponse"}}}},"403":{"description":"Current principal cannot view analytics for the app.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"App was not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/apps/{appId}/client-key":{"get":{"tags":["Apps"],"summary":"Read the app public client key","description":"Client keys identify public SDK feedback/crash submissions. They are not admin secrets.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","example":"app_123"},"required":true,"name":"appId","in":"path"}],"responses":{"200":{"description":"Client key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ClientKeyResponse"}}}},"403":{"description":"Current principal cannot read the client key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"App was not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/apps/{appId}/rotate-client-key":{"post":{"tags":["Apps"],"summary":"Rotate the app public client key","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","example":"app_123"},"required":true,"name":"appId","in":"path"}],"responses":{"200":{"description":"Rotated client key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ClientKeyResponse"}}}},"403":{"description":"Current principal cannot rotate the client key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"App was not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/apps/{appId}/builds":{"get":{"tags":["Builds"],"summary":"List builds for an app","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","example":"app_123"},"required":true,"name":"appId","in":"path"},{"schema":{"type":"string"},"required":false,"name":"channel_id","in":"query"},{"schema":{"type":"string"},"required":false,"name":"product_type","in":"query"}],"responses":{"200":{"description":"Build list.","content":{"application/json":{"schema":{"type":"object","properties":{"builds":{"type":"array","items":{"$ref":"#/components/schemas/GenericObject"}}},"required":["builds"]}}}},"403":{"description":"Current principal cannot view builds.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"App was not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"post":{"tags":["Builds"],"summary":"Create a build","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","example":"app_123"},"required":true,"name":"appId","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BuildInput"}}}},"responses":{"201":{"description":"Created build.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}}},"400":{"description":"Invalid build payload.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Current principal cannot create builds.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/apps/{appId}/builds/{buildId}":{"get":{"tags":["Builds"],"summary":"Get a build","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","example":"app_123"},"required":true,"name":"appId","in":"path"},{"schema":{"type":"string","example":"build_123"},"required":true,"name":"buildId","in":"path"}],"responses":{"200":{"description":"Build details.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}}},"403":{"description":"Current principal cannot view this build.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Build was not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"patch":{"tags":["Builds"],"summary":"Update a build","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","example":"app_123"},"required":true,"name":"appId","in":"path"},{"schema":{"type":"string","example":"build_123"},"required":true,"name":"buildId","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"channel_id":{"type":"string"},"product_type":{"type":"string"},"release_type":{"type":"string"},"version_name":{"type":"string"},"version_code":{"type":"integer"},"changelog":{"type":["string","null"]},"source_commit":{"type":["string","null"]},"source_branch":{"type":["string","null"]},"ci_provider":{"type":["string","null"]},"ci_run_id":{"type":["string","null"]},"ci_url":{"type":["string","null"]},"metadata_json":{"type":"object","additionalProperties":{}}},"additionalProperties":{}}}}},"responses":{"200":{"description":"Updated build.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}}},"400":{"description":"Invalid build payload.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Current principal cannot update this build.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Build was not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"delete":{"tags":["Builds"],"summary":"Delete a build","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","example":"app_123"},"required":true,"name":"appId","in":"path"},{"schema":{"type":"string","example":"build_123"},"required":true,"name":"buildId","in":"path"}],"responses":{"200":{"description":"Deleted build.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}}},"403":{"description":"Current principal cannot delete this build.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Build was not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/apps/{appId}/builds/{buildId}/assets":{"get":{"tags":["Builds"],"summary":"List build assets","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","example":"app_123"},"required":true,"name":"appId","in":"path"},{"schema":{"type":"string","example":"build_123"},"required":true,"name":"buildId","in":"path"}],"responses":{"200":{"description":"Build asset list.","content":{"application/json":{"schema":{"type":"object","properties":{"assets":{"type":"array","items":{"$ref":"#/components/schemas/GenericObject"}}},"required":["assets"]}}}},"403":{"description":"Current principal cannot view build assets.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Build was not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"post":{"tags":["Builds"],"summary":"Create build asset metadata","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","example":"app_123"},"required":true,"name":"appId","in":"path"},{"schema":{"type":"string","example":"build_123"},"required":true,"name":"buildId","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BuildAssetInput"}}}},"responses":{"201":{"description":"Created build asset.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}}},"400":{"description":"Invalid build asset payload.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Current principal cannot create build assets.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Build was not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/apps/{appId}/builds/{buildId}/assets/{assetId}/download":{"get":{"tags":["Builds"],"summary":"Download a build asset","description":"Streams an authenticated build asset, including installable and support artifacts such as metadata, mapping, or symbols.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","example":"app_123"},"required":true,"name":"appId","in":"path"},{"schema":{"type":"string","example":"build_123"},"required":true,"name":"buildId","in":"path"},{"schema":{"type":"string","example":"asset_123"},"required":true,"name":"assetId","in":"path"}],"responses":{"200":{"description":"Binary asset stream. Content-Disposition contains the suggested filename.","content":{"application/octet-stream":{"schema":{"type":"string","format":"binary"}},"application/vnd.android.package-archive":{"schema":{"type":"string","format":"binary"}},"application/json":{"schema":{"type":"string","format":"binary"}},"application/zip":{"schema":{"type":"string","format":"binary"}}}},"401":{"description":"Missing or invalid authentication.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Authenticated account or token does not have the required role.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Build asset or stored object was not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/apps/{appId}/builds/{buildId}/assets/{assetId}":{"delete":{"tags":["Builds"],"summary":"Delete a build asset","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","example":"app_123"},"required":true,"name":"appId","in":"path"},{"schema":{"type":"string","example":"build_123"},"required":true,"name":"buildId","in":"path"},{"schema":{"type":"string","example":"asset_123"},"required":true,"name":"assetId","in":"path"}],"responses":{"200":{"description":"Deleted build asset.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}}},"403":{"description":"Current principal cannot delete build assets.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Build asset was not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/apps/{appId}/upload":{"post":{"tags":["Builds"],"summary":"Upload an APK to object storage","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","example":"app_123"},"required":true,"name":"appId","in":"path"}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/GenericObject"}}}},"responses":{"200":{"description":"Uploaded APK.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}}},"400":{"description":"Invalid multipart upload.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Current principal cannot upload artifacts.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/parse-apk":{"post":{"tags":["Builds"],"summary":"Parse APK metadata without creating a build","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/GenericObject"}}}},"responses":{"200":{"description":"Parsed APK metadata.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}}},"400":{"description":"Invalid APK upload.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Current principal cannot parse APKs.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/apps/{appId}/releases":{"get":{"tags":["Releases"],"summary":"List releases","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","example":"app_123"},"required":true,"name":"appId","in":"path"},{"schema":{"type":"string"},"required":false,"name":"channel_id","in":"query"},{"schema":{"type":"string"},"required":false,"name":"product_type","in":"query"},{"schema":{"type":"string"},"required":false,"name":"status","in":"query"}],"responses":{"200":{"description":"Release list.","content":{"application/json":{"schema":{"type":"object","properties":{"releases":{"type":"array","items":{"$ref":"#/components/schemas/GenericObject"}}},"required":["releases"]}}}},"403":{"description":"Current principal cannot view releases.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"post":{"tags":["Releases"],"summary":"Create a draft or active release","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","example":"app_123"},"required":true,"name":"appId","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReleaseInput"}}}},"responses":{"201":{"description":"Created release.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}}},"400":{"description":"Invalid release payload.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Current principal cannot create releases.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/apps/{appId}/releases/{releaseId}":{"get":{"tags":["Releases"],"summary":"Get a release","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","example":"app_123"},"required":true,"name":"appId","in":"path"},{"schema":{"type":"string","example":"rel_123"},"required":true,"name":"releaseId","in":"path"}],"responses":{"200":{"description":"Release operation result.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}}},"400":{"description":"Invalid release operation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Current principal cannot modify this release.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Release was not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"patch":{"tags":["Releases"],"summary":"Update release metadata and scopes","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","example":"app_123"},"required":true,"name":"appId","in":"path"},{"schema":{"type":"string","example":"rel_123"},"required":true,"name":"releaseId","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}}},"responses":{"200":{"description":"Release operation result.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}}},"400":{"description":"Invalid release operation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Current principal cannot modify this release.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Release was not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"delete":{"tags":["Releases"],"summary":"Cancel or delete a release","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","example":"app_123"},"required":true,"name":"appId","in":"path"},{"schema":{"type":"string","example":"rel_123"},"required":true,"name":"releaseId","in":"path"}],"responses":{"200":{"description":"Release operation result.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}}},"400":{"description":"Invalid release operation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Current principal cannot modify this release.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Release was not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/apps/{appId}/releases/{releaseId}/publish":{"post":{"tags":["Releases"],"summary":"Publish a draft release","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","example":"app_123"},"required":true,"name":"appId","in":"path"},{"schema":{"type":"string","example":"rel_123"},"required":true,"name":"releaseId","in":"path"}],"responses":{"200":{"description":"Release operation result.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}}},"400":{"description":"Invalid release operation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Current principal cannot modify this release.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Release was not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/apps/{appId}/releases/{releaseId}/rollback":{"post":{"tags":["Releases"],"summary":"Roll back to a release","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","example":"app_123"},"required":true,"name":"appId","in":"path"},{"schema":{"type":"string","example":"rel_123"},"required":true,"name":"releaseId","in":"path"}],"responses":{"200":{"description":"Release operation result.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}}},"400":{"description":"Invalid release operation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Current principal cannot modify this release.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Release was not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/apps/{appId}/releases/{releaseId}/bump-rollout":{"post":{"tags":["Releases"],"summary":"Update rollout percentage","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","example":"app_123"},"required":true,"name":"appId","in":"path"},{"schema":{"type":"string","example":"rel_123"},"required":true,"name":"releaseId","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}}},"responses":{"200":{"description":"Release operation result.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}}},"400":{"description":"Invalid release operation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Current principal cannot modify this release.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Release was not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/apps/{appId}/releases/{releaseId}/force-update":{"post":{"tags":["Releases"],"summary":"Toggle force update","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","example":"app_123"},"required":true,"name":"appId","in":"path"},{"schema":{"type":"string","example":"rel_123"},"required":true,"name":"releaseId","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}}},"responses":{"200":{"description":"Release operation result.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}}},"400":{"description":"Invalid release operation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Current principal cannot modify this release.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Release was not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/apps/{appId}/shares":{"get":{"tags":["Release shares"],"summary":"List all share links for an app","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","example":"app_123"},"required":true,"name":"appId","in":"path"}],"responses":{"200":{"description":"App share list.","content":{"application/json":{"schema":{"type":"object","properties":{"shares":{"type":"array","items":{"$ref":"#/components/schemas/GenericObject"}}},"required":["shares"]}}}},"403":{"description":"Current principal cannot view shares.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/apps/{appId}/releases/{releaseId}/shares":{"get":{"tags":["Release shares"],"summary":"List release share links","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","example":"app_123"},"required":true,"name":"appId","in":"path"},{"schema":{"type":"string","example":"rel_123"},"required":true,"name":"releaseId","in":"path"}],"responses":{"200":{"description":"Release share list.","content":{"application/json":{"schema":{"type":"object","properties":{"shares":{"type":"array","items":{"$ref":"#/components/schemas/ReleaseShare"}}},"required":["shares"]}}}},"401":{"description":"Missing or invalid authentication.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Authenticated account or token does not have the required role.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Release was not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"post":{"tags":["Release shares"],"summary":"Create a public release share link","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","example":"app_123"},"required":true,"name":"appId","in":"path"},{"schema":{"type":"string","example":"rel_123"},"required":true,"name":"releaseId","in":"path"}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReleaseShareRequest"}}}},"responses":{"201":{"description":"Created share link.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateReleaseShareResponse"}}}},"400":{"description":"Invalid request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing or invalid authentication.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Authenticated account or token does not have the required role.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Release was not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Release cannot be shared, for example because it is cancelled.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/apps/{appId}/releases/{releaseId}/shares/{shareId}":{"patch":{"tags":["Release shares"],"summary":"Renew, password-protect, or change a release share","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","example":"app_123"},"required":true,"name":"appId","in":"path"},{"schema":{"type":"string","example":"rel_123"},"required":true,"name":"releaseId","in":"path"},{"schema":{"type":"string","example":"share_123"},"required":true,"name":"shareId","in":"path"}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReleaseShareRequest"}}}},"responses":{"200":{"description":"Updated share.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateReleaseShareResponse"}}}},"400":{"description":"Invalid request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing or invalid authentication.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Authenticated account or token does not have the required role.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Share was not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Share cannot be updated, for example because it is revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"delete":{"tags":["Release shares"],"summary":"Revoke a release share link","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","example":"app_123"},"required":true,"name":"appId","in":"path"},{"schema":{"type":"string","example":"rel_123"},"required":true,"name":"releaseId","in":"path"},{"schema":{"type":"string","example":"share_123"},"required":true,"name":"shareId","in":"path"}],"responses":{"200":{"description":"Revoked share.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RevokeResponse"}}}},"401":{"description":"Missing or invalid authentication.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Authenticated account or token does not have the required role.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Share was not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/apps/{appId}/server-grants":{"get":{"tags":["App access"],"summary":"List Raft server grants for an app","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","example":"app_123"},"required":true,"name":"appId","in":"path"}],"responses":{"200":{"description":"Server grant operation result.","content":{"application/json":{"schema":{"type":"object","properties":{"server_grants":{"type":"array","items":{"$ref":"#/components/schemas/AppServerGrant"}}},"required":["server_grants"]}}}},"400":{"description":"Invalid request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing or invalid authentication.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Authenticated account or token does not have the required role.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"post":{"tags":["App access"],"summary":"Add or update a Raft server visibility grant","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","example":"app_123"},"required":true,"name":"appId","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpsertAppServerGrantRequest"}}}},"responses":{"201":{"description":"Server grant operation result.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}}},"400":{"description":"Invalid request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing or invalid authentication.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Authenticated account or token does not have the required role.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/apps/{appId}/server-grants/{serverId}":{"patch":{"tags":["App access"],"summary":"Update a Raft server visibility grant","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","example":"app_123"},"required":true,"name":"appId","in":"path"},{"schema":{"type":"string","example":"oranix-main"},"required":true,"name":"serverId","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpsertAppServerGrantRequest"}}}},"responses":{"200":{"description":"Server grant operation result.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}}},"400":{"description":"Invalid request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing or invalid authentication.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Authenticated account or token does not have the required role.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"delete":{"tags":["App access"],"summary":"Remove a Raft server visibility grant","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","example":"app_123"},"required":true,"name":"appId","in":"path"},{"schema":{"type":"string","example":"oranix-main"},"required":true,"name":"serverId","in":"path"}],"responses":{"200":{"description":"Server grant operation result.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}}},"400":{"description":"Invalid request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing or invalid authentication.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Authenticated account or token does not have the required role.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/apps/{appId}/deploy-tokens":{"get":{"tags":["App access"],"summary":"List app deploy tokens","description":"Raw token values are never returned after creation.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","example":"app_123"},"required":true,"name":"appId","in":"path"},{"schema":{"type":"string","enum":["1"]},"required":false,"name":"include_revoked","in":"query"}],"responses":{"200":{"description":"Deploy token list.","content":{"application/json":{"schema":{"type":"object","properties":{"deploy_tokens":{"type":"array","items":{"$ref":"#/components/schemas/AppDeployToken"}}},"required":["deploy_tokens"]}}}},"401":{"description":"Missing or invalid authentication.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Authenticated account or token does not have the required role.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"post":{"tags":["App access"],"summary":"Create an app deploy token","description":"Creates an app-scoped deploy token. The raw token is returned once in this response; store it directly in a secret manager.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","example":"app_123"},"required":true,"name":"appId","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateAppDeployTokenRequest"}}}},"responses":{"201":{"description":"Created deploy token. token is shown once.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateAppDeployTokenResponse"}}}},"400":{"description":"Invalid request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing or invalid authentication.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Authenticated account or token does not have the required role.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/apps/{appId}/deploy-tokens/{tokenId}":{"delete":{"tags":["App access"],"summary":"Revoke an app deploy token","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","example":"app_123"},"required":true,"name":"appId","in":"path"},{"schema":{"type":"string","example":"token_123"},"required":true,"name":"tokenId","in":"path"}],"responses":{"200":{"description":"Revoked deploy token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RevokeResponse"}}}},"401":{"description":"Missing or invalid authentication.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Authenticated account or token does not have the required role.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Deploy token was not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/apps/{appId}/feedback":{"get":{"tags":["Feedback"],"summary":"List feedback and crash tickets","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","example":"app_123"},"required":true,"name":"appId","in":"path"},{"schema":{"type":"string"},"required":false,"name":"status","in":"query"},{"schema":{"type":"string","enum":["feedback","bug","crash"]},"required":false,"name":"kind","in":"query"},{"schema":{"type":["integer","null"]},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string"},"required":false,"name":"cursor","in":"query"}],"responses":{"200":{"description":"Feedback ticket list.","content":{"application/json":{"schema":{"type":"object","properties":{"tickets":{"type":"array","items":{"$ref":"#/components/schemas/GenericObject"}}},"required":["tickets"],"additionalProperties":{}}}}},"403":{"description":"Current principal cannot view feedback.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/apps/{appId}/feedback/stats":{"get":{"tags":["Feedback"],"summary":"Read feedback ticket statistics","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","example":"app_123"},"required":true,"name":"appId","in":"path"}],"responses":{"200":{"description":"Feedback stats.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}}},"403":{"description":"Current principal cannot view feedback stats.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/apps/{appId}/feedback/crash-groups":{"get":{"tags":["Feedback"],"summary":"List crash groups by signature","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","example":"app_123"},"required":true,"name":"appId","in":"path"},{"schema":{"type":"string"},"required":false,"name":"status","in":"query"},{"schema":{"type":["integer","null"]},"required":false,"name":"limit","in":"query"}],"responses":{"200":{"description":"Crash group list.","content":{"application/json":{"schema":{"type":"object","properties":{"groups":{"type":"array","items":{"$ref":"#/components/schemas/GenericObject"}}},"required":["groups"],"additionalProperties":{}}}}},"403":{"description":"Current principal cannot view crash groups.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/apps/{appId}/feedback/{ticketId}":{"get":{"tags":["Feedback"],"summary":"Get feedback ticket details","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","example":"app_123"},"required":true,"name":"appId","in":"path"},{"schema":{"type":"string","example":"ticket_123"},"required":true,"name":"ticketId","in":"path"}],"responses":{"200":{"description":"Feedback ticket details.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}}},"403":{"description":"Current principal cannot view feedback ticket.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Feedback ticket was not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"patch":{"tags":["Feedback"],"summary":"Update feedback ticket status or assignee","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","example":"app_123"},"required":true,"name":"appId","in":"path"},{"schema":{"type":"string","example":"ticket_123"},"required":true,"name":"ticketId","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FeedbackUpdateInput"}}}},"responses":{"200":{"description":"Updated feedback ticket.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}}},"400":{"description":"Invalid feedback update.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Current principal cannot update feedback ticket.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Feedback ticket was not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/apps/{appId}/feedback/{ticketId}/comments":{"post":{"tags":["Feedback"],"summary":"Add a comment to a feedback ticket","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","example":"app_123"},"required":true,"name":"appId","in":"path"},{"schema":{"type":"string","example":"ticket_123"},"required":true,"name":"ticketId","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FeedbackCommentInput"}}}},"responses":{"201":{"description":"Created feedback comment.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}}},"400":{"description":"Invalid comment payload.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Current principal cannot comment on feedback ticket.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Feedback ticket was not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/apps/{appId}/feedback/{ticketId}/attachments/{attachmentId}":{"get":{"tags":["Feedback"],"summary":"Download feedback attachment","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","example":"app_123"},"required":true,"name":"appId","in":"path"},{"schema":{"type":"string","example":"ticket_123"},"required":true,"name":"ticketId","in":"path"},{"schema":{"type":"string","example":"attachment_123"},"required":true,"name":"attachmentId","in":"path"}],"responses":{"200":{"description":"Attachment stream.","content":{"application/octet-stream":{"schema":{"type":"string","format":"binary"}}}},"403":{"description":"Current principal cannot download feedback attachment.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Feedback attachment was not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/orgs":{"get":{"tags":["Organizations"],"summary":"List organizations for the current principal","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Organization list.","content":{"application/json":{"schema":{"type":"object","properties":{"orgs":{"type":"array","items":{"$ref":"#/components/schemas/GenericObject"}}},"required":["orgs"]}}}},"401":{"description":"Missing or invalid authentication.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/orgs/{orgId}/members":{"get":{"tags":["Organizations"],"summary":"List organization members","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","example":"org_123"},"required":true,"name":"orgId","in":"path"}],"responses":{"200":{"description":"Organization member list.","content":{"application/json":{"schema":{"type":"object","properties":{"members":{"type":"array","items":{"$ref":"#/components/schemas/GenericObject"}}},"required":["members"]}}}},"403":{"description":"Current principal cannot view org members.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/orgs/{orgId}/members/{accountId}":{"patch":{"tags":["Organizations"],"summary":"Update organization member role","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","example":"org_123"},"required":true,"name":"orgId","in":"path"},{"schema":{"type":"string","example":"acct_123"},"required":true,"name":"accountId","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"org_role":{"type":"string","enum":["owner","admin","member","viewer"]}},"required":["org_role"]}}}},"responses":{"200":{"description":"Updated member.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}}},"400":{"description":"Invalid role.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Current principal cannot update org members.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"delete":{"tags":["Organizations"],"summary":"Remove organization member","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","example":"org_123"},"required":true,"name":"orgId","in":"path"},{"schema":{"type":"string","example":"acct_123"},"required":true,"name":"accountId","in":"path"}],"responses":{"200":{"description":"Removed member.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}}},"403":{"description":"Current principal cannot remove org members.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/orgs/{orgId}/invites":{"get":{"tags":["Invites"],"summary":"List organization invites","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","example":"org_123"},"required":true,"name":"orgId","in":"path"},{"schema":{"type":"string"},"required":false,"name":"status","in":"query"}],"responses":{"200":{"description":"Invite operation result.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}}},"400":{"description":"Invalid invite request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Current principal cannot manage invites.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Invite was not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"post":{"tags":["Invites"],"summary":"Create organization or app invite link","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","example":"org_123"},"required":true,"name":"orgId","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InviteInput"}}}},"responses":{"201":{"description":"Invite operation result.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}}},"400":{"description":"Invalid invite request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Current principal cannot manage invites.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Invite was not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/orgs/{orgId}/invites/{inviteId}/resend":{"post":{"tags":["Invites"],"summary":"Refresh invite link","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","example":"org_123"},"required":true,"name":"orgId","in":"path"},{"schema":{"type":"string","example":"invite_123"},"required":true,"name":"inviteId","in":"path"}],"responses":{"200":{"description":"Invite operation result.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}}},"400":{"description":"Invalid invite request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Current principal cannot manage invites.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Invite was not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/orgs/{orgId}/invites/{inviteId}":{"delete":{"tags":["Invites"],"summary":"Revoke invite link","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","example":"org_123"},"required":true,"name":"orgId","in":"path"},{"schema":{"type":"string","example":"invite_123"},"required":true,"name":"inviteId","in":"path"}],"responses":{"200":{"description":"Invite operation result.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}}},"400":{"description":"Invalid invite request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Current principal cannot manage invites.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Invite was not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/invites/{token}/accept":{"post":{"tags":["Invites"],"summary":"Accept an invite as the current principal","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","example":"invite_token"},"required":true,"name":"token","in":"path"}],"responses":{"200":{"description":"Accepted invite.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}}},"403":{"description":"Current principal cannot accept this invite.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Invite was not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Invite is not pending.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"410":{"description":"Invite expired.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/orgs/{orgId}/audit-logs":{"get":{"tags":["Audit"],"summary":"List organization audit logs","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","example":"org_123"},"required":true,"name":"orgId","in":"path"},{"schema":{"type":"string"},"required":false,"name":"actor_id","in":"query"},{"schema":{"type":"string"},"required":false,"name":"action_prefix","in":"query"}],"responses":{"200":{"description":"Audit log list.","content":{"application/json":{"schema":{"type":"object","properties":{"audit_logs":{"type":"array","items":{"$ref":"#/components/schemas/GenericObject"}}},"required":["audit_logs"],"additionalProperties":{}}}}},"403":{"description":"Current principal cannot view org audit logs.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/orgs/{orgId}/webhooks":{"get":{"tags":["Webhooks"],"summary":"List webhooks","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","example":"org_123"},"required":true,"name":"orgId","in":"path"}],"responses":{"200":{"description":"Webhook operation result.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}}},"400":{"description":"Invalid webhook request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Current principal cannot manage webhooks.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Webhook was not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"post":{"tags":["Webhooks"],"summary":"Create webhook","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","example":"org_123"},"required":true,"name":"orgId","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookInput"}}}},"responses":{"201":{"description":"Webhook operation result.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}}},"400":{"description":"Invalid webhook request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Current principal cannot manage webhooks.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Webhook was not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/orgs/{orgId}/webhooks/{webhookId}":{"patch":{"tags":["Webhooks"],"summary":"Update webhook","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","example":"org_123"},"required":true,"name":"orgId","in":"path"},{"schema":{"type":"string","example":"webhook_123"},"required":true,"name":"webhookId","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookInput"}}}},"responses":{"200":{"description":"Webhook operation result.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}}},"400":{"description":"Invalid webhook request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Current principal cannot manage webhooks.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Webhook was not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"delete":{"tags":["Webhooks"],"summary":"Delete webhook","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","example":"org_123"},"required":true,"name":"orgId","in":"path"},{"schema":{"type":"string","example":"webhook_123"},"required":true,"name":"webhookId","in":"path"}],"responses":{"200":{"description":"Webhook operation result.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}}},"400":{"description":"Invalid webhook request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Current principal cannot manage webhooks.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Webhook was not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/orgs/{orgId}/webhooks/{webhookId}/deliveries":{"get":{"tags":["Webhooks"],"summary":"List webhook deliveries","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","example":"org_123"},"required":true,"name":"orgId","in":"path"},{"schema":{"type":"string","example":"webhook_123"},"required":true,"name":"webhookId","in":"path"}],"responses":{"200":{"description":"Webhook operation result.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}}},"400":{"description":"Invalid webhook request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Current principal cannot manage webhooks.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Webhook was not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/apps/{appId}/channels":{"get":{"tags":["Channels"],"summary":"List channels","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","example":"app_123"},"required":true,"name":"appId","in":"path"}],"responses":{"200":{"description":"Channels list.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}}},"403":{"description":"Current principal cannot view channels.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"post":{"tags":["Channels"],"summary":"Create channels item","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","example":"app_123"},"required":true,"name":"appId","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChannelInput"}}}},"responses":{"201":{"description":"Channels item created.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}}},"400":{"description":"Invalid request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Current principal cannot create channels.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/apps/{appId}/channels/{channelId}":{"patch":{"tags":["Channels"],"summary":"Update channels item","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","example":"app_123"},"required":true,"name":"appId","in":"path"},{"schema":{"type":"string","example":"channel_123"},"required":true,"name":"channelId","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChannelInput"}}}},"responses":{"200":{"description":"Channels item updated.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}}},"400":{"description":"Invalid request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Current principal cannot modify channels.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Channels item was not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"delete":{"tags":["Channels"],"summary":"Delete channels item","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","example":"app_123"},"required":true,"name":"appId","in":"path"},{"schema":{"type":"string","example":"channel_123"},"required":true,"name":"channelId","in":"path"}],"responses":{"200":{"description":"Channels item deleted.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}}},"400":{"description":"Invalid request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Current principal cannot modify channels.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Channels item was not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/apps/{appId}/product-types":{"get":{"tags":["Product types"],"summary":"List product types","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","example":"app_123"},"required":true,"name":"appId","in":"path"}],"responses":{"200":{"description":"Product types list.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}}},"403":{"description":"Current principal cannot view product types.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"post":{"tags":["Product types"],"summary":"Create product types item","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","example":"app_123"},"required":true,"name":"appId","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProductTypeInput"}}}},"responses":{"201":{"description":"Product types item created.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}}},"400":{"description":"Invalid request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Current principal cannot create product types.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/apps/{appId}/product-types/{ptId}":{"patch":{"tags":["Product types"],"summary":"Update product types item","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","example":"app_123"},"required":true,"name":"appId","in":"path"},{"schema":{"type":"string","example":"pt_123"},"required":true,"name":"ptId","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProductTypeInput"}}}},"responses":{"200":{"description":"Product types item updated.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}}},"400":{"description":"Invalid request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Current principal cannot modify product types.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Product types item was not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"delete":{"tags":["Product types"],"summary":"Delete product types item","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","example":"app_123"},"required":true,"name":"appId","in":"path"},{"schema":{"type":"string","example":"pt_123"},"required":true,"name":"ptId","in":"path"}],"responses":{"200":{"description":"Product types item deleted.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}}},"400":{"description":"Invalid request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Current principal cannot modify product types.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Product types item was not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/apps/{appId}/release-types":{"get":{"tags":["Release types"],"summary":"List release types","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","example":"app_123"},"required":true,"name":"appId","in":"path"}],"responses":{"200":{"description":"Release types list.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}}},"403":{"description":"Current principal cannot view release types.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"post":{"tags":["Release types"],"summary":"Create release types item","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","example":"app_123"},"required":true,"name":"appId","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReleaseTypeInput"}}}},"responses":{"201":{"description":"Release types item created.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}}},"400":{"description":"Invalid request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Current principal cannot create release types.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/apps/{appId}/release-types/{rtId}":{"patch":{"tags":["Release types"],"summary":"Update release types item","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","example":"app_123"},"required":true,"name":"appId","in":"path"},{"schema":{"type":"string","example":"rt_123"},"required":true,"name":"rtId","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReleaseTypeInput"}}}},"responses":{"200":{"description":"Release types item updated.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}}},"400":{"description":"Invalid request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Current principal cannot modify release types.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Release types item was not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"delete":{"tags":["Release types"],"summary":"Delete release types item","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","example":"app_123"},"required":true,"name":"appId","in":"path"},{"schema":{"type":"string","example":"rt_123"},"required":true,"name":"rtId","in":"path"}],"responses":{"200":{"description":"Release types item deleted.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}}},"400":{"description":"Invalid request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Current principal cannot modify release types.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Release types item was not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/apps/{appId}/audit-logs":{"get":{"tags":["Audit"],"summary":"List app audit logs","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","example":"app_123"},"required":true,"name":"appId","in":"path"}],"responses":{"200":{"description":"App audit log list.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}}},"403":{"description":"Current principal cannot view app audit logs.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/users/{accountId}/audit":{"get":{"tags":["Audit"],"summary":"List audit logs for a user","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","example":"acct_123"},"required":true,"name":"accountId","in":"path"}],"responses":{"200":{"description":"User audit log list.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}}},"403":{"description":"Current principal cannot view user audit logs.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/apps/{appId}/members":{"get":{"tags":["App access"],"summary":"List app members","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","example":"app_123"},"required":true,"name":"appId","in":"path"}],"responses":{"200":{"description":"App member operation result.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}}},"400":{"description":"Invalid member request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Current principal cannot manage app members.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"App member was not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"post":{"tags":["App access"],"summary":"Add app member","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","example":"app_123"},"required":true,"name":"appId","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"account_id":{"type":"string"},"app_role":{"type":"string","enum":["viewer","publisher","admin"]}},"additionalProperties":{}}}}},"responses":{"201":{"description":"App member operation result.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}}},"400":{"description":"Invalid member request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Current principal cannot manage app members.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"App member was not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/apps/{appId}/members/{accountId}":{"patch":{"tags":["App access"],"summary":"Update app member role","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","example":"app_123"},"required":true,"name":"appId","in":"path"},{"schema":{"type":"string","example":"acct_123"},"required":true,"name":"accountId","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"account_id":{"type":"string"},"app_role":{"type":"string","enum":["viewer","publisher","admin"]}},"additionalProperties":{}}}}},"responses":{"200":{"description":"App member operation result.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}}},"400":{"description":"Invalid member request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Current principal cannot manage app members.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"App member was not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"delete":{"tags":["App access"],"summary":"Remove app member","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","example":"app_123"},"required":true,"name":"appId","in":"path"},{"schema":{"type":"string","example":"acct_123"},"required":true,"name":"accountId","in":"path"}],"responses":{"200":{"description":"App member operation result.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}}},"400":{"description":"Invalid member request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Current principal cannot manage app members.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"App member was not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/apps/{appId}/operations":{"get":{"tags":["Operations"],"summary":"List app operations","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","example":"app_123"},"required":true,"name":"appId","in":"path"}],"responses":{"200":{"description":"Operation list.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}}},"403":{"description":"Current principal cannot view operations.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/apps/{appId}/operations/stream":{"get":{"tags":["Operations"],"summary":"Stream app operation events","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","example":"app_123"},"required":true,"name":"appId","in":"path"}],"responses":{"200":{"description":"Server-sent event stream.","content":{"text/event-stream":{"schema":{"type":"string"}}}},"403":{"description":"Current principal cannot stream operations.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/apps/{appId}/operations/{opId}":{"get":{"tags":["Operations"],"summary":"Get app operation","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","example":"app_123"},"required":true,"name":"appId","in":"path"},{"schema":{"type":"string","example":"op_123"},"required":true,"name":"opId","in":"path"}],"responses":{"200":{"description":"Operation result.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}}},"403":{"description":"Current principal cannot modify operations.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Operation was not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"delete":{"tags":["Operations"],"summary":"Delete app operation","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","example":"app_123"},"required":true,"name":"appId","in":"path"},{"schema":{"type":"string","example":"op_123"},"required":true,"name":"opId","in":"path"}],"responses":{"200":{"description":"Operation result.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}}},"403":{"description":"Current principal cannot modify operations.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Operation was not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/apps/{appId}/operations/{opId}/retry":{"post":{"tags":["Operations"],"summary":"Retry app operation","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","example":"app_123"},"required":true,"name":"appId","in":"path"},{"schema":{"type":"string","example":"op_123"},"required":true,"name":"opId","in":"path"}],"responses":{"200":{"description":"Operation result.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}}},"403":{"description":"Current principal cannot modify operations.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Operation was not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}}},"webhooks":{}}