diff --git a/docs/openapi.yaml b/docs/openapi.yaml
index 945f83f19..107f72f24 100644
--- a/docs/openapi.yaml
+++ b/docs/openapi.yaml
@@ -8,6 +8,35 @@ info:
**The API endpoints documented here are not yet stable and may change or break without notice. Use them at your own
risk.**
+ ## Error responses
+
+ Most non-OAuth JSON endpoints return the shared `APIError` body for non-2xx responses:
+
+ ```json
+ {
+ "code": 40001,
+ "msg": "Invalid args"
+ }
+ ```
+
+ The first three digits of `code` match the HTTP status code. Clients should branch on `code` and HTTP status.
+
+ The `msg` field is a developer-facing diagnostic string and is not a stable programmatic contract. It may contain
+ safe validation details, but it must not contain stack traces, internal exception text, credentials, or other
+ sensitive implementation details.
+
+ Backend implementations should use the codes defined by `ErrorCode` and should add a new documented code before
+ exposing a new machine-readable error condition.
+
+ OAuth protocol error responses use the `OAuthError` body instead of `APIError`.
+
+ Moved-resource redirects return `301` with `Location` for `GET` and `HEAD`, while moved-resource write requests
+ return `409` with `MovedResourceError`.
+
+ Server-Sent Events endpoints may emit a stream-level `error` event after the HTTP response has already started.
+
+ Quota and rate-limit responses include `Retry-After` when the server can compute a retry time.
+
security:
- bearerAuth: []
@@ -52,6 +81,8 @@ paths:
type: array
items:
$ref: "#/components/schemas/AccountIdentityProvider"
+ "400":
+ $ref: "#/components/responses/BadRequest"
/account/identity-providers/{provider}/authorize:
get:
@@ -96,7 +127,7 @@ paths:
format: uri
minLength: 1
"400":
- description: Invalid hosted sign-in request.
+ $ref: "#/components/responses/BadRequest"
/account/identity-providers/{provider}/callback:
get:
@@ -105,9 +136,12 @@ paths:
- Account
summary: Handle identity provider callback
description: |
- Handle the identity provider callback for hosted sign-in. Callback state is used to associate the provider
- response with the hosted sign-in flow and provide CSRF protection. The provider callback includes either an
- authorization code or an OAuth error.
+ Handle the identity provider callback for hosted sign-in.
+
+ Callback state is used to associate the provider response with the hosted sign-in flow and provide CSRF
+ protection.
+
+ The provider callback includes either an authorization code or an OAuth error.
security: []
parameters:
- name: provider
@@ -140,7 +174,7 @@ paths:
description: Redirect back to hosted sign-in.
headers:
Location:
- description: Hosted sign-in URL containing the original `clientID`, `requestURI`, and optional `uiLocales`.
+ description: Hosted sign-in URL with the original `clientID`, `requestURI`, and optional `uiLocales`.
schema:
type: string
format: uri
@@ -150,15 +184,20 @@ paths:
Sets the `__Host-xbuilder-account-session` cookie when the provider callback creates an account session.
schema:
type: string
+ "400":
+ $ref: "#/components/responses/BadRequest"
post:
operationId: submitAccountIdentityProviderCallback
tags:
- Account
summary: Submit identity provider callback
description: |
- Handle identity provider callbacks that use form post response mode. These external callbacks use the OAuth
- state parameter for CSRF protection instead of a same-site web CSRF token. The provider callback includes either
- an authorization code or an OAuth error.
+ Handle identity provider callbacks that use form post response mode.
+
+ These external callbacks use the OAuth state parameter for CSRF protection instead of a same-site web CSRF
+ token.
+
+ The provider callback includes either an authorization code or an OAuth error.
security: []
parameters:
- name: provider
@@ -206,7 +245,7 @@ paths:
description: Redirect back to hosted sign-in.
headers:
Location:
- description: Hosted sign-in URL containing the original `clientID`, `requestURI`, and optional `uiLocales`.
+ description: Hosted sign-in URL with the original `clientID`, `requestURI`, and optional `uiLocales`.
schema:
type: string
format: uri
@@ -216,6 +255,8 @@ paths:
Sets the `__Host-xbuilder-account-session` cookie when the provider callback creates an account session.
schema:
type: string
+ "400":
+ $ref: "#/components/responses/BadRequestForIdentityProviderFormPostCallback"
/account/oauth/par:
post:
@@ -556,10 +597,12 @@ paths:
application/json:
schema:
$ref: "#/components/schemas/AccountUser"
+ "400":
+ $ref: "#/components/responses/BadRequest"
"401":
$ref: "#/components/responses/AccountUnauthorized"
"403":
- $ref: "#/components/responses/OAuthInsufficientScope"
+ $ref: "#/components/responses/AccountForbidden"
/account/user/avatar:
put:
@@ -592,7 +635,7 @@ paths:
description: |
Avatar image file.
- Maximum size is 5 MiB (5242880 bytes).
+ Maximum size is 5 MiB.
type: string
format: binary
encoding:
@@ -602,15 +645,15 @@ paths:
"204":
description: Account user avatar updated.
"400":
- description: Invalid request parameters.
+ $ref: "#/components/responses/BadRequest"
"401":
$ref: "#/components/responses/AccountUnauthorized"
"403":
- $ref: "#/components/responses/OAuthInsufficientScope"
+ $ref: "#/components/responses/AccountForbidden"
"413":
- description: Avatar image file is too large.
+ $ref: "#/components/responses/ContentTooLarge"
"415":
- description: Avatar image file type is not supported.
+ $ref: "#/components/responses/UnsupportedMediaType"
/account/user/identities:
get:
@@ -641,6 +684,8 @@ paths:
type: array
items:
$ref: "#/components/schemas/AccountUserIdentity"
+ "400":
+ $ref: "#/components/responses/BadRequest"
"401":
$ref: "#/components/responses/Unauthorized"
@@ -678,8 +723,12 @@ paths:
application/json:
schema:
$ref: "#/components/schemas/CurrentAccountSession"
+ "400":
+ $ref: "#/components/responses/BadRequest"
"401":
$ref: "#/components/responses/Unauthorized"
+ "403":
+ $ref: "#/components/responses/Forbidden"
get:
operationId: getAccountSession
tags:
@@ -718,6 +767,8 @@ paths:
type: string
"401":
$ref: "#/components/responses/Unauthorized"
+ "403":
+ $ref: "#/components/responses/Forbidden"
/account/sessions:
get:
@@ -748,6 +799,8 @@ paths:
type: array
items:
$ref: "#/components/schemas/AccountSession"
+ "400":
+ $ref: "#/components/responses/BadRequest"
"401":
$ref: "#/components/responses/Unauthorized"
delete:
@@ -771,6 +824,8 @@ paths:
type: string
"401":
$ref: "#/components/responses/Unauthorized"
+ "403":
+ $ref: "#/components/responses/Forbidden"
/account/sessions/{sessionID}:
delete:
@@ -799,10 +854,14 @@ paths:
description: Clears the `__Host-xbuilder-account-session` cookie when the deleted session is current.
schema:
type: string
+ "400":
+ $ref: "#/components/responses/BadRequest"
"401":
$ref: "#/components/responses/Unauthorized"
+ "403":
+ $ref: "#/components/responses/Forbidden"
"404":
- description: Account session not found.
+ $ref: "#/components/responses/NotFound"
/user:
get:
@@ -848,6 +907,8 @@ paths:
application/json:
schema:
$ref: "#/components/schemas/AuthenticatedUser"
+ "400":
+ $ref: "#/components/responses/BadRequest"
"401":
$ref: "#/components/responses/Unauthorized"
@@ -871,7 +932,7 @@ paths:
description: |
Avatar image file.
- Maximum size is 5 MiB (5242880 bytes).
+ Maximum size is 5 MiB.
type: string
format: binary
encoding:
@@ -881,13 +942,13 @@ paths:
"204":
description: Authenticated user avatar updated.
"400":
- description: Invalid request parameters.
+ $ref: "#/components/responses/BadRequest"
"401":
$ref: "#/components/responses/Unauthorized"
"413":
- description: Avatar image file is too large.
+ $ref: "#/components/responses/ContentTooLarge"
"415":
- description: Avatar image file type is not supported.
+ $ref: "#/components/responses/UnsupportedMediaType"
/user/followers:
get:
@@ -929,6 +990,8 @@ paths:
type: array
items:
$ref: "#/components/schemas/User"
+ "400":
+ $ref: "#/components/responses/BadRequest"
"401":
$ref: "#/components/responses/Unauthorized"
@@ -972,6 +1035,8 @@ paths:
type: array
items:
$ref: "#/components/schemas/User"
+ "400":
+ $ref: "#/components/responses/BadRequest"
"401":
$ref: "#/components/responses/Unauthorized"
@@ -997,7 +1062,7 @@ paths:
"401":
$ref: "#/components/responses/Unauthorized"
"404":
- description: The target user does not exist, or the authenticated user does not follow the target user.
+ $ref: "#/components/responses/NotFound"
put:
operationId: followUser
tags:
@@ -1128,6 +1193,8 @@ paths:
type: array
items:
$ref: "#/components/schemas/Project"
+ "400":
+ $ref: "#/components/responses/BadRequest"
"401":
$ref: "#/components/responses/Unauthorized"
post:
@@ -1199,19 +1266,12 @@ paths:
application/json:
schema:
$ref: "#/components/schemas/Project"
+ "400":
+ $ref: "#/components/responses/BadRequest"
"401":
$ref: "#/components/responses/Unauthorized"
"409":
- description: |
- Returned when `remixSource` references a moved project or project release.
-
- The response includes a `canonical` payload for the route-derived fields in `remixSource`.
-
- Clients may update the request and resubmit it explicitly.
- content:
- application/json:
- schema:
- $ref: "#/components/schemas/MovedResourceError"
+ $ref: "#/components/responses/ResourceMoved"
/user/liked-projects:
get:
@@ -1303,6 +1363,8 @@ paths:
type: array
items:
$ref: "#/components/schemas/Project"
+ "400":
+ $ref: "#/components/responses/BadRequest"
"401":
$ref: "#/components/responses/Unauthorized"
@@ -1334,7 +1396,7 @@ paths:
"401":
$ref: "#/components/responses/Unauthorized"
"404":
- description: The project does not exist, or the authenticated user has not liked the project.
+ $ref: "#/components/responses/NotFound"
put:
operationId: likeProject
tags:
@@ -1456,6 +1518,8 @@ paths:
type: array
items:
$ref: "#/components/schemas/Asset"
+ "400":
+ $ref: "#/components/responses/BadRequest"
"401":
$ref: "#/components/responses/Unauthorized"
post:
@@ -1518,10 +1582,12 @@ paths:
application/json:
schema:
$ref: "#/components/schemas/Asset"
+ "400":
+ $ref: "#/components/responses/BadRequest"
"401":
$ref: "#/components/responses/Unauthorized"
"403":
- description: Insufficient permissions to perform this operation.
+ $ref: "#/components/responses/Forbidden"
/user/courses:
get:
@@ -1568,6 +1634,8 @@ paths:
type: array
items:
$ref: "#/components/schemas/Course"
+ "400":
+ $ref: "#/components/responses/BadRequest"
"401":
$ref: "#/components/responses/Unauthorized"
post:
@@ -1620,10 +1688,12 @@ paths:
application/json:
schema:
$ref: "#/components/schemas/Course"
+ "400":
+ $ref: "#/components/responses/BadRequest"
"401":
$ref: "#/components/responses/Unauthorized"
"403":
- description: Insufficient permissions to perform this operation.
+ $ref: "#/components/responses/Forbidden"
/user/course-series:
get:
@@ -1665,6 +1735,8 @@ paths:
type: array
items:
$ref: "#/components/schemas/CourseSeries"
+ "400":
+ $ref: "#/components/responses/BadRequest"
"401":
$ref: "#/components/responses/Unauthorized"
post:
@@ -1715,10 +1787,12 @@ paths:
application/json:
schema:
$ref: "#/components/schemas/CourseSeries"
+ "400":
+ $ref: "#/components/responses/BadRequest"
"401":
$ref: "#/components/responses/Unauthorized"
"403":
- description: Insufficient permissions to perform this operation.
+ $ref: "#/components/responses/Forbidden"
/users:
get:
@@ -1760,6 +1834,8 @@ paths:
type: array
items:
$ref: "#/components/schemas/User"
+ "400":
+ $ref: "#/components/responses/BadRequest"
/users/{username}:
get:
@@ -1785,6 +1861,8 @@ paths:
$ref: "#/components/schemas/User"
"301":
$ref: "#/components/responses/MovedPermanently"
+ "404":
+ $ref: "#/components/responses/NotFound"
/users/{username}/followers:
get:
@@ -1835,6 +1913,10 @@ paths:
$ref: "#/components/schemas/User"
"301":
$ref: "#/components/responses/MovedPermanently"
+ "400":
+ $ref: "#/components/responses/BadRequest"
+ "404":
+ $ref: "#/components/responses/NotFound"
/users/{username}/following:
get:
@@ -1885,6 +1967,10 @@ paths:
$ref: "#/components/schemas/User"
"301":
$ref: "#/components/responses/MovedPermanently"
+ "400":
+ $ref: "#/components/responses/BadRequest"
+ "404":
+ $ref: "#/components/responses/NotFound"
/users/{username}/projects:
get:
@@ -1979,6 +2065,10 @@ paths:
$ref: "#/components/schemas/Project"
"301":
$ref: "#/components/responses/MovedPermanently"
+ "400":
+ $ref: "#/components/responses/BadRequest"
+ "404":
+ $ref: "#/components/responses/NotFound"
/users/{username}/liked-projects:
get:
@@ -2074,6 +2164,10 @@ paths:
$ref: "#/components/schemas/Project"
"301":
$ref: "#/components/responses/MovedPermanently"
+ "400":
+ $ref: "#/components/responses/BadRequest"
+ "404":
+ $ref: "#/components/responses/NotFound"
/users/{username}/assets:
get:
@@ -2147,6 +2241,10 @@ paths:
$ref: "#/components/schemas/Asset"
"301":
$ref: "#/components/responses/MovedPermanently"
+ "400":
+ $ref: "#/components/responses/BadRequest"
+ "404":
+ $ref: "#/components/responses/NotFound"
/users/{username}/courses:
get:
@@ -2202,6 +2300,10 @@ paths:
$ref: "#/components/schemas/Course"
"301":
$ref: "#/components/responses/MovedPermanently"
+ "400":
+ $ref: "#/components/responses/BadRequest"
+ "404":
+ $ref: "#/components/responses/NotFound"
/users/{username}/course-series:
get:
@@ -2252,6 +2354,10 @@ paths:
$ref: "#/components/schemas/CourseSeries"
"301":
$ref: "#/components/responses/MovedPermanently"
+ "400":
+ $ref: "#/components/responses/BadRequest"
+ "404":
+ $ref: "#/components/responses/NotFound"
/projects:
get:
@@ -2262,9 +2368,12 @@ paths:
description: |
Retrieve a list of projects visible to the request.
- Anonymous requests return public projects. Authenticated requests return public projects and the authenticated
- user's own projects when no visibility filter is provided. A non-public visibility filter requires
- authentication and is scoped to the authenticated user's own projects.
+ Visibility rules:
+
+ - Anonymous requests return public projects
+ - Authenticated requests return public projects and the authenticated user's own projects when no visibility
+ filter is provided
+ - A non-public visibility filter requires authentication and is scoped to the authenticated user's own projects
security:
- {}
- bearerAuth: []
@@ -2359,6 +2468,8 @@ paths:
type: array
items:
$ref: "#/components/schemas/Project"
+ "400":
+ $ref: "#/components/responses/BadRequest"
"401":
$ref: "#/components/responses/Unauthorized"
@@ -2447,6 +2558,8 @@ paths:
application/json:
schema:
$ref: "#/components/schemas/Project"
+ "400":
+ $ref: "#/components/responses/BadRequest"
"401":
$ref: "#/components/responses/Unauthorized"
"409":
@@ -2563,6 +2676,8 @@ paths:
$ref: "#/components/schemas/ProjectRelease"
"301":
$ref: "#/components/responses/MovedPermanently"
+ "400":
+ $ref: "#/components/responses/BadRequest"
"401":
$ref: "#/components/responses/Unauthorized"
post:
@@ -2616,19 +2731,12 @@ paths:
application/json:
schema:
$ref: "#/components/schemas/ProjectRelease"
+ "400":
+ $ref: "#/components/responses/BadRequest"
"401":
$ref: "#/components/responses/Unauthorized"
"409":
- description: |
- Returned when the project path references a moved project.
-
- The response includes a `canonical` payload for the project route.
-
- Clients may update the request and resubmit it explicitly.
- content:
- application/json:
- schema:
- $ref: "#/components/schemas/MovedResourceError"
+ $ref: "#/components/responses/ResourceMoved"
/projects/{owner}/{project}/releases/{release}:
get:
@@ -2680,9 +2788,12 @@ paths:
description: |
Retrieve a list of assets visible to the request.
- Anonymous requests return public assets. Authenticated requests return public assets and the authenticated
- user's own assets when no visibility filter is provided. A non-public visibility filter requires authentication
- and is scoped to the authenticated user's own assets.
+ Visibility rules:
+
+ - Anonymous requests return public assets
+ - Authenticated requests return public assets and the authenticated user's own assets when no visibility filter
+ is provided
+ - A non-public visibility filter requires authentication and is scoped to the authenticated user's own assets
security:
- {}
- bearerAuth: []
@@ -2747,6 +2858,8 @@ paths:
type: array
items:
$ref: "#/components/schemas/Asset"
+ "400":
+ $ref: "#/components/responses/BadRequest"
"401":
$ref: "#/components/responses/Unauthorized"
@@ -2826,10 +2939,12 @@ paths:
application/json:
schema:
$ref: "#/components/schemas/Asset"
+ "400":
+ $ref: "#/components/responses/BadRequest"
"401":
$ref: "#/components/responses/Unauthorized"
"403":
- description: Insufficient permissions to perform this operation.
+ $ref: "#/components/responses/Forbidden"
delete:
operationId: deleteAsset
tags:
@@ -2897,6 +3012,8 @@ paths:
type: array
items:
$ref: "#/components/schemas/Course"
+ "400":
+ $ref: "#/components/responses/BadRequest"
/courses/{courseID}:
get:
@@ -2922,6 +3039,8 @@ paths:
application/json:
schema:
$ref: "#/components/schemas/Course"
+ "404":
+ $ref: "#/components/responses/NotFound"
patch:
operationId: updateCourse
tags:
@@ -2965,10 +3084,12 @@ paths:
application/json:
schema:
$ref: "#/components/schemas/Course"
+ "400":
+ $ref: "#/components/responses/BadRequest"
"401":
$ref: "#/components/responses/Unauthorized"
"403":
- description: Insufficient permissions to perform this operation.
+ $ref: "#/components/responses/Forbidden"
delete:
operationId: deleteCourse
tags:
@@ -2993,7 +3114,7 @@ paths:
"401":
$ref: "#/components/responses/Unauthorized"
"403":
- description: Insufficient permissions to perform this operation.
+ $ref: "#/components/responses/Forbidden"
/course-series:
get:
@@ -3038,6 +3159,8 @@ paths:
type: array
items:
$ref: "#/components/schemas/CourseSeries"
+ "400":
+ $ref: "#/components/responses/BadRequest"
/course-series/{courseSeriesID}:
get:
@@ -3063,6 +3186,8 @@ paths:
application/json:
schema:
$ref: "#/components/schemas/CourseSeries"
+ "404":
+ $ref: "#/components/responses/NotFound"
patch:
operationId: updateCourseSeries
tags:
@@ -3106,10 +3231,12 @@ paths:
application/json:
schema:
$ref: "#/components/schemas/CourseSeries"
+ "400":
+ $ref: "#/components/responses/BadRequest"
"401":
$ref: "#/components/responses/Unauthorized"
"403":
- description: Insufficient permissions to perform this operation.
+ $ref: "#/components/responses/Forbidden"
delete:
operationId: deleteCourseSeries
tags:
@@ -3134,7 +3261,7 @@ paths:
"401":
$ref: "#/components/responses/Unauthorized"
"403":
- description: Insufficient permissions to perform this operation.
+ $ref: "#/components/responses/Forbidden"
/copilot/messages:
post:
@@ -3164,7 +3291,8 @@ paths:
- Each message consumes 1 quota from the authenticated user's allowance.
- Per-user short-window rate limits also apply to prevent bursts. Hitting them returns 429 with `Retry-After`.
- Long-window quota limits vary based on the authenticated user's plan.
- - When the long-window quota limit is reached, the 403 response includes a `Retry-After` header with the wait time in seconds.
+ - When the long-window quota limit is reached, the 403 response includes a `Retry-After` header with the wait
+ time in seconds.
requestBody:
required: true
content:
@@ -3181,7 +3309,7 @@ paths:
text/event-stream:
schema:
type: string
- description: Server-Sent Events stream containing `text_delta`, `tool_call_delta`, `done`, and `error` events.
+ description: SSE stream containing `text_delta`, `tool_call_delta`, `done`, and `error` events.
examples:
textOnly:
summary: Text-only assistant response
@@ -3210,22 +3338,14 @@ paths:
value: |
event: error
data: {"reason":"streamFailed","message":"stream failed"}
+ "400":
+ $ref: "#/components/responses/BadRequest"
"401":
$ref: "#/components/responses/Unauthorized"
"403":
- description: Insufficient permissions or quota to perform this operation.
- headers:
- Retry-After:
- description: Seconds to wait before retrying after hitting the long-window quota limit.
- schema:
- type: integer
+ $ref: "#/components/responses/ForbiddenOrQuotaExceeded"
"429":
- description: Too many requests to perform this operation.
- headers:
- Retry-After:
- description: Seconds to wait before retrying after hitting the short-window rate limit.
- schema:
- type: integer
+ $ref: "#/components/responses/RateLimitExceeded"
/ai-interaction/turns:
post:
@@ -3241,7 +3361,8 @@ paths:
- Each turn consumes 1 quota from the authenticated user's AI interaction turn allowance.
- Per-user short-window rate limits also apply to prevent bursts. Hitting them returns 429 with `Retry-After`.
- Long-window quota limits vary based on the authenticated user's plan.
- - When the long-window quota limit is reached, the 403 response includes a `Retry-After` header with the wait time in seconds.
+ - When the long-window quota limit is reached, the 403 response includes a `Retry-After` header with the wait
+ time in seconds.
requestBody:
required: true
content:
@@ -3366,8 +3487,11 @@ paths:
description: |
Current turn number in a multi-turn interaction sequence.
- A value of 0 means this is the initial turn from user input. Values greater than 0 indicate
- continuation turns where the AI continues the current interaction sequence based on command outcomes.
+ Turn values:
+
+ - 0 means this is the initial turn from user input
+ - Values greater than 0 indicate continuation turns where the AI continues the current interaction
+ sequence based on command outcomes
type: integer
format: int32
minimum: 0
@@ -3402,22 +3526,14 @@ paths:
- Row: 1
Col: 1
Result: ""
+ "400":
+ $ref: "#/components/responses/BadRequest"
"401":
$ref: "#/components/responses/Unauthorized"
"403":
- description: Insufficient permissions or quota to perform this operation.
- headers:
- Retry-After:
- description: Seconds to wait before retrying after hitting the long-window quota limit.
- schema:
- type: integer
+ $ref: "#/components/responses/ForbiddenOrQuotaExceeded"
"429":
- description: Too many requests to perform this operation.
- headers:
- Retry-After:
- description: Seconds to wait before retrying after hitting the short-window rate limit.
- schema:
- type: integer
+ $ref: "#/components/responses/RateLimitExceeded"
/ai-interaction/archives:
post:
@@ -3433,7 +3549,8 @@ paths:
- Each archive request consumes 1 quota from the authenticated user's AI interaction archive allowance.
- Per-user short-window rate limits also apply to prevent bursts. Hitting them returns 429 with `Retry-After`.
- Long-window quota limits vary based on the authenticated user's plan.
- - When the long-window quota limit is reached, the 403 response includes a `Retry-After` header with the wait time in seconds.
+ - When the long-window quota limit is reached, the 403 response includes a `Retry-After` header with the wait
+ time in seconds.
requestBody:
required: true
content:
@@ -3472,22 +3589,14 @@ paths:
type: string
examples:
- "Complete conversation summary including new turns..."
+ "400":
+ $ref: "#/components/responses/BadRequest"
"401":
$ref: "#/components/responses/Unauthorized"
"403":
- description: Insufficient permissions or quota to perform this operation.
- headers:
- Retry-After:
- description: Seconds to wait before retrying after hitting the long-window quota limit.
- schema:
- type: integer
+ $ref: "#/components/responses/ForbiddenOrQuotaExceeded"
"429":
- description: Too many requests to perform this operation.
- headers:
- Retry-After:
- description: Seconds to wait before retrying after hitting the short-window rate limit.
- schema:
- type: integer
+ $ref: "#/components/responses/RateLimitExceeded"
/aigc/tasks:
post:
@@ -3499,8 +3608,7 @@ paths:
Create an asynchronous AIGC task for resource-intensive generation and media-processing operations such as image
generation, video generation, background removal, and video frame extraction.
- Task-based generation and media-processing operations are processed asynchronously. Use the returned task ID to
- poll for status via `GET /aigc/tasks/{taskID}` or subscribe to real-time updates via
+ Use the returned task ID to poll for status via `GET /aigc/tasks/{taskID}` or subscribe to real-time updates via
`GET /aigc/tasks/{taskID}/events`.
Supported task types:
@@ -3624,7 +3732,7 @@ paths:
- 0
- 1500
duration:
- description: Duration in milliseconds of the segment to extract frames from. Precision is 100ms.
+ description: Segment extraction duration in milliseconds. Precision is 100ms.
type: integer
minimum: 0
multipleOf: 100
@@ -3684,23 +3792,13 @@ paths:
schema:
$ref: "#/components/schemas/AIGCTask"
"400":
- description: Invalid task type or parameters.
+ $ref: "#/components/responses/BadRequest"
"401":
$ref: "#/components/responses/Unauthorized"
"403":
- description: Insufficient permissions or quota.
- headers:
- Retry-After:
- description: Seconds to wait before retrying after hitting the long-window quota limit.
- schema:
- type: integer
+ $ref: "#/components/responses/ForbiddenOrQuotaExceeded"
"429":
- description: Too many requests.
- headers:
- Retry-After:
- description: Seconds to wait before retrying after hitting the short-window rate limit.
- schema:
- type: integer
+ $ref: "#/components/responses/RateLimitExceeded"
/aigc/tasks/{taskID}:
get:
@@ -3730,7 +3828,7 @@ paths:
"401":
$ref: "#/components/responses/Unauthorized"
"404":
- description: Task not found.
+ $ref: "#/components/responses/NotFound"
/aigc/tasks/{taskID}/events:
get:
@@ -3828,7 +3926,7 @@ paths:
"401":
$ref: "#/components/responses/Unauthorized"
"404":
- description: Task not found.
+ $ref: "#/components/responses/NotFound"
/aigc/tasks/{taskID}/cancellation:
put:
@@ -3839,9 +3937,6 @@ paths:
description: |
Cancel a pending or processing AIGC task.
- If subscribed via `GET /aigc/tasks/{taskID}/events`, a `cancelling` event will be emitted when cancellation
- begins, followed by a `cancelled` event when complete.
-
Cancellation rules:
| Current Status | Result |
@@ -3857,6 +3952,9 @@ paths:
- Tasks cancelled from `pending` status receive a full quota refund.
- Tasks cancelled from `processing` status do not receive a refund because resources are already consumed.
+
+ If subscribed via `GET /aigc/tasks/{taskID}/events`, a `cancelling` event will be emitted when cancellation
+ begins, followed by a `cancelled` event when complete.
parameters:
- name: taskID
description: The task ID to cancel.
@@ -3874,9 +3972,9 @@ paths:
"401":
$ref: "#/components/responses/Unauthorized"
"404":
- description: Task not found.
+ $ref: "#/components/responses/NotFound"
"409":
- description: Task cannot be cancelled because it has already completed or failed.
+ $ref: "#/components/responses/Conflict"
/aigc/project-descriptions:
post:
@@ -3885,15 +3983,16 @@ paths:
- AIGC
summary: Generate project description
description: |
- Generate an AI-powered descriptive summary of a game from the player's perspective based on provided game content
- such as spx source code and project structure.
+ Generate an AI-powered descriptive summary of a game from the player's perspective based on provided game
+ content such as spx source code and project structure.
Quota and rate limits:
- Each request consumes 1 quota from the authenticated user's AI description allowance.
- Per-user short-window rate limits also apply to prevent bursts. Hitting them returns 429 with `Retry-After`.
- Quota limits vary based on the authenticated user's plan.
- - When the long-window quota limit is reached, the 403 response includes a `Retry-After` header with the wait time in seconds.
+ - When the long-window quota limit is reached, the 403 response includes a `Retry-After` header with the wait
+ time in seconds.
requestBody:
required: true
content:
@@ -3904,7 +4003,7 @@ paths:
- content
properties:
content:
- description: The game content to generate a description for, such as spx source code or project structure.
+ description: Game content to summarize, such as spx source code or project structure.
type: string
minLength: 1
maxLength: 150000
@@ -3948,26 +4047,18 @@ paths:
examples:
- |
This is a Tic-Tac-Toe game played on a 3x3 grid. The player uses `X` marks while the AI opponent
- uses `O` marks. Players take turns placing their marks in empty squares, with the goal of getting
- three marks in a row horizontally, vertically, or diagonally. The game supports mouse click
- interaction. Click on an empty square to place your mark. The game ends when either player
+ uses `O` marks. Players take turns placing their marks in empty squares, with the goal of
+ getting three marks in a row horizontally, vertically, or diagonally. The game supports mouse
+ click interaction. Click on an empty square to place your mark. The game ends when either player
achieves three in a row or the board is completely filled.
+ "400":
+ $ref: "#/components/responses/BadRequest"
"401":
$ref: "#/components/responses/Unauthorized"
"403":
- description: Insufficient permissions or quota to perform this operation.
- headers:
- Retry-After:
- description: Seconds to wait before retrying after hitting the long-window quota limit.
- schema:
- type: integer
+ $ref: "#/components/responses/ForbiddenOrQuotaExceeded"
"429":
- description: Too many requests to perform this operation.
- headers:
- Retry-After:
- description: Seconds to wait before retrying after hitting the short-window rate limit.
- schema:
- type: integer
+ $ref: "#/components/responses/RateLimitExceeded"
/aigc/asset-descriptions:
post:
@@ -3979,13 +4070,15 @@ paths:
Generate a description for an asset using AI based on the provided text prompt and image input.
This endpoint accepts multimodal input to generate a contextual description suitable for embedding and search
- operations. The text prompt typically includes the asset's display name and additional context about how the
- description will be used.
+ operations.
+
+ The text prompt typically includes the asset's display name and additional context about how the description
+ will be used.
Image requirements:
- Format: PNG only (`image/png`)
- - Maximum image size: 5 MiB (5242880 bytes) after decoding the base64 content
+ - Maximum image size: 5 MiB after decoding the base64 content
- Images must be provided as base64-encoded data URLs
- Other formats must be converted to PNG before sending
@@ -4041,23 +4134,13 @@ paths:
examples:
- "A powerful rotating column of air extending from a thunderstorm to the ground, characterized by its distinctive funnel shape and destructive force."
"400":
- description: Invalid request parameters.
+ $ref: "#/components/responses/BadRequest"
"401":
$ref: "#/components/responses/Unauthorized"
"403":
- description: Insufficient permissions or quota to perform this operation.
- headers:
- Retry-After:
- description: Seconds to wait before retrying after hitting the long-window quota limit.
- schema:
- type: integer
+ $ref: "#/components/responses/ForbiddenOrQuotaExceeded"
"429":
- description: Too many requests to perform this operation.
- headers:
- Retry-After:
- description: Seconds to wait before retrying after hitting the short-window rate limit.
- schema:
- type: integer
+ $ref: "#/components/responses/RateLimitExceeded"
/aigc/asset-adoptions:
post:
@@ -4067,6 +4150,7 @@ paths:
summary: Adopt an AIGC-generated asset
description: |
Record that an AIGC-generated asset has been adopted.
+
The backend verifies task ownership and file provenance and may publish the adopted asset to the public library.
requestBody:
required: true
@@ -4119,11 +4203,11 @@ paths:
"204":
description: Asset adoption recorded.
"400":
- description: Invalid parameters.
+ $ref: "#/components/responses/BadRequest"
"401":
$ref: "#/components/responses/Unauthorized"
"403":
- description: Insufficient permissions for given tasks.
+ $ref: "#/components/responses/Forbidden"
/aigc/asset-settings-enrichments:
post:
@@ -4215,8 +4299,9 @@ paths:
lang:
description: |
Language the AI should use for all generated text.
- When provided, the output strictly follows this language regardless of the input language.
- When omitted, the AI infers language from the user input.
+
+ - When provided, the output strictly follows this language regardless of the input language
+ - When omitted, the AI infers language from the user input
type: string
enum:
- en
@@ -4232,22 +4317,14 @@ paths:
- $ref: "#/components/schemas/AIGCCostumeSettings"
- $ref: "#/components/schemas/AIGCAnimationSettings"
- $ref: "#/components/schemas/AIGCBackdropSettings"
+ "400":
+ $ref: "#/components/responses/BadRequest"
"401":
$ref: "#/components/responses/Unauthorized"
"403":
- description: Insufficient permissions or quota.
- headers:
- Retry-After:
- description: Seconds to wait before retrying after hitting the long-window quota limit.
- schema:
- type: integer
+ $ref: "#/components/responses/ForbiddenOrQuotaExceeded"
"429":
- description: Too many requests.
- headers:
- Retry-After:
- description: Seconds to wait before retrying after hitting the short-window rate limit.
- schema:
- type: integer
+ $ref: "#/components/responses/RateLimitExceeded"
/aigc/sprite-content-settings:
post:
@@ -4276,8 +4353,9 @@ paths:
lang:
description: |
Language the AI should use for all generated text.
- When provided, the output strictly follows this language regardless of the input language.
- When omitted, the AI infers language from the user input.
+
+ - When provided, the output strictly follows this language regardless of the input language
+ - When omitted, the AI infers language from the user input
type: string
enum:
- en
@@ -4307,8 +4385,12 @@ paths:
animationBindings:
description: |
Recommended mapping from sprite state enum values to animation names.
- Keys are sprite state enum values; values are animation name strings that should match the `name`
- field from the animations array, omitted if no animation is bound to that state.
+
+ Keys and values:
+
+ - Keys are sprite state enum values
+ - Values are animation name strings that should match the `name` field from the animations array
+ - Omit a state when no animation is bound to it
type: object
additionalProperties: false
properties:
@@ -4321,22 +4403,14 @@ paths:
example:
default: "idle"
step: "walk"
+ "400":
+ $ref: "#/components/responses/BadRequest"
"401":
$ref: "#/components/responses/Unauthorized"
"403":
- description: Insufficient permissions or quota.
- headers:
- Retry-After:
- description: Seconds to wait before retrying after hitting the long-window quota limit.
- schema:
- type: integer
+ $ref: "#/components/responses/ForbiddenOrQuotaExceeded"
"429":
- description: Too many requests.
- headers:
- Retry-After:
- description: Seconds to wait before retrying after hitting the short-window rate limit.
- schema:
- type: integer
+ $ref: "#/components/responses/RateLimitExceeded"
/upload-sessions:
post:
@@ -4404,6 +4478,8 @@ paths:
format: uri
examples:
- kodo://xbuilder-usercontent-test/files/FjgMMuSaAsRWx1t7UAQnQ5r4YsAe-195: https://xbuilder-usercontent-test.gopluscdn.com/files/FjgMMuSaAsRWx1t7UAQnQ5r4YsAe-195?e=1727658000&token=t_6AOOkCdDu4m7fPleblcK0gMBZfbGQzeEIVt5Au:EMJdLqcCWrqQ5pRd01diOv7nhQw=
+ "400":
+ $ref: "#/components/responses/BadRequest"
/project-conversions:
post:
@@ -4432,7 +4508,7 @@ paths:
description: |
Scratch project file, such as .sb2, .sb3, or project zip. Form field name must be `file`.
- Maximum size is 64 MiB (67108864 bytes).
+ Maximum size is 64 MiB.
type: string
format: binary
responses:
@@ -4446,6 +4522,12 @@ paths:
examples:
xbpFile:
summary: Example XBP zip file
+ "400":
+ $ref: "#/components/responses/BadRequest"
+ "413":
+ $ref: "#/components/responses/ContentTooLarge"
+ "501":
+ $ref: "#/components/responses/UnsupportedScratchFeature"
/admin/account/users:
get:
@@ -4497,10 +4579,12 @@ paths:
type: array
items:
$ref: "#/components/schemas/AccountUser"
+ "400":
+ $ref: "#/components/responses/BadRequest"
"401":
$ref: "#/components/responses/Unauthorized"
"403":
- description: Insufficient permissions to perform this operation.
+ $ref: "#/components/responses/Forbidden"
post:
operationId: createAdminAccountUser
tags:
@@ -4536,10 +4620,12 @@ paths:
application/json:
schema:
$ref: "#/components/schemas/AccountUser"
+ "400":
+ $ref: "#/components/responses/BadRequest"
"401":
$ref: "#/components/responses/Unauthorized"
"403":
- description: Insufficient permissions to perform this operation.
+ $ref: "#/components/responses/Forbidden"
/admin/account/users/{userID}:
get:
@@ -4565,12 +4651,14 @@ paths:
application/json:
schema:
$ref: "#/components/schemas/AccountUser"
+ "400":
+ $ref: "#/components/responses/BadRequest"
"401":
$ref: "#/components/responses/Unauthorized"
"403":
- description: Insufficient permissions to perform this operation.
+ $ref: "#/components/responses/Forbidden"
"404":
- description: Account user not found.
+ $ref: "#/components/responses/NotFound"
patch:
operationId: updateAdminAccountUser
tags:
@@ -4604,12 +4692,14 @@ paths:
application/json:
schema:
$ref: "#/components/schemas/AccountUser"
+ "400":
+ $ref: "#/components/responses/BadRequest"
"401":
$ref: "#/components/responses/Unauthorized"
"403":
- description: Insufficient permissions to perform this operation.
+ $ref: "#/components/responses/Forbidden"
"404":
- description: Account user not found.
+ $ref: "#/components/responses/NotFound"
/admin/account/users/{userID}/avatar:
put:
@@ -4641,7 +4731,7 @@ paths:
description: |
Avatar image file.
- Maximum size is 5 MiB (5242880 bytes).
+ Maximum size is 5 MiB.
type: string
format: binary
encoding:
@@ -4651,17 +4741,17 @@ paths:
"204":
description: Account user avatar updated.
"400":
- description: Invalid request parameters.
+ $ref: "#/components/responses/BadRequest"
"401":
$ref: "#/components/responses/Unauthorized"
"403":
- description: Insufficient permissions to perform this operation.
+ $ref: "#/components/responses/Forbidden"
"404":
- description: Account user not found.
+ $ref: "#/components/responses/NotFound"
"413":
- description: Avatar image file is too large.
+ $ref: "#/components/responses/ContentTooLarge"
"415":
- description: Avatar image file type is not supported.
+ $ref: "#/components/responses/UnsupportedMediaType"
/admin/account/users/{userID}/password:
put:
@@ -4697,12 +4787,14 @@ paths:
responses:
"204":
description: Password credential set.
+ "400":
+ $ref: "#/components/responses/BadRequest"
"401":
$ref: "#/components/responses/Unauthorized"
"403":
- description: Insufficient permissions to perform this operation.
+ $ref: "#/components/responses/Forbidden"
"404":
- description: Account user not found.
+ $ref: "#/components/responses/NotFound"
delete:
operationId: deleteAdminAccountUserPassword
tags:
@@ -4722,12 +4814,14 @@ paths:
responses:
"204":
description: Password credential deleted.
+ "400":
+ $ref: "#/components/responses/BadRequest"
"401":
$ref: "#/components/responses/Unauthorized"
"403":
- description: Insufficient permissions to perform this operation.
+ $ref: "#/components/responses/Forbidden"
"404":
- description: Account user not found.
+ $ref: "#/components/responses/NotFound"
/admin/account/users/{userID}/identities:
get:
@@ -4765,12 +4859,14 @@ paths:
type: array
items:
$ref: "#/components/schemas/AccountUserIdentity"
+ "400":
+ $ref: "#/components/responses/BadRequest"
"401":
$ref: "#/components/responses/Unauthorized"
"403":
- description: Insufficient permissions to perform this operation.
+ $ref: "#/components/responses/Forbidden"
"404":
- description: Account user not found.
+ $ref: "#/components/responses/NotFound"
/admin/account/users/{userID}/identities/{identityID}:
delete:
@@ -4798,12 +4894,14 @@ paths:
responses:
"204":
description: Account user identity deleted.
+ "400":
+ $ref: "#/components/responses/BadRequest"
"401":
$ref: "#/components/responses/Unauthorized"
"403":
- description: Insufficient permissions to perform this operation.
+ $ref: "#/components/responses/Forbidden"
"404":
- description: Account user or identity not found.
+ $ref: "#/components/responses/NotFound"
/admin/account/users/{userID}/sessions:
get:
@@ -4841,12 +4939,14 @@ paths:
type: array
items:
$ref: "#/components/schemas/AccountSession"
+ "400":
+ $ref: "#/components/responses/BadRequest"
"401":
$ref: "#/components/responses/Unauthorized"
"403":
- description: Insufficient permissions to perform this operation.
+ $ref: "#/components/responses/Forbidden"
"404":
- description: Account user not found.
+ $ref: "#/components/responses/NotFound"
delete:
operationId: deleteAdminAccountUserSessions
tags:
@@ -4866,12 +4966,14 @@ paths:
responses:
"204":
description: Account user sessions deleted.
+ "400":
+ $ref: "#/components/responses/BadRequest"
"401":
$ref: "#/components/responses/Unauthorized"
"403":
- description: Insufficient permissions to perform this operation.
+ $ref: "#/components/responses/Forbidden"
"404":
- description: Account user not found.
+ $ref: "#/components/responses/NotFound"
/admin/account/users/{userID}/app-grants:
get:
@@ -4922,12 +5024,14 @@ paths:
type: array
items:
$ref: "#/components/schemas/AccountAppGrant"
+ "400":
+ $ref: "#/components/responses/BadRequest"
"401":
$ref: "#/components/responses/Unauthorized"
"403":
- description: Insufficient permissions to perform this operation.
+ $ref: "#/components/responses/Forbidden"
"404":
- description: Account user not found.
+ $ref: "#/components/responses/NotFound"
/admin/account/app-grants/{appGrantID}:
get:
@@ -4953,12 +5057,14 @@ paths:
application/json:
schema:
$ref: "#/components/schemas/AccountAppGrant"
+ "400":
+ $ref: "#/components/responses/BadRequest"
"401":
$ref: "#/components/responses/Unauthorized"
"403":
- description: Insufficient permissions to perform this operation.
+ $ref: "#/components/responses/Forbidden"
"404":
- description: Account app grant not found.
+ $ref: "#/components/responses/NotFound"
/admin/account/app-grants/{appGrantID}/tokens:
get:
@@ -5014,12 +5120,14 @@ paths:
type: array
items:
$ref: "#/components/schemas/AccountAppToken"
+ "400":
+ $ref: "#/components/responses/BadRequest"
"401":
$ref: "#/components/responses/Unauthorized"
"403":
- description: Insufficient permissions to perform this operation.
+ $ref: "#/components/responses/Forbidden"
"404":
- description: Account app grant not found.
+ $ref: "#/components/responses/NotFound"
post:
operationId: createAdminAccountAppGrantToken
tags:
@@ -5028,10 +5136,12 @@ paths:
description: |
Create an Account-issued OAuth token associated with an account app grant.
+ The token scope is an Account OAuth scope inherited from the app grant.
+
Currently, this endpoint creates access tokens only. The created token is not issued with a refresh token and
- cannot be refreshed. The token value is only returned once in the creation response.
+ cannot be refreshed.
- The token scope is an Account OAuth scope inherited from the app grant.
+ The token value is only returned once in the creation response.
Requires the `accountAdmin` role.
parameters:
@@ -5055,13 +5165,13 @@ paths:
schema:
$ref: "#/components/schemas/CreatedAccountAppToken"
"400":
- description: Invalid request parameters.
+ $ref: "#/components/responses/BadRequest"
"401":
$ref: "#/components/responses/Unauthorized"
"403":
- description: Insufficient permissions to perform this operation.
+ $ref: "#/components/responses/Forbidden"
"404":
- description: Account app grant not found.
+ $ref: "#/components/responses/NotFound"
/admin/account/app-grants/{appGrantID}/tokens/{tokenID}:
delete:
@@ -5073,7 +5183,7 @@ paths:
Revoke an Account-issued OAuth token associated with an account app grant.
Revocation follows the existing Account OAuth token semantics. Revoking a refresh token follows refresh-token
- rotation semantics; revoking an access token revokes that access token.
+ rotation semantics, and revoking an access token revokes that access token.
Requires the `accountAdmin` role.
parameters:
@@ -5092,12 +5202,14 @@ paths:
responses:
"204":
description: Account app grant token revoked.
+ "400":
+ $ref: "#/components/responses/BadRequest"
"401":
$ref: "#/components/responses/Unauthorized"
"403":
- description: Insufficient permissions to perform this operation.
+ $ref: "#/components/responses/Forbidden"
"404":
- description: Account app grant or token not found.
+ $ref: "#/components/responses/NotFound"
/admin/account/sessions/{sessionID}:
delete:
@@ -5119,12 +5231,14 @@ paths:
responses:
"204":
description: Account session deleted.
+ "400":
+ $ref: "#/components/responses/BadRequest"
"401":
$ref: "#/components/responses/Unauthorized"
"403":
- description: Insufficient permissions to perform this operation.
+ $ref: "#/components/responses/Forbidden"
"404":
- description: Account session not found.
+ $ref: "#/components/responses/NotFound"
/admin/account/apps:
get:
@@ -5168,10 +5282,12 @@ paths:
type: array
items:
$ref: "#/components/schemas/AccountApp"
+ "400":
+ $ref: "#/components/responses/BadRequest"
"401":
$ref: "#/components/responses/Unauthorized"
"403":
- description: Insufficient permissions to perform this operation.
+ $ref: "#/components/responses/Forbidden"
post:
operationId: createAdminAccountApp
tags:
@@ -5210,10 +5326,12 @@ paths:
application/json:
schema:
$ref: "#/components/schemas/AccountApp"
+ "400":
+ $ref: "#/components/responses/BadRequest"
"401":
$ref: "#/components/responses/Unauthorized"
"403":
- description: Insufficient permissions to perform this operation.
+ $ref: "#/components/responses/Forbidden"
/admin/account/apps/{appID}:
get:
@@ -5239,12 +5357,14 @@ paths:
application/json:
schema:
$ref: "#/components/schemas/AccountApp"
+ "400":
+ $ref: "#/components/responses/BadRequest"
"401":
$ref: "#/components/responses/Unauthorized"
"403":
- description: Insufficient permissions to perform this operation.
+ $ref: "#/components/responses/Forbidden"
"404":
- description: Account app not found.
+ $ref: "#/components/responses/NotFound"
patch:
operationId: updateAdminAccountApp
tags:
@@ -5284,12 +5404,14 @@ paths:
application/json:
schema:
$ref: "#/components/schemas/AccountApp"
+ "400":
+ $ref: "#/components/responses/BadRequest"
"401":
$ref: "#/components/responses/Unauthorized"
"403":
- description: Insufficient permissions to perform this operation.
+ $ref: "#/components/responses/Forbidden"
"404":
- description: Account app not found.
+ $ref: "#/components/responses/NotFound"
/admin/account/apps/{appID}/secrets:
get:
@@ -5327,12 +5449,14 @@ paths:
type: array
items:
$ref: "#/components/schemas/AccountAppSecret"
+ "400":
+ $ref: "#/components/responses/BadRequest"
"401":
$ref: "#/components/responses/Unauthorized"
"403":
- description: Insufficient permissions to perform this operation.
+ $ref: "#/components/responses/Forbidden"
"404":
- description: Account app not found.
+ $ref: "#/components/responses/NotFound"
post:
operationId: createAdminAccountAppSecret
tags:
@@ -5367,12 +5491,14 @@ paths:
application/json:
schema:
$ref: "#/components/schemas/CreatedAccountAppSecret"
+ "400":
+ $ref: "#/components/responses/BadRequest"
"401":
$ref: "#/components/responses/Unauthorized"
"403":
- description: Insufficient permissions to perform this operation.
+ $ref: "#/components/responses/Forbidden"
"404":
- description: Account app not found.
+ $ref: "#/components/responses/NotFound"
/admin/account/apps/{appID}/secrets/{secretID}:
delete:
@@ -5400,12 +5526,14 @@ paths:
responses:
"204":
description: Account app secret deleted.
+ "400":
+ $ref: "#/components/responses/BadRequest"
"401":
$ref: "#/components/responses/Unauthorized"
"403":
- description: Insufficient permissions to perform this operation.
+ $ref: "#/components/responses/Forbidden"
"404":
- description: Account app or secret not found.
+ $ref: "#/components/responses/NotFound"
/admin/authorization/users/{userID}:
get:
@@ -5431,12 +5559,14 @@ paths:
application/json:
schema:
$ref: "#/components/schemas/UserAuthorization"
+ "400":
+ $ref: "#/components/responses/BadRequest"
"401":
$ref: "#/components/responses/Unauthorized"
"403":
- description: Insufficient permissions to perform this operation.
+ $ref: "#/components/responses/Forbidden"
"404":
- description: User authorization not found.
+ $ref: "#/components/responses/NotFound"
patch:
operationId: updateAdminUserAuthorization
tags:
@@ -5472,12 +5602,14 @@ paths:
application/json:
schema:
$ref: "#/components/schemas/UserAuthorization"
+ "400":
+ $ref: "#/components/responses/BadRequest"
"401":
$ref: "#/components/responses/Unauthorized"
"403":
- description: Insufficient permissions to perform this operation.
+ $ref: "#/components/responses/Forbidden"
"404":
- description: User authorization not found.
+ $ref: "#/components/responses/NotFound"
/admin/audit-logs:
get:
@@ -5532,10 +5664,12 @@ paths:
type: array
items:
$ref: "#/components/schemas/AuditLog"
+ "400":
+ $ref: "#/components/responses/BadRequest"
"401":
$ref: "#/components/responses/Unauthorized"
"403":
- description: Insufficient permissions to perform this operation.
+ $ref: "#/components/responses/Forbidden"
components:
securitySchemes:
@@ -5584,21 +5718,231 @@ components:
example: no-cache
ResourceMoved:
description: |
- Requested resource moved to its canonical route.
+ Requested resource moved to its canonical route. Returned on non-`GET` and non-`HEAD` requests.
- Returned on non-`GET` and non-`HEAD` requests.
+ The response includes a `canonical` payload with the canonical route. Clients may update the request and
+ resubmit it explicitly.
+ content:
+ application/json:
+ schema:
+ $ref: "#/components/schemas/MovedResourceError"
+ BadRequest:
+ description: Invalid request syntax, parameters, or body.
+ content:
+ application/json:
+ schema:
+ $ref: "#/components/schemas/APIError"
+ examples:
+ invalidArgs:
+ value:
+ code: 40001
+ msg: Invalid args
+ BadRequestForIdentityProviderFormPostCallback:
+ description: |
+ Invalid identity provider form-post callback request.
- The response includes a `canonical` payload with the canonical route.
+ Response body shapes:
- Clients may update the request and resubmit it explicitly.
+ - `APIError` for path, provider error, and callback parameter validation failures
+ - `OAuthError` for malformed form bodies parsed by the OAuth form parser
content:
application/json:
schema:
- $ref: "#/components/schemas/MovedResourceError"
+ oneOf:
+ - $ref: "#/components/schemas/APIError"
+ - $ref: "#/components/schemas/OAuthError"
+ examples:
+ invalidCallbackRequest:
+ summary: Invalid callback request
+ value:
+ code: 40001
+ msg: invalid provider
+ invalidFormBody:
+ summary: Malformed form body
+ value:
+ error: invalid_request
+ error_description: invalid form body
Unauthorized:
- description: Unauthorized. Authentication required.
+ description: Authentication is required or the supplied bearer token is invalid.
+ headers:
+ WWW-Authenticate:
+ description: Authentication challenge.
+ schema:
+ type: string
+ examples:
+ - Bearer
+ content:
+ application/json:
+ schema:
+ $ref: "#/components/schemas/APIError"
+ examples:
+ unauthorized:
+ value:
+ code: 40100
+ msg: Unauthorized
+ Forbidden:
+ description: The authenticated principal does not have permission to perform this operation.
+ content:
+ application/json:
+ schema:
+ $ref: "#/components/schemas/APIError"
+ examples:
+ forbidden:
+ value:
+ code: 40300
+ msg: Forbidden
+ QuotaExceeded:
+ description: The authenticated user exceeded a long-window quota for this operation.
+ headers:
+ Retry-After:
+ description: Seconds to wait before retrying.
+ schema:
+ type: integer
+ format: int64
+ minimum: 1
+ content:
+ application/json:
+ schema:
+ $ref: "#/components/schemas/APIError"
+ examples:
+ quotaExceeded:
+ value:
+ code: 40301
+ msg: aigc:image quota exceeded
+ ForbiddenOrQuotaExceeded:
+ description: |
+ The authenticated principal does not have permission to perform this operation, or a long-window quota was
+ exceeded.
+
+ When `code` is `40301`, `Retry-After` is included if the server can compute a retry time.
+ headers:
+ Retry-After:
+ description: Seconds to wait before retrying after a quota failure.
+ schema:
+ type: integer
+ format: int64
+ minimum: 1
+ content:
+ application/json:
+ schema:
+ $ref: "#/components/schemas/APIError"
+ examples:
+ forbidden:
+ value:
+ code: 40300
+ msg: Forbidden
+ quotaExceeded:
+ value:
+ code: 40301
+ msg: aigc:image quota exceeded
+ NotFound:
+ description: The requested resource was not found.
+ content:
+ application/json:
+ schema:
+ $ref: "#/components/schemas/APIError"
+ examples:
+ notFound:
+ value:
+ code: 40400
+ msg: Not found
+ Conflict:
+ description: The request conflicts with the current resource state.
+ content:
+ application/json:
+ schema:
+ $ref: "#/components/schemas/APIError"
+ examples:
+ conflict:
+ value:
+ code: 40900
+ msg: Conflict
+ ContentTooLarge:
+ description: The request or uploaded content exceeds the allowed size.
+ content:
+ application/json:
+ schema:
+ $ref: "#/components/schemas/APIError"
+ examples:
+ contentTooLarge:
+ value:
+ code: 41300
+ msg: Content too large
+ UnsupportedMediaType:
+ description: The request or uploaded content type is not supported.
+ content:
+ application/json:
+ schema:
+ $ref: "#/components/schemas/APIError"
+ examples:
+ unsupportedMediaType:
+ value:
+ code: 41500
+ msg: Unsupported media type
+ TooManyRequests:
+ description: Too many requests.
+ content:
+ application/json:
+ schema:
+ $ref: "#/components/schemas/APIError"
+ examples:
+ tooManyRequests:
+ value:
+ code: 42900
+ msg: Too many requests
+ RateLimitExceeded:
+ description: The authenticated user exceeded a short-window rate limit for this operation.
+ headers:
+ Retry-After:
+ description: Seconds to wait before retrying.
+ schema:
+ type: integer
+ format: int64
+ minimum: 1
+ content:
+ application/json:
+ schema:
+ $ref: "#/components/schemas/APIError"
+ examples:
+ rateLimitExceeded:
+ value:
+ code: 42901
+ msg: aigc:image rate limit exceeded
+ InternalServerError:
+ description: An internal server error occurred.
+ content:
+ application/json:
+ schema:
+ $ref: "#/components/schemas/APIError"
+ examples:
+ internalServerError:
+ value:
+ code: 50000
+ msg: Internal server error
+ UnsupportedScratchFeature:
+ description: The uploaded Scratch project uses a feature that cannot be converted.
+ content:
+ application/json:
+ schema:
+ $ref: "#/components/schemas/APIError"
+ examples:
+ unsupportedScratchFeature:
+ value:
+ code: 50101
+ msg: Unsupported scratch feature
OAuthError:
description: OAuth error response.
+ headers:
+ Cache-Control:
+ description: OAuth error responses are not cacheable.
+ schema:
+ type: string
+ example: no-store
+ Pragma:
+ description: OAuth error responses are not cacheable by HTTP/1.0 caches.
+ schema:
+ type: string
+ example: no-cache
content:
application/json:
schema:
@@ -5606,12 +5950,22 @@ components:
OAuthInvalidClient:
description: OAuth client authentication failed.
headers:
+ Cache-Control:
+ description: OAuth error responses are not cacheable.
+ schema:
+ type: string
+ example: no-store
+ Pragma:
+ description: OAuth error responses are not cacheable by HTTP/1.0 caches.
+ schema:
+ type: string
+ example: no-cache
WWW-Authenticate:
description: Client authentication challenge.
schema:
type: string
examples:
- - Basic realm="XBuilder Account"
+ - Basic realm="XBuilder Account", error="invalid_client"
content:
application/json:
schema:
@@ -5626,29 +5980,86 @@ components:
examples:
- Bearer realm="XBuilder Account", error="insufficient_scope", scope="account:user:read"
- Bearer realm="XBuilder Account", error="insufficient_scope", scope="account:user:write"
- OAuthUnsupportedMediaType:
- description: |
- OAuth form request content type is not supported.
-
- The server returns an OAuth `invalid_request` error before reading form-body OAuth parameters.
content:
application/json:
schema:
- $ref: "#/components/schemas/OAuthError"
+ $ref: "#/components/schemas/APIError"
+ examples:
+ insufficientScope:
+ value:
+ code: 40300
+ msg: Forbidden
+ AccountForbidden:
+ description: |
+ Account request is forbidden.
+
+ Bearer-token requests may lack the required scope. Cookie-authenticated mutation requests may fail Origin
+ validation.
+ headers:
+ WWW-Authenticate:
+ description: Bearer token insufficient scope challenge, when bearer authentication was used.
+ schema:
+ type: string
+ examples:
+ - Bearer realm="XBuilder Account", error="insufficient_scope", scope="account:user:write"
+ content:
+ application/json:
+ schema:
+ $ref: "#/components/schemas/APIError"
+ examples:
+ forbidden:
+ value:
+ code: 40300
+ msg: Forbidden
+ OAuthUnsupportedMediaType:
+ description: |
+ OAuth form request content type is not supported.
+
+ The server returns an OAuth `invalid_request` error before reading form-body OAuth parameters.
+ headers:
+ Cache-Control:
+ description: OAuth error responses are not cacheable.
+ schema:
+ type: string
+ example: no-store
+ Pragma:
+ description: OAuth error responses are not cacheable by HTTP/1.0 caches.
+ schema:
+ type: string
+ example: no-cache
+ content:
+ application/json:
+ schema:
+ $ref: "#/components/schemas/OAuthError"
AccountUnauthorized:
description: |
Account authentication is required.
- The request may authenticate with an account session cookie or an OAuth bearer token. When OAuth bearer token
- authentication fails, the response includes `WWW-Authenticate`.
+ The request may authenticate with an account session cookie or an OAuth bearer token.
+
+ The response includes `WWW-Authenticate`.
+
+ Challenge values:
+
+ - Missing credentials use the generic `Bearer` challenge
+ - Invalid bearer tokens use a realm-specific `invalid_token` challenge
headers:
WWW-Authenticate:
- description: Bearer token challenge returned for OAuth bearer token authentication failures.
+ description: Bearer token challenge.
schema:
type: string
examples:
- - Bearer realm="XBuilder Account"
+ - Bearer
- Bearer realm="XBuilder Account", error="invalid_token"
+ content:
+ application/json:
+ schema:
+ $ref: "#/components/schemas/APIError"
+ examples:
+ unauthorized:
+ value:
+ code: 40100
+ msg: Unauthorized
schemas:
Model:
@@ -5680,15 +6091,33 @@ components:
examples:
- 2006-01-02T15:04:05+07:00
+ ByPage:
+ description: Paginated response wrapper.
+ type: object
+ required:
+ - total
+ - data
+ properties:
+ total:
+ description: Total number of result items in the result set.
+ type: integer
+ format: int64
+ minimum: 0
+ data:
+ description: Array of result items.
+ type: array
+ items:
+ type: object
+
MovedResourceCanonical:
description: |
Canonical route information for a moved resource.
- User routes include `path` and `username`.
+ Route fields:
- Project routes include `path`, `owner`, and `name`.
-
- Project release routes include `path`, `owner`, `name`, and `release`.
+ - User routes include `path` and `username`
+ - Project routes include `path`, `owner`, and `name`
+ - Project release routes include `path`, `owner`, `name`, and `release`
type: object
required:
- path
@@ -5721,8 +6150,74 @@ components:
examples:
- v1.2.3
+ ErrorCode:
+ description: |
+ Stable machine-readable error code for the shared `APIError` envelope.
+
+ The first three digits match the HTTP status code. Clients should branch on this field instead of parsing
+ `msg`.
+
+ | Code | HTTP status | Default msg | Meaning |
+ |------|-------------|-------------|---------|
+ | 40001 | 400 | Invalid args | Invalid request syntax, parameters, or body. |
+ | 40100 | 401 | Unauthorized | Authentication is required or invalid. |
+ | 40300 | 403 | Forbidden | The authenticated principal lacks permission. |
+ | 40301 | 403 | Quota exceeded | A long-window quota was exceeded. |
+ | 40400 | 404 | Not found | The requested resource was not found. |
+ | 40900 | 409 | Conflict | The request conflicts with current resource state. |
+ | 40901 | 409 | Resource moved | The request used a historical resource route. |
+ | 41300 | 413 | Content too large | Request or uploaded content exceeds the allowed size. |
+ | 41500 | 415 | Unsupported media type | Request or uploaded content type is not supported. |
+ | 42900 | 429 | Too many requests | Generic request throttling. |
+ | 42901 | 429 | Rate limit exceeded | A short-window rate limit was exceeded. |
+ | 50000 | 500 | Internal server error | An unexpected server-side failure occurred. |
+ | 50101 | 501 | Unsupported scratch feature | Scratch conversion hit an unsupported feature. |
+ type: integer
+ format: int32
+ enum:
+ - 40001
+ - 40100
+ - 40300
+ - 40301
+ - 40400
+ - 40900
+ - 40901
+ - 41300
+ - 41500
+ - 42900
+ - 42901
+ - 50000
+ - 50101
+ examples:
+ - 40001
+
+ APIError:
+ description: |
+ Shared error payload for most non-OAuth JSON endpoints.
+
+ `msg` is a safe, developer-facing diagnostic string. It is not localized and is not stable enough for
+ programmatic handling.
+
+ User-facing clients should map `code` to their own localized copy.
+ type: object
+ required:
+ - code
+ - msg
+ properties:
+ code:
+ $ref: "#/components/schemas/ErrorCode"
+ msg:
+ description: Safe developer-facing diagnostic message.
+ type: string
+ minLength: 1
+ examples:
+ - Invalid args
+
MovedResourceError:
- description: Error payload for a moved resource route.
+ description: |
+ Error payload for a moved resource route.
+
+ This follows the `APIError` envelope and adds `canonical` route metadata.
type: object
required:
- code
@@ -5792,11 +6287,12 @@ components:
examples:
- John Doe
avatar:
- description: Public URL or universal URL of the user's avatar image.
+ description: Public HTTP URL or Kodo universal URL of the user's avatar image.
type: string
format: uri
examples:
- https://avatars.example.com/users/10137.png
+ - kodo://xbuilder-usercontent-test/files/avatar.png
description:
description: Brief bio or description of the user.
type: string
@@ -5853,14 +6349,6 @@ components:
**This field is only present for the authenticated user's own profile.**
$ref: "#/components/schemas/UserCapabilities"
- AuthenticatedUser:
- description: Authenticated user account information.
- allOf:
- - $ref: "#/components/schemas/User"
- - type: object
- required:
- - capabilities
-
UserCapabilities:
type: object
description: User permission capabilities.
@@ -5897,6 +6385,14 @@ components:
examples:
- true
+ AuthenticatedUser:
+ description: Authenticated user account information.
+ allOf:
+ - $ref: "#/components/schemas/User"
+ - type: object
+ required:
+ - capabilities
+
AccountUser:
description: User fields exposed by XBuilder Account.
type: object
@@ -6199,6 +6695,19 @@ components:
examples:
- production
+ CreatedAccountAppSecret:
+ description: OAuth client secret created response including the one-time secret value.
+ allOf:
+ - $ref: "#/components/schemas/AccountAppSecret"
+ - type: object
+ required:
+ - value
+ properties:
+ value:
+ description: One-time app secret value.
+ type: string
+ minLength: 1
+
AccountAppGrant:
type: object
description: Authorization grant from an account user to an account app.
@@ -6369,19 +6878,6 @@ components:
examples:
- xb_at_2L5f8xQy...
- CreatedAccountAppSecret:
- description: OAuth client secret created response including the one-time secret value.
- allOf:
- - $ref: "#/components/schemas/AccountAppSecret"
- - type: object
- required:
- - value
- properties:
- value:
- description: One-time app secret value.
- type: string
- minLength: 1
-
OAuthClientID:
description: OAuth client ID of the app.
type: string
@@ -6889,7 +7385,7 @@ components:
description: Full name of the project that the release is associated with, in the format `owner/project`.
$ref: "#/components/schemas/ProjectFullName"
name:
- description: Unique name of the project release, adhering to [Semantic Versioning 2.0.0](https://semver.org/spec/v2.0.0.html).
+ description: Project release name following [Semantic Versioning 2.0.0](https://semver.org/spec/v2.0.0.html).
type: string
maxLength: 255
pattern: '^v(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$'
@@ -7248,6 +7744,49 @@ components:
content:
$ref: "#/components/schemas/CopilotMessageContent"
+ CopilotTool:
+ description: Tool available for copilot to use.
+ type: object
+ required:
+ - type
+ - function
+ properties:
+ type:
+ description: Type of the tool.
+ type: string
+ enum:
+ - function
+ examples:
+ - function
+ function:
+ type: object
+ required:
+ - name
+ properties:
+ name:
+ description: Name of the function.
+ type: string
+ maxLength: 64
+ pattern: "^[a-zA-Z0-9_-]{1,64}$"
+ examples:
+ - create_project
+ description:
+ description: Description of the function.
+ type: string
+ examples:
+ - create project
+ parameters:
+ description: JSON Schema object that describes the function parameters.
+ type: object
+ examples:
+ - type: object
+ properties:
+ name:
+ type: string
+ required:
+ - name
+ additionalProperties: false
+
CopilotMessageRequest:
description: Request payload for copilot message generation endpoints.
type: object
@@ -7429,49 +7968,6 @@ components:
examples:
- stream failed
- CopilotTool:
- description: Tool available for copilot to use.
- type: object
- required:
- - type
- - function
- properties:
- type:
- description: Type of the tool.
- type: string
- enum:
- - function
- examples:
- - function
- function:
- type: object
- required:
- - name
- properties:
- name:
- description: Name of the function.
- type: string
- maxLength: 64
- pattern: "^[a-zA-Z0-9_-]{1,64}$"
- examples:
- - create_project
- description:
- description: Description of the function.
- type: string
- examples:
- - create project
- parameters:
- description: JSON Schema object that describes the function parameters.
- type: object
- examples:
- - type: object
- properties:
- name:
- type: string
- required:
- - name
- additionalProperties: false
-
AIInteractionTurn:
description: Single turn in an AI interaction session.
type: object
@@ -7744,7 +8240,7 @@ components:
- type: object
properties:
referenceImageUrl:
- description: Universal URL of the reference image to guide the costume generation (e.g. kodo://bucket/key).
+ description: Universal URL of the costume reference image (e.g. kodo://bucket/key).
type:
- string
- "null"
@@ -7768,7 +8264,7 @@ components:
- loopMode
properties:
referenceFrameUrl:
- description: Universal URL of the reference frame image to guide the animation generation (e.g. kodo://bucket/key).
+ description: Universal URL of the animation reference frame image (e.g. kodo://bucket/key).
type:
- string
- "null"
@@ -7793,44 +8289,6 @@ components:
- ui
- unspecified
- UpInfo:
- description: Upload credentials and configuration.
- type: object
- required:
- - token
- - expiresAt
- - maxSize
- - bucket
- - region
- properties:
- token:
- description: Upload token used for authenticating upload requests.
- type: string
- examples:
- - MY_ACCESS_KEY:wQ4ofysef1R7IKnrziqtomqyDvI=:eyJzY29wZSI6Im15LWJ1Y2tldDpzdW5mbG93ZXIuanBnIiwiZGVhZGxpbmUiOjE0NTE0OTEyMDAsInJldHVybkJvZHkiOiJ7XCJuYW1lXCI6JChmbmFtZSksXCJzaXplXCI6JChmc2l6ZSksXCJ3XCI6JChpbWFnZUluZm8ud2lkdGgpLFwiaFwiOiQoaW1hZ2VJbmZvLmhlaWdodCksXCJoYXNoXCI6JChldGFnKX0ifQ==
- expiresAt:
- description: Expiration timestamp of the upload token.
- type: string
- format: date-time
- examples:
- - 2006-01-02T15:04:05+07:00
- maxSize:
- description: Maximum allowed file size in bytes.
- type: integer
- format: int64
- examples:
- - 26214400
- bucket:
- description: Name of the Qiniu Kodo bucket where files will be uploaded.
- type: string
- examples:
- - xbuilder-usercontent-test
- region:
- description: Region of the Qiniu Kodo bucket.
- type: string
- examples:
- - z0
-
InputText:
description: Text input for multimodal content.
type: object
@@ -7873,12 +8331,11 @@ components:
description: |
Base64-encoded PNG image data URL.
- All images must be provided as PNG format. If you have images in other formats (SVG, JPEG, WebP),
- convert them to PNG before sending.
-
- Maximum image size: 5 MiB (5242880 bytes) after decoding the base64 content.
+ Data URL requirements:
- Format: `data:image/png;base64,