> For the complete documentation index, see [llms.txt](https://docs.denvrdata.com/docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.denvrdata.com/docs/platform/api-keys.md).

# API Keys

Long-lived, scoped credentials for API and automation access

API keys let you call the Denvr AI Cloud API from scripts, CI/CD pipelines, and applications without embedding your username and password, and without re-authenticating every day.

An API key is a long-lived credential issued to **your** user account. It is built on the same token mechanism as the interactive login, with two differences:

* **Longer lifetime.** A login access token expires after 24 hours. An API key can be valid for up to a year.
* **Scoped permissions.** A login token carries every permission your account has. An API key can be restricted to a subset of them.

|               | Login access token                 | API key                                   |
| ------------- | ---------------------------------- | ----------------------------------------- |
| Obtained from | `POST /api/TokenAuth/Authenticate` | Dashboard → `Administration` → `API Keys` |
| Lifetime      | 24 hours                           | Up to 1 year (you choose)                 |
| Permissions   | All permissions of your account    | All, or a subset you select               |
| Renewal       | Refresh token                      | Create a new key                          |
| Header        | `Authorization: Bearer <token>`    | `Authorization: ApiKey <token>`           |

{% hint style="warning" %}
An API key is a password-equivalent secret. Anyone who obtains it can act as you, with the permissions the key carries, until it expires or you revoke it.
{% endhint %}

### Before you begin

* Your account needs the `API Keys` permission. If you do not see `API Keys` under `Administration`, please contact the support team to enable it for your account - see [Technical support.](/docs/overview/getting-started.md)
* Each user may hold up to **10** active API keys at a time. Revoke one before creating another if you reach the limit.
* API keys belong to the user who created them. You can only see and revoke your own.

### Creating an API key

1. In the dashboard, go to `Administration` → `API Keys` and select `Create API key`.
2. Enter a **Description**. This is how you will recognize the key later, so name it after where it will be used - for example `ci-nightly-benchmarks` or `terraform-hou1`.
3. Choose an **Expiration**: one week, one month, three months, six months, one year, or a custom date and time. Prefer the shortest period that covers the job - a key that expires is a key that cannot be abused forever.
4. Choose the **Permissions** for the key:
   * **Use all user permissions** - the key can do everything your account can do. Its effective rights follow your account, so if your role changes later, the key changes with it.
   * **Use specific permissions** - pick individual permissions from the tree. Selecting a child permission automatically selects its parents.

{% hint style="info" %}
A key never grants more than its owner has. The effective permissions are the **intersection** of the permissions selected on the key and the permissions your account holds at the time of the request. If an administrator removes a permission from your role, every key you own loses it too.
{% endhint %}

5. Select `Create API key`. The key is displayed once.
6. Copy the key and store it in a password manager, a secrets vault, or your CI system's encrypted secret store. Then select `I have saved my API key`.

{% hint style="danger" %}
Denvr does not store the key and cannot recover it for you - only the last 12 characters are kept, so that you can identify the key in the list. If you lose the key, revoke it and create a new one.
{% endhint %}

### Using an API key

Send the key in the `Authorization` header using the `ApiKey` scheme:

```
curl -X 'GET' \
  'https://api.cloud.denvrdata.com/api/v1/clusters/GetAll' \
  -H 'accept: */*' \
  -H 'Content-Type: application/json-patch+json' \
  -H 'Authorization: ApiKey eyJhbGciOiJIUzI1NiIsInR5cC...'
```

Response:

```
{
    "result": [
        "Hou1","Msc1"
    ],
    "targetUrl": null,
    "success": true,
    "error": null,
    "unAuthorizedRequest": false,
    "__abp": true
}
```

The same header works for write operations:

```
curl -X 'POST' \
  'https://api.cloud.denvrdata.com/api/v1/servers/virtual/CreateServer' \
  -H 'accept: */*' \
  -H 'Content-Type: application/json-patch+json' \
  -H 'Authorization: ApiKey eyJhbGciOiJIUzI1NiIsInR5cC...' \
  -d '{
  "name": "my-test-vm",
  "rpool": "on-demand",
  "vpc": "YOUR_VPC_NAME",
  "configuration": "A100_80GB_SXM_1x",
  "cluster": "Hou1",
  "ssh_keys": [
    "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQC..."
  ],
  "operatingSystemImage": "Ubuntu 22.04.4 LTS",
  "rootDiskSize": 500
}'
```

In Python, read the key from the environment rather than hard-coding it:

```python
import os
import requests

BASE_URL = "https://api.cloud.denvrdata.com"
headers = {"Authorization": f"ApiKey {os.environ['DENVR_API_KEY']}"}

response = requests.get(f"{BASE_URL}/api/v1/clusters/GetAll", headers=headers)
response.raise_for_status()
print(response.json()["result"])
```

Every endpoint in the API Reference accepts an API key in place of a login token, except `POST /api/TokenAuth/Authenticate` and `POST /api/TokenAuth/RefreshToken`, which exist to issue login tokens and do not need one.

### Reviewing your API keys

`Administration` → `API Keys` lists the keys you own:

| Column          | Meaning                                                         |
| --------------- | --------------------------------------------------------------- |
| Token suffix    | The last 12 characters of the key, used to tell your keys apart |
| Description     | The name you gave the key                                       |
| Permissions     | The permissions selected for the key, or `All user permissions` |
| Expiration date | When the key stops working. Past dates are shown in red         |

Use `Actions` → `View` to see the full details of a key. The key itself is not shown - only its metadata.

### Revoking an API key

Revoke a key as soon as it is no longer needed, and immediately if you suspect it has been exposed - committed to a repository, pasted into a ticket, or written to a build log.

1. Go to `Administration` → `API Keys`.
2. Find the key by its description or token suffix.
3. Select `Actions` → `Revoke`.
4. Type the key's **token suffix** into the confirmation box and select `Revoke`.

Revocation takes effect immediately. Any request presenting the revoked key is rejected. Revocation cannot be undone - issue a new key and update your automation.

Keys also stop working on their own at the expiration date. Expired keys remain in the list so you can see what existed; revoke them to free up a slot against the 10-key limit.

### Good practice

* **Give each consumer its own key.** One key per pipeline, per host, per service. When one is compromised you revoke only that one, and the description tells you what will break.
* **Scope the key down.** If a job only reads cluster and VM state, do not give it permission to create servers or manage users.
* **Set a short expiration and rotate.** Create the new key, deploy it, verify, then revoke the old one - no downtime.
* **Never commit a key.** Use your CI provider's secret store, a secrets manager, or an environment variable loaded at runtime. Add `.env` files to `.gitignore`.
* **Never put a key in a URL.** URLs are recorded in browser history, proxy logs, and `Referer` headers. Always use the `Authorization` header.
* **Revoke on offboarding.** When someone leaves the team, have them revoke their keys, or delete the user account.

### Troubleshooting

| Symptom                                              | Cause                                                        | What to do                                                                                                                                                                         |
| ---------------------------------------------------- | ------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `401` or `"unAuthorizedRequest": true` on every call | Header is malformed, or the key has expired or been revoked  | Confirm the header reads `Authorization: ApiKey <key>`. The scheme name is case-insensitive, but the space after it is required. Check the key's expiration date in the dashboard. |
| `403` on some calls, others succeed                  | The key is scoped and lacks the permission for that endpoint | Create a new key with the required permission selected, or use `Use all user permissions`.                                                                                         |
| A previously working key starts returning `403`      | A permission was removed from your account or role           | Contact the support team to review the permissions on your account.                                                                                                                |
| `API Keys` not listed under `Administration`         | Your account does not have the `API Keys` permission         | Contact the support team to enable it for your account.                                                                                                                            |
| `You have reached the maximum limit of 10 API keys`  | The per-user key limit                                       | Revoke a key you no longer use.                                                                                                                                                    |

If a key has been exposed publicly, revoke it first and then contact Technical support.
