---
title: "Video Content API"
description: "Retrieve YouTube video details, comments, transcripts, subtitles, and RPM data."
source: "https://dashboard.nexlev.io/docs/api/video-content"
---

# Video Content API

Retrieve YouTube video details, comments, transcripts, subtitles, and RPM data.

**Base URL**: `https://prod.dashboard.nexlev.io` — see [Authentication](/docs/api/authentication). Most operations cost 🥞 1 quota; bulk transcript/subtitle operations cost 🥞 5 — see [Rate Limits & Quota](/docs/api/rate-limits).

## Operations Quick Reference

| Operation           | Method & Path                               | Quota Cost |
| ------------------- | ------------------------------------------- | ---------- |
| Get Video Details   | `GET /api/external/videos/details`          | 🥞 1       |
| Get Shorts Details  | `GET /api/external/shorts/details`          | 🥞 1       |
| Get Comments        | `GET /api/external/videos/comments`         | 🥞 1       |
| Get Transcript      | `GET /api/external/videos/transcript`       | 🥞 1       |
| Get Bulk Transcript | `POST /api/external/videos/bulk-transcript` | 🥞 5       |
| Get Subtitle        | `GET /api/external/videos/subtitle`         | 🥞 1       |
| Get Bulk Subtitle   | `POST /api/external/videos/bulk-subtitle`   | 🥞 5       |
| Get RPM             | `GET /api/external/videos/rpm`              | 🥞 1       |

## Available Operations

The Video Content resource provides eight different operations to retrieve various types of video data:

### Get Video Details

#### Get Video Details

```http
GET /api/external/videos/details
```

**Description**: Retrieve comprehensive metadata for a YouTube video including title, description, view count, likes, channel information, and engagement metrics.

> **Warning**
>
> **🥞 Quota Cost: 1 quota per request**
>
> Each call to this endpoint deducts **1 quota** from your account balance. Monitor your usage at [Manage API Key](https://dashboard.nexlev.io/nexlev-api/manage-api-key) to avoid interruptions.
>

**Query Parameters**: `videoId` (required) - YouTube video ID

**Example**:

```
https://prod.dashboard.nexlev.io/api/external/videos/details?videoId=xIL0ssyMh1k
```

**cURL Example**:

```bash
curl "https://prod.dashboard.nexlev.io/api/external/videos/details?videoId=xIL0ssyMh1k" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

**Status Code**: `200 OK`

**Response Body**:

```json
[
  {
    "id": "dQw4w9WgXcQ",
    "title": "Complete Guide to YouTube Success in 2024",
    "lengthSeconds": "942",
    "keywords": ["youtube", "tutorial", "growth", "2024"],
    "channelTitle": "Tech Creators Hub",
    "channelId": "UCxYz123ABC456DEF789GHI",
    "description": "In this comprehensive guide, we cover everything you need to know about growing your YouTube channel from scratch to success.",
    "thumbnail": [
      {
        "url": "https://i.ytimg.com/vi/dQw4w9WgXcQ/hqdefault.jpg?sqp=-oaymwEbCKgBEF5IVfKriqkDDggBFQAAiEIYAXABwAEG&rs=example",
        "width": 168,
        "height": 94
      }
    ],
    "allowRatings": true,
    "viewCount": "125430",
    "likeCount": "4521",
    "isPrivate": false,
    "isUnpluggedCorpus": false,
    "isLiveContent": false,
    "isCrawlable": true,
    "isFamilySafe": true,
    "availableCountries": ["US", "GB", "CA", "AU", "DE", "FR", "JP", "IN"],
    "isUnlisted": false,
    "category": "Education",
    "publishDate": "2024-08-15T10:30:00-07:00",
    "publishedAt": "2024-08-15T10:30:00-07:00",
    "uploadDate": "2024-08-15T10:30:00-07:00",
    "isShortsEligible": false,
    "hasCaption": true,
    "playableInEmbed": true
  }
]
```

**Response Fields**:

- `id` - The YouTube video ID
- `title` - Video title
- `lengthSeconds` - Video duration in seconds
- `keywords` - Array of video keywords/tags
- `channelTitle` - Name of the channel that uploaded the video
- `channelId` - Unique identifier for the video's channel
- `description` - Video description
- `thumbnail` - Array of video thumbnail objects
- `allowRatings` - Whether ratings are allowed on the video
- `viewCount` - Total view count
- `likeCount` - Total like count
- `isPrivate` - Whether the video is private
- `isUnpluggedCorpus` - Whether the video is part of YouTube Unplugged
- `isLiveContent` - Whether the video is/was a live stream
- `isCrawlable` - Whether the video can be crawled
- `isFamilySafe` - Whether the video is family-safe
- `availableCountries` - List of country codes where the video is available
- `isUnlisted` - Whether the video is unlisted
- `category` - Video category (e.g., "Education", "Entertainment")
- `publishDate` - Original publish date with timezone
- `publishedAt` - ISO 8601 timestamp of publish date
- `uploadDate` - Upload date with timezone
- `isShortsEligible` - Whether the video is eligible for Shorts
- `hasCaption` - Whether the video has captions
- `playableInEmbed` - Whether the video can be embedded

### Get Shorts Details

#### Get Shorts Details

```http
GET /api/external/shorts/details
```

**Description**: Retrieve shorts-specific metadata and performance metrics for YouTube Shorts videos.

> **Warning**
>
> **🥞 Quota Cost: 1 quota per request**
>
> Each call to this endpoint deducts **1 quota** from your account balance. Monitor your usage at [Manage API Key](https://dashboard.nexlev.io/nexlev-api/manage-api-key) to avoid interruptions.
>

**Query Parameters**: `videoId` (required) - YouTube shorts video ID

**Example**:

```
https://prod.dashboard.nexlev.io/api/external/shorts/details?videoId=rncxz2XROUg
```

**cURL Example**:

```bash
curl "https://prod.dashboard.nexlev.io/api/external/shorts/details?videoId=rncxz2XROUg" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

**Status Code**: `200 OK`

**Response Body**:

```json
[
  {
    "videoId": "Abc123XyZ9k",
    "likeStatus": "INDIFFERENT",
    "likeCount": 1523,
    "likeCountText": "1.5K",
    "likesAllowed": true,
    "title": "Quick Productivity Hack You Need to Know #shorts",
    "publishedTimeText": "3 months ago",
    "publishDate": "2024-09-15",
    "publishedAt": "2024-09-15T12:00:00.000Z",
    "isCommentDisabled": false,
    "commentCount": "87",
    "titleWithNavDetails": [
      {
        "text": "Quick Productivity Hack You Need to Know #shorts"
      }
    ],
    "channelTitle": "Tech Creators Hub",
    "viewCount": "52340",
    "channelId": "UCxYz123ABC456DEF789GHI",
    "channelHandle": "@techcreatorshub",
    "channelThumbnail": [
      {
        "url": "https://yt3.ggpht.com/example-channel-thumb/s176-c-k-c0x00ffffff-no-rj"
      }
    ],
    "soundAttribution": {
      "continuation": "",
      "title": "Quick Productivity Hack You Need to Know #shorts",
      "videoId": "Abc123XyZ9k",
      "playerParams": "",
      "params": "",
      "thumbnail": [
        {
          "url": "https://i.ytimg.com/vi_webp/Abc123XyZ9k/maxresdefault.webp",
          "width": 1920,
          "height": 1080
        }
      ],
      "channelAvatar": "https://yt3.ggpht.com/example-channel-thumb/s176-c-k-c0x00ffffff-no-rj",
      "channelTitle": "Tech Creators Hub",
      "channelId": "UCxYz123ABC456DEF789GHI"
    },
    "thumbnail": [
      {
        "url": "https://i.ytimg.com/vi_webp/Abc123XyZ9k/maxresdefault.webp",
        "width": 1920,
        "height": 1080
      }
    ],
    "playerParams": "",
    "params": ""
  }
]
```

**Response Fields**:

- `videoId` - The YouTube Shorts video ID
- `likeStatus` - User's like status (e.g., "INDIFFERENT", "LIKE")
- `likeCount` - Total like count as a number
- `likeCountText` - Formatted like count (e.g., "1.5K")
- `likesAllowed` - Whether likes are enabled
- `title` - Shorts title
- `publishedTimeText` - Human-readable publish time
- `publishDate` - Publish date in YYYY-MM-DD format
- `publishedAt` - ISO 8601 timestamp of publish date
- `isCommentDisabled` - Whether comments are disabled
- `commentCount` - Total comment count
- `titleWithNavDetails` - Title with navigation metadata
- `channelTitle` - Name of the channel
- `viewCount` - Total view count
- `channelId` - Channel's unique identifier
- `channelHandle` - Channel's @handle
- `channelThumbnail` - Channel profile image
- `soundAttribution` - Sound/audio attribution details (present when the Short reuses another video's audio)
  - `title` - Title of the original audio/video
  - `videoId` - Video ID the audio was sourced from
  - `channelId` - Channel ID of the original audio's creator
  - `channelTitle` - Original audio creator's channel name
  - `channelAvatar` - Original audio creator's avatar
  - `thumbnail` - Audio thumbnail images
  - `continuation` - Pagination token for browsing other Shorts using this audio (empty if none)
  - `playerParams` - Player parameters for the original video (may be empty)
  - `params` - Additional parameters for the original video (may be empty)
- `thumbnail` - Shorts thumbnail images
- `playerParams` - Player parameters
- `params` - Additional parameters

### Get Comments

#### Get Comments

```http
GET /api/external/videos/comments
```

**Description**: Retrieve comments from a YouTube video for sentiment analysis and engagement insights.

> **Warning**
>
> **🥞 Quota Cost: 1 quota per request**
>
> Each call to this endpoint deducts **1 quota** from your account balance. Monitor your usage at [Manage API Key](https://dashboard.nexlev.io/nexlev-api/manage-api-key) to avoid interruptions.
>

**Query Parameters**: `videoId` (required), `token` (optional)

**Example**:

```
https://prod.dashboard.nexlev.io/api/external/videos/comments?videoId=KkCXLABwHP0
```

**cURL Example**:

```bash
curl "https://prod.dashboard.nexlev.io/api/external/videos/comments?videoId=KkCXLABwHP0" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

**Parameters**:

| Parameter | Type   | Required | Description                                                                                   |
| --------- | ------ | -------- | --------------------------------------------------------------------------------------------- |
| `videoId` | string | Yes      | The unique YouTube video identifier                                                           |
| `token`   | string | No       | Token from previous response to fetch the next page of results (see Pagination section below) |

**Status Code**: `200 OK`

**Response Body**:

```json
{
  "commentsCount": "290K",
  "continuation": "Eg0SC0trQ1hMQUJ3SFAwGAYy3QIKswJnZXRfcmF....",
  "data": [
    {
      "commentId": "UgwhGTds5FObtvuk5DB4AaABAg",
      "authorText": "@knightherojedi6824",
      "authorChannelId": "UCy75Gdz5Gzhs4eA58E3O5qA",
      "authorThumbnail": [
        {
          "url": "https://yt3.ggpht.com/m1hmEQP060FIr3cr0dBlBErnjpHyNMl39cqNrwT3E-LfAqAcm-vc2kCyd8-CrFJV6No0B5C_RUM=s88-c-k-c0x00ffffff-no-rj",
          "width": 88,
          "height": 88
        }
      ],
      "textDisplay": "Mrbeast should get a Nobel prize for helping people",
      "publishedTimeText": "1 year ago",
      "publishDate": "2024-12-11T13:43:54.665Z",
      "publishedAt": "2024-12-11T13:43:54.665Z",
      "likesCount": "199K",
      "replyCount": "631",
      "authorIsChannelOwner": false,
      "isVerified": false,
      "isArtist": false,
      "isCreator": false
    },
    {
      "commentId": "UgyxpjEz079vEzYMM9F4AaABAg",
      "authorText": "@ashabahn",
      "authorChannelId": "UCvWClhCGCSgzPbWfKETShMQ",
      "authorThumbnail": [
        {
          "url": "https://yt3.ggpht.com/ytc/AIdro_mXzjOHTyiLjHmNG8G641kLqMCnNl7YywHfV5MqIG-aQps=s88-c-k-c0x00ffffff-no-rj",
          "width": 88,
          "height": 88
        }
      ],
      "textDisplay": "He was one of the guys who said \"if I become I millionaire I'll help people\"... But actually did it.\nThank you.",
      "publishedTimeText": "1 year ago",
      "publishDate": "2024-12-11T13:43:54.666Z",
      "publishedAt": "2024-12-11T13:43:54.666Z",
      "likesCount": "11K",
      "replyCount": "21",
      "authorIsChannelOwner": false,
      "isVerified": false,
      "isArtist": false,
      "isCreator": false
    }
  ],
  "msg": "success"
}
```

**Response Fields**:

- `commentsCount` - Total number of comments on the video
- `continuation` - Token for pagination (empty if no more comments)
- `data` - Array of comment objects
  - `commentId` - Unique identifier for the comment
  - `authorText` - Author's channel handle
  - `authorChannelId` - Author's channel ID
  - `authorThumbnail` - Author's profile image in various sizes
  - `textDisplay` - The comment text content
  - `publishedTimeText` - Human-readable publish time (e.g., "2 months ago")
  - `publishDate` - Publish date in ISO 8601 format
  - `publishedAt` - ISO 8601 timestamp of publish date
  - `likesCount` - Number of likes on the comment
  - `replyCount` - Number of replies to the comment
  - `authorIsChannelOwner` - Whether the author owns the video's channel
  - `isVerified` - Whether the author is verified
  - `isArtist` - Whether the author is an artist
  - `isCreator` - Whether the author is a creator
- `msg` - Response message (e.g., "success")

##### Pagination

When a video has more comments than can be returned in a single response, the API returns a `continuation` token in the response. Use this token to fetch the next page of results.

**How to use continuation tokens:**

1. Make an initial request without a continuation token to get the first page of comments
2. Check the `continuation` field in the response:
   - If it contains a token (non-empty string), more comments are available
   - If it's an empty string (`""`), you've reached the last page
3. To fetch the next page, make another request using the token from the previous response:
   - Set the `token` parameter to the value from the `continuation` field
   - Keep `videoId` the same
4. Repeat until the `continuation` field returns an empty string

**Example pagination workflow:**

```
// First request (no token)
GET /api/external/videos/comments?videoId=KkCXLABwHP0
```

```json
Response: {
  "commentsCount": "290K",
  "continuation": "Eg0SC0trQ1hMQUJ3SFAwGAYy3QIKswJn.....",
  "data": [ /* Array of 20 comment objects */ ],
  "msg": "success"
}
```

```
// Second request (with the token from the previous response)
GET /api/external/videos/comments?videoId=KkCXLABwHP0&token=Eg0SC0trQ1hMQUJ3SFAwGAYy3QIKswJnZXRf......
```

```json
Response: {
  "commentsCount": "290K",
  "continuation": "",  // Empty string means no more results
  "data": [ /* Array of remaining comment objects */ ],
  "msg": "success"
}
```

**Implementation Tips:**

- Store the continuation token from each response to fetch subsequent pages
- Use a loop node in n8n to automatically paginate through all results
- The continuation token is specific to the video - changing the video ID requires starting over
- Continuation tokens may expire after some time, so fetch all pages in a single workflow execution
- Each page typically returns 20 comments, but this may vary

### Get Transcript

#### Get Transcript

```http
GET /api/external/videos/transcript
```

**Description**: Extract video captions/transcript with timestamps for content analysis and accessibility.

> **Warning**
>
> **🥞 Quota Cost: 1 quota per request**
>
> Each call to this endpoint deducts **1 quota** from your account balance. Monitor your usage at [Manage API Key](https://dashboard.nexlev.io/nexlev-api/manage-api-key) to avoid interruptions.
>

**Query Parameters**: `videoId` (required) - YouTube video ID

**Example**:

```
https://prod.dashboard.nexlev.io/api/external/videos/transcript?videoId=8bMh8azh3CY
```

**cURL Example**:

```bash
curl "https://prod.dashboard.nexlev.io/api/external/videos/transcript?videoId=8bMh8azh3CY" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

**Status Code**: `200 OK`

**Response Body**:

```json
[
  {
    "id": "8bMh8azh3CY",
    "transcript": [
      {
        "startMs": "0",
        "endMs": "1401",
        "startTime": "0:00",
        "text": "I just bought this private jet,"
      },
      {
        "startMs": "1468",
        "endMs": "5205",
        "startTime": "0:01",
        "text": "and whichever one of these\n100 pilots wins this video, keeps it!"
      },
      {
        "startMs": "5271",
        "endMs": "8341",
        "startTime": "0:05",
        "text": "For the first challenge,\nthe pilots all split up into 3 teams."
      }
      // ... additional transcript segments
    ],
    "selected": {
      "title": "English",
      "params": "Cgs4Yk1oOGF6aDNDWRIOQ2dBU0FtVnVHZ0ElM0QYASozZW5nYWdlbWVudC1wYW5lbC1zZWFyY2hhYmxlLXRyYW5zY3JpcHQtc2VhcmNoLXBhbmVsMAE4AUAA"
    },
    "languageMenu": [
      {
        "title": "English",
        "params": "Cgs4Yk1oOGF6aDNDWRIOQ2dBU0FtVnVHZ0ElM0QYASozZW5nYWdlbWVudC1wYW5lbC1zZWFyY2hhYmxlLXRyYW5zY3JpcHQtc2VhcmNoLXBhbmVsMAE4AUAA"
      },
      {
        "title": "Spanish",
        "params": "Cgs4Yk1oOGF6aDNDWRIOQ2dBU0FtVnpHZ0ElM0QYASozZW5nYWdlbWVudC1wYW5lbC1zZWFyY2hhYmxlLXRyYW5zY3JpcHQtc2VhcmNoLXBhbmVsMAE4AUAA"
      },
      {
        "title": "French",
        "params": "Cgs4Yk1oOGF6aDNDWRIOQ2dBU0FtWnlHZ0ElM0QYASozZW5nYWdlbWVudC1wYW5lbC1zZWFyY2hhYmxlLXRyYW5zY3JpcHQtc2VhcmNoLXBhbmVsMAE4AUAA"
      }
      // ... additional languages
    ]
  }
]
```

**Response Fields**:

- `id` - The YouTube video ID
- `transcript` - Array of transcript segments with timestamps
  - `startMs` - Start time in milliseconds
  - `endMs` - End time in milliseconds
  - `startTime` - Start time in MM:SS format (e.g., "0:05")
  - `text` - The transcript text for this segment
- `selected` - Currently selected language information
  - `title` - Name of the selected language
  - `params` - Encoded parameters for the selected language
- `languageMenu` - Array of all available transcript languages
  - `title` - Human-readable language name (e.g., "English (auto-generated)")
  - `params` - Encoded parameters for fetching transcript in this language

**Notes:**

- The `transcript` array contains all caption segments with precise timing information
- Each segment includes start/end times in both milliseconds and human-readable format
- The `selected` object indicates which language transcript is currently provided
- Videos without captions will return an empty `transcript` array
- Auto-generated captions are indicated in the language title (e.g., "English (auto-generated)")
- The response may contain hundreds or thousands of transcript segments for long videos

### Get Bulk Transcript

#### Get Bulk Transcript

```http
POST /api/external/videos/bulk-transcript
```

**Description**: Batch transcript extraction for multiple videos (up to 10 videos per request) for large-scale content processing.

> **Warning**
>
> **🥞 Quota Cost: 5 quota per request**
>
> Each call to this endpoint deducts **5 quota** from your account balance. Monitor your usage at [Manage API Key](https://dashboard.nexlev.io/nexlev-api/manage-api-key) to avoid interruptions.
>

**Request Body**:

```json
{
  "videoIds": ["8bMh8azh3CY", "Z4hVGCWH1Kc"]
}
```

**Body Parameters**: `videoIds` (required) - Array of YouTube video IDs (max 10 videos)

**cURL Example**:

```bash
curl -X POST https://prod.dashboard.nexlev.io/api/external/videos/bulk-transcript \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"videoIds": ["8bMh8azh3CY", "Z4hVGCWH1Kc"]}'
```

##### Request Format

**Video IDs**: Comma-separated list of YouTube video IDs

```
8bMh8azh3CY, Z4hVGCWH1Kc
```

**Maximum**: 10 video IDs per request

##### Response

**Status Code**: `200 OK`

**Response Body**:

```json
{
  "total": 2,
  "successful": 2,
  "failed": 0,
  "results": [
    {
      "videoId": "8bMh8azh3CY",
      "success": true,
      "data": {
        "id": "8bMh8azh3CY",
        "transcript": [
          {
            "startMs": "0",
            "endMs": "1401",
            "startTime": "0:00",
            "text": "I just bought this private jet,"
          },
          {
            "startMs": "1468",
            "endMs": "5205",
            "startTime": "0:01",
            "text": "and whichever one of these\n100 pilots wins this video, keeps it!"
          },
          {
            "startMs": "5271",
            "endMs": "8341",
            "startTime": "0:05",
            "text": "For the first challenge,\nthe pilots all split up into 3 teams."
          }
          // ... additional transcript segments
        ],
        "selected": {
          "title": "English",
          "params": "Cgs4Yk1oOGF6aDNDWRIOQ2dBU0FtVnVHZ0ElM0QYASozZW5nYWdlbWVudC1wYW5lbC1zZWFyY2hhYmxlLXRyYW5zY3JpcHQtc2VhcmNoLXBhbmVsMAE4AUAA"
        },
        "languageMenu": [
          {
            "title": "Arabic",
            "params": "Cgs4Yk1oOGF6aDNDWRIOQ2dBU0FtRnlHZ0ElM0QYASozZW5nYWdlbWVudC1wYW5lbC1zZWFyY2hhYmxlLXRyYW5zY3JpcHQtc2VhcmNoLXBhbmVsMAE4AUAA"
          },
          {
            "title": "English",
            "params": "Cgs4Yk1oOGF6aDNDWRIOQ2dBU0FtVnVHZ0ElM0QYASozZW5nYWdlbWVudC1wYW5lbC1zZWFyY2hhYmxlLXRyYW5zY3JpcHQtc2VhcmNoLXBhbmVsMAE4AUAA"
          },
          {
            "title": "Spanish",
            "params": "Cgs4Yk1oOGF6aDNDWRIOQ2dBU0FtVnpHZ0ElM0QYASozZW5nYWdlbWVudC1wYW5lbC1zZWFyY2hhYmxlLXRyYW5zY3JpcHQtc2VhcmNoLXBhbmVsMAE4AUAA"
          }
          // ... additional languages
        ]
      }
    },
    {
      "videoId": "Z4hVGCWH1Kc",
      "success": true,
      "data": {
        "id": "Z4hVGCWH1Kc",
        "transcript": [
          {
            "startMs": "0",
            "endMs": "2169",
            "startTime": "0:00",
            "text": "We're on a mission to give\n2 million people"
          },
          {
            "startMs": "2236",
            "endMs": "3904",
            "startTime": "0:02",
            "text": "all around the world\nclean water."
          }
          // ... additional transcript segments
        ],
        "selected": {
          "title": "English",
          "params": "CgtaNGhWR0NXSDFLYxIOQ2dBU0FtVnVHZ0ElM0QYASozZW5nYWdlbWVudC1wYW5lbC1zZWFyY2hhYmxlLXRyYW5zY3JpcHQtc2VhcmNoLXBhbmVsMAE4AUAA"
        },
        "languageMenu": [
          {
            "title": "English",
            "params": "CgtaNGhWR0NXSDFLYxIOQ2dBU0FtVnVHZ0ElM0QYASozZW5nYWdlbWVudC1wYW5lbC1zZWFyY2hhYmxlLXRyYW5zY3JpcHQtc2VhcmNoLXBhbmVsMAE4AUAA"
          },
          {
            "title": "French",
            "params": "CgtaNGhWR0NXSDFLYxIOQ2dBU0FtWnlHZ0ElM0QYASozZW5nYWdlbWVudC1wYW5lbC1zZWFyY2hhYmxlLXRyYW5zY3JpcHQtc2VhcmNoLXBhbmVsMAE4AUAA"
          }
          // ... additional languages
        ]
      }
    }
  ]
}
```

**Response Fields**:

- `total` - Total number of video IDs in the request
- `successful` - Number of videos with successfully retrieved transcripts
- `failed` - Number of videos that failed to retrieve transcripts
- `results` - Array of result objects for each video
  - `videoId` - The YouTube video ID
  - `success` - Whether the transcript was successfully retrieved
  - `data` - Transcript data object (same structure as Get Transcript)
    - `id` - The YouTube video ID
    - `transcript` - Array of transcript segments with timestamps
      - `startMs` - Start time in milliseconds
      - `endMs` - End time in milliseconds
      - `startTime` - Start time in MM:SS format (e.g., "0:05")
      - `text` - The transcript text for this segment
    - `selected` - Currently selected language information
      - `title` - Name of the selected language
      - `params` - Encoded parameters for the selected language
    - `languageMenu` - Array of all available transcript languages
      - `title` - Human-readable language name
      - `params` - Encoded parameters for fetching transcript in this language
  - `error` - Error message (only present if success is false)

##### Failed Request Example

When some videos fail to retrieve transcripts, the response will include error information:

```json
{
  "total": 3,
  "successful": 2,
  "failed": 1,
  "results": [
    {
      "videoId": "8bMh8azh3CY",
      "success": true,
      "data": {
        // ... transcript data
      }
    },
    {
      "videoId": "invalidVideoId",
      "success": false,
      "error": "Video not found or transcripts not available"
    },
    {
      "videoId": "Z4hVGCWH1Kc",
      "success": true,
      "data": {
        // ... transcript data
      }
    }
  ]
}
```

### Get Subtitle

#### Get Subtitle

```http
GET /api/external/videos/subtitle
```

**Description**: Retrieve subtitle metadata and URLs for multi-language content support.

> **Warning**
>
> **🥞 Quota Cost: 1 quota per request**
>
> Each call to this endpoint deducts **1 quota** from your account balance. Monitor your usage at [Manage API Key](https://dashboard.nexlev.io/nexlev-api/manage-api-key) to avoid interruptions.
>

**Query Parameters**: `videoId` (required) - YouTube video ID

**Example**:

```
https://prod.dashboard.nexlev.io/api/external/videos/subtitle?videoId=Z4hVGCWH1Kc
```

**cURL Example**:

```bash
curl "https://prod.dashboard.nexlev.io/api/external/videos/subtitle?videoId=Z4hVGCWH1Kc" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

**Status Code**: `200 OK`

**Response Body**:

```json
[
  {
    "subtitles": [
      {
        "languageName": "English",
        "languageCode": "en",
        "url": "https://www.youtube.com/api/timedtext?v=Z4hVGCWH1Kc&ei=k1o6aY2tLvCgvdIPyY7_wAk&caps=asr&opi=112496729&xoaf=5&xowf=1&xospf=1&hl=en&ip=0.0.0.0&ipbits=0&expire=1765457155&sparams=ip%2Cipbits%2Cexpire%2Cv%2Cei%2Ccaps%2Copi%2Cxoaf&signature=AC90D22B82920D8DC979172C8CD47ADC9F99DD59.3E91B95540B4D0F8C0E81AE12A90AE6F04118B0E&key=yt8&lang=en&fmt=srv1&_ytc_=1&pot=&potc=1&c=WEB",
        "isTranslatable": true
      },
      {
        "languageName": "English (auto-generated)",
        "languageCode": "en",
        "url": "https://www.youtube.com/api/timedtext?v=Z4hVGCWH1Kc&ei=k1o6aY2tLvCgvdIPyY7_wAk&caps=asr&opi=112496729&xoaf=5&xowf=1&xospf=1&hl=en&ip=0.0.0.0&ipbits=0&expire=1765457155&sparams=ip%2Cipbits%2Cexpire%2Cv%2Cei%2Ccaps%2Copi%2Cxoaf&signature=AC90D22B82920D8DC979172C8CD47ADC9F99DD59.3E91B95540B4D0F8C0E81AE12A90AE6F04118B0E&key=yt8&kind=asr&lang=en&fmt=srv1&_ytc_=1&pot=&potc=1&c=WEB",
        "isTranslatable": true
      },
      {
        "languageName": "Spanish",
        "languageCode": "es",
        "url": "https://www.youtube.com/api/timedtext?v=Z4hVGCWH1Kc&ei=k1o6aY2tLvCgvdIPyY7_wAk&caps=asr&opi=112496729&xoaf=5&xowf=1&xospf=1&hl=en&ip=0.0.0.0&ipbits=0&expire=1765457155&sparams=ip%2Cipbits%2Cexpire%2Cv%2Cei%2Ccaps%2Copi%2Cxoaf&signature=AC90D22B82920D8DC979172C8CD47ADC9F99DD59.3E91B95540B4D0F8C0E81AE12A90AE6F04118B0E&key=yt8&lang=es&fmt=srv1&_ytc_=1&pot=&potc=1&c=WEB",
        "isTranslatable": true
      },
      {
        "languageName": "French",
        "languageCode": "fr",
        "url": "https://www.youtube.com/api/timedtext?v=Z4hVGCWH1Kc&ei=k1o6aY2tLvCgvdIPyY7_wAk&caps=asr&opi=112496729&xoaf=5&xowf=1&xospf=1&hl=en&ip=0.0.0.0&ipbits=0&expire=1765457155&sparams=ip%2Cipbits%2Cexpire%2Cv%2Cei%2Ccaps%2Copi%2Cxoaf&signature=AC90D22B82920D8DC979172C8CD47ADC9F99DD59.3E91B95540B4D0F8C0E81AE12A90AE6F04118B0E&key=yt8&lang=fr&fmt=srv1&_ytc_=1&pot=&potc=1&c=WEB",
        "isTranslatable": true
      },
      {
        "languageName": "German",
        "languageCode": "de",
        "url": "https://www.youtube.com/api/timedtext?v=Z4hVGCWH1Kc&ei=k1o6aY2tLvCgvdIPyY7_wAk&caps=asr&opi=112496729&xoaf=5&xowf=1&xospf=1&hl=en&ip=0.0.0.0&ipbits=0&expire=1765457155&sparams=ip%2Cipbits%2Cexpire%2Cv%2Cei%2Ccaps%2Copi%2Cxoaf&signature=AC90D22B82920D8DC979172C8CD47ADC9F99DD59.3E91B95540B4D0F8C0E81AE12A90AE6F04118B0E&key=yt8&lang=de&fmt=srv1&_ytc_=1&pot=&potc=1&c=WEB",
        "isTranslatable": true
      },
      {
        "languageName": "Japanese",
        "languageCode": "ja",
        "url": "https://www.youtube.com/api/timedtext?v=Z4hVGCWH1Kc&ei=k1o6aY2tLvCgvdIPyY7_wAk&caps=asr&opi=112496729&xoaf=5&xowf=1&xospf=1&hl=en&ip=0.0.0.0&ipbits=0&expire=1765457155&sparams=ip%2Cipbits%2Cexpire%2Cv%2Cei%2Ccaps%2Copi%2Cxoaf&signature=AC90D22B82920D8DC979172C8CD47ADC9F99DD59.3E91B95540B4D0F8C0E81AE12A90AE6F04118B0E&key=yt8&lang=ja&fmt=srv1&_ytc_=1&pot=&potc=1&c=WEB",
        "isTranslatable": true
      }
      // ... additional subtitle languages
    ],
    "format": "srv1",
    "msg": "",
    "translationLanguages": [
      {
        "languageCode": "en",
        "languageName": "English"
      },
      {
        "languageCode": "es",
        "languageName": "Spanish"
      },
      {
        "languageCode": "fr",
        "languageName": "French"
      },
      {
        "languageCode": "de",
        "languageName": "German"
      },
      {
        "languageCode": "ja",
        "languageName": "Japanese"
      },
      {
        "languageCode": "ko",
        "languageName": "Korean"
      },
      {
        "languageCode": "zh-Hans",
        "languageName": "Chinese (Simplified)"
      },
      {
        "languageCode": "zh-Hant",
        "languageName": "Chinese (Traditional)"
      },
      {
        "languageCode": "ar",
        "languageName": "Arabic"
      },
      {
        "languageCode": "hi",
        "languageName": "Hindi"
      }
      // ... additional translation languages
    ]
  }
]
```

**Response Fields**:

- `subtitles` - Array of available subtitle objects for the video
  - `languageName` - Human-readable name of the subtitle language
  - `languageCode` - ISO language code (e.g., "en", "es", "fr")
  - `url` - Direct URL to download the subtitle file in srv1 format
  - `isTranslatable` - Whether this subtitle can be translated to other languages
- `format` - Subtitle format (typically "srv1" for YouTube's timed text)
- `msg` - Optional message (usually empty on success)
- `translationLanguages` - Array of all languages that subtitles can be translated into
  - `languageCode` - ISO language code for translation target
  - `languageName` - Human-readable name of the translation language

**Notes:**

- The `subtitles` array contains all available subtitle languages for the video
- Auto-generated subtitles are marked with "(auto-generated)" in the language name
- Each subtitle URL is time-limited and will expire after the time specified in the `expire` parameter
- The `translationLanguages` array contains 100+ languages that can be used for subtitle translation
- Videos without subtitles will return an empty `subtitles` array
- The `format` field indicates the subtitle file format (srv1 is YouTube's standard timed text format)
- Use the subtitle URL with the HTTP Request node to download the actual subtitle content

### Get Bulk Subtitle

#### Get Bulk Subtitle

```http
POST /api/external/videos/bulk-subtitle
```

**Description**: Batch subtitle metadata retrieval for multiple videos (up to 10 videos per request) for language coverage analysis.

> **Warning**
>
> **🥞 Quota Cost: 5 quota per request**
>
> Each call to this endpoint deducts **5 quota** from your account balance. Monitor your usage at [Manage API Key](https://dashboard.nexlev.io/nexlev-api/manage-api-key) to avoid interruptions.
>

**Request Body**:

```json
{
  "videoIds": ["mwKJfNYwvm8", "Z4hVGCWH1Kc"]
}
```

**Body Parameters**: `videoIds` (required) - Array of YouTube video IDs (max 10 videos)

**cURL Example**:

```bash
curl -X POST https://prod.dashboard.nexlev.io/api/external/videos/bulk-subtitle \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"videoIds": ["mwKJfNYwvm8", "Z4hVGCWH1Kc"]}'
```

##### Request Format

**Video IDs**: Comma-separated list of YouTube video IDs

```
mwKJfNYwvm8, Z4hVGCWH1Kc
```

**Maximum**: 10 video IDs per request

##### Response

**Status Code**: `200 OK`

**Response Body**:

```json
{
  "total": 2,
  "successful": 2,
  "failed": 0,
  "results": [
    {
      "videoId": "mwKJfNYwvm8",
      "success": true,
      "data": {
        "subtitles": [
          {
            "languageName": "Arabic",
            "languageCode": "ar",
            "url": "https://www.youtube.com/api/timedtext?v=mwKJfNYwvm8&ei=0486adqYIuTDmLAP8Im2gQ8&caps=asr&opi=112496729&xoaf=5&xowf=1&hl=en&ip=0.0.0.0&ipbits=0&expire=1765470787&sparams=ip%2Cipbits%2Cexpire%2Cv%2Cei%2Ccaps%2Copi%2Cxoaf&signature=0236AC2234C161EA82F0DA0383CFA1FDC92CDCC5.6617022DBDD7B762B5100C21184EAFD66688038A&key=yt8&lang=ar&fmt=srv1",
            "isTranslatable": true
          },
          {
            "languageName": "English",
            "languageCode": "en",
            "url": "https://www.youtube.com/api/timedtext?v=mwKJfNYwvm8&ei=0486adqYIuTDmLAP8Im2gQ8&caps=asr&opi=112496729&xoaf=5&xowf=1&hl=en&ip=0.0.0.0&ipbits=0&expire=1765470787&sparams=ip%2Cipbits%2Cexpire%2Cv%2Cei%2Ccaps%2Copi%2Cxoaf&signature=0236AC2234C161EA82F0DA0383CFA1FDC92CDCC5.6617022DBDD7B762B5100C21184EAFD66688038A&key=yt8&lang=en&fmt=srv1",
            "isTranslatable": true
          },
          {
            "languageName": "English (auto-generated)",
            "languageCode": "en",
            "url": "https://www.youtube.com/api/timedtext?v=mwKJfNYwvm8&ei=0486adqYIuTDmLAP8Im2gQ8&caps=asr&opi=112496729&xoaf=5&xowf=1&hl=en&ip=0.0.0.0&ipbits=0&expire=1765470787&sparams=ip%2Cipbits%2Cexpire%2Cv%2Cei%2Ccaps%2Copi%2Cxoaf&signature=0236AC2234C161EA82F0DA0383CFA1FDC92CDCC5.6617022DBDD7B762B5100C21184EAFD66688038A&key=yt8&kind=asr&lang=en&fmt=srv1",
            "isTranslatable": true
          }
          // ... additional subtitle languages
        ],
        "format": "srv1",
        "msg": "",
        "translationLanguages": [
          {
            "languageCode": "en",
            "languageName": "English"
          },
          {
            "languageCode": "es",
            "languageName": "Spanish"
          },
          {
            "languageCode": "fr",
            "languageName": "French"
          }
          // ... additional translation languages
        ]
      }
    },
    {
      "videoId": "Z4hVGCWH1Kc",
      "success": true,
      "data": {
        "subtitles": [
          {
            "languageName": "Arabic",
            "languageCode": "ar",
            "url": "https://www.youtube.com/api/timedtext?v=Z4hVGCWH1Kc&ei=0486aaq9IIyJvdIP4vDVkQg&caps=asr&opi=112496729&xoaf=5&xowf=1&xospf=1&hl=en&ip=0.0.0.0&ipbits=0&expire=1765470787&sparams=ip%2Cipbits%2Cexpire%2Cv%2Cei%2Ccaps%2Copi%2Cxoaf&signature=5DD3C95DDCE1BB72E9A641B81C2B4AFF74F74999.B705A98822779E0A8475485717D5222C708B5082&key=yt8&lang=ar&fmt=srv1",
            "isTranslatable": true
          },
          {
            "languageName": "English",
            "languageCode": "en",
            "url": "https://www.youtube.com/api/timedtext?v=Z4hVGCWH1Kc&ei=0486aaq9IIyJvdIP4vDVkQg&caps=asr&opi=112496729&xoaf=5&xowf=1&xospf=1&hl=en&ip=0.0.0.0&ipbits=0&expire=1765470787&sparams=ip%2Cipbits%2Cexpire%2Cv%2Cei%2Ccaps%2Copi%2Cxoaf&signature=5DD3C95DDCE1BB72E9A641B81C2B4AFF74F74999.B705A98822779E0A8475485717D5222C708B5082&key=yt8&lang=en&fmt=srv1",
            "isTranslatable": true
          }
          // ... additional subtitle languages
        ],
        "format": "srv1",
        "msg": "",
        "translationLanguages": [
          {
            "languageCode": "en",
            "languageName": "English"
          },
          {
            "languageCode": "es",
            "languageName": "Spanish"
          }
          // ... additional translation languages
        ]
      }
    }
  ]
}
```

**Response Fields**:

- `total` - Total number of video IDs in the request
- `successful` - Number of videos with successfully retrieved subtitle data
- `failed` - Number of videos that failed to retrieve subtitle data
- `results` - Array of result objects for each video
  - `videoId` - The YouTube video ID
  - `success` - Whether the subtitle data was successfully retrieved
  - `data` - Subtitle data object (same structure as Get Subtitle)
    - `subtitles` - Array of available subtitle objects
      - `languageName` - Human-readable name of the subtitle language
      - `languageCode` - ISO language code (e.g., "en", "es", "fr")
      - `url` - Direct URL to download the subtitle file
      - `isTranslatable` - Whether this subtitle can be translated
    - `format` - Subtitle format (typically "srv1")
    - `msg` - Optional message (usually empty on success)
    - `translationLanguages` - Array of all available translation languages
      - `languageCode` - ISO language code for translation target
      - `languageName` - Human-readable name of translation language
  - `error` - Error message (only present if success is false)

##### Failed Request Example

When some videos fail to retrieve subtitle data, the response will include error information:

```json
{
  "total": 3,
  "successful": 2,
  "failed": 1,
  "results": [
    {
      "videoId": "mwKJfNYwvm8",
      "success": true,
      "data": {
        // ... subtitle data
      }
    },
    {
      "videoId": "invalidVideoId",
      "success": false,
      "error": "Video not found or subtitles not available"
    },
    {
      "videoId": "Z4hVGCWH1Kc",
      "success": true,
      "data": {
        // ... subtitle data
      }
    }
  ]
}
```

### Get RPM

#### Get RPM

```http
GET /api/external/videos/rpm
```

**Description**: Retrieve revenue per mille (RPM) estimates for monetization analysis and revenue research.

> **Warning**
>
> **🥞 Quota Cost: 1 quota per request**
>
> Each call to this endpoint deducts **1 quota** from your account balance. Monitor your usage at [Manage API Key](https://dashboard.nexlev.io/nexlev-api/manage-api-key) to avoid interruptions.
>

**Query Parameters**: `videoId` (required) - YouTube video ID

**Example**:

```
https://prod.dashboard.nexlev.io/api/external/videos/rpm?videoId=AKJfakEsgy0
```

**cURL Example**:

```bash
curl "https://prod.dashboard.nexlev.io/api/external/videos/rpm?videoId=AKJfakEsgy0" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

##### Request Format

**Video ID**: Single YouTube video ID

```
AKJfakEsgy0
```

##### Response

**Status Code**: `200 OK`

**Response Body**:

```json
{
  "success": true,
  "videoId": "AKJfakEsgy0",
  "video": {
    "title": "Hi Me In 5 Years",
    "channel": "MrBeast",
    "lengthSec": 127,
    "views": 146180042,
    "publishedAt": "2020-10-04"
  },
  "prediction": {
    "rpm": 1.1,
    "rpmMin": 0.69,
    "rpmMax": 1.51,
    "estimatedEarnings": 160798.05,
    "estimatedEarningsMin": 100864.23,
    "estimatedEarningsMax": 220731.86
  }
}
```

**Response Fields**:

- `success` - Indicates if the request was successful
- `videoId` - The YouTube video ID
- `video` - Video metadata
  - `title` - Video title
  - `channel` - Channel name
  - `lengthSec` - Video length in seconds
  - `views` - Total view count
  - `publishedAt` - Video publish date (YYYY-MM-DD)
- `prediction` - RPM prediction data
  - `rpm` - Estimated revenue per 1,000 views (in USD)
  - `rpmMin` - Minimum estimated RPM (in USD)
  - `rpmMax` - Maximum estimated RPM (in USD)
  - `estimatedEarnings` - Estimated total earnings (in USD)
  - `estimatedEarningsMin` - Minimum estimated total earnings (in USD)
  - `estimatedEarningsMax` - Maximum estimated total earnings (in USD)

##### Factors Affecting RPM

RPM can vary significantly based on several factors:

- **Content Category**: Educational and business content typically has higher RPM than entertainment
- **Viewer Geography**: Views from countries with higher ad rates (US, UK, Canada) increase RPM
- **Video Length**: Longer videos with mid-roll ads often have higher RPM
- **Audience Demographics**: Advertiser-friendly demographics command higher CPM/RPM
- **Seasonality**: Q4 (holiday season) typically sees higher ad rates and RPM
- **Ad Types**: Videos with skippable, non-skippable, and display ads may have different RPM
- **Watch Time**: Videos with higher audience retention can generate more ad impressions
- **Advertiser Demand**: Topics with high advertiser competition tend to have higher RPM

##### Error Handling

If RPM data is not available for a video, the response may indicate:

```json
{
  "success": false,
  "videoId": "AKJfakEsgy0",
  "error": "RPM data not available",
  "message": "Video is not monetized or data is insufficient"
}
```

**Common reasons for unavailable RPM data:**

- Video is not monetized
- Insufficient view count for reliable RPM estimation
- Video is too new (not enough data collected)
- Video is private, unlisted, or removed
- Monetization is disabled by creator or YouTube

##### Notes

- RPM estimates are provided for informational and research purposes only
- Actual creator earnings may differ based on numerous factors
- RPM data should be used for trend analysis and niche research
- This operation respects YouTube's terms of service and privacy guidelines
- RPM values are estimates based on industry data and public information
- Use this data ethically and responsibly for content research and strategy

## Error Responses

### Bad Request

**Status Code**: `400 Bad Request`

**Description**: The request was invalid or malformed.

```json
{
  "error": {
    "code": 400,
    "message": "Invalid video ID format",
    "details": "Video ID must be a valid YouTube video identifier"
  }
}
```

### Unauthorized

**Status Code**: `401 Unauthorized`

**Description**: Authentication credentials are missing or invalid.

```json
{
  "error": {
    "code": 401,
    "message": "Unauthorized",
    "details": "Invalid API key or credentials not provided. Create your API key at https://dashboard.nexlev.io/nexlev-api/create-api-key"
  }
}
```

### Not Found

**Status Code**: `404 Not Found`

**Description**: The specified video could not be found.

```json
{
  "error": {
    "code": 404,
    "message": "Video not found",
    "details": "No video exists with the provided video ID"
  }
}
```

### Rate Limit

**Status Code**: `429 Too Many Requests`

**Description**: You have exceeded your API rate limit.

```json
{
  "error": {
    "code": 429,
    "message": "Rate limit exceeded",
    "details": "You have exceeded your API quota. Please try again later.",
    "retryAfter": 3600
  }
}
```
