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

# Authentication

### 1. Overview

The Firework Public API supports OAuth 2.0 Client Credentials flow for server-to-server authentication. This authentication method is designed for backend applications that need to access Firework APIs without user interaction.

**Production Base URL**: `https://api.firework.com`

> ⚠️ **Important**:
>
> * OAuth apps must be registered and configured by the Firework IS (Internal Systems) team before use
> * Client credentials are scoped to your business. You can only access resources (videos, channels, live streams) that belong to your business
> * OAuth apps must be granted specific scopes that determine which API endpoints they can access
> * Client credentials authentication is only supported for `/api/v1/*` Public API endpoints

### 2. OAuth App Registration

Before using the Client Credentials flow, you must have an OAuth app registered by the Firework IS team.

#### 2.1. Registration Process

Contact the Firework IS team to register your OAuth app. Provide the following information:

1. **Business ID** - The Firework business that will own the OAuth app
2. **App Name** - A descriptive name for your application
3. **Required Scopes** - The specific scopes your app needs (see section 2.2)

The IS team will provide you with:

* `client_id` - Your OAuth app's unique identifier
* `client_secret` - Your OAuth app's secret key (store securely!)

#### 2.2. Available Scopes

OAuth apps must be granted one or more scopes that determine which API endpoints they can access:

| Endpoint                                                                  | Scope               | Description                                    |
| ------------------------------------------------------------------------- | ------------------- | ---------------------------------------------- |
| `POST /api/v1/upload_signatures`                                          | `videos:write`      | Get pre-signed credentials for S3 upload       |
| `POST /api/v1/upload_multipart/signatures`                                | `videos:write`      | Initiate multipart upload                      |
| `POST /api/v1/upload_multipart/complete`                                  | `videos:write`      | Complete a multipart upload                    |
| `POST /api/v1/videos`                                                     | `videos:write`      | Create a video (file, URL, S3 key, or base64)  |
| `PATCH /api/v1/videos/:id`                                                | `videos:write`      | Update a video                                 |
| `DELETE /api/v1/videos/:id`                                               | `videos:write`      | Delete a video                                 |
| `POST /api/v1/videos/:id/archive`, `/unarchive`                           | `videos:write`      | Archive or unarchive a video                   |
| `POST /api/v1/videos/:id/publish`, `/unpublish`                           | `videos:write`      | Publish (optionally scheduled) or unpublish    |
| `POST /api/v1/videos/:id/subtitles`                                       | `videos:write`      | Add a subtitle                                 |
| `DELETE /api/v1/videos/:id/subtitles/:subtitle_id`                        | `videos:write`      | Remove a subtitle                              |
| `POST /api/v1/videos/:id/posters`                                         | `videos:write`      | Add a poster                                   |
| `DELETE /api/v1/videos/:id/posters/:poster_id`                            | `videos:write`      | Remove a poster                                |
| `GET /api/v1/videos`                                                      | `videos:read`       | List videos in a channel                       |
| `GET /api/v1/videos/:id`                                                  | `videos:read`       | Read video details                             |
| `GET /api/v1/videos/imports/:id`                                          | `videos:read`       | Get async import job status                    |
| `GET /api/v1/businesses`                                                  | `businesses:read`   | List businesses the token can act on           |
| `GET /api/v1/channels`                                                    | `channels:read`     | List channels                                  |
| `PATCH /api/v1/channels/:id`                                              | `channels:write`    | Update a channel's metadata                    |
| `GET /api/v1/business_stores`                                             | `products:read`     | List business stores                           |
| `GET /api/v1/products`                                                    | `products:read`     | List or search products in a store             |
| `GET /api/v1/products/:id`                                                | `products:read`     | Get a product                                  |
| `GET /api/v1/products/:product_id/videos`                                 | `products:read`     | List videos for a product                      |
| `POST /api/v1/products`                                                   | `products:write`    | Upsert (create or update) a product            |
| `DELETE /api/v1/products/:product_id`                                     | `products:write`    | Delete a product                               |
| `GET /api/v1/live_streams`                                                | `livestreams:read`  | List livestreams of a channel                  |
| `GET /api/v1/live_streams/:id`                                            | `livestreams:read`  | Get live stream details                        |
| `GET /api/v1/live_streams/:id/detail`                                     | `livestreams:read`  | Get viewer-side livestream details             |
| `GET /api/v1/live_streams/:id/messages`                                   | `livestreams:read`  | List a replay's chat messages                  |
| `GET /api/v1/live_streams/:id/comments_csv`                               | `livestreams:read`  | Download comments CSV (after end)              |
| `GET /api/v1/live_streams/:id/interactions/:interaction_id/responses_csv` | `livestreams:read`  | Download interaction responses CSV (after end) |
| `GET /api/v1/live_streams/playlists/:playlist_id/videos`                  | `livestreams:read`  | List videos of a livestream playlist           |
| `GET /api/v1/stats/live_streams/:live_stream_id`                          | `livestreams:read`  | Consolidated livestream reporting stats        |
| `POST /api/v1/live_streams`                                               | `livestreams:write` | Schedule a livestream                          |
| `PATCH /api/v1/live_streams/:id`                                          | `livestreams:write` | Update a livestream                            |
| `PATCH /api/v1/live_streams/:id/end`                                      | `livestreams:write` | End a live stream                              |
| `POST /api/v1/live_streams/:id/pin_product`                               | `livestreams:write` | Pin products to live stream                    |
| `POST /api/v1/live_streams/:id/unpin_product`                             | `livestreams:write` | Unpin products from live stream                |
| `GET /api/v1/playlists`                                                   | `playlists:read`    | List playlists of a channel                    |
| `GET /api/v1/playlists/:id/videos`                                        | `playlists:read`    | List a playlist's videos                       |
| `POST /api/v1/playlists`                                                  | `playlists:write`   | Create a playlist                              |
| `PATCH /api/v1/playlists/:id`                                             | `playlists:write`   | Update a playlist                              |
| `DELETE /api/v1/playlists/:id`                                            | `playlists:write`   | Delete a playlist                              |
| `POST /api/v1/playlists/:id/videos`                                       | `playlists:write`   | Add a video to a playlist                      |
| `PUT /api/v1/playlists/:id/videos`                                        | `playlists:write`   | Reorder a playlist's videos                    |
| `DELETE /api/v1/playlists/:id/videos/:video_id`                           | `playlists:write`   | Remove a video from a playlist                 |
| `POST /api/v1/playlists/:id/videos/:video_id/pin`, `DELETE .../pin`       | `playlists:write`   | Pin/unpin a video (AI-feed playlists only)     |
| `GET /api/v1/insights/videos/:video_id`                                   | `insights:read`     | Get insights for a video                       |
| `GET /api/v1/insights/live_streams/:live_stream_id`                       | `insights:read`     | Get insights for a livestream                  |
| `GET /api/v1/stats/playlists/:playlist_id/video_views`                    | `insights:read`     | List a playlist's per-video view counts        |
| All Public API endpoints                                                  | `api:admin`         | Full administrative access                     |

> 📝 **Note**:
>
> * Request only the minimum scopes your application needs (principle of least privilege)
> * The `api:admin` scope bypasses all scope checks and should be used sparingly
> * Scopes are set during OAuth app registration and cannot be changed via API
> * **Scope Hierarchy**: Write scopes automatically grant read access. For example, `livestreams:write` grants both read and write operations, and `videos:write` grants both read and write access to videos

***

### 3. Client Credentials Flow

The authentication process has two steps:

1. **Get Access Token** - Exchange client credentials for an access token
2. **Use Access Token** - Include token in API requests

***

### 4. Endpoint Summary

| Endpoint            | Notes            |
| ------------------- | ---------------- |
| `POST /oauth/token` | Get access token |

***

### 5. Get Access Token

Exchange your client credentials for an access token.

**Endpoint**: `POST /oauth/token`\
**Authentication**: None required\
**Token lifetime**: 15 minutes

#### 5.1. Request Parameters

| Parameter       | Type   | Required | Description                                                                       |
| --------------- | ------ | -------- | --------------------------------------------------------------------------------- |
| `grant_type`    | string | ✅        | Must be `"client_credentials"`                                                    |
| `client_id`     | string | ✅        | Your OAuth app's Client ID                                                        |
| `client_secret` | string | ✅        | Your OAuth app's Client Secret                                                    |
| `scope`         | string | ✅        | Space-separated list of requested scopes (must be subset of app's allowed scopes) |

#### 5.2. Get Access Token Response

**Success Response**: `200 OK`

| Field          | Type   | Nullable | Description                                                            |
| -------------- | ------ | -------- | ---------------------------------------------------------------------- |
| `access_token` | string | ❌        | JWT bearer token for API authentication (contains scope in JWT claims) |
| `expires_in`   | number | ❌        | Token lifetime in seconds (900)                                        |

#### 5.3. Examples

**CURL Request**

```bash
curl -X POST "https://api.firework.com/oauth/token" \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "grant_type=client_credentials" \
  -d "client_id={CLIENT_ID}" \
  -d "client_secret={CLIENT_SECRET}" \
  -d "scope=videos:write livestreams:write"
```

**Example Response**

```json
{
  "access_token": "eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJGaXJld29yayIsImJpZCI6ImFiYzEyMyIsImV4cCI6MTc2MTQ5NjA5MSwiaWF0IjoxNzYxNDk1MTkxLCJpc3MiOiJGaXJld29yayIsImp0aSI6IjlkZTdkM2JiLWU4MWYtNDU4Zi05NTg3LTBkYzgyNzg5YWEwYiIsIm5iZiI6MTc2MTQ5NTE5MCwic2NvcGUiOiJ2aWRlb3M6d3JpdGUgbGl2ZXN0cmVhbXM6d3JpdGUiLCJzdWIiOiJhOmxvd2VzX3ZpZGVvX2NsaWVudF8xMjM0NWFiY2RlZiIsInR5cCI6ImFjY2VzcyJ9.example_signature",
  "expires_in": 900
}
```

> 📝 **Note**: The granted scopes are embedded within the JWT token claims. You can decode the JWT to see the `scope` field which contains the scopes that were granted for this token. The token also includes a `bid` (business ID) claim that scopes the token to your business.

***

### 6. Using Access Tokens

Include the access token in the `Authorization` header for all API requests:

```
Authorization: Bearer {ACCESS_TOKEN}
```

> **Important**:
>
> * Client credentials access tokens are only valid for `/api/v1/*` Public API endpoints
> * Your OAuth app must have the required scope to access each endpoint
> * Requests without the required scope will return `403 Forbidden` with an `insufficient_scope` error

#### 6.1. Supported Endpoints and Required Scopes

The following Firework Public API v1 endpoints support client credentials authentication:

**Video Management (requires `videos:read` or `videos:write` scope)**

* `GET /api/v1/videos` - List videos in a channel (requires `videos:read`)
* `GET /api/v1/videos/:id` - Get video details (requires `videos:read`)
* `GET /api/v1/videos/imports/:id` - Get the status of an async import job (requires `videos:read`)
* `POST /api/v1/videos` - Create a video from a file, URL, S3 key, or base64 payload (requires `videos:write`)
* `PATCH /api/v1/videos/:id` - Update video metadata (requires `videos:write`)
* `DELETE /api/v1/videos/:id` - Delete a video (requires `videos:write`)
* `POST /api/v1/videos/:id/archive`, `POST /api/v1/videos/:id/unarchive` - Archive or unarchive a video (requires `videos:write`)
* `POST /api/v1/videos/:id/publish`, `POST /api/v1/videos/:id/unpublish` - Publish (optionally scheduled) or unpublish a video (requires `videos:write`)
* `POST /api/v1/videos/:id/subtitles`, `DELETE /api/v1/videos/:id/subtitles/:subtitle_id` - Add or remove a subtitle (requires `videos:write`)
* `POST /api/v1/videos/:id/posters`, `DELETE /api/v1/videos/:id/posters/:poster_id` - Add or remove a poster (requires `videos:write`)
* `POST /api/v1/upload_signatures` - Get pre-signed credentials for S3 upload (requires `videos:write`)
* `POST /api/v1/upload_multipart/signatures` - Initiate multipart upload (requires `videos:write`)
* `POST /api/v1/upload_multipart/complete` - Complete a multipart upload (requires `videos:write`)

**Business Read-Only (requires `businesses:read` scope)**

* `GET /api/v1/businesses` - List the businesses the token can act on

**Channel Management (requires `channels:read` or `channels:write` scope)**

* `GET /api/v1/channels` - List channels for a business (requires `channels:read`)
* `PATCH /api/v1/channels/:id` - Update a channel's metadata (requires `channels:write`)

**Product Management (requires `products:read` or `products:write` scope)**

* `GET /api/v1/products` - List or search products in a store (requires `products:read`)
* `GET /api/v1/products/:id` - Get a product (requires `products:read`)
* `GET /api/v1/products/:product_id/videos` - List videos associated with a product (requires `products:read`)
* `POST /api/v1/products` - Upsert a product (requires `products:write`)
* `DELETE /api/v1/products/:product_id` - Delete a product (requires `products:write`)

**Business Store Management (requires `products:read` scope)**

* `GET /api/v1/business_stores` - List business stores for a business (requires `products:read`)

**Playlist Management (requires `playlists:read` or `playlists:write` scope)**

* `GET /api/v1/playlists` - List playlists for a channel (requires `playlists:read`)
* `GET /api/v1/playlists/:id/videos` - List a playlist's videos (requires `playlists:read`)
* `POST /api/v1/playlists` - Create a playlist (requires `playlists:write`)
* `PATCH /api/v1/playlists/:id` - Update a playlist (requires `playlists:write`)
* `DELETE /api/v1/playlists/:id` - Delete a playlist (requires `playlists:write`)
* `POST /api/v1/playlists/:id/videos` - Add a video to a playlist (requires `playlists:write`)
* `PUT /api/v1/playlists/:id/videos` - Reorder a playlist's videos (requires `playlists:write`)
* `DELETE /api/v1/playlists/:id/videos/:video_id` - Remove a video from a playlist (requires `playlists:write`)
* `POST /api/v1/playlists/:id/videos/:video_id/pin`, `DELETE /api/v1/playlists/:id/videos/:video_id/pin` - Pin or unpin a video, AI-feed playlists only (requires `playlists:write`)

**Live Stream Management (requires `livestreams:read` or `livestreams:write` scope)**

* `GET /api/v1/live_streams` - List livestreams of a channel (requires `livestreams:read`)
* `GET /api/v1/live_streams/:id` - Get live stream details (requires `livestreams:read`)
* `GET /api/v1/live_streams/:id/detail` - Get viewer-side livestream details (requires `livestreams:read`)
* `GET /api/v1/live_streams/:id/messages` - List an ended stream's replay chat messages (requires `livestreams:read`)
* `GET /api/v1/live_streams/:id/comments_csv` - Download comments as CSV, after the stream ends (requires `livestreams:read`)
* `GET /api/v1/live_streams/:id/interactions/:interaction_id/responses_csv` - Download interaction (poll/quiz/question) responses as CSV, after the stream ends (requires `livestreams:read`)
* `GET /api/v1/live_streams/playlists/:playlist_id/videos` - List videos of a livestream playlist (requires `livestreams:read`)
* `GET /api/v1/stats/live_streams/:live_stream_id` - Consolidated livestream reporting stats (requires `livestreams:read`)
* `POST /api/v1/live_streams` - Schedule a livestream (requires `livestreams:write`)
* `PATCH /api/v1/live_streams/:id` - Update a livestream (requires `livestreams:write`)
* `PATCH /api/v1/live_streams/:id/end` - End a live stream (requires `livestreams:write`)
* `POST /api/v1/live_streams/:id/pin_product` - Pin products to live stream, max 3 per request (requires `livestreams:write`)
* `POST /api/v1/live_streams/:id/unpin_product` - Unpin products from live stream, max 3 per request (requires `livestreams:write`)

**Insights Read-Only (requires `insights:read` scope)**

* `GET /api/v1/insights/videos/:video_id` - Get insights for a video
* `GET /api/v1/insights/live_streams/:live_stream_id` - Get insights for a livestream
* `GET /api/v1/stats/playlists/:playlist_id/video_views` - List active and replay view counts for a playlist's videos

> 📝 **Note**:
>
> * OAuth apps with the `api:admin` scope can access all endpoints regardless of other scope requirements
> * Write scopes automatically grant read access. For example, `livestreams:write` grants both read and write operations

#### 6.2. Example API Requests

**Create/Upload Video**

```bash
curl -X POST "https://api.firework.com/api/v1/videos" \
  -H "Authorization: Bearer {ACCESS_TOKEN}" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://example.com/video.mp4",
    "channel_id": "abc123",
    "caption": "Product Demo",
    "hashtags": ["demo", "product"],
    "product_ids": ["prod_123", "prod_456"]
  }'
```

**List Videos for a Product (Read-Only)**

```bash
curl -X GET "https://api.firework.com/api/v1/products/{PRODUCT_ID}/videos?channel_id={CHANNEL_ID}" \
  -H "Authorization: Bearer {ACCESS_TOKEN}"
```

**Pin Products to Live Stream**

```bash
curl -X POST "https://api.firework.com/api/v1/live_streams/{LIVE_STREAM_ID}/pin_product" \
  -H "Authorization: Bearer {ACCESS_TOKEN}" \
  -H "Content-Type: application/json" \
  -d '{
    "product_ids": ["prod_123", "prod_456", "prod_789"]
  }'
```

**Unpin Products from Live Stream**

```bash
curl -X POST "https://api.firework.com/api/v1/live_streams/{LIVE_STREAM_ID}/unpin_product" \
  -H "Authorization: Bearer {ACCESS_TOKEN}" \
  -H "Content-Type: application/json" \
  -d '{
    "product_ids": ["prod_123", "prod_456"]
  }'
```

**End Live Stream**

```bash
curl -X PATCH "https://api.firework.com/api/v1/live_streams/{LIVE_STREAM_ID}/end" \
  -H "Authorization: Bearer {ACCESS_TOKEN}" \
  -H "Content-Type: application/json"
```

**Get Live Stream Details (Read-Only)**

```bash
curl -X GET "https://api.firework.com/api/v1/live_streams/{LIVE_STREAM_ID}" \
  -H "Authorization: Bearer {ACCESS_TOKEN}"
```
