Skip to content

YouTube API ​

This page documents the public YouTube API for connecting a channel, uploading videos, and managing channels, playlists, playlist items, videos, and video categories.

Connect a Google account once, then use the same USER_API_KEY for all YouTube requests. YouTube access tokens stay server-side and are never returned by the API.

Connect ​

Create a short-lived connection ticket:

bash
curl -X POST https://auth.genium.one/api/social/connect-ticket \
  -H "Authorization: Bearer $USER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"provider":"youtube"}'

Open the returned connect_url in a browser. The Google OAuth callback is:

text
https://auth.genium.one/callback/youtube

List connected channels:

bash
curl https://auth.genium.one/api/youtube/channels \
  -H "Authorization: Bearer $USER_API_KEY"

Example:

json
{
  "channels": [
    {
      "id": 3,
      "channel_id": "UC123456789",
      "display_name": "Genium Channel",
      "scopes": "https://www.googleapis.com/auth/youtube.upload"
    }
  ]
}

Reconnect the account after changing OAuth scopes or when Google revokes the connection.

Endpoint and authentication ​

text
POST https://auth.genium.one/api/youtube/actions
Authorization: Bearer <USER_API_KEY>
Content-Type: application/json

The endpoint accepts one JSON action per request. Write requests support the optional Idempotency-Key header:

text
Idempotency-Key: youtube-video-update-001

Reuse the same key when retrying the same write. Do not reuse it for a different operation.

Successful action responses are the corresponding YouTube API result. Delete operations return { "success": true } when YouTube returns no body. Errors return an error string with an HTTP error status.

Common fields ​

FieldTypeUsed byDescription
resourcestringAll actionschannel, playlist, playlistItem, video, or videoCategory.
operationstringAll actionsOperation for the selected resource.
account_idnumberAll actionsGenium ID of the connected YouTube channel. If omitted, Genium uses the available connected account.
channel_idstringChannel, bannerYouTube channel ID.
playlist_idstringPlaylist, playlist itemYouTube playlist ID.
playlist_item_idstringPlaylist itemYouTube playlist-item ID.
video_idstringVideo, playlist itemYouTube video ID.
media_keystringVideo upload, banner uploadExisting Genium R2 object key.
titlestringPlaylist/video writesPlaylist or video title. Video titles are limited to 100 characters by the upload pipeline.
descriptionstringPlaylist/video writesPlaylist or video description. Video descriptions are limited to 5,000 characters by the upload pipeline.
privacy_statusstringPlaylist/video writesprivate, unlisted, or public. Video uploads default to private.
category_idstringVideo updateYouTube video category ID. Defaults to 27 when updating a video.
ratingstringVideo ratelike, dislike, or none.
partsstring[]Reads and writesYouTube API parts to request. Defaults to all supported parts for the resource.
return_allbooleangetAllFetch every available page when true. Default is false.
limitnumberReadsMaximum number of items to return, from 1 to 50.
page_tokenstringReadsYouTube pageToken for continuing a paginated request.
paramsobjectReadsAdditional YouTube query parameters, such as channelId or publishedAfter.
dataobjectChannel/playlist/video writesAdditional raw resource data merged into the YouTube request body.
positionnumberPlaylist item addPosition of the video in the playlist.
notestringPlaylist item addNote attached to the playlist item.
start_atstringPlaylist item addClip start time, using YouTube's time format.
end_atstringPlaylist item addClip end time, using YouTube's time format.

Read options ​

parts ​

parts controls the YouTube fields returned by a read action. For example:

json
{
  "resource": "video",
  "operation": "get",
  "video_id": "VIDEO_ID",
  "parts": ["snippet", "status", "statistics"]
}

Use parts: ["*"], or omit parts, to request all supported parts for that resource. The adapter expands * to a safe list of YouTube parts.

return_all, limit, and page_token ​

By default, list actions return at most limit items and include next_page_token when more items are available:

json
{
  "resource": "playlist",
  "operation": "getAll",
  "limit": 25,
  "return_all": false,
  "page_token": "PAGE_TOKEN"
}

Set return_all to true to let Genium follow all YouTube pages. limit is validated from 1 through 50 and is ignored as a total cap when return_all is true.

params ​

params passes additional query filters to YouTube. Values may be strings, numbers, or booleans:

json
{
  "resource": "video",
  "operation": "getAll",
  "params": {
    "q": "Genium",
    "publishedAfter": "2026-01-01T00:00:00Z",
    "order": "date"
  }
}

channel/getAll defaults to the connected user's channel (mine=true) unless you provide a channel filter such as id, categoryId, forUsername, or managedByMe. playlist/getAll defaults to the connected user's playlists unless id or channelId is provided. video/getAll uses YouTube search and always requests video results.

data ​

Use data for additional fields supported by YouTube but not represented by a common Genium field. It is merged into the request body for channel, playlist, and video updates/creates:

json
{
  "resource": "video",
  "operation": "update",
  "video_id": "VIDEO_ID",
  "title": "Updated title",
  "data": {
    "localizations": {
      "en": { "title": "Updated title", "description": "English copy" }
    }
  }
}

Channel actions ​

1. Get a channel ​

Requires channel_id. Returns the selected channel and requested parts.

bash
curl -X POST https://auth.genium.one/api/youtube/actions \
  -H "Authorization: Bearer $USER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"resource":"channel","operation":"get","channel_id":"CHANNEL_ID","parts":["snippet","statistics"]}'

2. List channels ​

Returns channels matching params. Without a channel filter, Genium requests the connected user's channel.

bash
curl -X POST https://auth.genium.one/api/youtube/actions \
  -H "Authorization: Bearer $USER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"resource":"channel","operation":"getAll","limit":10,"params":{"mine":true}}'

3. Update a channel ​

Requires channel_id. Put the YouTube branding settings payload in data.

bash
curl -X POST https://auth.genium.one/api/youtube/actions \
  -H "Authorization: Bearer $USER_API_KEY" \
  -H "Idempotency-Key: youtube-channel-update-001" \
  -H "Content-Type: application/json" \
  -d '{"resource":"channel","operation":"update","channel_id":"CHANNEL_ID","data":{"brandingSettings":{"channel":{"title":"Genium Channel","description":"Updated channel description"}}}}'

4. Upload a channel banner ​

Requires channel_id and an image media_key already stored in Genium R2.

bash
curl -X POST https://auth.genium.one/api/youtube/actions \
  -H "Authorization: Bearer $USER_API_KEY" \
  -H "Idempotency-Key: youtube-banner-001" \
  -H "Content-Type: application/json" \
  -d '{"resource":"channel","operation":"uploadBanner","channel_id":"CHANNEL_ID","media_key":"images/BANNER_KEY"}'

Playlist actions ​

5. Create a playlist ​

Requires title. privacy_status defaults to private.

bash
curl -X POST https://auth.genium.one/api/youtube/actions \
  -H "Authorization: Bearer $USER_API_KEY" \
  -H "Idempotency-Key: youtube-playlist-create-001" \
  -H "Content-Type: application/json" \
  -d '{"resource":"playlist","operation":"create","title":"Genium tests","description":"Temporary playlist","privacy_status":"private"}'

6. Delete a playlist ​

Requires playlist_id.

bash
curl -X POST https://auth.genium.one/api/youtube/actions \
  -H "Authorization: Bearer $USER_API_KEY" \
  -H "Idempotency-Key: youtube-playlist-delete-001" \
  -H "Content-Type: application/json" \
  -d '{"resource":"playlist","operation":"delete","playlist_id":"PLAYLIST_ID"}'

7. Get a playlist ​

Requires playlist_id.

bash
curl -X POST https://auth.genium.one/api/youtube/actions \
  -H "Authorization: Bearer $USER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"resource":"playlist","operation":"get","playlist_id":"PLAYLIST_ID","parts":["snippet","status"]}'

8. List playlists ​

Use params.channelId or params.id to list another channel or selected playlists. Otherwise, Genium lists playlists owned by the connected account.

bash
curl -X POST https://auth.genium.one/api/youtube/actions \
  -H "Authorization: Bearer $USER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"resource":"playlist","operation":"getAll","limit":25,"return_all":false}'

9. Update a playlist ​

Requires playlist_id and title.

bash
curl -X POST https://auth.genium.one/api/youtube/actions \
  -H "Authorization: Bearer $USER_API_KEY" \
  -H "Idempotency-Key: youtube-playlist-update-001" \
  -H "Content-Type: application/json" \
  -d '{"resource":"playlist","operation":"update","playlist_id":"PLAYLIST_ID","title":"Updated playlist","description":"Updated description","privacy_status":"unlisted"}'

Playlist item actions ​

10. Add a video to a playlist ​

Requires playlist_id and video_id. position, note, start_at, and end_at are optional.

bash
curl -X POST https://auth.genium.one/api/youtube/actions \
  -H "Authorization: Bearer $USER_API_KEY" \
  -H "Idempotency-Key: youtube-playlist-item-add-001" \
  -H "Content-Type: application/json" \
  -d '{"resource":"playlistItem","operation":"add","playlist_id":"PLAYLIST_ID","video_id":"VIDEO_ID","position":0}'

11. Delete a playlist item ​

Requires playlist_item_id.

bash
curl -X POST https://auth.genium.one/api/youtube/actions \
  -H "Authorization: Bearer $USER_API_KEY" \
  -H "Idempotency-Key: youtube-playlist-item-delete-001" \
  -H "Content-Type: application/json" \
  -d '{"resource":"playlistItem","operation":"delete","playlist_item_id":"PLAYLIST_ITEM_ID"}'

12. Get a playlist item ​

Requires playlist_item_id.

bash
curl -X POST https://auth.genium.one/api/youtube/actions \
  -H "Authorization: Bearer $USER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"resource":"playlistItem","operation":"get","playlist_item_id":"PLAYLIST_ITEM_ID"}'

13. List playlist items ​

Requires playlist_id.

bash
curl -X POST https://auth.genium.one/api/youtube/actions \
  -H "Authorization: Bearer $USER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"resource":"playlistItem","operation":"getAll","playlist_id":"PLAYLIST_ID","limit":50}'

Video actions ​

14. Delete a video ​

Requires video_id. When the video was uploaded through Genium, this also marks its Genium post as DELETED and removes its temporary R2 media unless the media was retained.

bash
curl -X POST https://auth.genium.one/api/youtube/actions \
  -H "Authorization: Bearer $USER_API_KEY" \
  -H "Idempotency-Key: youtube-video-delete-001" \
  -H "Content-Type: application/json" \
  -d '{"resource":"video","operation":"delete","video_id":"VIDEO_ID"}'

15. Get a video ​

Requires video_id.

bash
curl -X POST https://auth.genium.one/api/youtube/actions \
  -H "Authorization: Bearer $USER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"resource":"video","operation":"get","video_id":"VIDEO_ID","parts":["snippet","status","statistics"]}'

16. List videos ​

video/getAll uses YouTube search. Pass filters such as q, channelId, publishedAfter, publishedBefore, order, or regionCode in params.

bash
curl -X POST https://auth.genium.one/api/youtube/actions \
  -H "Authorization: Bearer $USER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"resource":"video","operation":"getAll","limit":25,"params":{"q":"Genium","order":"date"}}'

17. Rate a video ​

Requires video_id and rating.

bash
curl -X POST https://auth.genium.one/api/youtube/actions \
  -H "Authorization: Bearer $USER_API_KEY" \
  -H "Idempotency-Key: youtube-video-rate-001" \
  -H "Content-Type: application/json" \
  -d '{"resource":"video","operation":"rate","video_id":"VIDEO_ID","rating":"like"}'

18. Update a video ​

Requires video_id and title. category_id defaults to 27. Use privacy_status to change visibility.

bash
curl -X POST https://auth.genium.one/api/youtube/actions \
  -H "Authorization: Bearer $USER_API_KEY" \
  -H "Idempotency-Key: youtube-video-update-001" \
  -H "Content-Type: application/json" \
  -d '{"resource":"video","operation":"update","video_id":"VIDEO_ID","title":"Updated title","description":"Updated description","category_id":"27","privacy_status":"unlisted"}'

19. Upload a video from R2 ​

Requires media_key and title. This action uses an existing Genium R2 video and publishes it immediately through YouTube's resumable upload API. It does not accept a local multipart file; use /api/youtube/videos for that.

bash
curl -X POST https://auth.genium.one/api/youtube/actions \
  -H "Authorization: Bearer $USER_API_KEY" \
  -H "Idempotency-Key: youtube-video-upload-001" \
  -H "Content-Type: application/json" \
  -d '{"resource":"video","operation":"upload","media_key":"videos/VIDEO_KEY","title":"Video title","description":"Video description","privacy_status":"unlisted"}'

Video upload and status ​

Upload a local video ​

Use the upload endpoint when the source is a local file. title is required; description is optional. privacy_status accepts private, unlisted, or public and defaults to private.

bash
curl -X POST https://auth.genium.one/api/youtube/videos \
  -H "Authorization: Bearer $USER_API_KEY" \
  -F "video=@video.mp4;type=video/mp4" \
  -F "title=Video title" \
  -F "description=Video description #hashtag" \
  -F "privacy_status=private"

The endpoint returns 202 Accepted after YouTube accepts the upload:

json
{
  "post_id": 42,
  "publish_id": "VIDEO_ID",
  "permalink": "https://www.youtube.com/watch?v=VIDEO_ID",
  "status": "PROCESSING",
  "privacy_status": "private"
}

Reuse an R2 video ​

Send an existing video key instead of a multipart file:

bash
curl -X POST https://auth.genium.one/api/youtube/videos \
  -H "Authorization: Bearer $USER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"media_key":"videos/VIDEO_KEY","title":"Video title","description":"Video description","privacy_status":"unlisted"}'

When media_key is used, Genium keeps the R2 object for reuse by another provider. Local multipart uploads follow the normal temporary-media cleanup flow.

Check upload status ​

Use the post_id returned by upload:

bash
curl "https://auth.genium.one/api/youtube/status?post_id=42" \
  -H "Authorization: Bearer $USER_API_KEY"

Example while YouTube is processing:

json
{
  "post_id": 42,
  "publish_id": "VIDEO_ID",
  "permalink": "https://www.youtube.com/watch?v=VIDEO_ID",
  "status": "PROCESSING",
  "provider_status": "processing",
  "media_deleted": false
}

When processing succeeds, status becomes PUBLISH_COMPLETE and temporary media is deleted unless it was retained:

json
{
  "post_id": 42,
  "publish_id": "VIDEO_ID",
  "permalink": "https://www.youtube.com/watch?v=VIDEO_ID",
  "status": "PUBLISH_COMPLETE",
  "provider_status": "succeeded",
  "media_deleted": true
}

Poll until PUBLISH_COMPLETE or FAILED. The permalink is available as soon as YouTube returns the video ID.

Video categories ​

20. List video categories ​

Use params.regionCode or params.id to filter categories.

bash
curl -X POST https://auth.genium.one/api/youtube/actions \
  -H "Authorization: Bearer $USER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"resource":"videoCategory","operation":"getAll","params":{"regionCode":"US"},"limit":50}'

Errors and limits ​

  • Missing or invalid JSON returns HTTP 400.
  • Invalid resource/operation returns HTTP 400.
  • limit must be an integer from 1 through 50.
  • parts must be a non-empty array of non-empty strings.
  • Missing required fields return HTTP 400, for example title, video_id, or playlist_id.
  • A missing connected channel or missing media_key returns HTTP 404.
  • YouTube API, upload, or processing failures return HTTP 400 or 502 with a sanitized error message.
  • A revoked or insufficient Google OAuth connection requires reconnecting YouTube.
  • YouTube may reject public publishing based on channel eligibility, account restrictions, or quota.

Genium Social Hub