# License API

Source: https://userguide.qualytics.io/self-hosted/license/api/

*Deployment availability: Self-hosted.*

The License API allows you to check the license status, generate license request codes, and apply signed licenses programmatically.

> **Tip**
>
> For complete API documentation, including request/response schemas, visit the [API docs](https://userguide.qualytics.io/api/docs).

All endpoints use the base URL of your Qualytics deployment (for example, `https://your-instance.qualytics.io/api`).

In the examples, `YOUR_TOKEN` is an API token for a Qualytics user with the **Admin** role. It is not the container registry token, deployment identifier, license request, or signed license.

---

## Get License Info

Retrieve the license expiration date, deployment type, and grace period information.

**Endpoint**: `GET /api/license/expiration`

**Permission**: Admin user role

> **Example: Example request and response**
>
> **Request**:
>
> ```bash
> curl -X GET "https://your-instance.qualytics.io/api/license/expiration" \
>   -H "Authorization: Bearer YOUR_TOKEN"
> ```
>
> **Response** (active license):
>
> ```json
> {
>   "license_expiration": "2027-12-30T21:00:00Z",
>   "is_saas_deployment": false,
>   "days_since_first_db_creation": 45
> }
> ```
>
> **Response** (no license):
>
> ```json
> {
>   "license_expiration": null,
>   "is_saas_deployment": false,
>   "days_since_first_db_creation": 10
> }
> ```

### Response Schema

| Field | Type | Description |
| --- | --- | --- |
| `license_expiration` | `datetime` or `null` | The license expiration date in UTC. `null` if no license exists. |
| `is_saas_deployment` | `boolean` | If `true`, this is a managed deployment and the UI hides license management. |
| `days_since_first_db_creation` | `integer` or `null` | Days since the first **datastore** was created (the field name uses `db` as shorthand for datastore, not database). Used to calculate the remaining days in the 31-day grace period. `null` if no datastores exist. |

For the UI equivalent, see the [Introduction](https://userguide.qualytics.io/self-hosted/license/deep-dive/how-it-works/) page.

---

## Generate License Request

Generate an encoded license request code for an initial or renewed signed license.

**Endpoint**: `GET /api/license/request`

**Permission**: Admin user role

> **Example: Example request and response**
>
> **Request**:
>
> ```bash
> curl -X GET "https://your-instance.qualytics.io/api/license/request" \
>   -H "Authorization: Bearer YOUR_TOKEN"
> ```
>
> **Response**:
>
> ```json
> {
>   "license_request": "eJyrVkrOz0nVUbJSKs9ILUpVslIqS8wpTgUA..."
> }
> ```

### Response Schema

| Field | Type | Description |
| --- | --- | --- |
| `license_request` | `string` | An encoded license request containing your deployment's fingerprint. Contact your Qualytics account team or [support team](mailto:support@qualytics.ai) to arrange an approved secure transfer method for the request and signed license. Do not place either value in ordinary email. |

For the UI equivalent, see the [Generate License Request](https://userguide.qualytics.io/self-hosted/license/how-tos/generate-license-request/) page.

---

## Assign License

Apply a new or renewed signed license to the deployment.

> **Note**
>
> This endpoint is called **Assign License** in the API, but corresponds to the **Update License** button in the UI. Both apply a signed license to the deployment.

**Endpoint**: `POST /api/license/assign`

**Permission**: Admin user role

**Request Body**:

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `signed_license` | `string` | Yes | An unexpired signed license from Qualytics. |

> **Example: Example request**
>
> **Request**:
>
> ```bash
> curl -X POST "https://your-instance.qualytics.io/api/license/assign" \
>   -H "Authorization: Bearer YOUR_TOKEN" \
>   -H "Content-Type: application/json" \
>   -d '{
>     "signed_license": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9..."
>   }'
> ```
>
> **Response**: `204 No Content` (empty body)

For the UI equivalent, see the [Update License](https://userguide.qualytics.io/self-hosted/license/how-tos/update-license/) page.

---

## Error Responses

| Status Code | Description |
| --- | --- |
| `400 Bad Request` | Invalid signed license due to its signature, format, expiration, or fingerprint. Also returned when deployment data is in an invalid state. |
| `401 Unauthorized` | Missing or invalid API token. |
| `403 Forbidden` | User does not have the Admin role. |

> **Example: Error response examples**
>
> **403 Forbidden**:
>
> ```json
> { "detail": "Not enough permissions" }
> ```
>
> **400 Bad Request** (invalid license signature):
>
> ```json
> { "detail": "Invalid license signature. Please contact your Qualytics account manager for assistance." }
> ```
>
> **400 Bad Request** (expired license):
>
> ```json
> { "detail": "License has expired. Please contact your Qualytics account manager for assistance" }
> ```
>
> **400 Bad Request** (fingerprint mismatch):
>
> ```json
> { "detail": "License is invalid due to fingerprint mismatch. Please contact your Qualytics account manager for assistance" }
> ```
>
> **400 Bad Request** (invalid format):
>
> ```json
> { "detail": "Invalid license format: Expecting value" }
> ```
>
> **400 Bad Request** (missing required field):
>
> ```json
> { "detail": "Missing required field in license: expiration_time" }
> ```
>
> **400 Bad Request** (invalid deployment state):
>
> ```json
> { "detail": "This deployment's data is in an invalid state. Please contact your Qualytics account representative" }
> ```
>
> **400 Bad Request** (grace period exceeded, no license):
>
> ```json
> { "detail": "A license is required after 31 days of datastore connectivity. Please contact your Qualytics account representative" }
> ```

---

## Permission Summary

| Operation | Minimum Permission |
| --- | --- |
| Get license info | Admin user role |
| Generate license request | Admin user role |
| Assign license | Admin user role |

> **Info**
>
> All License API endpoints require the **Admin** role. See the [Permissions](https://userguide.qualytics.io/self-hosted/license/deep-dive/permissions/) page for the full matrix.

*Last updated: July 27, 2026.*
