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

# API Keys

> Create and manage API keys for your district via the API.

API keys let you authenticate programmatic access to your district's data. Each key carries specific scopes that limit what it can do.

<Note>
  Managing API keys requires the **Admin** role (or a role with the Settings permission). API key operations cannot themselves be performed using an API key — you must use a session token.
</Note>

## List API keys

```bash theme={null}
GET /api/keys
```

Returns all active API keys for your district. The full key value is never returned — only the last 4 characters are shown as a hint.

**Example:**

```bash theme={null}
curl https://app.credentialsportal.com/api/keys \
  -H "Authorization: Bearer your_session_token"
```

**Response:**

```json theme={null}
[
  {
    "id": "key01",
    "name": "Reporting Script",
    "hint": "p6q7",
    "scopes": ["read:people", "read:interviews"],
    "created_at": 1739577600000
  },
  {
    "id": "key02",
    "name": "Import Tool",
    "hint": "r8s9",
    "scopes": ["read:people", "write:people"],
    "created_at": 1741564800000
  }
]
```

***

## Create an API key

```bash theme={null}
POST /api/keys
```

Creates a new API key. The full key value is returned **only once** in this response — store it securely.

**Request body:**

<ParamField body="name" type="string" required>
  A descriptive name for the key (e.g., `"Google Sheets Script"`)
</ParamField>

<ParamField body="scopes" type="array" required>
  Array of scope strings. Available scopes:

  * `read:people`
  * `write:people`
  * `read:interviews`
  * `write:interviews`
</ParamField>

**Example:**

```bash theme={null}
curl -X POST https://app.credentialsportal.com/api/keys \
  -H "Authorization: Bearer your_session_token" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Reporting Script",
    "scopes": ["read:people", "read:interviews"]
  }'
```

**Response:**

```json theme={null}
{
  "id": "key03",
  "name": "Reporting Script",
  "key": "ck_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6",
  "hint": "p6q7",
  "scopes": ["read:people", "read:interviews"],
  "created_at": 1741564800000
}
```

<Warning>
  The `key` field is only returned once at creation time. Copy and store it immediately — you will not be able to retrieve it again.
</Warning>

***

## Revoke an API key

```bash theme={null}
DELETE /api/keys/:id
```

Revokes the key immediately. Any requests using this key will receive a `401 Unauthorized` response.

**Example:**

```bash theme={null}
curl -X DELETE https://app.credentialsportal.com/api/keys/key03 \
  -H "Authorization: Bearer your_session_token"
```

**Response:**

```json theme={null}
{ "ok": true }
```

***

## Using an API key

Include your API key as a Bearer token in the `Authorization` header:

```http theme={null}
Authorization: Bearer ck_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6
```

See [Authentication](/api/authentication) for full details.

## Security best practices

* Create a separate key for each integration
* Grant only the scopes each key needs
* Revoke keys you no longer use
* Rotate keys periodically
* Never commit keys to version control
