Replace the organization theme

PUT /v1/branding/organizations/{org_id} · permission branding:write

Replaces the whole theme draft of the scope; tokens missing from the body are cleared. {"theme":{}} clears the scope. If-Match carries this scope's ETag (from the matching GET), not the environment's. Any token other than logo, light.color.primary and dark.color.primary fails with 422 (token_not_allowed_in_scope).

Request

Field Type Required Description
org_id path yes org_… id.
If-Match header yes The ETag of the draft as last read ("0" if never written). Missing: 428; stale: 412.
theme object yes Full BrandingTheme of the scope.

Response

200 OK with the scope's theme draft and its ETag (each scope has its own version).

{
  "theme": {"logo": "logo_acme", "light": {"color": {"primary": "#0a3d91"}}},
  "updated_at": "2026-10-05T09:30:00.123456Z"
}

Errors

HTTP code When
400 unknown_field The body has an unknown field or is not a JSON object.
404 not_found The id is not a valid org_… id.
412 precondition_failed If-Match does not match the current version of the draft.
422 validation_failed A token value is invalid (invalid_value, out_of_range, unknown_token); pointer names the token, e.g. /theme/light/color/primary.
428 precondition_required The If-Match header is missing.
401 unauthenticated The credential is missing, invalid or revoked.
403 insufficient_permissions The credential lacks the required permission.
429 rate_limited The rate limit was exceeded; retry after the Retry-After period.
503 service_unavailable A dependency is temporarily unavailable; retry after the Retry-After period.

Example

curl -X PUT https://api.eu.keenauth.com/v1/branding/organizations/org_01jbexample0000000000000000 \
  -H "Authorization: Bearer $KEENAUTH_SECRET_KEY" \
  -H "Content-Type: application/json" \
  -H 'If-Match: "1"' \
  -d '{"theme":{"logo":"logo_acme","light":{"color":{"primary":"#0a3d91"}}}}'