YouTube
YouTube channels through your Google Cloud project, with the single youtube.force-ssl scope.
The permissions each capability needs are in App Review: YouTube.
- YouTube keeps no Shorts flag and classifies uploads on criteria it does not publish, so reads report
durationSecondsandaspectRatioand carry novariant; publishing withvariant: "short"applies Shorts media rules. - YouTube publishes no comment webhooks, so uploads and comments are collected by polling against your project's daily quota; a spent quota answers
platform_rate_limitwithRetry-Afterset to Google's midnight-Pacific reset. - Uploads from a project that has not passed Google's compliance audit are made private by YouTube, whatever
privacyStatusyou asked for. - Livestreams and live chat are not a surface yet.
| Content type | Operations | Events | Backfill |
|---|---|---|---|
youtube.videos.items | list, get, publish, update, delete | created | yes |
youtube.videos.comments | list, get, publish, update, moderate, delete | created | yes |
youtube.videos.items
The channel's uploads, videos and Shorts alike.
list
List the channel's videos and Shorts, newest first.
| Field | Type | Required | Description |
|---|---|---|---|
connectedProfileId | string | yes | Koil Connected Profile associated with the operation. |
cursor | string | no | Opaque cursor for fetching the next result page. |
limit | number | no | Maximum number of items to return. |
includeProviderRaw | boolean | no | Whether to include transient provider-native payloads. |
JSON Schema
{
"additionalProperties": false,
"type": "object",
"properties": {
"connectedProfileId": {
"description": "Koil Connected Profile associated with the operation.",
"minLength": 1,
"type": "string"
},
"cursor": {
"description": "Opaque cursor for fetching the next result page.",
"minLength": 1,
"type": "string"
},
"limit": {
"description": "Maximum number of items to return.",
"minimum": 1,
"type": "number"
},
"includeProviderRaw": {
"description": "Whether to include transient provider-native payloads.",
"type": "boolean"
}
},
"required": [
"connectedProfileId"
]
}get
Get one YouTube video by provider id.
| Field | Type | Required | Description |
|---|---|---|---|
connectedProfileId | string | yes | Koil Connected Profile associated with the operation. |
externalId | string | yes | |
includeProviderRaw | boolean | no | Whether to include transient provider-native payloads. |
JSON Schema
{
"additionalProperties": false,
"type": "object",
"properties": {
"connectedProfileId": {
"description": "Koil Connected Profile associated with the operation.",
"minLength": 1,
"type": "string"
},
"externalId": {
"minLength": 1,
"type": "string"
},
"includeProviderRaw": {
"description": "Whether to include transient provider-native payloads.",
"type": "boolean"
}
},
"required": [
"connectedProfileId",
"externalId"
]
}publish
Upload a YouTube video or Short through the resumable upload protocol.
Submit through POST /v1/publish-requests with contentType: "youtube.videos.items". These fields go in the item's args; connectedProfileId and variant are item fields.
| Field | Type | Required | Description |
|---|---|---|---|
title | string | yes | Up to 100 characters; YouTube refuses < and >. |
text | string | no | Description, up to 5,000 bytes; YouTube refuses < and >. |
tags | string[] | no | Keyword tags; at most 500 characters in total. |
categoryId | string | no | A YouTube video category id, e.g. 22 for People & Blogs. |
privacyStatus | "public" | "private" | "unlisted" | yes | Who can see the video. |
publishAt | string (date-time) | no | YouTube's scheduled release time. Requires privacyStatus private; YouTube makes the video public at this instant. |
madeForKids | boolean | no | The self-declared audience setting YouTube requires an answer for. |
containsSyntheticMedia | boolean | no | Disclose altered or synthetic content. |
notifySubscribers | boolean | no | Whether YouTube notifies subscribers; defaults to true. |
media | object | object[] | yes | |
scheduling | object | no | Future operation time and optional wall-clock timezone. |
JSON Schema
{
"additionalProperties": false,
"type": "object",
"properties": {
"title": {
"minLength": 1,
"maxLength": 100,
"pattern": "^[^<>]*$",
"description": "Up to 100 characters; YouTube refuses < and >.",
"type": "string"
},
"text": {
"maxLength": 5000,
"pattern": "^[^<>]*$",
"description": "Description, up to 5,000 bytes; YouTube refuses < and >.",
"type": "string"
},
"tags": {
"description": "Keyword tags; at most 500 characters in total.",
"type": "array",
"items": {
"minLength": 1,
"type": "string"
}
},
"categoryId": {
"minLength": 1,
"description": "A YouTube video category id, e.g. 22 for People & Blogs.",
"type": "string"
},
"privacyStatus": {
"description": "Who can see the video.",
"anyOf": [
{
"const": "public",
"type": "string"
},
{
"const": "private",
"type": "string"
},
{
"const": "unlisted",
"type": "string"
}
]
},
"publishAt": {
"format": "date-time",
"description": "YouTube's scheduled release time. Requires privacyStatus private; YouTube makes the video public at this instant.",
"type": "string"
},
"madeForKids": {
"description": "The self-declared audience setting YouTube requires an answer for.",
"type": "boolean"
},
"containsSyntheticMedia": {
"description": "Disclose altered or synthetic content.",
"type": "boolean"
},
"notifySubscribers": {
"description": "Whether YouTube notifies subscribers; defaults to true.",
"type": "boolean"
},
"media": {
"minItems": 1,
"maxItems": 1,
"type": "array",
"items": {
"anyOf": [
{
"additionalProperties": false,
"type": "object",
"properties": {
"mediaId": {
"minLength": 1,
"type": "string"
},
"contentType": {
"minLength": 1,
"pattern": "^video/",
"type": "string"
},
"altText": {
"minLength": 1,
"type": "string"
}
},
"required": [
"mediaId"
]
},
{
"additionalProperties": false,
"type": "object",
"properties": {
"sourceUrl": {
"minLength": 1,
"type": "string"
},
"contentType": {
"minLength": 1,
"pattern": "^video/",
"type": "string"
},
"altText": {
"minLength": 1,
"type": "string"
}
},
"required": [
"sourceUrl"
]
}
]
}
},
"scheduling": {
"additionalProperties": false,
"description": "Future operation time and optional wall-clock timezone.",
"type": "object",
"properties": {
"at": {
"format": "date-time",
"description": "Future execution time as an ISO-8601 string.",
"type": "string"
},
"timezone": {
"minLength": 1,
"type": "string"
}
},
"required": [
"at"
]
}
},
"required": [
"title",
"privacyStatus",
"media"
]
}update
Edit a video's title, description, tags, category, or privacy.
| Field | Type | Required | Description |
|---|---|---|---|
connectedProfileId | string | yes | Koil Connected Profile associated with the operation. |
externalId | string | yes | |
title | string | no | |
text | string | no | |
tags | string[] | no | |
categoryId | string | no | |
privacyStatus | "public" | "private" | "unlisted" | no | Who can see the video. |
includeProviderRaw | boolean | no |
JSON Schema
{
"additionalProperties": false,
"type": "object",
"properties": {
"connectedProfileId": {
"description": "Koil Connected Profile associated with the operation.",
"minLength": 1,
"type": "string"
},
"externalId": {
"minLength": 1,
"type": "string"
},
"title": {
"minLength": 1,
"maxLength": 100,
"pattern": "^[^<>]*$",
"type": "string"
},
"text": {
"maxLength": 5000,
"pattern": "^[^<>]*$",
"type": "string"
},
"tags": {
"type": "array",
"items": {
"minLength": 1,
"type": "string"
}
},
"categoryId": {
"minLength": 1,
"type": "string"
},
"privacyStatus": {
"description": "Who can see the video.",
"anyOf": [
{
"const": "public",
"type": "string"
},
{
"const": "private",
"type": "string"
},
{
"const": "unlisted",
"type": "string"
}
]
},
"includeProviderRaw": {
"type": "boolean"
}
},
"required": [
"connectedProfileId",
"externalId"
]
}delete
Delete one of the channel's videos.
| Field | Type | Required | Description |
|---|---|---|---|
connectedProfileId | string | yes | Koil Connected Profile associated with the operation. |
externalId | string | yes |
JSON Schema
{
"additionalProperties": false,
"type": "object",
"properties": {
"connectedProfileId": {
"description": "Koil Connected Profile associated with the operation.",
"minLength": 1,
"type": "string"
},
"externalId": {
"minLength": 1,
"type": "string"
}
},
"required": [
"connectedProfileId",
"externalId"
]
}Not offered
moderate: not applicable
Events
Backfill: supported (bounded coverage); see Backfill history.
Item schema
What list and get return and what events carry as data.
| Field | Type | Required | Description |
|---|---|---|---|
externalId | string | yes | Provider-owned content identifier. |
title | string | yes | |
text | string | no | Caption/body text for content. |
tags | string[] | no | |
media | object[] | no | |
providerPermalink | string (uri) | no | Canonical provider URL for content. |
privacyStatus | "public" | "private" | "unlisted" | no | Who can see the video. |
aspectRatio | number | no | |
uploadStatus | string | no | |
liveBroadcast | "none" | "live" | "upcoming" | no | |
madeForKids | boolean | no | |
durationSeconds | number | no | |
engagement | object | no | Provider-reported engagement counts. |
publishedAt | string (date-time) | no | Provider publish timestamp as an ISO-8601 string. |
scheduledPublishAt | string (date-time) | no | When a private video is scheduled to go public. |
providerRaw | unknown | no | Optional provider-native payload included only for transient delivery/debug use. |
contentType | "youtube.videos.items" | yes |
youtube.videos.comments
Comments on the channel's videos, and replies to them.
list
List comments across the channel's videos (newest thread first, replies inline), one video's comments, or the replies to one comment.
| Field | Type | Required | Description |
|---|---|---|---|
connectedProfileId | string | yes | Koil Connected Profile associated with the operation. |
mediaExternalId | string | no | Only this video's comments; every video of the channel otherwise. |
parentExternalId | string | no | The replies to this top-level comment instead of the threads. |
moderationStatus | "published" | "heldForReview" | "likelySpam" | no | Which of YouTube's queues to read; defaults to published. Ignored with parentExternalId. |
searchTerms | string | no | Only threads containing these terms. Ignored with parentExternalId. |
cursor | string | no | Opaque cursor for fetching the next result page. |
limit | number | no | Maximum number of items to return. |
includeProviderRaw | boolean | no | Whether to include transient provider-native payloads. |
JSON Schema
{
"additionalProperties": false,
"type": "object",
"properties": {
"connectedProfileId": {
"description": "Koil Connected Profile associated with the operation.",
"minLength": 1,
"type": "string"
},
"mediaExternalId": {
"minLength": 1,
"description": "Only this video's comments; every video of the channel otherwise.",
"type": "string"
},
"parentExternalId": {
"minLength": 1,
"description": "The replies to this top-level comment instead of the threads.",
"type": "string"
},
"moderationStatus": {
"description": "Which of YouTube's queues to read; defaults to published. Ignored with parentExternalId.",
"anyOf": [
{
"const": "published",
"type": "string"
},
{
"const": "heldForReview",
"type": "string"
},
{
"const": "likelySpam",
"type": "string"
}
]
},
"searchTerms": {
"minLength": 1,
"description": "Only threads containing these terms. Ignored with parentExternalId.",
"type": "string"
},
"cursor": {
"description": "Opaque cursor for fetching the next result page.",
"minLength": 1,
"type": "string"
},
"limit": {
"description": "Maximum number of items to return.",
"minimum": 1,
"type": "number"
},
"includeProviderRaw": {
"description": "Whether to include transient provider-native payloads.",
"type": "boolean"
}
},
"required": [
"connectedProfileId"
]
}get
Get one YouTube comment by provider id.
| Field | Type | Required | Description |
|---|---|---|---|
connectedProfileId | string | yes | Koil Connected Profile associated with the operation. |
externalId | string | yes | |
includeProviderRaw | boolean | no | Whether to include transient provider-native payloads. |
JSON Schema
{
"additionalProperties": false,
"type": "object",
"properties": {
"connectedProfileId": {
"description": "Koil Connected Profile associated with the operation.",
"minLength": 1,
"type": "string"
},
"externalId": {
"minLength": 1,
"type": "string"
},
"includeProviderRaw": {
"description": "Whether to include transient provider-native payloads.",
"type": "boolean"
}
},
"required": [
"connectedProfileId",
"externalId"
]
}publish
Publish a YouTube comment: a top-level comment on a video, or a reply to a top-level comment.
Submit through POST /v1/publish-requests with contentType: "youtube.videos.comments". These fields go in the item's args; connectedProfileId and variant are item fields.
| Field | Type | Required | Description |
|---|---|---|---|
target | object | yes | The provider content this publish targets, identified as events identify it. |
text | string | yes | Comment text as the author wrote it. |
JSON Schema
{
"additionalProperties": false,
"type": "object",
"properties": {
"target": {
"additionalProperties": false,
"description": "The provider content this publish targets, identified as events identify it.",
"type": "object",
"properties": {
"contentType": {
"anyOf": [
{
"const": "youtube.videos.comments",
"type": "string"
},
{
"const": "youtube.videos.items",
"type": "string"
}
]
},
"externalId": {
"description": "Provider-owned content identifier.",
"minLength": 1,
"type": "string"
}
},
"required": [
"contentType",
"externalId"
]
},
"text": {
"description": "Comment text as the author wrote it.",
"minLength": 1,
"maxLength": 10000,
"type": "string"
}
},
"required": [
"target",
"text"
]
}update
Edit the text of a comment the channel made.
| Field | Type | Required | Description |
|---|---|---|---|
connectedProfileId | string | yes | Koil Connected Profile associated with the operation. |
externalId | string | yes | |
text | string | yes | Comment text as the author wrote it. |
includeProviderRaw | boolean | no | Whether to include transient provider-native payloads. |
JSON Schema
{
"additionalProperties": false,
"type": "object",
"properties": {
"connectedProfileId": {
"description": "Koil Connected Profile associated with the operation.",
"minLength": 1,
"type": "string"
},
"externalId": {
"minLength": 1,
"type": "string"
},
"text": {
"description": "Comment text as the author wrote it.",
"minLength": 1,
"maxLength": 10000,
"type": "string"
},
"includeProviderRaw": {
"description": "Whether to include transient provider-native payloads.",
"type": "boolean"
}
},
"required": [
"connectedProfileId",
"externalId",
"text"
]
}moderate
Publish, hold for review, or reject a comment on one of the channel's videos, optionally banning its author.
| Field | Type | Required | Description |
|---|---|---|---|
connectedProfileId | string | yes | Koil Connected Profile associated with the operation. |
externalId | string | yes | |
moderationStatus | "published" | "heldForReview" | "rejected" | yes | |
banAuthor | boolean | no | Also block the comment's author from the channel. Only with moderationStatus rejected. |
JSON Schema
{
"additionalProperties": false,
"type": "object",
"properties": {
"connectedProfileId": {
"description": "Koil Connected Profile associated with the operation.",
"minLength": 1,
"type": "string"
},
"externalId": {
"minLength": 1,
"type": "string"
},
"moderationStatus": {
"anyOf": [
{
"const": "published",
"type": "string"
},
{
"const": "heldForReview",
"type": "string"
},
{
"const": "rejected",
"type": "string"
}
]
},
"banAuthor": {
"description": "Also block the comment's author from the channel. Only with moderationStatus rejected.",
"type": "boolean"
}
},
"required": [
"connectedProfileId",
"externalId",
"moderationStatus"
]
}delete
Delete a comment on one of the channel's videos.
| Field | Type | Required | Description |
|---|---|---|---|
connectedProfileId | string | yes | Koil Connected Profile associated with the operation. |
externalId | string | yes |
JSON Schema
{
"additionalProperties": false,
"type": "object",
"properties": {
"connectedProfileId": {
"description": "Koil Connected Profile associated with the operation.",
"minLength": 1,
"type": "string"
},
"externalId": {
"minLength": 1,
"type": "string"
}
},
"required": [
"connectedProfileId",
"externalId"
]
}Events
Backfill: supported (bounded coverage); see Backfill history.
Item schema
What list and get return and what events carry as data.
| Field | Type | Required | Description |
|---|---|---|---|
externalId | string | yes | Provider-owned content identifier. |
mediaExternalId | string | yes | |
text | string | no | Caption/body text for content. |
author | object | no | Provider actor reference for observed content. |
authorProfileImageUrl | string | no | |
thread | object | no | Parent/root identifiers for threaded contexts. |
moderationStatus | "published" | "heldForReview" | "likelySpam" | "rejected" | no | YouTube's moderation state of a comment. |
engagement | object | no | Provider-reported engagement counts. |
providerPermalink | string (uri) | no | Canonical provider URL for content. |
publishedAt | string (date-time) | no | Provider publish timestamp as an ISO-8601 string. |
updatedAt | string (date-time) | no | Provider update timestamp as an ISO-8601 string. |
providerRaw | unknown | no | Optional provider-native payload included only for transient delivery/debug use. |
contentType | "youtube.videos.comments" | yes |