# Recording API Documentation

This guide explains how to create OAuth2 credentials and use them to authenticate against the Recording API.

With the token you can then make calls to the public or private, in swagger documented, endpoints.

Public Docs: `https://api.<tenant_name>.unique.app/public/docs`

Private Docs: `https://api.<tenant_name>.unique.app/docs`

* * *

## Prerequisites

Before you can register a client, the following must be in place:

| Requirement | Details |
| --- | --- |
| **Admin email allowlisted** | Your email address must be added to the `ADMIN_USER_EMAILS` environment variable on the target cluster. Contact the platform team to have your email (or a domain pattern such as `*@yourdomain.com`) added. Without this, the registration endpoints will return `403 Forbidden`. |
| **Platform login** | You must be able to log in to the Unique platform on the target environment to obtain a user JWT. |
| **Company ID** | You will need your company ID when making API calls. Request this from the platform team if you do not have it. |

**Base URL:**`https://api.<tenant_name>.unique.app`

* * *

## Overview: Two Registration Paths

There are two ways to register an OAuth2 client. Choose the one that fits your use case.

|  | Service Token (`registerClient`) | Integration Token (`registerIntegration`) |
| --- | --- | --- |
| **Best for** | Programmatic access to all recordings within your company | Scoped access tied to a company, embedded in the token |
| **Company scoping** | You must pass `x-company-id` header on every API request | Company ID is embedded in the token at registration time |
| **Access level** | Full read/write access to all meetings in the specified company | Access restricted to meetings you own or participate in |
| **Token lifetime** | 1 hour | 1 hour |

> _**Recommendation:** If you need to download any recording from your company programmatically, use the **Service Token** path._

* * *

## Path A: Service Token (registerClient)

### Step 1 — Obtain your user JWT

Log in to the Unique Recording (`https://<tenant_name>.unique.app/recording`) platform through the web application. Then extract your Bearer token:

1. Open your browser's Developer Tools (F12)
2. Go to the **Network** tab
3. Navigate to any page that makes an API request
4. Locate a request to the API base URL and copy the `Authorization` header value (everything after `Bearer`)

### Step 2 — Register a client

```
POST /oauth2/registerClient
```

**Request:**

```bash
curl -X POST "https://api.<tenant_name>.unique.app/oauth2/registerClient" \
  -H "Authorization: Bearer <YOUR_USER_JWT>" \
  -H "Content-Type: application/json" \
  -d '{
    "clientId": "your-client-name",
    "personal": true
  }'
```

> _**Important:** The_`"personal": true` _field is required. Without it, token generation will be rejected when called from outside the cluster network._

**Response:**

```
{
  "clientId": "your-client-name",
  "clientSecret": "a1b2c3d4e5f6..."
}
```

> _**Save the**_`clientSecret` _**immediately.** It is returned only once and cannot be retrieved later. If you lose it, repeat this step with the query parameter_`?force=true` _to overwrite the existing client and generate a new secret._

### Step 3 — Generate a service token

```
POST /oauth2/token
```

This endpoint does not require authentication. It is rate-limited to 20 requests per 60 seconds.

**Request:**

```bash
curl -X POST "https://api.<tenant_name>.unique.app/oauth2/token" \
  -H "Content-Type: application/json" \
  -d '{
    "clientId": "your-client-name",
    "clientSecret": "<CLIENT_SECRET_FROM_STEP_2>"
  }'
```

**Response:**

```
{
  "accessToken": "eyJhbGciOiJSUzI1NiIs...",
  "tokenExpirationInMs": 3600000
}
```

The token expires after **1 hour** (3,600,000 ms). Call this endpoint again to obtain a fresh token when needed.

### Step 4 — Call the API

Include the service token in the `Authorization` header and your company ID in the `x-company-id` header on every request.

**Example — Download a video recording:**

```bash
curl -X GET "https://api.<tenant_name>.unique.app/v2/video/<VIDEO_ID>/download" \
  -H "Authorization: Bearer <ACCESS_TOKEN_FROM_STEP_3>" \
  -H "x-company-id: <YOUR_COMPANY_ID>" \
  -o recording.mp4
```

* * *

## Path B: Integration Token (registerIntegration)

The integration token path is similar but embeds the company ID directly in the token, removing the need for the `x-company-id` header on subsequent requests. However, access is more restricted — the token does not grant blanket access to all meetings in the company.

### Step 1 — Obtain your user JWT

Same as Path A, Step 1.

### Step 2 — Register an integration client

```
POST /oauth2/registerIntegration
```

**Request:**

```bash
curl -X POST "https://api.<tenant_name>.unique.app/oauth2/registerIntegration" \
  -H "Authorization: Bearer <YOUR_USER_JWT>" \
  -H "Content-Type: application/json" \
  -d '{
    "clientId": "your-integration-name",
    "personal": true,
    "companyId": "<YOUR_COMPANY_ID>"
  }'
```

> _**Important:** The_`"personal": true` _field is required for the same reason as Path A. The_`companyId` _field is optional but recommended — it embeds the company scope into every token generated for this client._

**Response:**

```
{
  "clientId": "your-integration-name",
  "clientSecret": "a1b2c3d4e5f6..."
}
```

> _**Save the**_`clientSecret` _**immediately.** Same rules as Path A apply._

### Step 3 — Generate an integration token

```
POST /oauth2/token
```

**Request:**

```bash
curl -X POST "https://api.<tenant_name>.unique.app/oauth2/token" \
  -H "Content-Type: application/json" \
  -d '{
    "clientId": "your-integration-name",
    "clientSecret": "<CLIENT_SECRET_FROM_STEP_2>"
  }'
```

**Response:**

```
{
  "accessToken": "eyJhbGciOiJSUzI1NiIs...",
  "tokenExpirationInMs": 3600000
}
```

### Step 4 — Call the API

Since the company ID is embedded in the token, you do not need the `x-company-id` header.

**Example — Download a video recording:**

```bash
curl -X GET "https://api.<tenant_name>.unique.app/v2/video/<VIDEO_ID>/download" \
  -H "Authorization: Bearer <ACCESS_TOKEN_FROM_STEP_3>" \
  -o recording.mp4
```

> _**Note:** Integration tokens have limited access. You can only access meetings where you are an owner, participant, or attendee, or meetings associated with a public deal in your company. If you need unrestricted access to all recordings, use the Service Token path (Path A) instead._

* * *

## Quick Reference

| Step | Endpoint | Method | Authentication |
| --- | --- | --- | --- |
| Register client | `/oauth2/registerClient` | POST | User JWT (Bearer) |
| Register integration | `/oauth2/registerIntegration` | POST | User JWT (Bearer) |
| Generate token | `/oauth2/token` | POST | None (uses clientId + clientSecret in body) |
| Download video | `/v2/video/{videoId}/download` | GET | Service/Integration token (Bearer) + `x-company-id` header (service tokens only) |

**Common issues:**

| Symptom | Cause | Solution |
| --- | --- | --- |
| `403 Forbidden` on register | Email not in admin allowlist | Contact platform team to add your email to `ADMIN_USER_EMAILS` |
| `401 Unauthorized` on token | Incorrect clientId or clientSecret | Verify credentials; re-register with `?force=true` if secret was lost |
| `401 Unauthorized` on token (external) | `personal: true` was not set during registration | Re-register the client with `"personal": true` |
| `400 Bad Request` on API call | Missing `x-company-id` header (service tokens) | Add `x-company-id: <YOUR_COMPANY_ID>` header |
| `404 Not Found` on download | Video ID does not exist or belongs to a different company | Verify the video ID and ensure the correct company ID is used |
