Issue mints a signed license token for a product the caller's org already pays…
Issue mints a signed license token for a product the caller's org already pays for.
POST /v1/licensing/issue
| Address | https://api.hanzo.ai/v1/licensing/issue |
| Method | POST |
| Operation | post_licensing_issue |
| Auth | Authorization: Bearer $HANZO_API_KEY |
Issue mints a signed license token for a product the caller's org already pays for.
The order is the whole security argument: the caller is an IAM-validated principal, commerce is then asked whether that principal's ORG holds an ACTIVE entitlement for the product, and only then is a token signed — by the KMS, never by key material in this process. A product the org does not own answers 403 and no token. The signed features are the plan's features verbatim, so the engine enforces exactly what was bought, and the expiry is clamped to the entitlement's so a token cannot outlive the subscription that paid for it.
The token is the credential the engine runs on. Treat it as a secret.
Request
14 fields, body application/json (required).
| Field | In | Type | Required | Description |
|---|---|---|---|---|
fingerprint | body | string | — | Fingerprint is a previously-registered device binding value, as returned by POST /v1/licensing/fingerprint. |
holder | body | string | — | Holder overrides who the token is issued to; defaults to the caller's own validated subject. |
product | body | string | yes | Product is the licensed commerce product the caller wants a token for. |
release | body | string | — | Release scopes the token to one signed binary release, recorded as a "release:<id>" feature so a single bad release can be revoked on its own. |
signals | body | licensing.DeviceSignals | — | |
signals.arch | body | string | — | |
signals.cpuid | body | string | — | CPUID is a CPU/board identifier string. |
signals.disk_serial | body | string | — | DiskSerial of the boot/root volume. |
signals.hostname | body | string | — | Hostname is a weak signal, used only as a tiebreaker. |
signals.install_id | body | string | — | InstallID is a per-install random the agent persists locally on first run. |
signals.machine_id | body | string | — | MachineID is a stable per-host id (e.g. |
signals.macs | body | string[] | — | MAC addresses of stable interfaces (order-insensitive; we sort). |
signals.os | body | string | — | OS / Arch coarse platform tags. |
ttl_seconds | body | integer | — | TTLSeconds requests a token lifetime in seconds. |
Response
| Status | Body | Meaning |
|---|---|---|
200 | licensing.IssueResponse | ok |
200 body — 7 fields.
| Field | In | Type | Always | Description |
|---|---|---|---|---|
app_id | body | string | — | AppID is the brand this token runs under ("hanzo" | "lux" | "zoo"). |
exp | body | integer | — | Exp is the token's expiry, Unix seconds. |
features | body | string[] | — | Features are the capability grants copied verbatim from the plan the org bought. |
fingerprint_bound | body | boolean | — | Bound reports whether a device fingerprint was folded into the token. |
holder | body | string | — | Holder is who the token was issued to. |
nonce | body | string | — | Nonce uniquely identifies this token, and is what a per-token revocation names. |
token | body | string | — | Token is the signed license, base64url(payload).base64url(ed25519_sig). |
Failure carries the platform error shape — see Errors.
Examples
hanzo licensing issue --product <product>import { Configuration, LicensingApi } from 'hanzoai';
const api = new LicensingApi(new Configuration({ accessToken: process.env.HANZO_API_KEY }));
const { data } = await api.postLicensingIssue({ product: "<product>" });from hanzoai.cloud import ApiClient, Configuration
from hanzoai.cloud.api import LicensingApi
client = ApiClient(Configuration(access_token=os.environ["HANZO_API_KEY"]))
result = LicensingApi(client).post_licensing_issue(product="<product>")cfg := cloud.NewConfiguration()
cfg.AddDefaultHeader("Authorization", "Bearer "+os.Getenv("HANZO_API_KEY"))
client := cloud.NewAPIClient(cfg)
resp, _, err := client.LicensingAPI.PostLicensingIssue(context.Background()).Execute()
if err != nil {
return err
}use hanzo_cloud::apis::{configuration::Configuration, licensing_api};
let mut cfg = Configuration::new();
cfg.bearer_access_token = std::env::var("HANZO_API_KEY").ok();
let result = licensing_api::post_licensing_issue(&cfg, Default::default()).await?;import ai.hanzo.cloud.ApiClient;
import ai.hanzo.cloud.api.LicensingApi;
ApiClient client = new ApiClient();
client.setRequestInterceptor(b -> b.header("Authorization", "Bearer " + System.getenv("HANZO_API_KEY")));
var result = new LicensingApi(client).postLicensingIssue();curl -X POST https://api.hanzo.ai/v1/licensing/issue \
-H "Authorization: Bearer $HANZO_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"product": "<product>"
}'The door reaches licensing through the licensing tool, which names its 11 operations with its own verbs — this one among them, under a name only the door declares. describe explains any of them:
curl -X POST https://api.hanzo.ai/v1/mcp \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "describe",
"arguments": {
"op": "get_licensing_download"
}
}
}'How is this guide?