Hanzo

Licensing

Licensing — 6 operations on https://api.hanzo.ai.

The REST reference for Licensing — 6 operations, generated from the OpenAPI document.

Base URLhttps://api.hanzo.ai
Operations6
AuthAuthorization: Bearer $HANZO_API_KEY

licensing

GET /v1/licensing/{wildcard1}

Read the licensing subtree: releases, the public verification key, health

The subtree is mounted as ONE wildcard route, so the path segment selects the real operation. Under GET those are:

  • /v1/licensing/releases — every release the deployment knows.
  • /v1/licensing/releases/{release} — one release's metadata; an unknown id is 404.
  • /v1/licensing/download/{release} — the license-gated artifact download. It is gated on the minted LICENSE token rather than the OIDC bearer, because that is exactly what the engine runs on: present it as an X-License-Token header or a ?token= query parameter. No token is 401; a token whose signature, app or expiry fails, or that has been revoked, or that lacks the features the release requires, is 403; a yanked release is 410. The answer carries the artifact AND its cosign signature, so a client verifies the binary before trusting it.
  • /v1/licensing/pubkey and /v1/licensing/jwks — the same Ed25519 PUBLIC key, in raw base64 and as a JWK. This is the only public-safe surface here, and it is what lets an engine verify tokens OFFLINE. The private key never enters this process: signing goes through the KMS signer abstraction, not key material.
  • /v1/licensing/healthz — status, deployment env, and which signer provider is in use.

Any other path under the subtree is 404.

ParameterInTypeRequiredDescription
wildcard1pathstringyes

POST /v1/licensing/{wildcard1}

Issue, verify and revoke license tokens, bind a device, publish a release

The subtree is mounted as ONE wildcard route, so the path segment selects the real operation. Under POST those are:

  • /v1/licensing/issue — mints an Ed25519 license token for a paid product. The caller must be authenticated (mounted in cloud, that is an IAM-verified bearer), and the entitlement is then checked in commerce for that caller's org and subject: a caller who does not own the product is 403, never a token. The token's app_id is the DEPLOYMENT's brand, so a hanzo deployment can never mint a lux- or zoo-scoped token. Device binding comes from a fingerprint you registered earlier or from signals bound at issue time, and a deployment configured to require one refuses without it. The lifetime is clamped both to policy and to the entitlement's own expiry, so a token never outlives the entitlement that justified it. Naming a release scopes the token to it as a release:<id> feature, which is what makes release-scoped revocation reach it.
  • /v1/licensing/verify — an online, unauthenticated check of a token: signature, app and expiry, then the revocation list. The rule worth knowing is that an INVALID token is still 200 — the answer is {valid:false, reason}, not an HTTP error — because this read is informational and the engine is what enforces the license, offline, from the public key.
  • /v1/licensing/revoke — appends a revocation entry scoped by nonce, holder, fingerprint or release, stamped with the admin who did it. Authenticated; any other scope, or a missing value, is 400.
  • /v1/licensing/fingerprint — turns device signals into the opaque binding value /issue accepts. Authenticated, and the raw signals are never echoed back.
  • /v1/licensing/releases — publishes a release, answering 201. Authenticated, and outside dev a release carrying no cosign signature is refused, so an unsigned binary cannot enter the download path.

Any other path under the subtree is 404.

ParameterInTypeRequiredDescription
wildcard1pathstringyes

PUT /v1/licensing/{wildcard1}

Not served — nothing in the licensing subtree is replaced by PUT

The subtree is mounted as ONE wildcard route, so every method that route can carry is published — but the mux behind it registers GET and POST handlers only. A PUT to a real licensing path (/v1/licensing/issue, /v1/licensing/releases, and the rest) is 405, with an Allow header naming the methods that path does serve; a PUT to a path the subtree does not have at all is 404.

There is no replace-in-place anywhere here: a release is published again through POST /v1/licensing/releases, and a license is re-issued rather than edited.

ParameterInTypeRequiredDescription
wildcard1pathstringyes

PATCH /v1/licensing/{wildcard1}

Not served — nothing in the licensing subtree is patched

The subtree is mounted as ONE wildcard route, so every method that route can carry is published — but the mux behind it registers GET and POST handlers only. A PATCH to a real licensing path is 405, with an Allow header naming the methods that path does serve; a PATCH to a path the subtree does not have is 404.

Nothing here is mutable in part. A license is an immutable signed token — you issue a new one — and a release is republished whole.

ParameterInTypeRequiredDescription
wildcard1pathstringyes

DELETE /v1/licensing/{wildcard1}

Not served — a license is revoked, never deleted

The subtree is mounted as ONE wildcard route, so every method that route can carry is published — but the mux behind it registers GET and POST handlers only. A DELETE to a real licensing path is 405, with an Allow header naming the methods that path does serve; a DELETE to a path the subtree does not have is 404.

The delete-shaped operation here is revocation, and it is POST /v1/licensing/revoke. It APPENDS a revocation entry rather than removing anything, because a token already in the field cannot be recalled — it can only be denied at verify and download time, and the entry is the record of who denied it and why.

ParameterInTypeRequiredDescription
wildcard1pathstringyes

OPTIONS /v1/licensing/{wildcard1}

Not served — but the refusal still names the methods a path allows

The subtree is mounted as ONE wildcard route, so every method that route can carry is published — but the mux behind it registers GET and POST handlers only, and OPTIONS is not among them. An OPTIONS to a real licensing path is therefore 405 rather than a capability answer; it does still carry the Allow header naming that path's real methods, which is the part a client was asking for. An OPTIONS to a path the subtree does not have is 404.

ParameterInTypeRequiredDescription
wildcard1pathstringyes

All Hanzo APIs · Interactive reference

How is this guide?

On this page