Licenses
Licenses are the core resource in Licentric. Each license is bound to a product and governed by a policy that defines its constraints.
Create License
/licensesCreate a new license key. Requires API Key auth with licenses:write scope.
Request Body
| Parameter | Type | Required | Description |
|---|---|---|---|
| productId | uuid | Required | ID of the product this license belongs to |
| policyId | uuid | Required | ID of the policy governing this license |
| name | string | Optional | Display name for the license (max 255 chars) |
| expiresAt | datetime | Optional | Expiration date in ISO 8601 format |
| maxMachinesOverride | integer | null | Optional | Override the policy machine limit for this license |
| maxUsesOverride | integer | null | Optional | Override the policy usage limit for this license |
| userEmail | Optional | Email address of the license holder | |
| userName | string | Optional | Name of the license holder (max 255 chars) |
| entitlementIds | uuid[] | Optional | Array of entitlement IDs to attach to this license |
| metadata | object | Optional | Arbitrary key-value metadata |
{
"productId": "d9e5f0a1-4c82-5e6f-a023-9b7c4d8e5f60",
"policyId": "e0f1a2b3-5d93-6f70-b134-ac8d5e9f6071",
"name": "Enterprise License",
"userEmail": "jane@example.com",
"userName": "Jane Doe",
"expiresAt": "2027-01-15T00:00:00.000Z",
"entitlementIds": ["a1b2c3d4-1111-2222-3333-444455556666"],
"metadata": { "company": "Acme Corp" }
}{
"data": {
"id": "c8f4e9a2-3b71-4d5e-9f12-8a6b3c7d4e5f",
"key": "DSK-A1B2-C3D4-E5F6-G7H8",
"name": "Enterprise License",
"status": "active",
"productId": "d9e5f0a1-4c82-5e6f-a023-9b7c4d8e5f60",
"policyId": "e0f1a2b3-5d93-6f70-b134-ac8d5e9f6071",
"userEmail": "jane@example.com",
"userName": "Jane Doe",
"expiresAt": "2027-01-15T00:00:00.000Z",
"maxMachinesOverride": null,
"maxUsesOverride": null,
"usesCount": 12,
"machineCount": 1,
"entitlements": ["feature_export", "feature_analytics"],
"createdAt": "2026-01-15T10:30:00.000Z",
"updatedAt": "2026-01-15T10:30:00.000Z",
"deletedAt": null,
"metadata": {}
}
}List Licenses
/licensesList licenses with cursor-based pagination and optional filters. Requires API Key auth with licenses:read scope.
Query Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| status | string | Optional | Filter by status: active, expired, suspended, revoked |
| productId | uuid | Optional | Filter by product ID |
| cursor | uuid | Optional | Pagination cursor from previous response |
| limit | integer | Optional | Results per page (1-100, default 25) |
GET /api/v1/licenses?status=active&productId=d9e5f0a1-4c82-5e6f-a023-9b7c4d8e5f60&limit=10{
"data": [{
"id": "c8f4e9a2-3b71-4d5e-9f12-8a6b3c7d4e5f",
"key": "DSK-A1B2-C3D4-E5F6-G7H8",
"name": "Enterprise License",
"status": "active",
"productId": "d9e5f0a1-4c82-5e6f-a023-9b7c4d8e5f60",
"policyId": "e0f1a2b3-5d93-6f70-b134-ac8d5e9f6071",
"userEmail": "jane@example.com",
"userName": "Jane Doe",
"expiresAt": "2027-01-15T00:00:00.000Z",
"maxMachinesOverride": null,
"maxUsesOverride": null,
"usesCount": 12,
"machineCount": 1,
"entitlements": ["feature_export", "feature_analytics"],
"createdAt": "2026-01-15T10:30:00.000Z",
"updatedAt": "2026-01-15T10:30:00.000Z",
"deletedAt": null,
"metadata": {}
}
}],
"pagination": { "nextCursor": "c8f4e9a2-3b71-4d5e-9f12-8a6b3c7d4e5f", "hasMore": true }
}Get License
/licenses/:idRetrieve a single license by ID. Requires API Key auth with licenses:read scope.
GET /api/v1/licenses/c8f4e9a2-3b71-4d5e-9f12-8a6b3c7d4e5f{
"data": {
"id": "c8f4e9a2-3b71-4d5e-9f12-8a6b3c7d4e5f",
"key": "DSK-A1B2-C3D4-E5F6-G7H8",
"name": "Enterprise License",
"status": "active",
"productId": "d9e5f0a1-4c82-5e6f-a023-9b7c4d8e5f60",
"policyId": "e0f1a2b3-5d93-6f70-b134-ac8d5e9f6071",
"userEmail": "jane@example.com",
"userName": "Jane Doe",
"expiresAt": "2027-01-15T00:00:00.000Z",
"maxMachinesOverride": null,
"maxUsesOverride": null,
"usesCount": 12,
"machineCount": 1,
"entitlements": ["feature_export", "feature_analytics"],
"createdAt": "2026-01-15T10:30:00.000Z",
"updatedAt": "2026-01-15T10:30:00.000Z",
"deletedAt": null,
"metadata": {}
}
}Update License
/licenses/:idUpdate a license. Only provided fields are changed. Requires API Key auth with licenses:write scope.
Request Body
| Parameter | Type | Required | Description |
|---|---|---|---|
| name | string | Optional | Updated display name (max 255 chars) |
| expiresAt | datetime | null | Optional | Updated expiration date, or null to remove |
| maxMachinesOverride | integer | null | Optional | Updated machine limit override |
| maxUsesOverride | integer | null | Optional | Updated usage limit override |
| userEmail | email | null | Optional | Updated license holder email |
| userName | string | null | Optional | Updated license holder name |
| metadata | object | Optional | Merged with existing metadata |
{
"name": "Enterprise License v2",
"expiresAt": "2027-06-30T23:59:59.000Z",
"metadata": { "company": "Acme Corp", "plan": "enterprise" }
}{
"data": {
"id": "c8f4e9a2-3b71-4d5e-9f12-8a6b3c7d4e5f",
"key": "DSK-A1B2-C3D4-E5F6-G7H8",
"name": "Enterprise License",
"status": "active",
"productId": "d9e5f0a1-4c82-5e6f-a023-9b7c4d8e5f60",
"policyId": "e0f1a2b3-5d93-6f70-b134-ac8d5e9f6071",
"userEmail": "jane@example.com",
"userName": "Jane Doe",
"expiresAt": "2027-01-15T00:00:00.000Z",
"maxMachinesOverride": null,
"maxUsesOverride": null,
"usesCount": 12,
"machineCount": 1,
"entitlements": ["feature_export", "feature_analytics"],
"createdAt": "2026-01-15T10:30:00.000Z",
"updatedAt": "2026-01-15T10:30:00.000Z",
"deletedAt": null,
"metadata": {}
}
}Delete License
/licenses/:idSoft-delete a license. Sets the deletedAt timestamp. Requires API Key auth with licenses:write scope.
DELETE /api/v1/licenses/c8f4e9a2-3b71-4d5e-9f12-8a6b3c7d4e5f{ "data": { "id": "c8f4e9a2-3b71-4d5e-9f12-8a6b3c7d4e5f", "deleted": true } }Validate by Key
/licenses/validate-keyValidate a license using its raw key. No authentication required -- the key is provided in the request body.
Request Body
| Parameter | Type | Required | Description |
|---|---|---|---|
| key | string | Required | The full license key (e.g. DSK-A1B2-C3D4-E5F6-G7H8) |
| fingerprint | string | Optional | Machine fingerprint to validate against |
| entitlements | string[] | Optional | Entitlement codes to check for |
{
"key": "DSK-A1B2-C3D4-E5F6-G7H8",
"fingerprint": "hw-a1b2c3d4e5f6",
"entitlements": ["feature_export"]
}{
"data": {
"valid": true,
"code": "VALID",
"license": {
"id": "c8f4e9a2-3b71-4d5e-9f12-8a6b3c7d4e5f",
"name": "Enterprise License",
"status": "active",
"expiresAt": "2027-01-15T00:00:00.000Z"
},
"machine": {
"id": "f1a2b3c4-6e04-7081-c245-bd9e6f0a1b82",
"fingerprint": "hw-a1b2c3d4e5f6",
"name": "Dev Laptop"
},
"entitlements": ["feature_export", "feature_analytics"],
"metadata": {}
}
}Validation Codes
| Code | Description |
|---|---|
| VALID | License is valid and active |
| EXPIRED | License has passed its expiration date |
| SUSPENDED | License has been suspended |
| REVOKED | License has been permanently revoked |
| BANNED | License has been banned |
| NOT_FOUND | No license exists with the provided key |
| FINGERPRINT_NOT_FOUND | Machine fingerprint not activated |
| MACHINE_LIMIT_EXCEEDED | Maximum machine activations reached |
| HEARTBEAT_REQUIRED | Machine heartbeat is required but expired |
| USES_EXCEEDED | Maximum validation count exceeded |
| ENTITLEMENTS_MISSING | Required entitlements not attached |
Validate by ID
/licenses/:id/validateValidate a license by its ID. Requires API Key auth with licenses:read scope.
Request Body
| Parameter | Type | Required | Description |
|---|---|---|---|
| fingerprint | string | Optional | Machine fingerprint to validate against |
| entitlements | string[] | Optional | Entitlement codes to check for |
{
"data": {
"valid": true,
"code": "VALID",
"license": {
"id": "c8f4e9a2-3b71-4d5e-9f12-8a6b3c7d4e5f",
"name": "Enterprise License",
"status": "active",
"expiresAt": "2027-01-15T00:00:00.000Z"
},
"machine": {
"id": "f1a2b3c4-6e04-7081-c245-bd9e6f0a1b82",
"fingerprint": "hw-a1b2c3d4e5f6",
"name": "Dev Laptop"
},
"entitlements": ["feature_export", "feature_analytics"],
"metadata": {}
}
}Suspend License
/licenses/:id/suspendSuspend an active license. Requires API Key auth with licenses:write scope.
POST /api/v1/licenses/c8f4e9a2-3b71-4d5e-9f12-8a6b3c7d4e5f/suspend{
"data": {
"id": "c8f4e9a2-3b71-4d5e-9f12-8a6b3c7d4e5f",
"status": "suspended",
"updatedAt": "2026-03-01T14:00:00.000Z"
}
}Reinstate License
/licenses/:id/reinstateReinstate a suspended or expired license. Requires API Key auth with licenses:write scope.
POST /api/v1/licenses/c8f4e9a2-3b71-4d5e-9f12-8a6b3c7d4e5f/reinstate{
"data": {
"id": "c8f4e9a2-3b71-4d5e-9f12-8a6b3c7d4e5f",
"status": "active",
"updatedAt": "2026-03-01T14:05:00.000Z"
}
}Renew License
/licenses/:id/renewSet a new expiration date for a license. Requires API Key auth with licenses:write scope.
Request Body
| Parameter | Type | Required | Description |
|---|---|---|---|
| expiresAt | datetime | Required | New expiration date in ISO 8601 format |
{ "expiresAt": "2027-12-31T23:59:59.000Z" }{
"data": {
"id": "c8f4e9a2-3b71-4d5e-9f12-8a6b3c7d4e5f",
"status": "active",
"expiresAt": "2027-12-31T23:59:59.000Z",
"updatedAt": "2026-03-01T14:10:00.000Z"
}
}Offline Checkout
/licenses/:id/checkoutGenerate a signed offline license certificate. Requires API Key auth with licenses:read scope.
Request Body
| Parameter | Type | Required | Description |
|---|---|---|---|
| fingerprint | string | Required | Machine fingerprint (8-256 characters) |
| ttl | integer | Optional | Time-to-live in seconds (3600-7776000, default 1209600 = 14 days) |
{
"fingerprint": "hw-a1b2c3d4e5f6",
"ttl": 1209600
}{
"data": {
"certificate": "eyJhbGciOiJFZERTQSIsInR5cCI6IkpXVCJ9...",
"ttl": 1209600,
"expiresAt": "2026-01-29T10:30:00.000Z",
"fingerprint": "hw-a1b2c3d4e5f6"
}
}