> 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                                   |
| `PATCH /api/v1/videos/:id/posters`, `PATCH .../posters/:poster_id`          | `videos:write`                            | Update poster rotation weights                 |
| `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/:id/download`                                           | `videos:read`                             | Get a transcoded-file download URL             |
| `GET /api/v1/videos/:id/product_matches`                                    | `videos:read`                             | List AI product matches                        |
| `POST /api/v1/videos/:id/product_matches`, `/product_matches/accept`        | `videos:write`                            | Run or accept AI product matches               |
| `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`, `GET /api/v1/business_stores/:id`            | `business_stores:read` or `products:read` | Read business stores                           |
| `POST /api/v1/business_stores`                                              | `business_stores:write`                   | Create a local business store                  |
| `PATCH /api/v1/business_stores/:id`, `DELETE .../:id`                       | `business_stores:write`                   | Update or delete a business store              |
| `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        |
| `GET /api/v1/channels/:id/ai_curation/feed`                                 | `videos:read`                             | Browse the AI-curation feed                    |
| `GET /api/v1/channels/:id/ai_curation/settings`                             | `channels:read`                           | Read AI-curation settings                      |
| `PATCH /api/v1/channels/:id/ai_curation/settings`                           | `channels:write`                          | Update AI-curation settings                    |
| `GET /api/v1/channels/:id/ai_curation/creators`                             | `channels:read`                           | List the creator whitelist                     |
| `POST /api/v1/channels/:id/ai_curation/creators`, `DELETE .../creators/:id` | `channels:write`                          | Add or remove whitelisted creators             |
| `GET /api/v1/channels/:id/ai_curation/social_accounts`                      | `channels:read`                           | List connected social accounts                 |
| `POST /api/v1/channels/:id/ai_curation/social_accounts/connect_url`         | `channels:write`                          | Start a social-account connection              |
| `POST /api/v1/channels/:id/ai_curation/imports`                             | `videos:write`                            | Import a curated feed item                     |
| 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`, `PATCH /api/v1/videos/:id/posters`, `PATCH/DELETE /api/v1/videos/:id/posters/:poster_id` - Add, reweight, or remove posters (requires `videos:write`)
* `GET /api/v1/videos/:id/download` - Get the transcoded-file download URL (requires `videos:read` and the `content_download` subscription feature)
* `GET /api/v1/videos/:id/product_matches` - List AI product matches (requires `videos:read`)
* `POST /api/v1/videos/:id/product_matches`, `POST /api/v1/videos/:id/product_matches/accept` - Run or accept AI product matching (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**

* `GET /api/v1/business_stores`, `GET /api/v1/business_stores/:id` - List or get stores (accepts either `business_stores:read` or the legacy `products:read`)
* `POST /api/v1/business_stores` - Create a local business store (requires `business_stores:write`)
* `PATCH /api/v1/business_stores/:id` - Update a business store (requires `business_stores:write`)
* `DELETE /api/v1/business_stores/:id` - Soft-delete a business store (requires `business_stores:write`)

**AI Content Curation (requires the `ai_content_curation` subscription feature)**

* `GET /api/v1/channels/:channel_id/ai_curation/feed` - Browse the discovery feed (requires `videos:read`)
* `GET/PATCH /api/v1/channels/:channel_id/ai_curation/settings` - Read/update discovery settings (requires `channels:read` / `channels:write`)
* `GET/POST /api/v1/channels/:channel_id/ai_curation/creators`, `DELETE .../creators/:id` - Manage creator whitelist entries (requires `channels:read` / `channels:write`)
* `GET /api/v1/channels/:channel_id/ai_curation/social_accounts` - List connections (requires `channels:read`)
* `POST /api/v1/channels/:channel_id/ai_curation/social_accounts/connect_url` - Begin connecting an account (requires `channels:write`)
* `POST /api/v1/channels/:channel_id/ai_curation/imports` - Import a feed item (requires `videos:write`)

**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}"
```
