# API Keys

API keys allow your server to authenticate with the DailyPlay API. Keys are created from the
dashboard and used in the `x-api-key` header when making API calls.

:::note[Business Tier Required]
API keys are only available for organizations on the **Business
tier** or higher.
:::

## Creating an API Key

1. Log in to the DailyPlay dashboard
2. Navigate to **Connect → API Keys** in the sidebar
3. Click **Create API Key**
4. Enter a name (e.g., "Production CRM") and an optional description
5. Optionally enable **MCP scopes** if the key will power an AI agent (see below)
6. Optionally set an expiration date
7. Click **Create**

:::caution
Copy the generated key immediately — it is only shown once and cannot be retrieved later.
:::
The key format is `dpk_<40 hex characters>`, for example:

```
dpk_a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0
```

## Key Scoping

API keys can be scoped to restrict which resources they can access:

| Scope                   | Description                                                       |
| ----------------------- | ----------------------------------------------------------------- |
| **All games & streams** | Default — the key can create sessions for any resource in the org |
| **Specific games**      | Restrict to a list of game IDs                                    |
| **Specific streams**    | Restrict to a list of stream IDs                                  |

Attempting to create a session for a resource outside the key's scope returns a `403 Forbidden`
error.

## MCP Scopes

In addition to game/stream allowlists, keys can carry **MCP scopes** that grant access to the remote
[MCP server](/api/mcp/). Scopes are deny-by-default:

| Scope | Grants |
| --- | --- |
| _(none)_ | Session-token minting only (legacy / REST behavior) |
| `mcp:templates:read` | List and inspect templates |
| `mcp:games:read` / `mcp:games:write` | Read or create/update games and prizes |
| `mcp:streams:read` / `mcp:streams:write` | Read or create/update streams |
| `mcp:connections:read` / `mcp:connections:write` | Manage org integrations |
| `mcp:gallery:read` / `mcp:gallery:write` | List gallery media or delete unused assets |
| `mcp:vouchers:read` / `mcp:vouchers:write` | Read or manage voucher sets and codes |
| `mcp:reports:read` | Read org analytics and reports |
| `mcp:ai` | Brand extract, funnel wizard, image generation |
| `mcp:sessions:write` | Mint play sessions via MCP |

You can edit MCP scopes later from the API Keys list without rotating the key. See
[MCP Tools](/api/mcp-tools/) for the full tool list.

## Rate Limits

Each API key has configurable rate limits:

| Limit      | Default | Description                 |
| ---------- | ------- | --------------------------- |
| Per minute | 60      | Maximum requests per minute |
| Per day    | 10,000  | Maximum requests per day    |

When a rate limit is exceeded, the API returns a `429 Too Many Requests` response.

## Revoking a Key

You can revoke an API key at any time from the dashboard:

1. Go to **Connect → API Keys**
2. Find the key in the list (identified by its `dpk_****` prefix and name)
3. Click the revoke action

Revoking a key:

- Immediately blocks all future API calls using that key
- Does **not** invalidate session tokens already created with the key
- Preserves the audit trail — the key record is retained but marked inactive
- Can be reactivated if needed

## Security

- Keys are **hashed with SHA-256** before storage — raw keys cannot be recovered from the database
- Only the first 8 characters (`dpk_xxxx`) are stored in plaintext for identification
- Keys can be set to **expire automatically** on a specific date
- All key usage is logged for auditing purposes

## Managing Keys via API

You can also manage API keys programmatically using authenticated requests (Clerk bearer token):

| Method   | Endpoint                                | Description                   |
| -------- | --------------------------------------- | ----------------------------- |
| `GET`    | `/api/org-api-keys?org_id=<id>`         | List all API keys for an org  |
| `POST`   | `/api/org-api-keys`                     | Create a new API key          |
| `PATCH`  | `/api/org-api-keys`                     | Update or revoke an API key   |
| `DELETE` | `/api/org-api-keys?id=<id>&org_id=<id>` | Permanently delete an API key |

### Create a Key (API)

```bash
curl -X POST https://app.dailyplay.ai/api/org-api-keys \
  -H "Authorization: Bearer <clerk_token>" \
  -H "Content-Type: application/json" \
  -d '{
    "org_id": 1,
    "name": "Production CRM",
    "description": "Used by the CRM to issue game links",
    "allowed_game_ids": [42, 43],
    "rate_limit_per_minute": 60,
    "rate_limit_per_day": 10000,
    "expires_at": "2027-01-01T00:00:00Z"
  }'
```

The response includes the raw key (shown only once):

```json
{
  "success": true,
  "data": {
    "id": 1,
    "name": "Production CRM",
    "key_prefix": "dpk_a1b2",
    "key": "dpk_a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0"
  }
}
```