License Management

CRUD endpoints for managing licenses. All management endpoints require session authentication.

List Licenses

GET/api/v1/licenses

Filter 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/licenses
Request 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

FieldTypeRequiredDescription
productNamestringYes1-255 characters
projectIdstringYesUUID of the project to assign this license to
maxActivationsnumberNo1-100, default: 1
expiresAtstringNoISO 8601 datetime. Null = never expires
metadataobjectNoArbitrary key-value pairs
ipLockedbooleanNoLock license to the IP of first activation. Default: false
notesstringNoInternal 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/:id
200 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/:id
Request bodyjson
{
  "status": "suspended",
  "maxActivations": 3,
  "notes": "Upgraded to 3 seats",
  "metadata": { "tier": "enterprise" },
  "ipLocked": true
}

Updatable Fields

FieldTypeDescription
productNamestring1-255 characters
maxActivationsnumber1-100
expiresAtstring | nullISO 8601 or null to remove expiry
statusstringactive, suspended, revoked, or expired
notesstringMax 1000 chars
metadataobject | nullCustom key-value pairs. Set null to clear.
ipLockedbooleanEnable/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/:id
200 OKjson
{
  "success": true,
  "data": {
    "deleted": true
  }
}

Reset Hardware Bindings

POST/api/v1/licenses/:id/reset-hwid

Removes 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

PlanMax LicensesMax Validations
Free101,000/day
Developer (£4.99/mo or £24.99/yr)10,0001M/day