License Management
CRUD endpoints for managing licenses. All management endpoints require session authentication.
List Licenses
GET
/api/v1/licensesFilter by project with ?projectId=uuid. Search within a project with &search=query (matches key and product name).
All license responses include a computed timeLeft field, which is the seconds remaining until the license expires. Returns null for licenses with no expiration.
Requestbash
curl "https://onyxauth.xyz/api/v1/licenses?projectId=a1b2c3d4-..." \
-H "Cookie: session-token=..."200 OKjson
{
"success": true,
"data": [
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"key": "A3F9-KM7X-P2VB-8NQT",
"productName": "My App",
"status": "active",
"maxActivations": 1,
"currentActivations": 0,
"expiresAt": "2026-12-31T23:59:59.000Z",
"timeLeft": 31536000,
"createdAt": "2026-01-15T10:30:00.000Z"
}
]
}Create License
POST
/api/v1/licensesRequest bodyjson
{
"productName": "My App",
"projectId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"maxActivations": 1,
"expiresAt": "2026-12-31T23:59:59Z",
"ipLocked": false,
"metadata": { "version": "2.0", "tier": "pro" },
"notes": "Customer #1234"
}Parameters
| Field | Type | Required | Description |
|---|---|---|---|
| productName | string | Yes | 1-255 characters |
| projectId | string | Yes | UUID of the project to assign this license to |
| maxActivations | number | No | 1-100, default: 1 |
| expiresAt | string | No | ISO 8601 datetime. Null = never expires |
| metadata | object | No | Arbitrary key-value pairs |
| ipLocked | boolean | No | Lock license to the IP of first activation. Default: false |
| notes | string | No | Internal notes, max 1000 chars |
201 Createdjson
{
"success": true,
"data": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"key": "A3F9-KM7X-P2VB-8NQT",
"productName": "My App",
"status": "active",
"maxActivations": 1,
"currentActivations": 0,
"expiresAt": "2026-12-31T23:59:59.000Z",
"timeLeft": 31536000
}
}403 - Plan limit reachedjson
{
"success": false,
"error": {
"code": "PLAN_LIMIT_REACHED",
"message": "You've reached your plan limit of 10 licenses. Upgrade to create more."
}
}Get License
GET
/api/v1/licenses/:id200 OKjson
{
"success": true,
"data": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"key": "A3F9-KM7X-P2VB-8NQT",
"productName": "My App",
"status": "active",
"maxActivations": 1,
"currentActivations": 1,
"expiresAt": "2026-12-31T23:59:59.000Z",
"timeLeft": 31536000,
"hardwareIds": [
{
"id": "...",
"fingerprintHash": "b3a1c9...",
"label": "Desktop-PC",
"lastSeen": "2026-01-20T15:00:00.000Z"
}
]
}
}Update License
PATCH
/api/v1/licenses/:idRequest bodyjson
{
"status": "suspended",
"maxActivations": 3,
"notes": "Upgraded to 3 seats",
"metadata": { "tier": "enterprise" },
"ipLocked": true
}Updatable Fields
| Field | Type | Description |
|---|---|---|
| productName | string | 1-255 characters |
| maxActivations | number | 1-100 |
| expiresAt | string | null | ISO 8601 or null to remove expiry |
| status | string | active, suspended, revoked, or expired |
| notes | string | Max 1000 chars |
| metadata | object | null | Custom key-value pairs. Set null to clear. |
| ipLocked | boolean | Enable/disable IP lock |
200 OKjson
{
"success": true,
"data": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"status": "suspended",
"maxActivations": 3,
"timeLeft": 31536000
}
}Delete License
DELETE
/api/v1/licenses/:id200 OKjson
{
"success": true,
"data": {
"deleted": true
}
}Reset Hardware Bindings
POST
/api/v1/licenses/:id/reset-hwidRemoves all stored hardware fingerprints for a license. The next validation call will bind the license to the new hardware. Useful when a customer replaces their machine.
200 OKjson
{
"success": true,
"data": {
"message": "Hardware bindings reset successfully"
}
}Error Responses
All management endpoints share these error responses:
401 - Not authenticatedjson
{
"success": false,
"error": {
"code": "UNAUTHORIZED",
"message": "Not authenticated"
}
}404 - License not foundjson
{
"success": false,
"error": {
"code": "NOT_FOUND",
"message": "License not found"
}
}400 - Validation errorjson
{
"success": false,
"error": {
"code": "VALIDATION_ERROR",
"message": "Invalid request data",
"details": [
{ "path": ["maxActivations"], "message": "Number must be at most 100" }
]
}
}Plan Limits
| Plan | Max Licenses | Max Validations |
|---|---|---|
| Free | 10 | 1,000/day |
| Developer (£4.99/mo or £24.99/yr) | 10,000 | 1M/day |