# API Reference

This page lists all available API endpoints for third-party integrations.

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

## Authentication

Third-party integrations authenticate using an **API key** passed in the `x-api-key` header:

```bash
curl -H "x-api-key: dpk_YOUR_API_KEY" https://app.dailyplay.ai/api/...
```

Dashboard management endpoints use a **Clerk bearer token** instead:

```bash
curl -H "Authorization: Bearer <clerk_token>" https://app.dailyplay.ai/api/...
```

---

## Session Endpoints

These endpoints are used by third-party integrations to create and manage one-time session tokens.

### Create Session

Creates a one-time session token for a game or stream.

```
POST /api/org-api-keys?action=create-session
```

**Headers:**

| Header         | Value                    |
| -------------- | ------------------------ |
| `Content-Type` | `application/json`       |
| `x-api-key`    | Your API key (`dpk_...`) |

**Body:**

```json
{
  "game_id": 42,
  "stream_id": null,
  "external_ref": "user-12345",
  "metadata": { "campaign": "summer-promo" },
  "expires_in_minutes": 60
}
```

| Field                | Type   | Required | Description                 |
| -------------------- | ------ | -------- | --------------------------- |
| `game_id`            | number | \*       | Target game ID              |
| `stream_id`          | number | \*       | Target stream ID            |
| `external_ref`       | string | No       | Your tracking reference     |
| `metadata`           | object | No       | Arbitrary JSON data         |
| `expires_in_minutes` | number | No       | Expiry time (default: 1440) |

\* At least one of `game_id` or `stream_id` is required.

**Response `200`:**

```json
{
  "success": true,
  "data": {
    "token": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "stream_id": null,
    "game_id": 42,
    "expires_at": "2026-02-17T12:00:00.000Z",
    "external_ref": "user-12345"
  }
}
```

---

### Validate Session

Checks whether a session token is still valid without consuming it.

```
GET /api/org-api-keys?action=validate-session&token=<uuid>
```

**Query Parameters:**

| Parameter | Type          | Required | Description                   |
| --------- | ------------- | -------- | ----------------------------- |
| `token`   | string (UUID) | Yes      | The session token to validate |

**Response `200`:**

```json
{
  "success": true,
  "data": {
    "valid": true,
    "status": "active",
    "stream_id": null,
    "game_id": 42,
    "expires_at": "2026-02-17T12:00:00.000Z",
    "external_ref": "user-12345",
    "metadata": { "campaign": "summer-promo" }
  }
}
```

---

### Consume Session

Atomically consumes a session token so it cannot be reused.

```
POST /api/org-api-keys?action=consume-session
```

**Headers:**

| Header         | Value              |
| -------------- | ------------------ |
| `Content-Type` | `application/json` |

**Body:**

```json
{
  "token": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "player_uuid": "player-uuid-here"
}
```

| Field         | Type          | Required | Description                  |
| ------------- | ------------- | -------- | ---------------------------- |
| `token`       | string (UUID) | Yes      | The session token to consume |
| `player_uuid` | string        | No       | UUID identifying the player  |

**Response `200`:**

```json
{
  "success": true,
  "data": {
    "session_id": 1,
    "org_id": 5,
    "stream_id": null,
    "game_id": 42,
    "external_ref": "user-12345",
    "metadata": { "campaign": "summer-promo" }
  }
}
```

**Response `410` (already consumed/expired):**

```json
{
  "success": false,
  "error": "Session is invalid, already consumed, or expired"
}
```

---

## API Key Management Endpoints

These endpoints require a **Clerk bearer token** and are used by the DailyPlay dashboard to manage
API keys.

### List API Keys

```
GET /api/org-api-keys?org_id=<id>
```

Returns all API keys for the specified organization.

---

### Create API Key

```
POST /api/org-api-keys
```

**Body:**

```json
{
  "org_id": 1,
  "name": "Production CRM",
  "description": "Used by the CRM to issue game links",
  "allowed_game_ids": [42, 43],
  "allowed_stream_ids": null,
  "rate_limit_per_minute": 60,
  "rate_limit_per_day": 10000,
  "expires_at": "2027-01-01T00:00:00Z"
}
```

**Response `200`:**

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

:::caution
The `key` field is only included in the creation response. It cannot be retrieved again.
:::
---

### Update / Revoke API Key

```
PATCH /api/org-api-keys
```

**Body:**

```json
{
  "id": 1,
  "org_id": 1,
  "is_active": false
}
```

Set `is_active` to `false` to revoke a key, or `true` to reactivate it.

---

### Delete API Key

```
DELETE /api/org-api-keys?id=<id>&org_id=<id>
```

Permanently removes the API key record.

---

## Error Responses

All error responses follow this format:

```json
{
  "success": false,
  "error": "Description of what went wrong"
}
```

### Status Codes

| Code  | Meaning                                                        |
| ----- | -------------------------------------------------------------- |
| `200` | Success                                                        |
| `400` | Bad request — missing or invalid parameters                    |
| `401` | Unauthorized — invalid or revoked API key / missing auth       |
| `403` | Forbidden — key does not have access to the requested resource |
| `410` | Gone — session token already consumed or expired               |
| `429` | Too Many Requests — rate limit exceeded                        |
| `500` | Internal server error                                          |