Operation details

GET /v1/admin/themes

operationId
listThemes
Auth
  • Session: the Bearer session of a signed-in control plane user, used by the customer in their own control plane; a plugin must never ask for it.
Required permissions

The contract has no separate permission annotation; see the description below and the 403 response.

Description (from the contract)

Catalog themes with download state and the downloaded packages. Requires system_configuration.read.

Responses

listThemes Responses
StatusDescription
200Catalog

Fields:schema: const cdnca.theme.catalog/v1 activation_revision: integer active_package_sha256: string user_package_sha256: string user_follows_admin: boolean available: array<object> packages: array<Package> error_page_republication: ErrorPageRepublication

401Unauthenticated
403Permission denied

What to do on failure

  • 401 Check the credential format and whether it expired or was rotated.
  • 403 Check the key scopes, the owner’s current permissions and the tenant scope; never switch to a more privileged account.

↑ Back to list

POST /v1/admin/themes/catalog/{theme_id}/download

operationId
downloadTheme
Auth
  • Session: the Bearer session of a signed-in control plane user, used by the customer in their own control plane; a plugin must never ask for it.
Required permissions

The contract has no separate permission annotation; see the description below and the 403 response.

Description (from the contract)

Store a catalog theme (downloaded, not active). Requires system_configuration.manage.

Parameters

downloadTheme Parameters
NameInTypeRequiredDescription
theme_idpathstringYes—

Responses

downloadTheme Responses
StatusDescription
200Downloaded package

Fields:package_sha256: string theme_id: string version: string name: object description?: object source: any requires_feature?: string downloaded_at: string(date-time) active: boolean tokens_url: string stylesheet_url: string preview_url?: string derived_from?: object

404Unknown catalog theme

What to do on failure

  • 404 The resource does not exist or belongs to another tenant.

↑ Back to list

POST /v1/admin/themes/packages

operationId
uploadTheme
Auth
  • Session: the Bearer session of a signed-in control plane user, used by the customer in their own control plane; a plugin must never ask for it.
Required permissions

The contract has no separate permission annotation; see the description below and the 403 response.

Description (from the contract)

Upload a custom cdnca.theme/v1 package (id custom.*). Packages with url(), @import, external links, script or undeclared classes are refused.

Request body

application/json · Required:Yes

Responses

uploadTheme Responses
StatusDescription
201Downloaded package

Fields:package_sha256: string theme_id: string version: string name: object description?: object source: any requires_feature?: string downloaded_at: string(date-time) active: boolean tokens_url: string stylesheet_url: string preview_url?: string derived_from?: object

413Larger than 8 MiB
422Refused package

↑ Back to list

GET /v1/admin/themes/packages/{sha}

operationId
getThemePackage
Auth
  • Session: the Bearer session of a signed-in control plane user, used by the customer in their own control plane; a plugin must never ask for it.
Required permissions

The contract has no separate permission annotation; see the description below and the 403 response.

Description (from the contract)

The cdnca.theme/v1 JSON of a package this installation stored (removed ones too) or a catalog theme, byte for byte (its SHA-256 is the path digest). The theme management page edits a copy of it and uploads the copy as a custom.* package whose derived_from names this package. Requires system_configuration.read.

Parameters

getThemePackage Parameters
NameInTypeRequiredDescription
shapathstringYes—

Responses

getThemePackage Responses
StatusDescription
200Package JSON
404Never stored and not in the catalog

What to do on failure

  • 404 The resource does not exist or belongs to another tenant.

↑ Back to list

DELETE /v1/admin/themes/packages/{sha}

operationId
removeTheme
Auth
  • Session: the Bearer session of a signed-in control plane user, used by the customer in their own control plane; a plugin must never ask for it.
Required permissions

The contract has no separate permission annotation; see the description below and the 403 response.

Parameters

removeTheme Parameters
NameInTypeRequiredDescription
shapathstringYes—

Responses

removeTheme Responses
StatusDescription
204Removed (can be downloaded again)
409The active package, or one a tenant uses (theme_package_selected_by_tenant), cannot be removed

What to do on failure

  • 409 Read the current state first; a retry of the same operation keeps the original Idempotency-Key and body.

↑ Back to list

POST /v1/admin/themes/packages/{sha}/activate

operationId
activateTheme
Auth
  • Session: the Bearer session of a signed-in control plane user, used by the customer in their own control plane; a plugin must never ask for it.
Required permissions

The contract has no separate permission annotation; see the description below and the 403 response.

Description (from the contract)

Make a downloaded package the active theme of one console: no body is both consoles as before; {"slot":"admin"|"user"|"all"} names one. The admin console (admin, all) takes official themes only (built in, uploads and copies, or the io.cdnca market namespace); a third party's market theme is a user console theme. An admin activation records a new error page publication revision pinned to the theme; node default error pages follow the admin console, so a user activation republishes nothing.

Parameters

activateTheme Parameters
NameInTypeRequiredDescription
shapathstringYes—
If-MatchheaderstringYesActivation revision the caller saw ("0" before any).

Request body

application/json · Required:No

activateTheme Request body
NameTypeRequiredDescription
slotstring: all / admin / userNo—

Responses

activateTheme Responses
StatusDescription
200Activated

Fields:revision: integer package_sha256: string theme_id: string error_page_publication_revision: integer error_page_republish_scopes: integer already_active?: boolean

400Unknown slot
403Permission denied
404Not downloaded
412Revision conflict

What to do on failure

  • 400 Fix the parameters or body per the field list; do not retry unchanged.
  • 403 Check the key scopes, the owner’s current permissions and the tenant scope; never switch to a more privileged account.
  • 404 The resource does not exist or belongs to another tenant.
  • 412 The revision changed: read the latest ETag, decide again, then send the new If-Match.

↑ Back to list

GET /v1/admin/themes/tenant-policy

operationId
getTenantThemePolicy
Auth
  • Session: the Bearer session of a signed-in control plane user, used by the customer in their own control plane; a plugin must never ask for it.
Required permissions

The contract has no separate permission annotation; see the description below and the 403 response.

Responses

getTenantThemePolicy Responses
StatusDescription
200Platform default

Fields:tenant_selection_allowed: boolean revision: integer

↑ Back to list

PUT /v1/admin/themes/tenant-policy

operationId
updateTenantThemePolicy
Auth
  • Session: the Bearer session of a signed-in control plane user, used by the customer in their own control plane; a plugin must never ask for it.
Required permissions

The contract has no separate permission annotation; see the description below and the 403 response.

Description (from the contract)

Whether tenants in inherit mode may choose their theme. Audited as theme.tenant_policy.update.

Parameters

updateTenantThemePolicy Parameters
NameInTypeRequiredDescription
If-MatchheaderstringYes—

Request body

application/json · Required:Yes

updateTenantThemePolicy Request body
NameTypeRequiredDescription
tenant_selection_allowedbooleanYes—

Responses

updateTenantThemePolicy Responses
StatusDescription
200New policy

Fields:tenant_selection_allowed: boolean revision: integer

412theme_revision_conflict

What to do on failure

  • 412 The revision changed: read the latest ETag, decide again, then send the new If-Match.

↑ Back to list

GET /v1/admin/themes/tenants/{tenant_scope_id}

operationId
getTenantThemeForPlatform
Auth
  • Session: the Bearer session of a signed-in control plane user, used by the customer in their own control plane; a plugin must never ask for it.
Required permissions

The contract has no separate permission annotation; see the description below and the 403 response.

Parameters

getTenantThemeForPlatform Parameters
NameInTypeRequiredDescription
tenant_scope_idpathstring(uuid)Yes—

Responses

getTenantThemeForPlatform Responses
StatusDescription
200Tenant theme

Fields:schema: const cdnca.theme.tenant/v1 tenant_scope_id: string(uuid) selection_mode: any platform_allows: boolean selection_allowed: boolean selected_package_sha256?: string assigned_by?: any effective_package_sha256: string effective_theme_id: string follows_platform: boolean revision: integer domains: array<string> choices: array<object>

404Unknown tenant scope

What to do on failure

  • 404 The resource does not exist or belongs to another tenant.

↑ Back to list

PUT /v1/admin/themes/tenants/{tenant_scope_id}

operationId
updateTenantThemeForPlatform
Auth
  • Session: the Bearer session of a signed-in control plane user, used by the customer in their own control plane; a plugin must never ask for it.
Required permissions

The contract has no separate permission annotation; see the description below and the 403 response.

Description (from the contract)

Set the tenant's selection_mode (inherit | allow | deny) and, with assign, the theme the platform assigns it (package_sha256 "" clears the assignment). An assigned theme applies whatever the selection mode. Audited as theme.tenant.activate (assign) or theme.tenant.selection_update.

Parameters

updateTenantThemeForPlatform Parameters
NameInTypeRequiredDescription
tenant_scope_idpathstring(uuid)Yes—
If-MatchheaderstringYes—

Request body

application/json · Required:Yes

updateTenantThemeForPlatform Request body
NameTypeRequiredDescription
selection_modeanyYes—
assignbooleanNo—
package_sha256stringNoRequired exactly when assign is true

Responses

updateTenantThemeForPlatform Responses
StatusDescription
200New tenant theme

Fields:schema: const cdnca.theme.tenant/v1 tenant_scope_id: string(uuid) selection_mode: any platform_allows: boolean selection_allowed: boolean selected_package_sha256?: string assigned_by?: any effective_package_sha256: string effective_theme_id: string follows_platform: boolean revision: integer domains: array<string> choices: array<object>

412theme_revision_conflict

What to do on failure

  • 412 The revision changed: read the latest ETag, decide again, then send the new If-Match.

↑ Back to list

PUT /v1/admin/themes/tenants/{tenant_scope_id}/domains/{hostname}

operationId
bindTenantThemeDomain
Auth
  • Session: the Bearer session of a signed-in control plane user, used by the customer in their own control plane; a plugin must never ask for it.
Required permissions

The contract has no separate permission annotation; see the description below and the 403 response.

Description (from the contract)

Bind a sign-in hostname to the tenant (its sign-in page shows the tenant theme). Audited as theme.tenant_domain.bind.

Parameters

bindTenantThemeDomain Parameters
NameInTypeRequiredDescription
tenant_scope_idpathstring(uuid)Yes—
hostnamepathstringYes—

Responses

bindTenantThemeDomain Responses
StatusDescription
200Tenant theme

Fields:schema: const cdnca.theme.tenant/v1 tenant_scope_id: string(uuid) selection_mode: any platform_allows: boolean selection_allowed: boolean selected_package_sha256?: string assigned_by?: any effective_package_sha256: string effective_theme_id: string follows_platform: boolean revision: integer domains: array<string> choices: array<object>

409theme_domain_conflict (bound to another tenant)

What to do on failure

  • 409 Read the current state first; a retry of the same operation keeps the original Idempotency-Key and body.

↑ Back to list

DELETE /v1/admin/themes/tenants/{tenant_scope_id}/domains/{hostname}

operationId
unbindTenantThemeDomain
Auth
  • Session: the Bearer session of a signed-in control plane user, used by the customer in their own control plane; a plugin must never ask for it.
Required permissions

The contract has no separate permission annotation; see the description below and the 403 response.

Parameters

unbindTenantThemeDomain Parameters
NameInTypeRequiredDescription
tenant_scope_idpathstring(uuid)Yes—
hostnamepathstringYes—

Responses

unbindTenantThemeDomain Responses
StatusDescription
200Tenant theme

Fields:schema: const cdnca.theme.tenant/v1 tenant_scope_id: string(uuid) selection_mode: any platform_allows: boolean selection_allowed: boolean selected_package_sha256?: string assigned_by?: any effective_package_sha256: string effective_theme_id: string follows_platform: boolean revision: integer domains: array<string> choices: array<object>

404Not bound

What to do on failure

  • 404 The resource does not exist or belongs to another tenant.

↑ Back to list