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

# Licenses

> Issue and revoke org licenses.

# Licenses

Base: `/v1/licenses`. Authenticate with an API key:

```http theme={"system"}
Authorization: Bearer sk_live_…
```

| Method   | Path           | Body / params                                                                     | Notes                                                                |
| -------- | -------------- | --------------------------------------------------------------------------------- | -------------------------------------------------------------------- |
| `POST`   | `/`            | `{ customer_id, expires_at?, external_license_id? }`                              | `201` — `license_key` under `data`, returned **once**                |
| `GET`    | `/`            | `?customer_id=` (required), `?external_license_id=`, optional `page` / `per_page` | `{ data, meta }`                                                     |
| `GET`    | `/:id`         | path                                                                              | Retrieve (no key hash) → `{ data }`                                  |
| `GET`    | `/:id/devices` | optional `?status=`, `page` / `per_page`                                          | Devices on this license (all statuses by default) → `{ data, meta }` |
| `POST`   | `/:id/revoke`  | —                                                                                 | Revoke license (no linked `pending`/`enrolled` devices) → `{ data }` |
| `DELETE` | `/:id`         | path                                                                              | Must already be **revoked** → `{ data: { ok: true } }`               |

Wrong-org access returns `404` (no existence oracle).

## External id

Optional `external_license_id` (string, max 200). Trimmed; empty → `null`. Unique per customer when set (`409` on conflict). Returned on license payloads. Filter list with `?external_license_id=` (still requires `customer_id`). There is no PATCH for licenses — set the id at create time.

## Create license

```bash theme={"system"}
curl -s -X POST "$API/v1/licenses" \
  -H "Authorization: Bearer $ORQUESTR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"customer_id":"ORG_UUID","expires_at":null,"external_license_id":"lic-pos-main"}'
```

| Field                 | Type           | Required | Notes                               |
| --------------------- | -------------- | -------- | ----------------------------------- |
| `customer_id`         | UUID           | Yes      |                                     |
| `expires_at`          | ISO datetime   | No       | `null` = no expiry                  |
| `external_license_id` | string \| null | No       | Integration id; unique per customer |

Response is `{ "data": { …, "license_key": "…", "max_devices": 1, … } }` — `license_key` is shown once.

## List licenses

```bash theme={"system"}
curl -s "$API/v1/licenses?customer_id=ORG_UUID&external_license_id=lic-pos-main" \
  -H "Authorization: Bearer $ORQUESTR_API_KEY"
```

Returns `{ data: License[], meta }`. Optional `page` / `per_page` (max 100); omit both for the full set.

## Revoke license

```bash theme={"system"}
curl -s -X POST "$API/v1/licenses/$LICENSE_ID/revoke" \
  -H "Authorization: Bearer $ORQUESTR_API_KEY"
```

Revokes the license and soft-revokes API keys / license tokens bound to it.

**Prerequisite:** every device on the license must already be **revoked** (no `pending` or `enrolled` rows). Unlink devices first with [`POST /v1/devices/{id}/revoke`](/api/devices).

If linked devices remain, the API returns **`409 conflict`** and includes the blocking device id(s):

```json theme={"system"}
{
  "error": {
    "code": "conflict",
    "message": "Cannot revoke license while devices are linked; revoke each device first",
    "details": {
      "device_id": "DEVICE_UUID",
      "device_ids": ["DEVICE_UUID"]
    }
  }
}
```

| Field                | Notes                                           |
| -------------------- | ----------------------------------------------- |
| `details.device_id`  | First blocking device (convenience)             |
| `details.device_ids` | All `pending` / `enrolled` devices still linked |

## List devices for a license

Returns every non-deleted device bound to the license — **`pending`**, **`enrolled`**, and **`revoked`** — unless you filter with `status`.

```bash theme={"system"}
# All statuses (pending + enrolled + revoked)
curl -s "$API/v1/licenses/$LICENSE_ID/devices" \
  -H "Authorization: Bearer $ORQUESTR_API_KEY"
```

```bash theme={"system"}
# Only enrolled (Gateway-activated) devices
curl -s "$API/v1/licenses/$LICENSE_ID/devices?status=enrolled" \
  -H "Authorization: Bearer $ORQUESTR_API_KEY"
```

```bash theme={"system"}
# Only revoked devices
curl -s "$API/v1/licenses/$LICENSE_ID/devices?status=revoked" \
  -H "Authorization: Bearer $ORQUESTR_API_KEY"
```

| Query      | Required | Notes                                            |
| ---------- | -------- | ------------------------------------------------ |
| `status`   | No       | `pending` · `enrolled` · `revoked`. Omit for all |
| `page`     | No       | Pagination                                       |
| `per_page` | No       | Max 100; omit both for the full set              |

Response: `{ data: Device[], meta }`. Revoked rows sort after active ones. Example payloads:

```json theme={"system"}
{
  "data": [
    {
      "id": "…",
      "license_id": "LICENSE_UUID",
      "name": "Caja 1",
      "status": "enrolled",
      "adapter": "sicarv4"
    },
    {
      "id": "…",
      "license_id": "LICENSE_UUID",
      "name": "Caja vieja",
      "status": "revoked",
      "revoked_at": "2026-09-01T18:22:00.000Z"
    }
  ],
  "meta": { "page": 1, "per_page": 2, "total_pages": 1, "total_count": 2 }
}
```

Requires `devices.read` (account API key) or a product key for that license.

## Delete license

```bash theme={"system"}
curl -s -X DELETE "$API/v1/licenses/$LICENSE_ID" \
  -H "Authorization: Bearer $ORQUESTR_API_KEY"
```

Only **revoked** licenses can be deleted (`409` otherwise). Success: `{ "data": { "ok": true } }`.
