{"skill":{"slug":"tubelab-api","displayName":"YouTube Outliers & Niche Finder Data by TubeLab","summary":"YouTube analytics and research API. Search channels, find video outliers, get video details/transcripts/comments, and run scans. Use for YouTube niche resear...","description":"---\nname: tubelab\ndescription: YouTube analytics and research API. Search channels, find video outliers, get video details/transcripts/comments, and run scans. Use for YouTube niche research, competitor analysis, and channel analytics.\nmetadata: {\"openclaw\":{\"emoji\":\"📊\",\"requires\":{\"bins\":[\"curl\",\"jq\"],\"env\":[\"TUBELAB_API_KEY\"]},\"primaryEnv\":\"TUBELAB_API_KEY\"}}\n---\n\n# TubeLab API\n\nYouTube analytics and research API. Discover profitable niches, find viral outlier videos, analyze channels, get transcripts and comments, and run automated scans - all through REST endpoints returning JSON.\n\n- **Base URL:** `https://public-api.tubelab.net/v1`\n- **Auth:** API key in header\n- **Rate limit:** 10 requests/minute per API key\n- **Format:** JSON request/response\n- **Docs:** https://tubelab.net/docs/api/introduction\n\n## Authentication\n\nEvery request requires an `Authorization` header with your API key:\n\n```\nAuthorization: Api-Key $TUBELAB_API_KEY\n```\n\nGet your API key at https://tubelab.net/developers - requires an [active subscription](https://tubelab.net/pricing).\n\n## Rate Limits & Credits\n\nRate limited to **10 requests per minute** per API key. Exceeding this returns `429 Too Many Requests`.\n\nMost endpoints cost credits. Cached responses (same request within a short window) are free.\n\n| Endpoint | Cost |\n| --- | --- |\n| `GET /search/channels` | 10 credits |\n| `GET /search/channels/related` | 10 credits |\n| `GET /search/outliers` | 5 credits |\n| `GET /search/outliers/related` | 5 credits |\n| `GET /channel/videos/{id}` | free |\n| `GET /channel/shorts/{id}` | free |\n| `GET /video/{id}` | free |\n| `GET /video/transcript/{id}` | free |\n| `GET /video/comments/{id}` | free |\n| `POST /scan` | 50–100 credits |\n| `GET /scan/{id}` | free |\n\nScan cost depends on mode: **Fast** = 50 credits, **Standard** = 100 credits.\n\n## Search Endpoints\n\nSearch for YouTube channels and viral videos (outliers). All search endpoints support pagination, sorting, and 30+ filters.\n\n### GET /search/channels\n\n**Channels**\nSearch for channels directly from the [YouTube Niche Finder](https://tubelab.net/youtube-niche-finder) with AI enhanced data and 30+ filters.\nCost: **10 credits** per request.\n\n```bash\ncurl -s \"https://public-api.tubelab.net/v1/search/channels?query=minecraft%20adventures\" \\\n  -H \"Authorization: Api-Key $TUBELAB_API_KEY\"\n```\n\n**Query parameters:**\n\n| Name | Type | Required | Description |\n| --- | --- | --- | --- |\n| `query` | string[] | no | Search queries |\n| `seed` | string \\| number \\| null | no | Randomize search results by passing a random seed |\n| `filterBy` | \"video\" \\| \"short\" | no | Filter by statistics of each content kind |\n| `contentKind` | \"video\" \\| \"short\" \\| \"long-form\" \\| \"short-form\" | no | Filter by type of content created by channel: - `video` - channel has videos; - `short` - channel has shorts; - `long-form` - channel has more... |\n| `publishedAtFrom` | string | no | Filter by a channel's last parsed video upload date (from a sample of 100 videos) - Expects an ISO date time string. |\n| `publishedAtTo` | string | no |  |\n| `averageViewsFrom` | integer | no |  |\n| `averageViewsTo` | integer | no |  |\n| `medianViewsFrom` | integer | no |  |\n| `medianViewsTo` | integer | no |  |\n| `language` | string[] | no | ISO 639-1 language codes |\n| `avgViewsToSubscribersRatioFrom` | number | no | Filter by the outlier score of a channel |\n| `avgViewsToSubscribersRatioTo` | number | no |  |\n| `subscribersFrom` | integer | no |  |\n| `subscribersTo` | integer | no |  |\n| `videosCountFrom` | integer | no |  |\n| `videosCountTo` | integer | no |  |\n| `viewVariationCoefficientFrom` | number | no |  |\n| `viewVariationCoefficientTo` | number | no |  |\n| `revenueMonthlyEstimationFrom` | number | no |  |\n| `revenueMonthlyEstimationTo` | number | no |  |\n| `rpmEstimationFrom` | number | no |  |\n| `rpmEstimationTo` | number | no |  |\n| `avgDurationFrom` | integer | no | Average duration of videos in seconds |\n| `avgDurationTo` | integer | no |  |\n| `monetizationAdsense` | boolean | no | Filter by whether the channel has AdSense enabled or not |\n| `excludeNiche` | string[] | no | Exclude niches from search results by keywords |\n| `classificationQuality` | \"negative\" \\| \"neutral\" \\| \"positive\" | no | **AI** classification of a channel quality. |\n| `classificationIsFaceless` | boolean | no | **AI**  classification wether channel content has faceless potential or not |\n| `from` | integer | no | Page to fetch |\n| `size` | integer | no | Number of items per page |\n| `sortBy` | \"subscribers\" \\| \"averageViews\" \\| \"avgViewsToSubscribersRatio\" \\| \"viewVariationCoefficient\" \\| \"revenueMonthly\" \\| \"rpm\" \\| \"foundAt\" \\| \"recency\" | no | Sort results by a specific metric:  Beaware when using semantic search (applying a query with the `by` parameter set to `semantic`) the sorting... |\n| `sortOrder` | \"asc\" \\| \"desc\" | no | Sorting order of results, where asc is ascending and desc is descending |\n\n**Response shape (abbreviated):**\n\n```json\n{\n  \"pagination\": { \"total\": 100, \"from\": 0, \"size\": 20 },\n  \"hits\": [\n    {\n      \"id\": \"UChn5jutPQB_bRjnG80pzl5w\",\n      \"snippet\": { \"handle\": \"@tubelabhq\", \"title\": \"TubeLab\", \"contentKind\": [\"video\",\"long-form\"] },\n      \"statistics\": { \"subscribers\": 15000, \"averageViews\": 5000, \"avgViewsToSubscribersRatio\": 0.33 },\n      \"language\": { \"code\": \"en\" },\n      \"monetization\": { \"adsense\": true },\n      \"classification\": { \"quality\": \"positive\", \"isFaceless\": false }\n    }\n  ]\n}\n```\n\n### GET /search/channels/related\n\n**Similar Channels**\nSearch for YouTube channels with **related content to another channel**.\nCost: **10 credits** per request.\n\n```bash\ncurl -s \"https://public-api.tubelab.net/v1/search/channels/related?relatedChannelId=UChn5jutPQB_bRjnG80pzl5w\" \\\n  -H \"Authorization: Api-Key $TUBELAB_API_KEY\"\n```\n\n**Query parameters:**\n\n| Name | Type | Required | Description |\n| --- | --- | --- | --- |\n| `relatedChannelId` | string[] | yes |  |\n| `filterBy` | \"video\" \\| \"short\" | no | Filter by statistics of each content kind |\n| `contentKind` | \"video\" \\| \"short\" \\| \"long-form\" \\| \"short-form\" | no | Filter by type of content created by channel: - `video` - channel has videos; - `short` - channel has shorts; - `long-form` - channel has more... |\n| `publishedAtFrom` | string | no | Filter by a channel's last parsed video upload date (from a sample of 100 videos) - Expects an ISO date time string. |\n| `publishedAtTo` | string | no |  |\n| `averageViewsFrom` | integer | no |  |\n| `averageViewsTo` | integer | no |  |\n| `medianViewsFrom` | integer | no |  |\n| `medianViewsTo` | integer | no |  |\n| `language` | string[] | no | ISO 639-1 language codes |\n| `avgViewsToSubscribersRatioFrom` | number | no | Filter by the outlier score of a channel |\n| `avgViewsToSubscribersRatioTo` | number | no |  |\n| `subscribersFrom` | integer | no |  |\n| `subscribersTo` | integer | no |  |\n| `videosCountFrom` | integer | no |  |\n| `videosCountTo` | integer | no |  |\n| `viewVariationCoefficientFrom` | number | no |  |\n| `viewVariationCoefficientTo` | number | no |  |\n| `revenueMonthlyEstimationFrom` | number | no |  |\n| `revenueMonthlyEstimationTo` | number | no |  |\n| `rpmEstimationFrom` | number | no |  |\n| `rpmEstimationTo` | number | no |  |\n| `avgDurationFrom` | integer | no | Average duration of videos in seconds |\n| `avgDurationTo` | integer | no |  |\n| `monetizationAdsense` | boolean | no | Filter by whether the channel has AdSense enabled or not |\n| `excludeNiche` | string[] | no | Exclude niches from search results by keywords |\n| `classificationQuality` | \"negative\" \\| \"neutral\" \\| \"positive\" | no | **AI** classification of a channel quality. |\n| `classificationIsFaceless` | boolean | no | **AI**  classification wether channel content has faceless potential or not |\n| `from` | integer | no | Page to fetch |\n| `size` | integer | no | Number of items per page |\n\n**Response shape (abbreviated):**\n\n```json\n{\n  \"pagination\": { \"total\": 50, \"from\": 0, \"size\": 20 },\n  \"hits\": [\n    {\n      \"id\": \"UCX6OQ3DkcsbYNE6H8uQQuVA\",\n      \"snippet\": { \"handle\": \"@example\", \"title\": \"Example Channel\", \"contentKind\": [\"video\"] },\n      \"statistics\": { \"subscribers\": 25000, \"averageViews\": 8000 },\n      \"language\": { \"code\": \"en\" }\n    }\n  ]\n}\n```\n\n### GET /search/outliers\n\n**Outliers**\nSearch for videos directly from the [YouTube Outliers Finder](https://tubelab.net/youtube-outliers-finder) library with AI enhanced data and 30+ filters.\nCost: **5 credits** per request.\n\n```bash\ncurl -s \"https://public-api.tubelab.net/v1/search/outliers?query=minecraft%20adventures&type=video\" \\\n  -H \"Authorization: Api-Key $TUBELAB_API_KEY\"\n```\n\n**Query parameters:**\n\n| Name | Type | Required | Description |\n| --- | --- | --- | --- |\n| `query` | string[] | no | Search queries |\n| `seed` | string \\| number \\| null | no | Randomize search results by passing a random seed |\n| `sortBy` | \"views\" \\| \"zScore\" \\| \"averageViewsRatio\" \\| \"publishedAt\" \\| \"revenue\" \\| \"rpm\" | no | Sort results by a specific metric:  Beaware when using semantic search (applying a query with the `by` parameter set to `semantic`) the sorting... |\n| `sortOrder` | \"asc\" \\| \"desc\" | no | Sorting order of results, where asc is ascending and desc is descending |\n| `type` | \"video\" \\| \"short\" | no |  |\n| `averageViewsRatioFrom` | number | no |  |\n| `averageViewsRatioTo` | number | no |  |\n| `zScoreFrom` | number | no |  |\n| `zScoreTo` | number | no |  |\n| `viewCountFrom` | integer | no |  |\n| `viewCountTo` | integer | no |  |\n| `language` | string[] | no | ISO 639-1 language codes |\n| `durationFrom` | integer | no |  |\n| `durationTo` | integer | no |  |\n| `publishedAtFrom` | string \\| string | no |  |\n| `publishedAtTo` | string | no |  |\n| `subscribersCountFrom` | integer | no |  |\n| `subscribersCountTo` | integer | no |  |\n| `channelAvgViewsFrom` | number | no |  |\n| `channelAvgViewsTo` | number | no |  |\n| `channelVideoCountFrom` | integer | no |  |\n| `channelVideoCountTo` | integer | no |  |\n| `channelId` | string | no |  |\n| `channelAvgViewsToSubscribersRatioFrom` | number | no |  |\n| `channelAvgViewsToSubscribersRatioTo` | number | no |  |\n| `titlePattern` | string | no |  |\n| `referenceId` | string | no |  |\n| `rpmEstimationFrom` | number | no |  |\n| `rpmEstimationTo` | number | no |  |\n| `revenueEstimationFrom` | number | no |  |\n| `revenueEstimationTo` | number | no |  |\n| `channelMonetizationAdsense` | boolean | no |  |\n| `classificationQuality` | \"negative\" \\| \"neutral\" \\| \"positive\" | no |  |\n| `classificationIsFaceless` | boolean | no |  |\n| `excludeKeyword` | string[] | no |  |\n| `from` | integer | no | Page to fetch |\n| `size` | integer | no | Number of items per page |\n| `by` | \"semantic\" \\| \"lexical\" | no | Search by semantics (meaning of words) or lexical (exact words) |\n\n**Response shape (abbreviated):**\n\n```json\n{\n  \"pagination\": { \"total\": 100, \"from\": 0, \"size\": 20 },\n  \"hits\": [\n    {\n      \"id\": \"SVeXR66hcIg\",\n      \"kind\": \"video\",\n      \"snippet\": { \"channelId\": \"UChn5jutPQB_bRjnG80pzl5w\", \"title\": \"Video Title\", \"channelTitle\": \"Channel Name\", \"publishedAt\": \"2025-01-15T00:00:00Z\" },\n      \"statistics\": { \"viewCount\": 500000, \"zScore\": 4.2, \"averageViewsRatio\": 10.5, \"likeCount\": 15000, \"commentCount\": 1200 },\n      \"classification\": { \"quality\": \"positive\", \"isFaceless\": false }\n    }\n  ]\n}\n```\n\n### GET /search/outliers/related\n\n**Similar Outliers**\nSearch for YouTube outliers with **related content to another outlier(s)**.\nCost: **5 credits** per request.\n\n```bash\ncurl -s \"https://public-api.tubelab.net/v1/search/outliers/related?title=minecraft%20survival%20tutorial&type=video&by=semantic\" \\\n  -H \"Authorization: Api-Key $TUBELAB_API_KEY\"\n```\n\n**Query parameters:**\n\n| Name | Type | Required | Description |\n| --- | --- | --- | --- |\n| `title` | string[] | no |  |\n| `videoId` | string[] | no |  |\n| `thumbnailVideoId` | string | no | A unique YouTube video identifier |\n| `relatedChannelId` | string[] | no |  |\n| `type` | \"video\" \\| \"short\" | no |  |\n| `averageViewsRatioFrom` | number | no |  |\n| `averageViewsRatioTo` | number | no |  |\n| `zScoreFrom` | number | no |  |\n| `zScoreTo` | number | no |  |\n| `viewCountFrom` | integer | no |  |\n| `viewCountTo` | integer | no |  |\n| `language` | string[] | no | ISO 639-1 language codes |\n| `durationFrom` | integer | no |  |\n| `durationTo` | integer | no |  |\n| `publishedAtFrom` | string \\| string | no |  |\n| `publishedAtTo` | string | no |  |\n| `subscribersCountFrom` | integer | no |  |\n| `subscribersCountTo` | integer | no |  |\n| `channelAvgViewsFrom` | number | no |  |\n| `channelAvgViewsTo` | number | no |  |\n| `channelVideoCountFrom` | integer | no |  |\n| `channelVideoCountTo` | integer | no |  |\n| `channelId` | string | no |  |\n| `channelAvgViewsToSubscribersRatioFrom` | number | no |  |\n| `channelAvgViewsToSubscribersRatioTo` | number | no |  |\n| `titlePattern` | string | no |  |\n| `referenceId` | string | no |  |\n| `rpmEstimationFrom` | number | no |  |\n| `rpmEstimationTo` | number | no |  |\n| `revenueEstimationFrom` | number | no |  |\n| `revenueEstimationTo` | number | no |  |\n| `channelMonetizationAdsense` | boolean | no |  |\n| `classificationQuality` | \"negative\" \\| \"neutral\" \\| \"positive\" | no |  |\n| `classificationIsFaceless` | boolean | no |  |\n| `excludeKeyword` | string[] | no |  |\n| `from` | integer | no | Page to fetch |\n| `size` | integer | no | Number of items per page |\n| `by` | \"semantic\" \\| \"lexical\" | no | Search by semantics (meaning of words) or lexical (exact words) |\n\n**Response shape (abbreviated):**\n\n```json\n{\n  \"pagination\": { \"total\": 50, \"from\": 0, \"size\": 20 },\n  \"hits\": [\n    {\n      \"id\": \"dQw4w9WgXcQ\",\n      \"kind\": \"video\",\n      \"snippet\": { \"channelId\": \"UChn5jutPQB_bRjnG80pzl5w\", \"title\": \"Similar Video\", \"publishedAt\": \"2025-02-01T00:00:00Z\" },\n      \"statistics\": { \"viewCount\": 120000, \"zScore\": 3.1, \"averageViewsRatio\": 5.2 }\n    }\n  ]\n}\n```\n\n## Channel & Video Endpoints\n\nGet detailed information about specific channels and videos.\n\n### GET /channel/videos/{id}\n\n**Channel Videos**\nGet videos from a YouTube channel with sampled metrics.\nCost: **free** per request.\n\n```bash\ncurl -s \"https://public-api.tubelab.net/v1/channel/videos/UChn5jutPQB_bRjnG80pzl5w\" \\\n  -H \"Authorization: Api-Key $TUBELAB_API_KEY\"\n```\n\n**Path parameters:**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| `id` | string | A unique YouTube channel identifier |\n\n**Response shape (abbreviated):**\n\n```json\n{\n  \"id\": \"UChn5jutPQB_bRjnG80pzl5w\",\n  \"time\": \"2025-06-15T12:00:00Z\",\n  \"item\": {\n    \"id\": \"UChn5jutPQB_bRjnG80pzl5w\",\n    \"kind\": \"channel\",\n    \"snippet\": { \"title\": \"TubeLab\", \"handle\": \"@tubelabhq\" },\n    \"videos\": [{ \"id\": \"SVeXR66hcIg\", \"title\": \"Video Title\", \"viewCount\": 50000, \"publishedAt\": \"2025-01-15T00:00:00Z\" }],\n    \"statistics\": { \"subscribers\": 15000, \"totalViews\": 500000, \"videoCount\": 120 }\n  }\n}\n```\n\n### GET /channel/shorts/{id}\n\n**Channel Shorts**\nGet shorts from a YouTube channel with sampled metrics.\nCost: **free** per request.\n\n```bash\ncurl -s \"https://public-api.tubelab.net/v1/channel/shorts/UChn5jutPQB_bRjnG80pzl5w\" \\\n  -H \"Authorization: Api-Key $TUBELAB_API_KEY\"\n```\n\n**Path parameters:**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| `id` | string | A unique YouTube channel identifier |\n\n**Response shape (abbreviated):**\n\n```json\n{\n  \"id\": \"UChn5jutPQB_bRjnG80pzl5w\",\n  \"time\": \"2025-06-15T12:00:00Z\",\n  \"item\": {\n    \"id\": \"UChn5jutPQB_bRjnG80pzl5w\",\n    \"kind\": \"channel\",\n    \"snippet\": { \"title\": \"TubeLab\", \"handle\": \"@tubelabhq\" },\n    \"shorts\": [{ \"id\": \"abc123\", \"title\": \"Short Title\", \"viewCount\": 100000, \"publishedAt\": \"2025-03-01T00:00:00Z\" }],\n    \"statistics\": { \"subscribers\": 15000, \"totalViews\": 500000 }\n  }\n}\n```\n\n### GET /video/{id}\n\n**Video Details**\nGet details of a YouTube video.\nCost: **free** per request.\n\n```bash\ncurl -s \"https://public-api.tubelab.net/v1/video/SVeXR66hcIg\" \\\n  -H \"Authorization: Api-Key $TUBELAB_API_KEY\"\n```\n\n**Path parameters:**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| `id` | string | A unique YouTube video identifier |\n\n**Response shape (abbreviated):**\n\n```json\n{\n  \"ids\": [\"SVeXR66hcIg\"],\n  \"time\": \"2025-06-15T12:00:00Z\",\n  \"items\": [\n    {\n      \"id\": \"SVeXR66hcIg\",\n      \"kind\": \"video\",\n      \"snippet\": { \"channelId\": \"UChn5jutPQB_bRjnG80pzl5w\", \"title\": \"Video Title\", \"publishedAt\": \"2025-01-15T00:00:00Z\" },\n      \"statistics\": { \"viewCount\": 50000, \"likeCount\": 2000, \"commentCount\": 300 }\n    }\n  ]\n}\n```\n\n### GET /video/transcript/{id}\n\n**Video Transcript**\nGet the transcript of a YouTube video.\nCost: **free** per request.\n\n```bash\ncurl -s \"https://public-api.tubelab.net/v1/video/transcript/SVeXR66hcIg\" \\\n  -H \"Authorization: Api-Key $TUBELAB_API_KEY\"\n```\n\n**Path parameters:**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| `id` | string | A unique YouTube video identifier |\n\n**Response shape (abbreviated):**\n\n```json\n{\n  \"ids\": [\"SVeXR66hcIg\"],\n  \"items\": [\n    {\n      \"id\": \"SVeXR66hcIg\",\n      \"events\": [{ \"startMs\": 0, \"durationMs\": 5000, \"endMs\": 5000, \"text\": \"Hello and welcome...\" }],\n      \"transcript\": \"Hello and welcome to this video...\"\n    }\n  ]\n}\n```\n\n### GET /video/comments/{id}\n\n**Video Comments**\nGet the last 100 comments of a YouTube video.\nCost: **free** per request.\n\n```bash\ncurl -s \"https://public-api.tubelab.net/v1/video/comments/SVeXR66hcIg\" \\\n  -H \"Authorization: Api-Key $TUBELAB_API_KEY\"\n```\n\n**Path parameters:**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| `id` | string | A unique YouTube video identifier |\n\n**Response shape (abbreviated):**\n\n```json\n{\n  \"ids\": [\"SVeXR66hcIg\"],\n  \"time\": \"2025-06-15T12:00:00Z\",\n  \"items\": [\n    {\n      \"id\": \"SVeXR66hcIg\",\n      \"comments\": [{ \"authorText\": \"User\", \"text\": \"Great video!\", \"likesCount\": 42, \"replyCount\": 3, \"publishedAt\": \"2025-01-16T00:00:00Z\" }],\n      \"statistics\": { \"count\": 300 }\n    }\n  ]\n}\n```\n\n## Scanning Endpoints\n\nStart YouTube scans to discover channels and outlier videos in any niche. Scans run asynchronously - start one, then poll for status.\n\n### POST /scan\n\n**Scan**\nStart a YouTube scan to search for outliers and channels on any given topic.\nCost: **50–100 credits** per request.\n\n```bash\ncurl -s -X POST \"https://public-api.tubelab.net/v1/scan\" \\\n  -H \"Authorization: Api-Key $TUBELAB_API_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"findBy\":\"query\",\"query\":[\"UCUyeluBRhGPCW4rPe_UvBZQ\",\"UCX6OQ3DkcsbYNE6H8uQQuVA\"],\"mode\":\"standard\"}'\n```\n\n**Body parameters:**\n\n| Name | Type | Required | Default | Description |\n| --- | --- | --- | --- | --- |\n| `findBy` | \"channels\" \\| \"query\" | no | `query` | Start the scan from queries (search results) or channels |\n| `query` | string[] | yes |  | Search queries or YouTube channel ids |\n| `mode` | \"fast\" \\| \"standard\" | no | `fast` | - **Fast**: 1000 outliers or 100 channels - **Standard**: 2500 outliers or 250 channels |\n\n**Response shape (abbreviated):**\n\n```json\n{\n  \"id\": \"2a5e56f5-75f3-4f01-ac85-6e796f5cde87\",\n  \"name\": \"minecraft, gaming\",\n  \"status\": \"Queued\",\n  \"input\": { \"query\": [\"minecraft\", \"gaming\"], \"threshold\": 1000 },\n  \"endedAt\": null,\n  \"createdAt\": \"2025-06-15T12:00:00Z\",\n  \"updatedAt\": \"2025-06-15T12:00:00Z\"\n}\n```\n\n### GET /scan/{id}\n\n**Scan**\nGet a scan by id.\nCost: **free** per request.\n\n```bash\ncurl -s \"https://public-api.tubelab.net/v1/scan/2a5e56f5-75f3-4f01-ac85-6e796f5cde87\" \\\n  -H \"Authorization: Api-Key $TUBELAB_API_KEY\"\n```\n\n**Path parameters:**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| `id` | string | Scan id |\n\n**Response shape (abbreviated):**\n\n```json\n{\n  \"id\": \"2a5e56f5-75f3-4f01-ac85-6e796f5cde87\",\n  \"name\": \"minecraft, gaming\",\n  \"status\": \"Completed\",\n  \"input\": { \"query\": [\"minecraft\", \"gaming\"], \"threshold\": 1000 },\n  \"endedAt\": \"2025-06-15T13:30:00Z\",\n  \"createdAt\": \"2025-06-15T12:00:00Z\",\n  \"updatedAt\": \"2025-06-15T13:30:00Z\"\n}\n```\n\n## Scan Workflow\n\nScans run asynchronously. Here's the typical flow:\n\n1. **Start a scan** with `POST /scan` - returns a scan ID and status `Queued`\n2. **Poll for status** with `GET /scan/{id}` - status progresses: `Queued` → `Running` → `Completed`\n3. **Search results** with `GET /search/outliers?referenceId={scanId}` - returns discovered outlier videos\n\n```bash\n# 1. Start scan\nSCAN_ID=$(curl -s -X POST \"https://public-api.tubelab.net/v1/scan\" \\\n  -H \"Authorization: Api-Key $TUBELAB_API_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"query\":[\"minecraft\",\"gaming\"],\"mode\":\"fast\"}' | jq -r '.id')\n\n# 2. Poll until complete\ncurl -s \"https://public-api.tubelab.net/v1/scan/$SCAN_ID\" \\\n  -H \"Authorization: Api-Key $TUBELAB_API_KEY\" | jq '.status'\n\n# 3. Search results once completed\ncurl -s \"https://public-api.tubelab.net/v1/search/outliers?referenceId=$SCAN_ID\" \\\n  -H \"Authorization: Api-Key $TUBELAB_API_KEY\"\n```\n\n| Mode | Outliers Limit | Channels Limit | Cost | Est. Time |\n| --- | --- | --- | --- | --- |\n| Fast | 1,000 | 100 | 50 credits | 30 min – 2 hrs |\n| Standard | 2,500 | 250 | 100 credits | 2 – 4 hrs |\n\n## Common Patterns\n\n### Pagination\n\nSearch endpoints return `pagination.total`, `pagination.from`, and `pagination.size`. Use `from` and `size` query params to paginate:\n\n```bash\n# Page 1 (items 0-19)\ncurl -s \"https://public-api.tubelab.net/v1/search/outliers?query=minecraft%20adventures&type=video&from=0&size=20\" \\\n  -H \"Authorization: Api-Key $TUBELAB_API_KEY\"\n\n# Page 2 (items 20-39)\ncurl -s \"https://public-api.tubelab.net/v1/search/outliers?query=minecraft%20adventures&type=video&from=20&size=20\" \\\n  -H \"Authorization: Api-Key $TUBELAB_API_KEY\"\n```\n\n### Range Filters\n\nMany numeric fields support `From`/`To` suffixes for range filtering:\n\n```bash\n# Channels with 10k-100k subscribers and avg views > 5000\ncurl -s \"https://public-api.tubelab.net/v1/search/channels?query=cooking%20healthy%20recipes&subscribersFrom=10000&subscribersTo=100000&averageViewsFrom=5000\" \\\n  -H \"Authorization: Api-Key $TUBELAB_API_KEY\"\n```\n\n### Sorting\n\nUse `sortBy` and `sortOrder` params. Available sort fields vary by endpoint.\n\n**Important:** When using `query`, omit `sortBy` to get the default relevance-based ranking. Adding a sort like `sortBy=views` overrides relevance and returns results ordered by that field, which usually produces worse matches. Only add `sortBy` when you don't use `query` (e.g. filter-only searches).\n\n```bash\n# Filter-only search (no query) — sorting makes sense here\ncurl -s \"https://public-api.tubelab.net/v1/search/outliers?type=video&classificationQuality=positive&sortBy=views&sortOrder=desc\" \\\n  -H \"Authorization: Api-Key $TUBELAB_API_KEY\"\n```\n\n### Array Parameters\n\nArray params use repeated keys:\n\n```bash\n# Multiple search queries\ncurl -s \"https://public-api.tubelab.net/v1/search/channels?query=minecraft%20adventures&query=gaming%20tutorials\" \\\n  -H \"Authorization: Api-Key $TUBELAB_API_KEY\"\n```\n\n## Search Recipes\n\nReady-to-use filter combinations for common research tasks. Date filters use ISO 8601 format - compute relative dates with `date` or substitute directly.\n\n**Tip - queries:** Search is semantic — longer, descriptive queries return much better results than single keywords. Use `query=minecraft adventures` or `query=cooking healthy recipes` instead of just `query=minecraft` or `query=cooking`. Think 2-4 words that describe the niche.\n\n**Tip - sorting:** When using `query`, do NOT add `sortBy` — the default sort is by relevance and gives the best matches. Only use `sortBy` for filter-only searches (no `query`), e.g. sorting by `foundAt` or `views`.\n\n**Tip - `averageViewsRatio`:** When searching outliers, prefer `averageViewsRatioFrom=1` to find videos that outperformed the channel's average. A ratio of 2 means the video got 2x the channel's usual views. Values above 5 are very rare and indicate extreme virality - only use higher thresholds when you want to narrow results significantly.\n\n**Tip - content type:** When searching outliers, prefer `type=video` to focus on long-form videos. Shorts tend to have inflated view counts and skew results. Only use `type=short` when specifically researching short-form content.\n\n### Profitable channels (recently found)\n\nMonetized channels found in the last year with estimated monthly revenue above $1,000 and at least 1,000 subscribers. Sorted by discovery date.\n\n```bash\nONE_YEAR_AGO=$(date -u -d \"1 year ago\" +%Y-%m-%dT00:00:00Z 2>/dev/null || date -u -v-1y +%Y-%m-%dT00:00:00Z)\ncurl -s \"https://public-api.tubelab.net/v1/search/channels?monetizationAdsense=true&revenueMonthlyEstimationFrom=1000&subscribersFrom=1000&publishedAtFrom=$ONE_YEAR_AGO&language=en&language=de&language=fr&excludeNiche=music&excludeNiche=song&excludeNiche=lofi&excludeNiche=movies&excludeNiche=kids&excludeNiche=news&excludeNiche=politic&sortBy=foundAt&size=20\" \\\n  -H \"Authorization: Api-Key $TUBELAB_API_KEY\"\n```\n\n### Trending channels\n\nChannels with high engagement (avg views/subscribers ratio above 1) and at least 10,000 average views, found in the last 6 months. Good for spotting rising creators.\n\n```bash\nSIX_MONTHS_AGO=$(date -u -d \"6 months ago\" +%Y-%m-%dT00:00:00Z 2>/dev/null || date -u -v-6m +%Y-%m-%dT00:00:00Z)\ncurl -s \"https://public-api.tubelab.net/v1/search/channels?avgViewsToSubscribersRatioFrom=1&averageViewsFrom=10000&subscribersFrom=100&publishedAtFrom=$SIX_MONTHS_AGO&language=en&language=de&language=fr&excludeNiche=music&excludeNiche=song&excludeNiche=lofi&excludeNiche=movies&sortBy=foundAt&size=20\" \\\n  -H \"Authorization: Api-Key $TUBELAB_API_KEY\"\n```\n\n### Faceless viral videos\n\nAI-classified faceless videos with positive quality published in the last month. Useful for finding faceless niche ideas.\n\n```bash\nONE_MONTH_AGO=$(date -u -d \"1 month ago\" +%Y-%m-%dT00:00:00Z 2>/dev/null || date -u -v-1m +%Y-%m-%dT00:00:00Z)\ncurl -s \"https://public-api.tubelab.net/v1/search/outliers?type=video&classificationIsFaceless=true&classificationQuality=positive&publishedAtFrom=$ONE_MONTH_AGO&size=20\" \\\n  -H \"Authorization: Api-Key $TUBELAB_API_KEY\"\n```\n\n### High authenticity videos\n\nVideos classified as positive quality by AI. Filters out low-effort and spammy content.\n\n```bash\ncurl -s \"https://public-api.tubelab.net/v1/search/outliers?type=video&classificationQuality=positive&size=20\" \\\n  -H \"Authorization: Api-Key $TUBELAB_API_KEY\"\n```\n\n### Monetized channel videos\n\nOutlier videos from channels with AdSense enabled. Useful for researching niches that generate ad revenue.\n\n```bash\ncurl -s \"https://public-api.tubelab.net/v1/search/outliers?type=video&channelMonetizationAdsense=true&size=20\" \\\n  -H \"Authorization: Api-Key $TUBELAB_API_KEY\"\n```\n\n## Error Handling\n\nAll errors return JSON with an `error` object:\n\n| Status | Meaning | Response |\n| --- | --- | --- |\n| 400 | Validation error | `{ \"error\": { \"errors\": [{ \"code\": \"...\", \"message\": \"...\", \"path\": [\"param\"] }] } }` |\n| 401 | Invalid/missing API key | `{ \"error\": { \"message\": \"Unauthorized\" }, \"status\": \"error\" }` |\n| 402 | Insufficient credits | `{ \"error\": { \"message\": \"Insufficient credits\" }, \"status\": \"error\" }` |\n| 429 | Rate limited | `{ \"error\": { \"message\": \"Rate limit exceeded\", \"rateLimit\": { \"limit\": 10, \"current\": 11, \"remaining\": 0 } } }` |\n\n## jq Recipes\n\n```bash\n# Profitable channels: extract name, subs, revenue, and views\nONE_YEAR_AGO=$(date -u -d \"1 year ago\" +%Y-%m-%dT00:00:00Z 2>/dev/null || date -u -v-1y +%Y-%m-%dT00:00:00Z)\ncurl -s \"https://public-api.tubelab.net/v1/search/channels?monetizationAdsense=true&revenueMonthlyEstimationFrom=1000&subscribersFrom=1000&publishedAtFrom=$ONE_YEAR_AGO&sortBy=foundAt&size=10\" \\\n  -H \"Authorization: Api-Key $TUBELAB_API_KEY\" | jq '[.hits[] | {title: .snippet.title, handle: .snippet.handle, subs: .statistics.subscribers, avgViews: .statistics.averageViews}]'\n\n# Trending channels: list titles with engagement ratio\nSIX_MONTHS_AGO=$(date -u -d \"6 months ago\" +%Y-%m-%dT00:00:00Z 2>/dev/null || date -u -v-6m +%Y-%m-%dT00:00:00Z)\ncurl -s \"https://public-api.tubelab.net/v1/search/channels?avgViewsToSubscribersRatioFrom=1&averageViewsFrom=10000&subscribersFrom=100&publishedAtFrom=$SIX_MONTHS_AGO&sortBy=foundAt&size=10\" \\\n  -H \"Authorization: Api-Key $TUBELAB_API_KEY\" | jq '[.hits[] | {title: .snippet.title, subs: .statistics.subscribers, ratio: .statistics.avgViewsToSubscribersRatio}]'\n\n# Faceless viral videos: extract title, views, and z-score\nONE_MONTH_AGO=$(date -u -d \"1 month ago\" +%Y-%m-%dT00:00:00Z 2>/dev/null || date -u -v-1m +%Y-%m-%dT00:00:00Z)\ncurl -s \"https://public-api.tubelab.net/v1/search/outliers?type=video&classificationIsFaceless=true&classificationQuality=positive&publishedAtFrom=$ONE_MONTH_AGO&size=10\" \\\n  -H \"Authorization: Api-Key $TUBELAB_API_KEY\" | jq '[.hits[] | {title: .snippet.title, views: .statistics.viewCount, zScore: .statistics.zScore, channel: .snippet.channelTitle}]'\n\n# High-quality outliers: get top videos by views\ncurl -s \"https://public-api.tubelab.net/v1/search/outliers?type=video&classificationQuality=positive&sortBy=views&sortOrder=desc&size=10\" \\\n  -H \"Authorization: Api-Key $TUBELAB_API_KEY\" | jq '[.hits[] | {title: .snippet.title, views: .statistics.viewCount, channel: .snippet.channelTitle}]'\n\n# Get full transcript as plain text\ncurl -s \"https://public-api.tubelab.net/v1/video/transcript/SVeXR66hcIg\" \\\n  -H \"Authorization: Api-Key $TUBELAB_API_KEY\" | jq -r '.items[0].transcript'\n\n# Poll scan status until complete\ncurl -s \"https://public-api.tubelab.net/v1/scan/2a5e56f5-75f3-4f01-ac85-6e796f5cde87\" \\\n  -H \"Authorization: Api-Key $TUBELAB_API_KEY\" | jq '{status: .status, endedAt: .endedAt}'\n```\n","tags":{"latest":"1.0.4"},"stats":{"comments":0,"downloads":1148,"installsAllTime":1,"installsCurrent":1,"stars":1,"versions":5},"createdAt":1771513446167,"updatedAt":1778491581507},"latestVersion":{"version":"1.0.4","createdAt":1771530301124,"changelog":"- No changes detected in this version.\n- Version 1.0.4 is functionally identical to the previous release.","license":null},"metadata":{"setup":[{"key":"TUBELAB_API_KEY","required":true}],"os":null,"systems":null},"owner":{"handle":"antoniojps","userId":"s1779dksj8gn8wnyw3pp9fkzjd885gyt","displayName":"António Santos","image":"https://avatars.githubusercontent.com/u/19779828?v=4"},"moderation":null}