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

# API Keys

> Streaming keys for data ingestion and programmatic keys for the HTTP API.

Tell has two types of keys. **Streaming keys** authenticate SDKs and pipeline sources sending data over TCP, HTTP, or syslog. **Programmatic API keys** authenticate HTTP API calls for automation and integrations.

## Streaming keys

Streaming keys are 32-character hex strings that map directly to a workspace:

```
a1b2c3d4e5f60718293a4b5c6d7e8f90
```

You get your first streaming key when you run [setup](/api/authentication). SDKs and pipeline sources use this key to authenticate data ingestion.

### Managing streaming keys

Use the CLI to create, list, and delete streaming keys:

```bash theme={null}
# List keys
tell apikeys

# Create a new key for workspace 1
tell apikeys new mobile-prod --workspace 1

# Show the full key
tell apikeys show mobile-prod

# Delete a key
tell apikeys delete mobile-prod
```

### Key file format

Streaming keys are stored in a key file with one key per line:

```
# Production workspace
a1b2c3d4e5f60718293a4b5c6d7e8f90:1
# Staging workspace
b2c3d4e5f6071829304a5b6c7d8e9f01:2:staging
```

Format: `{32_hex_chars}:{workspace_id}[:{optional_name}]`. Lines starting with `#` are comments.

### Using streaming keys

Configure your SDK with the key:

```javascript theme={null}
import { Tell } from '@tell-rs/node';

const tell = new Tell({
  apiKey: 'a1b2c3d4e5f60718293a4b5c6d7e8f90',
  endpoint: 'https://your-tell-server',
});
```

Pipeline sources (TCP, HTTP, syslog) validate the key on every connection.

## Programmatic API keys

For automating HTTP API calls (querying metrics, managing boards, etc.), create programmatic API keys:

```bash theme={null}
curl -X POST https://your-tell-server/api/v1/user/apikeys \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "CI Pipeline",
    "workspace_id": "ws-1",
    "expires_at": "2026-12-31T23:59:59Z"
  }'
```

The response includes the full key — it's only shown once:

```json theme={null}
{
  "key": "tell_a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4",
  "id": "key_...",
  "name": "CI Pipeline",
  "key_prefix": "tell_a1b2"
}
```

Use it like a regular JWT token:

```bash theme={null}
curl https://your-tell-server/api/v1/metrics/dau?range=30d \
  -H "Authorization: Bearer tell_a1b2c3d4..."
```

### Key options

| Field          | Required | Description                                                     |
| -------------- | -------- | --------------------------------------------------------------- |
| `name`         | Yes      | Display name (1-100 characters)                                 |
| `description`  | No       | Optional description (max 500 characters)                       |
| `workspace_id` | No       | Scope to a workspace (empty = user-level key)                   |
| `permissions`  | No       | Specific permissions (empty = inherit from your role)           |
| `expires_at`   | No       | Expiration date (max 1 year from now, never expires if omitted) |

### Managing API keys

```bash theme={null}
# List your keys
curl https://your-tell-server/api/v1/user/apikeys \
  -H "Authorization: Bearer $TOKEN"

# Revoke a key
curl -X DELETE https://your-tell-server/api/v1/user/apikeys/{key-id} \
  -H "Authorization: Bearer $TOKEN"
```

Admins can view and revoke any key in their workspace:

```bash theme={null}
# List all keys in workspace
curl https://your-tell-server/api/v1/admin/apikeys \
  -H "Authorization: Bearer $TOKEN" \
  -H "X-Workspace-ID: ws-1"

# Revoke any key in workspace
curl -X DELETE https://your-tell-server/api/v1/admin/apikeys/{key-id} \
  -H "Authorization: Bearer $TOKEN" \
  -H "X-Workspace-ID: ws-1"
```

## Security

* Streaming keys use constant-time comparison to prevent timing attacks
* Programmatic API keys are stored as SHA-256 hashes — only the `key_prefix` is visible after creation
* Programmatic API keys inherit the creator's role — they can't do more than you can
* Passwords are hashed with Argon2id
* Revoked tokens are blacklisted and cannot be reused even if the JWT hasn't expired
* All key creation and revocation events are [audit logged](/running-tell/audit-privacy)
