> ## Documentation Index
> Fetch the complete documentation index at: https://docs.ancestraldev.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Avalex Licenses API — Issue, Update, and Delete Licenses

> Issue, update, and manage software licenses via the Avalex API. Control HWID and IP binding slots, expiration, and view validation history.

The `/licenses` resource is the core of Avalex's licensing system. A license ties a specific product to a specific customer and controls how, where, and for how long their software can run. Each license tracks which IP addresses and hardware IDs (HWIDs) have been bound to it, records every validation attempt, and carries a version counter for safe concurrent updates. You can issue licenses manually, adjust slot limits, extend expiry dates, and clear bound devices — all through this API.

## Required Permissions

| Action                   | Permission        |
| ------------------------ | ----------------- |
| List / retrieve licenses | `licenses:read`   |
| Create / update licenses | `licenses:write`  |
| Delete licenses          | `licenses:delete` |

***

## List All Licenses

<ParamField header="Authorization" type="string" required>
  Bearer `<token>` or Basic credentials.
</ParamField>

Returns an array of all license records in your Avalex account.

```bash theme={null}
curl http://localhost:8080/licenses \
  -H "Authorization: Bearer <token>"
```

**Response — 200 OK**

```json theme={null}
[
  {
    "id": "lic_12345",
    "productId": "prod_123",
    "customerId": "cust_123",
    "expiresAtEpochMillis": 1754676000000,
    "maxIps": 5,
    "maxHwids": 2,
    "usedIps": ["192.168.1.1"],
    "usedHwids": ["HWID-A1B2"],
    "version": 1,
    "validationAttempts": [],
    "createdAtEpochMillis": 1723140000000
  }
]
```

***

## Create a License

<ParamField header="Authorization" type="string" required>
  Bearer `<token>` or Basic credentials.
</ParamField>

<ParamField body="productId" type="string" required>
  ID of the product this license is issued for.
</ParamField>

<ParamField body="customerId" type="string" required>
  ID of the customer who owns this license.
</ParamField>

<ParamField body="expiresAtEpochMillis" type="number | null">
  Expiry timestamp in milliseconds. Set to `null` for a perpetual (never-expiring) license.
</ParamField>

<ParamField body="maxIps" type="integer | null">
  Maximum number of IP addresses this license may bind to. Overrides the product-level default. Set to `null` for unlimited.
</ParamField>

<ParamField body="maxHwids" type="integer | null">
  Maximum number of hardware IDs this license may bind to. Overrides the product-level default. Set to `null` for unlimited.
</ParamField>

Creates a new license and returns the created record.

```bash theme={null}
curl -X POST http://localhost:8080/licenses \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{
    "productId": "prod_123",
    "customerId": "cust_123",
    "expiresAtEpochMillis": 1754676000000,
    "maxIps": 5,
    "maxHwids": 2
  }'
```

**Response — 201 Created**

```json theme={null}
{
  "id": "lic_12345",
  "productId": "prod_123",
  "customerId": "cust_123",
  "expiresAtEpochMillis": 1754676000000,
  "maxIps": 5,
  "maxHwids": 2,
  "usedIps": [],
  "usedHwids": [],
  "version": 1,
  "validationAttempts": [],
  "createdAtEpochMillis": 1723140000000
}
```

***

## Get a License by ID

<ParamField path="id" type="string" required>
  The unique license ID (e.g. `lic_12345`).
</ParamField>

Returns a single license record including its current bound IPs, HWIDs, and validation history. Responds with `404 Not Found` if the license does not exist.

```bash theme={null}
curl http://localhost:8080/licenses/lic_12345 \
  -H "Authorization: Bearer <token>"
```

**Response — 200 OK**

```json theme={null}
{
  "id": "lic_12345",
  "productId": "prod_123",
  "customerId": "cust_123",
  "expiresAtEpochMillis": 1754676000000,
  "maxIps": 5,
  "maxHwids": 2,
  "usedIps": ["192.168.1.1"],
  "usedHwids": ["HWID-A1B2"],
  "version": 1,
  "validationAttempts": [
    {
      "hwid": "HWID-A1B2",
      "ip": "192.168.1.1",
      "timestampEpochMillis": 1723140500000,
      "successful": true
    }
  ],
  "createdAtEpochMillis": 1723140000000
}
```

***

## Update a License

<ParamField path="id" type="string" required>
  The unique license ID.
</ParamField>

Performs a full replacement of the license record. You must include all fields you want to retain. Returns `404 Not Found` if the license does not exist.

<Note>
  This is a full replacement (`PUT`). To remove a bound HWID or IP address, omit it from the `usedHwids` or `usedIps` arrays in your request body. Any entries you include will be retained; any you omit will be cleared.
</Note>

```bash theme={null}
curl -X PUT http://localhost:8080/licenses/lic_12345 \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{
    "productId": "prod_123",
    "customerId": "cust_123",
    "expiresAtEpochMillis": 1786212000000,
    "maxIps": 5,
    "maxHwids": 2,
    "usedIps": ["192.168.1.1"],
    "usedHwids": [],
    "version": 1,
    "validationAttempts": []
  }'
```

**Response — 200 OK**

```json theme={null}
{
  "id": "lic_12345",
  "productId": "prod_123",
  "customerId": "cust_123",
  "expiresAtEpochMillis": 1786212000000,
  "maxIps": 5,
  "maxHwids": 2,
  "usedIps": ["192.168.1.1"],
  "usedHwids": [],
  "version": 2,
  "validationAttempts": [],
  "createdAtEpochMillis": 1723140000000
}
```

***

## Delete a License

<ParamField path="id" type="string" required>
  The unique license ID.
</ParamField>

Permanently removes the license record. Returns `204 No Content` on success and `404 Not Found` if the ID does not exist.

```bash theme={null}
curl -X DELETE http://localhost:8080/licenses/lic_12345 \
  -H "Authorization: Bearer <token>"
```

**Response — 204 No Content**

***

## License Schema

<Expandable title="License fields">
  <ResponseField name="id" type="string">
    Unique identifier for the license, assigned by Avalex on creation (e.g. `lic_12345`).
  </ResponseField>

  <ResponseField name="productId" type="string">
    ID of the product this license was issued for.
  </ResponseField>

  <ResponseField name="customerId" type="string">
    ID of the customer who holds this license.
  </ResponseField>

  <ResponseField name="expiresAtEpochMillis" type="number | null">
    Expiry timestamp in milliseconds. `null` indicates the license never expires.
  </ResponseField>

  <ResponseField name="maxIps" type="integer | null">
    Maximum number of IP addresses that can be bound to this license. `null` means unlimited. Overrides the product-level default when set explicitly.
  </ResponseField>

  <ResponseField name="maxHwids" type="integer | null">
    Maximum number of hardware IDs that can be bound to this license. `null` means unlimited. Overrides the product-level default when set explicitly.
  </ResponseField>

  <ResponseField name="usedIps" type="string[]">
    Array of IP address strings currently bound to this license.
  </ResponseField>

  <ResponseField name="usedHwids" type="string[]">
    Array of hardware ID strings currently bound to this license.
  </ResponseField>

  <ResponseField name="version" type="integer">
    Monotonically incrementing version counter used for optimistic concurrency control. The server increments this on every successful update.
  </ResponseField>

  <ResponseField name="validationAttempts" type="array">
    Array of validation attempt objects recorded when the license is checked by client software.

    <Expandable title="ValidationAttempt fields">
      <ResponseField name="hwid" type="string">
        Hardware ID presented during the validation attempt.
      </ResponseField>

      <ResponseField name="ip" type="string">
        IP address from which the validation was made.
      </ResponseField>

      <ResponseField name="timestampEpochMillis" type="number">
        Unix timestamp in milliseconds of when the attempt occurred.
      </ResponseField>

      <ResponseField name="successful" type="boolean">
        Whether the validation attempt succeeded.
      </ResponseField>
    </Expandable>
  </ResponseField>

  <ResponseField name="createdAtEpochMillis" type="number">
    Unix timestamp in milliseconds representing when this license was created.
  </ResponseField>
</Expandable>

### Full Schema Example

```json theme={null}
{
  "id": "lic_12345",
  "productId": "prod_123",
  "customerId": "cust_123",
  "expiresAtEpochMillis": 1754676000000,
  "maxIps": 5,
  "maxHwids": 2,
  "usedIps": ["192.168.1.1"],
  "usedHwids": ["HWID-A1B2"],
  "version": 1,
  "validationAttempts": [
    {
      "hwid": "HWID-A1B2",
      "ip": "192.168.1.1",
      "timestampEpochMillis": 1723140500000,
      "successful": true
    }
  ],
  "createdAtEpochMillis": 1723140000000
}
```
