# Create issue

URL: https://docs.hanzo.ai/docs/openapi/licensing/post-licensing-issue

> Mints a signed license token for a product the caller's org already pays for.

`POST /v1/licensing/issue`

> [Licensing →](https://docs.hanzo.ai/docs/openapi/licensing) · [All API references →](https://docs.hanzo.ai/docs/openapi) · [Get started →](https://docs.hanzo.ai/docs/guides)

|               |                                           |
| ------------- | ----------------------------------------- |
| **Address**   | `https://api.hanzo.ai/v1/licensing/issue` |
| **Method**    | `POST`                                    |
| **Operation** | `post_licensing_issue`                    |
| **Auth**      | `Authorization: Bearer $HANZO_API_KEY`    |

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, with the
production key KMS holds. 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. /etc/machine-id, IOPlatformUUID, MachineGuid).                                                          |
| `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 (int64)         | —        | TTLSeconds requests a token lifetime in seconds.                                                                                                |

## Response

| Status    | Body                    | Meaning |
| --------- | ----------------------- | ------- |
| `200`     | licensing.IssueResponse | ok      |
| `default` | problem-details         | refused |

`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 (int64) | —      | 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](https://docs.hanzo.ai/docs/errors).

## Examples

**CLI**

```bash
hanzo licensing issue --product <product>
```

**SDK**

**.ts**

```ts
import { Configuration, LicensingApi } from 'hanzoai';

const api = new LicensingApi(new Configuration({ accessToken: process.env.HANZO_API_KEY }));
const { data } = await api.postLicensingIssue({ product: "<product>" });
```

**.py**

```python
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>")
```

**.go**

```go
cfg := hanzoai.NewConfiguration()
cfg.AddDefaultHeader("Authorization", "Bearer "+os.Getenv("HANZO_API_KEY"))
client := hanzoai.NewAPIClient(cfg)

resp, _, err := client.LicensingAPI.PostLicensingIssue(context.Background()).Execute()
if err != nil {
	return err
}
```

**.rs**

```rust
use hanzo_client::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?;
```

**.java**

```java
import ai.hanzo.cloud.ApiClient;
import ai.hanzo.cloud.api.LicensingApi;

ApiClient client = new ApiClient();
client.setBearerToken(System.getenv("HANZO_API_KEY"));

var result = new LicensingApi(client).postLicensingIssue();
```

**HTTP**

```bash
curl -X POST https://api.hanzo.ai/v1/licensing/issue \
  -H "Authorization: Bearer $HANZO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
       "product": "<product>"
     }'
```

**MCP**

MCP reaches **licensing** through the `licensing` tool, which names its 9 operations with its own verbs — this one among them, under a name only MCP declares. `describe` explains any of them:

```bash
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"
         }
       }
     }'
```

---

[Licensing API](https://docs.hanzo.ai/docs/openapi/licensing) · [All Hanzo APIs](https://docs.hanzo.ai/docs/openapi) · [Interactive reference](https://docs.hanzo.ai/docs/openapi/reference)
