Registry token

Operations of the License API. Paths are relative to your deployment's API host.

GET /api/license-api/.well-known/jwks.json

Publish the RSA verification key(s) for the OCI registry token.

Public, unauthenticated and cacheable. NOT the license key — see /.well-known/xema-license-keys.json for the Ed25519 key that verifies a LICENSE. The registry consumes a materialised copy of this document from a mounted Secret rather than fetching this URL. Several keys may appear at once: that overlap IS the rotation mechanism, and the key currently being signed with is always the first entry.

Authentication: none

StatusDescriptionBody
200application/json RegistryJwksDto
400application/problem+json ProblemDetailsDto
401application/problem+json ProblemDetailsDto
403application/problem+json ProblemDetailsDto
404application/problem+json ProblemDetailsDto
409application/problem+json ProblemDetailsDto
422application/problem+json ProblemDetailsDto
500application/problem+json ProblemDetailsDto

GET /api/license-api/v2/token

Exchange a Xema license for a short-lived, repository-scoped registry token.

Implements the OCI/Distribution token specification. The license is presented as HTTP Basic with the JWS in the PASSWORD field (what docker, podman, helm, skopeo and containerd actually send; the username is conventional and is ignored) or as Bearer for programmatic callers. A PARTIAL grant is a success: asking for pull,push and receiving pull is the specified behaviour, and the registry denies the push itself. offline_token=true with no scope is a docker login probe and returns 200 with an empty access array.

Authentication: none

ParameterInTypeRequiredDescription
accountqueryanynoThe username the client typed. ADVISORY ONLY — attacker-controlled, so it never influences the entitlement decision. Used for the sub of an anonymous probe and for audit.
client_idqueryanynoSent by docker (client_id=docker). Ignored.
offline_tokenqueryanynodocker login sends true with no scope. Answered 200 with an empty grant — an error here makes docker login fail outright and the user concludes their license is bad.
scopequeryarray of anynorepository:<name>:<actions>, REPEATABLE. Distribution sends several in one request during a cross-repo blob mount, so handling only the first would silently degrade mounts into full layer re-uploads. A malformed scope is DISCARDED, never fatal — a 500 here would turn a client bug into an outage. registry:catalog:* is never granted, because /v2/_catalog enumerates every repository on the registry.
servicequeryanyyesMust equal the configured registry service. This is the AUDIENCE binding — accepting an arbitrary value would let a token minted here be replayed against a different registry that trusts the same JWKS. A mismatch is a 400.
StatusDescriptionBody
200application/json RegistryTokenResponseDto
400application/problem+json ProblemDetailsDto
401application/problem+json ProblemDetailsDto
403application/problem+json ProblemDetailsDto
404application/problem+json ProblemDetailsDto
409application/problem+json ProblemDetailsDto
422application/problem+json ProblemDetailsDto
500application/problem+json ProblemDetailsDto