Search live YouTube for videos, channels, playlists, and shorts. Results come straight from YouTube at request time — nothing is read from the NexLev catalog.
Base URL: https://prod.dashboard.nexlev.io — see Authentication. This operation costs 🥞 1 quota per request — see Rate Limits & Quota.
Requests are served with automatic failover across upstream data providers. The source field in every response reports whether the primary or the fallback path answered; the payload shape is identical either way.
Operations Quick Reference
| Operation | Method & Path | Quota Cost |
|---|---|---|
| Search YouTube | GET /api/external/youtube/search | 🥞 1 |
Rate Limit
Search YouTube
GET /api/external/youtube/searchDescription: Run a YouTube search and return the videos, channels, playlists, and shorts YouTube currently ranks for that query, with optional type, duration, recency, feature, and region filters.
When to use this operation:
- Checking what YouTube ranks for a keyword right now
- Keyword and title research against live search results
- Finding channels or playlists by name when you do not have a channel ID
- Sampling shorts for a topic without going channel by channel
Query Parameters
Parameter names are camelCase. Unknown parameters are rejected with a 400 rather than silently ignored — so a typo or a snake_case name (sort_by, upload_date) fails loudly instead of returning unfiltered results.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
query | string | Yes | — | Search terms, e.g. mkbhd. |
type | video | channel | playlist | shorts | movie | show | No | — | Restrict to one content type. Omit to get a mixed result set — check the type field on each item. |
sortBy | relevance | popularity | rating | date | views | No | relevance (YouTube default) | Result ordering. |
duration | short | medium | long | No | — | short under 4 min, medium 4–20 min, long over 20 min. |
uploadDate | hour | today | week | month | year | No | — | Restrict by upload recency. |
features | string (comma-separated) | No | — | Any of HD, subtitles, CCommons, 3D, Live, 4K, 360, HDR, VR180. Example: HD,subtitles. |
geo | string | No | — | ISO 3166-2 country code, e.g. US, GB, IN. Changes which regional results YouTube returns. |
lang | string | No | — | Locale, e.g. en, gb, hi. |
token | string | No | — | Pagination token. Pass the continuation value from the previous response. Omit for the first page. |
Example URLs
https://prod.dashboard.nexlev.io/api/external/youtube/search?query=mkbhd
https://prod.dashboard.nexlev.io/api/external/youtube/search?query=mkbhd&type=video&sortBy=views
cURL Example:
curl "https://prod.dashboard.nexlev.io/api/external/youtube/search?query=mkbhd&type=video&sortBy=views" \
-H "Authorization: Bearer YOUR_API_KEY"Status Code: 200 OK
Response Body:
{
"query": "mkbhd",
"estimatedResults": "360582",
"continuation": "EpoDEgVta2JoZBqQA0VnSVFBVWdV...",
"resultCount": 20,
"source": "primary",
"results": [
{
"type": "video",
"videoId": "_xjxwl1zLMc",
"title": "Framework 13 Pro: The Modular Laptop is Real!",
"channelTitle": "Marques Brownlee",
"channelId": "UCBJycsmduvYEL83R_U4JriQ",
"channelHandle": "@mkbhd",
"description": "The modular Macbook Pro for Linux users. Color me impressed...",
"viewCount": "2643412",
"publishedTime": "3 days ago",
"duration": "12:49",
"isLive": false,
"badges": ["New", "4K"],
"thumbnail": [
{
"url": "https://i.ytimg.com/vi/_xjxwl1zLMc/hq720.jpg?...",
"width": 720,
"height": 404
},
{
"url": "https://i.ytimg.com/vi/_xjxwl1zLMc/hq720.jpg?...",
"width": 360,
"height": 202
}
]
}
],
"filters": {
"type": "video",
"sortBy": "views"
}
}Envelope Fields
query- The query that was executedestimatedResults- YouTube's own estimate of total matches, as a numeric string. May be absent on some responses — do not assume it is presentcontinuation- Token for the next page.nullmeans there are no further pagesresultCount- Number of items inresultsfor this pagesource-"primary"or"fallback"; which leg of the failover chain served the request. Informational onlyresults- The result items. The shape varies bytype— see belowfilters- Echo of the filters that were applied. Onlytype,sortBy,duration,uploadDate, andgeoare echoed —featuresandlangare not. Filters you did not pass are omitted, notnull, so this is{}for an unfiltered query
Result Item Shapes
Every item carries a type discriminator. Branch on it — the available fields differ significantly. Pick a type below for its fields and a sample payload.
Video Item
The richest shape — full metadata for a long-form video or a live stream.
{
"type": "video",
"videoId": "_xjxwl1zLMc",
"title": "Framework 13 Pro: The Modular Laptop is Real!",
"channelTitle": "Marques Brownlee",
"channelId": "UCBJycsmduvYEL83R_U4JriQ",
"channelHandle": "@mkbhd",
"description": "The modular Macbook Pro for Linux users. Color me impressed...",
"viewCount": "2643412",
"publishedTime": "3 days ago",
"duration": "12:49",
"isLive": false,
"badges": ["New", "4K"],
"thumbnail": [
{
"url": "https://i.ytimg.com/vi/_xjxwl1zLMc/hq720.jpg?...",
"width": 720,
"height": 404
}
]
}Response Fields:
videoId- YouTube video IDtitle- Video titlechannelTitle/channelId/channelHandle- Uploading channeldescription- Truncated search-snippet description, not the full video descriptionviewCount- View count as a numeric stringpublishedTime- Relative human string, e.g."3 days ago"duration- Display string, e.g."12:49"isLive-truefor an ongoing live streambadges- YouTube badges such asNew,4K,CCthumbnail- Array of thumbnail objects withurl,width,height
Shorts Item
Sparse. YouTube nests shorts inside a shelf object; this endpoint lifts them out so every shorts item is an individual, linkable result.
{
"type": "shorts",
"videoId": "YHqpKFaFbyc",
"title": "Tomahawk Steak Frites!🥩 @ChefRush",
"viewCount": 29000000,
"thumbnail": []
}Response Fields:
videoId- YouTube video IDtitle- Shorts titleviewCount- View count as a number (not a string, unlikevideoitems)thumbnail- Frequently an empty array — fall back tohttps://i.ytimg.com/vi/{videoId}/hqdefault.jpg
Channel Item
{
"type": "channel",
"title": "Marques Brownlee",
"channelTitle": "Marques Brownlee",
"channelId": "UCBJycsmduvYEL83R_U4JriQ",
"channelHandle": "@mkbhd",
"description": "MKBHD: Quality Tech Videos | YouTuber | Geek | ...",
"thumbnail": [{ "url": "//yt3.ggpht.com/...", "width": 176, "height": 176 }]
}Response Fields:
channelId- Channel ID, usable directly with Channel Content and Channel Analyticstitle/channelTitle- Channel name (both present, same value)channelHandle- Handle, e.g.@mkbhddescription- Channel description snippetthumbnail- Avatar images
There is no subscriber count in the search payload. Call Get About with the channelId for full channel stats.
Playlist Item
{
"type": "playlist",
"title": "Tech Reviews 2025",
"videoId": "_xjxwl1zLMc",
"channelTitle": "Marques Brownlee",
"channelId": "UCBJycsmduvYEL83R_U4JriQ",
"channelHandle": "@mkbhd",
"thumbnail": [
{
"url": "https://i.ytimg.com/vi/_xjxwl1zLMc/hqdefault.jpg",
"width": 336,
"height": 188
}
]
}Response Fields:
title- Playlist titlevideoId- The first video in the playlist, not a playlist IDchannelTitle/channelId/channelHandle- Owning channelthumbnail- Playlist cover images
To enumerate a channel's playlists properly, use Get Playlists.
Integration Notes
These are all consequences of what YouTube returns upstream — worth handling defensively:
viewCountis not consistently typed. It is a numeric string onvideoitems ("2643412") and a number onshortsitems (29000000). Coerce before doing arithmetic.publishedTimeis a relative human string, not a timestamp —"3 days ago","1 year ago". There is no absolute date in the search payload; call Video Details if you need one.durationis a display string ("12:49"), not seconds.- Shorts are flattened out of their shelf, and their thumbnail array is frequently empty — fall back to
https://i.ytimg.com/vi/{videoId}/hqdefault.jpg. - Channel thumbnails may be protocol-relative (
//yt3.ggpht.com/...). Prefix withhttps:before use. - Mixed results by default. Without
type, a single page can contain videos, channels, playlists, and shorts together, andresultCountcounts them all. - Result counts per page are not fixed and are not controllable — there is no
limitparameter. Observed pages range from ~20 to 80+ items, depending on what YouTube returns and how many shorts got unpacked from their shelf. Paginate withtoken; never assume a page size. type=movieandtype=showare accepted and do return results, but items are tagged with the standard types above —moviecomes back asvideoitems, andshowreturns a mix ofvideo,shorts, andplaylist. There is nomovieorshowitem type.
Pagination
When more results are available, the response returns a continuation token. Pass it back as token to fetch the next page.
How to use continuation tokens:
- Make an initial request without
tokento get the first page - Check the
continuationfield in the response:- If it contains a token, more results are available
- If it is
null, you have reached the last page
- To fetch the next page, repeat the request with
tokenset to that value — and resend the samequeryand all the same filters - Repeat until
continuationisnull
Example pagination workflow:
# page 1
curl "https://prod.dashboard.nexlev.io/api/external/youtube/search?query=cooking%20tutorials&type=video" \
-H "Authorization: Bearer YOUR_API_KEY"Response: {
"continuation": "EpoDEgVta2JoZBqQA0VnSVFBVWdV...",
"resultCount": 20,
"results": [
/* Array of result items */
]
}# page 2 — feed `continuation` back in as `token`
curl "https://prod.dashboard.nexlev.io/api/external/youtube/search?query=cooking%20tutorials&type=video&token=EpoDEgVta2JoZBqQA0VnSVFBVWdV..." \
-H "Authorization: Bearer YOUR_API_KEY"Response: {
"continuation": null, // null means no more results
"resultCount": 18,
"results": [
/* Array of remaining result items */
]
}Error Responses
Status Code: 400 Bad Request
Description: Validation failure — a missing query, an out-of-enum value, or an unrecognized parameter name. The response message lists exactly what was wrong.
{
"success": false,
"statusCode": 400,
"message": [
"property sort_by should not exist",
"property upload_date should not exist"
],
"error": "Bad Request",
"path": "/api/external/youtube/search?query=x&sort_by=date&upload_date=week"
}Status Code: 401 Unauthorized
Description: Authentication credentials are missing or invalid.
{
"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"
}
}Status Code: 429 Too Many Requests
Description: You exceeded either the per-minute rate limit (20 requests per minute on this endpoint) or your plan quota.
{
"error": {
"code": 429,
"message": "Rate limit exceeded",
"details": "You have exceeded your API quota. Please try again later.",
"retryAfter": 3600
}
}Status Code: 502 Bad Gateway
Description: The upstream YouTube data provider is unavailable — both the primary and the fallback path failed. Safe to retry, ideally with exponential backoff.
{
"error": {
"code": 502,
"message": "Upstream provider unavailable",
"details": "The YouTube data provider did not respond. Please retry."
}
}More Examples
# Most-viewed videos for a term
curl "https://prod.dashboard.nexlev.io/api/external/youtube/search?query=mkbhd&type=video&sortBy=views" \
-H "Authorization: Bearer YOUR_API_KEY"
# Channels only
curl "https://prod.dashboard.nexlev.io/api/external/youtube/search?query=mkbhd&type=channel" \
-H "Authorization: Bearer YOUR_API_KEY"
# Shorts, US region
curl "https://prod.dashboard.nexlev.io/api/external/youtube/search?query=cooking&type=shorts&geo=US&lang=en" \
-H "Authorization: Bearer YOUR_API_KEY"
# Short, recent, HD videos with subtitles
curl "https://prod.dashboard.nexlev.io/api/external/youtube/search?query=news&type=video&duration=short&uploadDate=week&features=HD,subtitles" \
-H "Authorization: Bearer YOUR_API_KEY"Related Endpoints
| Endpoint | Data source | Use when |
|---|---|---|
GET /api/external/youtube/search | Live YouTube | You need current YouTube search results. |
GET /api/external/videos/video-search | NexLev catalog | You need catalog filters — outlier score, subscriber count, RPM, dates. |
| Video Details | Live YouTube | Full metadata for one video, including absolute publish date. |
| Get About | Live YouTube | Channel stats for one channel (note: takes id, not channelId). |
| Get Videos | Live YouTube | A specific channel's uploads (takes id and sort_by). |