# Authentication

### 1. Overview <a href="#id-1.-overview" id="id-1.-overview"></a>

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 (Integration Solutions) 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 <a href="#id-2.-oauth-app-registration" id="id-2.-oauth-app-registration"></a>

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

#### 2.1. Registration Process <a href="#id-2.1.-registration-process" id="id-2.1.-registration-process"></a>

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 <a href="#id-2.2.-available-scopes" id="id-2.2.-available-scopes"></a>

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

<table data-header-hidden><thead><tr><th width="400.8203125"></th><th></th><th></th></tr></thead><tbody><tr><td>Endpoint</td><td>Scope</td><td>Description</td></tr><tr><td><code>POST /api/v1/upload_signatures</code></td><td><code>videos:write</code></td><td>Get pre-signed credentials for S3 upload</td></tr><tr><td><code>POST /api/v1/upload_multipart/signatures</code></td><td><code>videos:write</code></td><td>Initiate multipart upload</td></tr><tr><td><code>POST /api/v1/upload_multipart/complete</code></td><td><code>videos:write</code></td><td>Complete a multipart upload</td></tr><tr><td><code>POST /api/v1/videos</code></td><td><code>videos:write</code></td><td>Create videos</td></tr><tr><td><code>GET /api/v1/videos/{id}</code></td><td><code>videos:read</code></td><td>Read video details</td></tr><tr><td><code>PATCH /api/v1/videos/{id}</code></td><td><code>videos:write</code></td><td>Update videos</td></tr><tr><td><code>GET /api/v1/products/{product_id}/videos</code></td><td><code>products:read</code></td><td>List videos for a product</td></tr><tr><td><code>GET /api/v1/live_streams/{id}/detail</code></td><td><code>livestreams:read</code></td><td>Get live stream details</td></tr><tr><td><code>POST /api/v1/live_streams/{id}/pin_product</code></td><td><code>livestreams:write</code></td><td>Pin products to live stream</td></tr><tr><td><code>POST /api/v1/live_streams/{id}/unpin_product</code></td><td><code>livestreams:write</code></td><td>Unpin products from live stream</td></tr><tr><td><code>PATCH /api/v1/live_streams/{id}/end</code></td><td><code>livestreams:write</code></td><td>End a live stream</td></tr><tr><td>All Public API endpoints</td><td><code>api:admin</code></td><td>Full administrative access</td></tr></tbody></table>

> 📝 **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 <a href="#id-3.-client-credentials-flow" id="id-3.-client-credentials-flow"></a>

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 <a href="#id-4.-endpoint-summary" id="id-4.-endpoint-summary"></a>

| Endpoint            | Status        | Notes            |
| ------------------- | ------------- | ---------------- |
| `POST /oauth/token` | ✅ Implemented | Get access token |

***

### 5. Get Access Token <a href="#id-5.-get-access-token" id="id-5.-get-access-token"></a>

Exchange your client credentials for an access token.

**Endpoint**: `POST /oauth/token`\
**Authentication**: None required\
**Token lifetime**: 1 hour

#### 5.1. Request Parameters <a href="#id-5.1.-request-parameters" id="id-5.1.-request-parameters"></a>

| 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 <a href="#id-5.2.-get-access-token-response" id="id-5.2.-get-access-token-response"></a>

**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 (3600)                                       |

#### 5.3. Examples <a href="#id-5.3.-examples" id="id-5.3.-examples"></a>

**CURL Request**

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

```
{ "access_token": "{ACCESS_TOKEN}", "expires_in": 3600 }
```

> 📝 **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 <a href="#id-6.-using-access-tokens" id="id-6.-using-access-tokens"></a>

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 <a href="#id-6.1.-supported-endpoints-and-required-scopes" id="id-6.1.-supported-endpoints-and-required-scopes"></a>

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

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

* `POST /api/v1/videos` - Create/upload video
* `PATCH /api/v1/videos/:id` - Update video metadata

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

* `POST /api/v1/live_streams/:id/pin_product` - Pin products to live stream (max 3 products per request)
* `POST /api/v1/live_streams/:id/unpin_product` - Unpin products from live stream (max 3 products per request)
* `PATCH /api/v1/live_streams/:id/end` - End a live stream

**Live Stream Read-Only (requires `livestreams:read` scope)**

* `GET /api/v1/live_streams/:live_stream_id/detail` - Get live stream details

> 📝 **Note**:
>
> * OAuth apps with the `api:admin` scope can access all endpoints regardless of other scope requirements
> * OAuth apps with `livestreams:write` scope can also access read-only livestream endpoints (write scope grants read access)

#### 6.2. Example API Requests <a href="#id-6.2.-example-api-requests" id="id-6.2.-example-api-requests"></a>

**Create/Upload Video**

```
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"] }'
```

**Pin Products to Live Stream**

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

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

```
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)**

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


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.firework.com/firework-for-developers/api/authentication.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
