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