{"openapi":"3.1.0","info":{"title":"Stoaken API","version":"2026-09-29","description":"Read and propose changes to your design tokens. Authenticate with an API key (Settings -> API keys) or an OAuth access token as `Authorization: Bearer <token>`; every call runs with exactly that user's permissions.\n\n**Versioning.** Send `Stoaken-Version: 2026-09-29` to pin this version (omit it to get the current one). Responses carry `Stoaken-Version`; a deprecated version also answers with `Deprecation` (RFC 9745) and `Sunset` (RFC 8594) headers.\n\n**Errors** are RFC 9457 problem details (`application/problem+json`); each `type` links to its description.\n\n**Pagination.** Lists return `{ data, next_cursor }`; pass `next_cursor` back as `cursor`. `limit` defaults to 50 (max 100).\n\n**Idempotency.** Every state-changing request needs an `Idempotency-Key` header. Retrying with the same key returns the original result (`Idempotent-Replayed: true`) instead of applying the change twice; reusing a key for a different request is a 422. Keys are kept for 24 hours.\n\n**Rate limits** (per credential): 120 requests per 60s, and 60 state-changing requests per 1h. See the `RateLimit-*` response headers; a 429 carries `Retry-After`.\n\n**Governance.** The API can edit token sets and propose releases, but never approves or publishes them: a Reviewer does that in the Command Center, exactly as for changes made in the app."},"servers":[{"url":"/","description":"This Stoaken deployment"}],"security":[{"bearer":[]}],"paths":{"/api/brands":{"get":{"operationId":"listBrands","summary":"List the Brands you can view","parameters":[{"$ref":"#/components/parameters/Cursor"},{"$ref":"#/components/parameters/Limit"}],"responses":{"200":{"description":"A page of Brands.","content":{"application/json":{"schema":{"type":"object","required":["data","next_cursor"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Brand"}},"next_cursor":{"type":["string","null"],"description":"Pass as `cursor` to get the next page; null on the last page."}}}}}},"401":{"description":"Missing or invalid credentials.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not found or not accessible.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limited.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/api/brands/{brandId}":{"get":{"operationId":"getBrand","summary":"Get a Brand and your role on it","parameters":[{"name":"brandId","in":"path","required":true,"description":"The Brand's id.","schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"The Brand.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BrandDetail"}}}},"401":{"description":"Missing or invalid credentials.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not found or not accessible.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limited.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/api/brands/{brandId}/token-sets":{"get":{"operationId":"listTokenSets","summary":"List a Brand's token sets (without documents)","parameters":[{"name":"brandId","in":"path","required":true,"description":"The Brand's id.","schema":{"type":"string","format":"uuid"}},{"$ref":"#/components/parameters/Cursor"},{"$ref":"#/components/parameters/Limit"}],"responses":{"200":{"description":"A page of token sets.","content":{"application/json":{"schema":{"type":"object","required":["data","next_cursor"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/TokenSet"}},"next_cursor":{"type":["string","null"],"description":"Pass as `cursor` to get the next page; null on the last page."}}}}}},"401":{"description":"Missing or invalid credentials.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not found or not accessible.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limited.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/api/brands/{brandId}/themes":{"get":{"operationId":"listThemes","summary":"List a Brand's Themes","parameters":[{"name":"brandId","in":"path","required":true,"description":"The Brand's id.","schema":{"type":"string","format":"uuid"}},{"$ref":"#/components/parameters/Cursor"},{"$ref":"#/components/parameters/Limit"}],"responses":{"200":{"description":"A page of Themes.","content":{"application/json":{"schema":{"type":"object","required":["data","next_cursor"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Theme"}},"next_cursor":{"type":["string","null"],"description":"Pass as `cursor` to get the next page; null on the last page."}}}}}},"401":{"description":"Missing or invalid credentials.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not found or not accessible.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limited.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/api/token-sets/{tokenSetId}":{"get":{"operationId":"getTokenSet","summary":"Get a token set with its DTCG document","parameters":[{"name":"tokenSetId","in":"path","required":true,"description":"The token set's id.","schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"The token set.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TokenSetDetail"}}}},"401":{"description":"Missing or invalid credentials.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not found or not accessible.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limited.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/api/token-sets/{tokenSetId}/document":{"put":{"operationId":"putTokenSetDocument","summary":"Replace a token set's DTCG document (Editor+)","description":"Validated against the DTCG 2025.10 schema. Saving doesn't publish anything: create a release to put the change through review.","parameters":[{"name":"tokenSetId","in":"path","required":true,"description":"The token set's id.","schema":{"type":"string","format":"uuid"}},{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","description":"A DTCG 2025.10 token document."}}}},"responses":{"200":{"description":"Saved.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TokenSetUpdated"}}}},"400":{"description":"Malformed request or missing Idempotency-Key.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Missing or invalid credentials.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Your role doesn't allow this.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not found or not accessible.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"Same Idempotency-Key still in progress, or the resource is in the wrong state.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"Validation failed, or the Idempotency-Key was reused for a different request.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limited.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/api/themes/{themeId}":{"get":{"operationId":"getTheme","summary":"Get a Theme and its axes/modes","parameters":[{"name":"themeId","in":"path","required":true,"description":"The Theme's id.","schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"The Theme.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ThemeDetail"}}}},"401":{"description":"Missing or invalid credentials.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not found or not accessible.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limited.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/api/themes/{themeId}/tokens":{"get":{"operationId":"getThemeTokens","summary":"A Theme's resolved tokens for one mode-combination","description":"Aliases followed, $type and $deprecated inherited, brand inheritance and token-set status applied -- the tokens as a release would publish them right now.","parameters":[{"name":"themeId","in":"path","required":true,"description":"The Theme's id.","schema":{"type":"string","format":"uuid"}},{"$ref":"#/components/parameters/Mode"}],"responses":{"200":{"description":"Resolved tokens.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResolvedTokens"}}}},"400":{"description":"Unknown mode.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Missing or invalid credentials.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not found or not accessible.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limited.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/api/themes/{themeId}/export":{"get":{"operationId":"exportThemeTokens","summary":"Export a Theme's live release as code","description":"CSS variables (every mode in one file, as attribute selectors), W3C 2025.10 JSON, Style Dictionary v4 JSON, or a JS/TS module, from the Theme's published release. No timestamps, so committing the output gives clean diffs.","parameters":[{"name":"themeId","in":"path","required":true,"description":"The Theme's id.","schema":{"type":"string","format":"uuid"}},{"name":"format","in":"query","required":false,"description":"`css`: A custom property for every token. Modes become attribute selectors, so one file covers them all. `json-dtcg`: Resolved tokens in the W3C 2025.10 format, for Style Dictionary v5 and other current tools. One mode per file. `json-sd4`: The same tokens with the older value format Style Dictionary v4 reads: hex colours, \"16px\", \"200ms\". One mode per file. `js`: An ES module exporting a nested object of CSS-ready values. One mode per file. `ts`: The JavaScript module, typed with as const so values autocomplete. One mode per file.","schema":{"type":"string","enum":["css","json-dtcg","json-sd4","js","ts"],"default":"css"}},{"name":"mode","in":"query","required":false,"description":"A mode-combination key, for the one-mode-per-file formats; omit for the default combination. CSS ignores it and includes every mode.","schema":{"type":"string"}},{"name":"prefix","in":"query","required":false,"description":"CSS only: a prefix for every variable name (`acme` gives `--acme-color-brand-primary`).","schema":{"type":"string"}}],"responses":{"200":{"description":"The file. `Content-Disposition` carries a file name; `Stoaken-Export-Warnings` says how many tokens were left out or adjusted (the reasons are in the file's header comment for CSS, JS and TS).","headers":{"Content-Disposition":{"schema":{"type":"string"}},"Stoaken-Export-Warnings":{"schema":{"type":"integer"}}},"content":{"text/css":{"schema":{"type":"string"}},"application/json":{"schema":{"type":"string"}},"text/javascript":{"schema":{"type":"string"}},"text/plain":{"schema":{"type":"string"}}}},"400":{"description":"Unknown format or mode.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Missing or invalid credentials.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not found or not accessible.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"The Theme has no live release yet.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limited.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/api/themes/{themeId}/tokens/raw":{"get":{"operationId":"getThemeRawTokens","summary":"A Theme's cascade-merged tokens with aliases left as written","parameters":[{"name":"themeId","in":"path","required":true,"description":"The Theme's id.","schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Raw tokens.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RawTokens"}}}},"401":{"description":"Missing or invalid credentials.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not found or not accessible.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limited.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/api/themes/{themeId}/deprecations":{"get":{"operationId":"listDeprecations","summary":"Deprecated tokens and what still references them","parameters":[{"name":"themeId","in":"path","required":true,"description":"The Theme's id.","schema":{"type":"string","format":"uuid"}},{"$ref":"#/components/parameters/Mode"}],"responses":{"200":{"description":"The deprecation report.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeprecationReport"}}}},"400":{"description":"Unknown mode.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Missing or invalid credentials.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not found or not accessible.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limited.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"post":{"operationId":"proposeDeprecation","summary":"Deprecate or un-deprecate a token (Editor+) and submit it for review","description":"Writes $deprecated on the token in every token set of this Theme's own Brand that defines it, then creates a minor release and submits it for approval. Never publishes.","parameters":[{"name":"themeId","in":"path","required":true,"description":"The Theme's id.","schema":{"type":"string","format":"uuid"}},{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeprecationRequest"}}}},"responses":{"201":{"description":"Submitted for review.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeprecationProposed"}}}},"400":{"description":"Malformed request or missing Idempotency-Key.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Missing or invalid credentials.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Your role doesn't allow this.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not found or not accessible.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"Same Idempotency-Key still in progress, or the resource is in the wrong state.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"Validation failed, or the Idempotency-Key was reused for a different request.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limited.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/api/themes/{themeId}/releases":{"get":{"operationId":"listReleases","summary":"List a Theme's releases","parameters":[{"name":"themeId","in":"path","required":true,"description":"The Theme's id.","schema":{"type":"string","format":"uuid"}},{"$ref":"#/components/parameters/Cursor"},{"$ref":"#/components/parameters/Limit"}],"responses":{"200":{"description":"A page of releases.","content":{"application/json":{"schema":{"type":"object","required":["data","next_cursor"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Release"}},"next_cursor":{"type":["string","null"],"description":"Pass as `cursor` to get the next page; null on the last page."}}}}}},"401":{"description":"Missing or invalid credentials.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not found or not accessible.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limited.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"post":{"operationId":"createRelease","summary":"Create a release of the Theme's current token sets (Editor+)","description":"Creates a draft and, unless `submit` is false, submits it for approval (snapshot + diff against the published release). Never publishes. If submission fails, the problem includes `release_id` of the draft that was created.","parameters":[{"name":"themeId","in":"path","required":true,"description":"The Theme's id.","schema":{"type":"string","format":"uuid"}},{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReleaseRequest"}}}},"responses":{"201":{"description":"Created.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReleaseCreated"}}}},"400":{"description":"Malformed request or missing Idempotency-Key.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Missing or invalid credentials.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Your role doesn't allow this.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not found or not accessible.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"Same Idempotency-Key still in progress, or the resource is in the wrong state.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"Validation failed, or the Idempotency-Key was reused for a different request.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limited.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/api/releases/{releaseId}":{"get":{"operationId":"getRelease","summary":"Get a release with its change summary","parameters":[{"name":"releaseId","in":"path","required":true,"description":"The release's id.","schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"The release.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReleaseDetail"}}}},"401":{"description":"Missing or invalid credentials.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not found or not accessible.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limited.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/api/releases/{releaseId}/snapshot":{"get":{"operationId":"getReleaseSnapshot","summary":"A release's resolved token snapshot","parameters":[{"name":"releaseId","in":"path","required":true,"description":"The release's id.","schema":{"type":"string","format":"uuid"}},{"name":"mode","in":"query","required":false,"description":"A mode-combination key; omit for the default combination.","schema":{"type":"string"}}],"responses":{"200":{"description":"The snapshot.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReleaseSnapshot"}}}},"400":{"description":"Unknown mode.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Missing or invalid credentials.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not found or not accessible.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"A draft has no snapshot yet.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limited.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/api/releases/{releaseId}/export":{"get":{"operationId":"exportReleaseTokens","summary":"Export one release as code (any status with a snapshot)","description":"Same formats as the Theme export, for a specific release: useful in CI to preview a release that is still waiting for review.","parameters":[{"name":"releaseId","in":"path","required":true,"description":"The release's id.","schema":{"type":"string","format":"uuid"}},{"name":"format","in":"query","required":false,"description":"`css`: A custom property for every token. Modes become attribute selectors, so one file covers them all. `json-dtcg`: Resolved tokens in the W3C 2025.10 format, for Style Dictionary v5 and other current tools. One mode per file. `json-sd4`: The same tokens with the older value format Style Dictionary v4 reads: hex colours, \"16px\", \"200ms\". One mode per file. `js`: An ES module exporting a nested object of CSS-ready values. One mode per file. `ts`: The JavaScript module, typed with as const so values autocomplete. One mode per file.","schema":{"type":"string","enum":["css","json-dtcg","json-sd4","js","ts"],"default":"css"}},{"name":"mode","in":"query","required":false,"description":"A mode-combination key, for the one-mode-per-file formats; omit for the default combination. CSS ignores it and includes every mode.","schema":{"type":"string"}},{"name":"prefix","in":"query","required":false,"description":"CSS only: a prefix for every variable name (`acme` gives `--acme-color-brand-primary`).","schema":{"type":"string"}}],"responses":{"200":{"description":"The file. `Content-Disposition` carries a file name; `Stoaken-Export-Warnings` says how many tokens were left out or adjusted (the reasons are in the file's header comment for CSS, JS and TS).","headers":{"Content-Disposition":{"schema":{"type":"string"}},"Stoaken-Export-Warnings":{"schema":{"type":"integer"}}},"content":{"text/css":{"schema":{"type":"string"}},"application/json":{"schema":{"type":"string"}},"text/javascript":{"schema":{"type":"string"}},"text/plain":{"schema":{"type":"string"}}}},"400":{"description":"Unknown format or mode.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Missing or invalid credentials.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not found or not accessible.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"A draft has no snapshot yet.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limited.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/api/releases/{releaseId}/submit":{"post":{"operationId":"submitRelease","summary":"Submit a draft release for review (Editor+)","parameters":[{"name":"releaseId","in":"path","required":true,"description":"The release's id.","schema":{"type":"string","format":"uuid"}},{"$ref":"#/components/parameters/IdempotencyKey"}],"responses":{"200":{"description":"Submitted.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReleaseSubmitted"}}}},"400":{"description":"Malformed request or missing Idempotency-Key.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Missing or invalid credentials.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Your role doesn't allow this.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not found or not accessible.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"Same Idempotency-Key still in progress, or the resource is in the wrong state.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"Validation failed, or the Idempotency-Key was reused for a different request.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limited.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/api/openapi.json":{"get":{"operationId":"getOpenApi","summary":"This document","security":[],"responses":{"200":{"description":"OpenAPI 3.1 document.","content":{"application/json":{"schema":{"type":"object"}}}}}}},"/api/problems/{slug}":{"get":{"operationId":"getProblemType","summary":"Describe a problem type","security":[],"parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","enum":["bad-request","unsupported-version","idempotency-key-required","unauthorized","forbidden","not-found","method-not-allowed","idempotency-conflict","conflict","payload-too-large","unsupported-media-type","idempotency-key-reused","invalid","rate-limited","internal"]}}],"responses":{"200":{"description":"The problem type.","content":{"application/json":{"schema":{"type":"object"}}}},"404":{"description":"Unknown problem type.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}}},"webhooks":{"release.pending_approval":{"post":{"summary":"Sent when a release becomes pending_approval","description":"Signed per Standard Webhooks: verify `webhook-signature` (v1, HMAC-SHA256 over `webhook-id.webhook-timestamp.body` with the endpoint secret's bytes after `whsec_`), reject stale `webhook-timestamp`s, and dedupe on `webhook-id` (delivery is at-least-once; retries at ~1m, 5m, 30m, 2h, 12h). Respond 2xx within 5 seconds; redirects are not followed.","parameters":[{"name":"webhook-id","in":"header","required":true,"schema":{"type":"string"}},{"name":"webhook-timestamp","in":"header","required":true,"schema":{"type":"string"}},{"name":"webhook-signature","in":"header","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEvent"}}}},"responses":{"2XX":{"description":"Received."}}}},"release.published":{"post":{"summary":"Sent when a release becomes published","description":"Signed per Standard Webhooks: verify `webhook-signature` (v1, HMAC-SHA256 over `webhook-id.webhook-timestamp.body` with the endpoint secret's bytes after `whsec_`), reject stale `webhook-timestamp`s, and dedupe on `webhook-id` (delivery is at-least-once; retries at ~1m, 5m, 30m, 2h, 12h). Respond 2xx within 5 seconds; redirects are not followed.","parameters":[{"name":"webhook-id","in":"header","required":true,"schema":{"type":"string"}},{"name":"webhook-timestamp","in":"header","required":true,"schema":{"type":"string"}},{"name":"webhook-signature","in":"header","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEvent"}}}},"responses":{"2XX":{"description":"Received."}}}},"release.rejected":{"post":{"summary":"Sent when a release becomes rejected","description":"Signed per Standard Webhooks: verify `webhook-signature` (v1, HMAC-SHA256 over `webhook-id.webhook-timestamp.body` with the endpoint secret's bytes after `whsec_`), reject stale `webhook-timestamp`s, and dedupe on `webhook-id` (delivery is at-least-once; retries at ~1m, 5m, 30m, 2h, 12h). Respond 2xx within 5 seconds; redirects are not followed.","parameters":[{"name":"webhook-id","in":"header","required":true,"schema":{"type":"string"}},{"name":"webhook-timestamp","in":"header","required":true,"schema":{"type":"string"}},{"name":"webhook-signature","in":"header","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEvent"}}}},"responses":{"2XX":{"description":"Received."}}}},"ping":{"post":{"summary":"A test event sent from Settings -> Webhooks","description":"Signed per Standard Webhooks: verify `webhook-signature` (v1, HMAC-SHA256 over `webhook-id.webhook-timestamp.body` with the endpoint secret's bytes after `whsec_`), reject stale `webhook-timestamp`s, and dedupe on `webhook-id` (delivery is at-least-once; retries at ~1m, 5m, 30m, 2h, 12h). Respond 2xx within 5 seconds; redirects are not followed.","parameters":[{"name":"webhook-id","in":"header","required":true,"schema":{"type":"string"}},{"name":"webhook-timestamp","in":"header","required":true,"schema":{"type":"string"}},{"name":"webhook-signature","in":"header","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEvent"}}}},"responses":{"2XX":{"description":"Received."}}}}},"components":{"securitySchemes":{"bearer":{"type":"http","scheme":"bearer","description":"An API key or an OAuth access token."}},"parameters":{"Cursor":{"name":"cursor","in":"query","required":false,"description":"The next_cursor from the previous page.","schema":{"type":"string"}},"Limit":{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":100,"default":50}},"Mode":{"name":"mode","in":"query","required":false,"description":"A mode-combination key such as \"scheme:dark\"; omit for the default.","schema":{"type":"string"}},"IdempotencyKey":{"name":"Idempotency-Key","in":"header","required":true,"description":"1-255 characters, unique per intended change (a UUID works well).","schema":{"type":"string","minLength":1,"maxLength":255}},"StoakenVersion":{"name":"Stoaken-Version","in":"header","required":false,"schema":{"type":"string","enum":["2026-09-29"]}}},"schemas":{"Problem":{"type":"object","required":["type","title","status","detail"],"properties":{"type":{"type":"string","description":"A relative URI such as /api/problems/not-found."},"title":{"type":"string"},"status":{"type":"integer"},"detail":{"type":"string"},"instance":{"type":"string"}},"additionalProperties":true},"Brand":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"workspace_id":{"type":"string","format":"uuid"},"extends_brand_id":{"type":["string","null"],"format":"uuid"},"created_at":{"type":"string","format":"date-time"}}},"BrandDetail":{"allOf":[{"$ref":"#/components/schemas/Brand"},{"type":"object","properties":{"your_role":{"type":"string","enum":["owner","admin","editor","reviewer","viewer"]}}}]},"TokenSet":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"brand_id":{"type":"string","format":"uuid"},"name":{"type":"string"},"status":{"type":"string"},"position":{"type":"integer"},"created_at":{"type":"string","format":"date-time"}}},"TokenSetDetail":{"allOf":[{"$ref":"#/components/schemas/TokenSet"},{"type":"object","properties":{"dtcg_document":{"type":"object"}}}]},"TokenSetUpdated":{"allOf":[{"$ref":"#/components/schemas/TokenSet"},{"type":"object","properties":{"updated":{"const":true},"note":{"type":"string"}}}]},"Theme":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"brand_id":{"type":"string","format":"uuid"},"name":{"type":"string"},"created_at":{"type":"string","format":"date-time"}}},"ThemeDetail":{"allOf":[{"$ref":"#/components/schemas/Theme"},{"type":"object","properties":{"axes":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string"},"modes":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string"},"is_default":{"type":"boolean"}}}}}}}}}]},"ResolvedTokens":{"type":"object","properties":{"theme_id":{"type":"string"},"mode":{"type":"string"},"default_mode":{"type":"string"},"modes":{"type":"array","items":{"type":"string"}},"tokens":{"type":"object"},"diagnostics":{"type":"object"}}},"RawTokens":{"type":"object","properties":{"theme_id":{"type":"string"},"tokens":{"type":"object"}}},"DeprecationReport":{"type":"object","properties":{"theme_id":{"type":"string"},"mode":{"type":"string"},"deprecated":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":["string","null"]},"replacement":{"type":["string","null"]},"replacementExists":{"type":"boolean"},"declaredOn":{"type":"object"},"referencedBy":{"type":"array","items":{"type":"string"}}}}}}},"DeprecationRequest":{"type":"object","required":["token_path","version"],"properties":{"token_path":{"type":"string"},"action":{"type":"string","enum":["deprecate","undeprecate"],"default":"deprecate"},"replacement":{"type":"string","description":"A token path; written into the notice as {path}."},"note":{"type":"string"},"version":{"type":"string","description":"Version of the release to create (a minor release)."}}},"DeprecationProposed":{"type":"object","properties":{"release_id":{"type":"string"},"version":{"type":"string"},"status":{"const":"pending_approval"},"edited_token_sets":{"type":"integer"}}},"Release":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"theme_id":{"type":"string","format":"uuid"},"version":{"type":"string"},"version_type":{"type":"string","enum":["major","minor","patch"]},"status":{"type":"string","enum":["draft","pending_approval","published","superseded","rejected"]},"is_exception":{"type":"boolean"},"change_count":{"type":["integer","null"]},"is_breaking":{"type":"boolean"},"deprecation_changes":{"type":"integer"},"created_at":{"type":"string","format":"date-time"}}},"ReleaseDetail":{"allOf":[{"$ref":"#/components/schemas/Release"},{"type":"object","properties":{"created_by":{"type":["string","null"]},"approved_by":{"type":["string","null"]},"exception":{"type":["object","null"]},"rejection_reason":{"type":["string","null"]},"delegated_to":{"type":["string","null"]},"change_summary":{"type":["array","null"],"items":{"type":"object"}},"deprecations":{"type":"array","items":{"type":"object"}}}}]},"ReleaseRequest":{"type":"object","required":["version"],"properties":{"version":{"type":"string"},"version_type":{"type":"string","enum":["major","minor","patch"],"default":"minor"},"submit":{"type":"boolean","default":true}}},"ReleaseCreated":{"type":"object","properties":{"id":{"type":"string"},"theme_id":{"type":"string"},"version":{"type":"string"},"version_type":{"type":"string"},"status":{"type":"string","enum":["draft","pending_approval"]}}},"ReleaseSnapshot":{"type":"object","properties":{"release_id":{"type":"string"},"mode":{"type":["string","null"]},"modes":{"type":"array","items":{"type":"string"}},"tokens":{"type":"object"}}},"ReleaseSubmitted":{"type":"object","properties":{"id":{"type":"string"},"status":{"const":"pending_approval"}}},"WebhookEvent":{"type":"object","required":["type","timestamp","data"],"properties":{"type":{"type":"string","enum":["release.pending_approval","release.published","release.rejected","ping"]},"timestamp":{"type":"string","format":"date-time"},"data":{"type":"object","description":"Ids and state only -- fetch details (change summary, snapshot) with GET /api/releases/{release_id}.","properties":{"event_id":{"type":"string","format":"uuid"},"release_id":{"type":"string","format":"uuid"},"theme_id":{"type":"string","format":"uuid"},"brand_id":{"type":"string","format":"uuid"},"version":{"type":"string"},"status":{"type":"string"},"previous_status":{"type":"string"},"is_exception":{"type":"boolean"},"endpoint_id":{"type":"string","format":"uuid","description":"ping only"}}}}}}}}