Appearance
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/youtubeList 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/jsonThe endpoint accepts one JSON action per request. Write requests support the optional Idempotency-Key header:
text
Idempotency-Key: youtube-video-update-001Reuse 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
| Field | Type | Used by | Description |
|---|---|---|---|
resource | string | All actions | channel, playlist, playlistItem, video, or videoCategory. |
operation | string | All actions | Operation for the selected resource. |
account_id | number | All actions | Genium ID of the connected YouTube channel. If omitted, Genium uses the available connected account. |
channel_id | string | Channel, banner | YouTube channel ID. |
playlist_id | string | Playlist, playlist item | YouTube playlist ID. |
playlist_item_id | string | Playlist item | YouTube playlist-item ID. |
video_id | string | Video, playlist item | YouTube video ID. |
media_key | string | Video upload, banner upload | Existing Genium R2 object key. |
title | string | Playlist/video writes | Playlist or video title. Video titles are limited to 100 characters by the upload pipeline. |
description | string | Playlist/video writes | Playlist or video description. Video descriptions are limited to 5,000 characters by the upload pipeline. |
privacy_status | string | Playlist/video writes | private, unlisted, or public. Video uploads default to private. |
category_id | string | Video update | YouTube video category ID. Defaults to 27 when updating a video. |
rating | string | Video rate | like, dislike, or none. |
parts | string[] | Reads and writes | YouTube API parts to request. Defaults to all supported parts for the resource. |
return_all | boolean | getAll | Fetch every available page when true. Default is false. |
limit | number | Reads | Maximum number of items to return, from 1 to 50. |
page_token | string | Reads | YouTube pageToken for continuing a paginated request. |
params | object | Reads | Additional YouTube query parameters, such as channelId or publishedAfter. |
data | object | Channel/playlist/video writes | Additional raw resource data merged into the YouTube request body. |
position | number | Playlist item add | Position of the video in the playlist. |
note | string | Playlist item add | Note attached to the playlist item. |
start_at | string | Playlist item add | Clip start time, using YouTube's time format. |
end_at | string | Playlist item add | Clip 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/operationreturns HTTP400. limitmust be an integer from1through50.partsmust be a non-empty array of non-empty strings.- Missing required fields return HTTP
400, for exampletitle,video_id, orplaylist_id. - A missing connected channel or missing
media_keyreturns HTTP404. - YouTube API, upload, or processing failures return HTTP
400or502with a sanitizederrormessage. - A revoked or insufficient Google OAuth connection requires reconnecting YouTube.
- YouTube may reject
publicpublishing based on channel eligibility, account restrictions, or quota.