TL;DR, Respuesta Rápida
8 min de lecturaLa programación pasa por status.publishAt en el recurso videos. El campo solo se puede fijar mientras status.privacyStatus sea private, y en videos.update tienes que reenviar privacyStatus como private en la misma petición aunque el vídeo ya sea privado. Una marca de tiempo pasada publica de inmediato en lugar de dar error. Los valores incorrectos devuelven invalidPublishAt como un 400. El insert cuesta 1 unidad contra un compartimento de subidas de 100 al día; el update cuesta 50 unidades del fondo principal.
¿Cómo se programa un vídeo con la API de YouTube?
No hay ningún endpoint para programar un vídeo con la API de YouTube al que llamar: la programación es una única propiedad de fecha y hora, status.publishAt, fijada en el recurso videos mediante videos.insert o videos.update. La lista de métodos no tiene ningún verbo schedule, ningún recurso de programación aparte ni ningún objeto de cola. Tú fijas una marca de tiempo y YouTube pone el vídeo en público cuando el reloj llega.
Ese diseño es la razón de que la mayoría de los fallos de programación en YouTube sean fallos de metadatos. Todo lo que puede salir mal sale mal con la forma de un campo o del valor de privacidad que tiene al lado. La cuestión del momento, a qué hueco apuntar, es otra cosa y está cubierta en cuándo subir un vídeo a YouTube.
¿Qué exige status.publishAt?
La documentación de Google para el recurso videos plantea la restricción dos veces, con palabras distintas, porque la gente sigue pasándola por alto.
Primero: "The date and time when the video is scheduled to publish. It can be set only if the privacy status of the video is private".
Después, una segunda vez, con la parte que rompe las llamadas de actualización: "If you set this property's value when calling the videos.update method, you must also set the status.privacyStatus property value to private even if the video is already private". Fijar publishAt solo en un vídeo que ya es privado no basta. La petición tiene que volver a llevar private.
Y una tercera condición: "This property can only be set if the video's privacy status is private and the video has never been published". Un vídeo que estuvo público una vez no se puede devolver a una programación fijando publishAt.
status.privacyStatus acepta tres valores: private, public y unlisted. Solo private es compatible con una hora de publicación programada.
¿Qué formato toma publishAt, y es RFC 3339?
Aquí la documentación y el ecosistema no coinciden en el vocabulario.
El recurso videos describe status.publishAt como un datetime y dice que "the value is specified in ISO 8601 format". No dice RFC 3339 en ninguna parte de esa página. La cadena RFC 3339 sí aparece en la referencia de la YouTube Data API, pero en otros campos: search.list documenta publishedAfter y publishedBefore como "an RFC 3339 formatted date-time value (1970-01-01T00:00:00Z)".
En la práctica las dos etiquetas describen la misma cadena aceptada para este campo, porque RFC 3339 es un perfil de ISO 8601 y el escalar datetime de Google es RFC 3339 en todas sus APIs. Lo que importa es la forma que envías:
2026-10-01T14:30:00Z
2026-10-01T10:30:00-04:00Una fecha sin hora, una hora sin desplazamiento o una marca de tiempo local con la zona sobreentendida en lugar de declarada es de donde sale invalidPublishAt. Envía un desplazamiento explícito o una Z. Si conviertes desde la hora local de un usuario, haz la conversión antes de la petición en vez de esperar que la API deduzca una zona que nunca recibió.

¿Qué pasa si la marca de tiempo está en el pasado?
Publica. De inmediato. Está documentado y no es un error.
"If your request schedules a video to be published at some time in the past, the video will be published right away. As such, the effect of setting the status.publishAt property to a past date and time is the same as of changing the video's privacyStatus from private to public."
Ese comportamiento merece una defensa en cualquier ruta de código que calcule una hora de publicación. Una conversión de zona horaria que aterriza una hora por detrás, una cola que reintenta un trabajo caducado o un borrador que se quedó en un paso de revisión durante un fin de semana no van a fallar con estruendo. Van a salir en directo. Valida que la marca de tiempo calculada esté en el futuro antes de enviarla, porque YouTube no lo hará por ti.
AdaptlyPost
Prueba gratis de 7 días
Analíticas multiplataforma
Bandeja Social
Asistente con IA
- El vídeo permanece privado hasta que llega el momento
- YouTube lo pone en público por su cuenta
- No hace falta ninguna acción en el momento de publicar
- El vídeo se publica de inmediato al guardar
- El mismo efecto que cambiar privacyStatus a public a mano
- No se devuelve ningún error que señale el fallo
¿Qué errores devuelve la API?
Tanto videos.insert como videos.update documentan el mismo error de programación, además de un conjunto de vecinos que saltan por los metadatos enviados junto a él.
| Tipo de error | Detalle del error | Qué significa |
|---|---|---|
| badRequest (400) | invalidPublishAt | "The request metadata specifies an invalid scheduled publishing time." |
| badRequest (400) | invalidVideoMetadata | "The request metadata is invalid." |
| badRequest (400) | invalidTitle | "The request metadata specifies an invalid or empty video title." |
| badRequest (400) | invalidDescription | "The request metadata specifies an invalid video description." |
| badRequest (400) | invalidCategoryId | El snippet.categoryId no es una categoría admitida. |
| badRequest (400) | invalidTags | "The request metadata specifies invalid video keywords." |
| badRequest (400) | defaultLanguageNotSet | Detalles localizados enviados sin un idioma por defecto. |
| forbidden (403) | forbiddenPrivacySetting | "The request attempts to set an invalid privacy setting for the video." |
| forbidden (403) | forbiddenLicenseSetting | "The request attempts to set an invalid license for the video." |
| notFound (404) | videoNotFound | Solo en update. El id del cuerpo de la petición no resuelve. |
videos.insert añade tres propios: mediaBodyRequired cuando la petición no lleva contenido de vídeo, invalidFilename cuando la cabecera Slug está mal formada y uploadLimitExceeded, que la documentación glosa como "the user has exceeded the number of videos they may upload".
Fíjate en que forbiddenPrivacySetting es un 403, no un 400. Si solo capturas 400 alrededor de una llamada de programación, un valor de privacidad rechazado se escapará del manejador.
¿Qué hace part en una actualización y por qué borra cosas?
Este es el segundo error más caro después del de la marca de tiempo pasada, y es consecuencia directa de cómo trata videos.update el parámetro part. También es la razón por la que la mayoría de los equipos recurren a un programador de vídeos de YouTube en lugar de llamar al endpoint por su cuenta.
La documentación es explícita: "this method will override the existing values for all of the mutable properties that are contained in any parts that the parameter value specifies". Y da después el caso exacto que muerde a quien programa: "if your request is updating a private video, and the request's part parameter value includes the status part, the video's privacy setting will be updated to whatever value the request body specifies. If the request body does not specify a value, the existing privacy setting will be removed and the video will revert to the default privacy setting".
Así que part=status no es un parche. Cada propiedad mutable dentro de status que omitas queda borrada. Lo mismo aplica a part=snippet, y por eso una actualización de programación que envía solo publishAt bajo part=snippet,status puede borrar una descripción, por muy cerca que la hubieras escrito del límite de caracteres de la descripción. Lee el recurso actual, muta los campos que quieres cambiar y devuelve la parte entera.

¿Cuánta cuota cuesta programar?
Las dos llamadas están en fondos distintos desde el cambio de compartimentos de junio de 2026.
| Llamada | Impacto en cuota, según la documentación |
|---|---|
videos.insert | "100 calls per day. A call to this method has a quota cost of 1 unit in the Video Uploads quota bucket." |
videos.update | "A call to this method has a quota cost of 50 units." |
videos.list | 1 unidad |
thumbnails.set | 50 unidades |
La asimetría tiene una consecuencia de planificación. Fijar publishAt en el videos.insert original no cuesta nada extra; la subida en sí es la que tira del compartimento de 100 al día. Reprogramar después cuesta 50 unidades por intento del fondo principal de 10.000 unidades, y lo mismo cada miniatura que fijes. Un flujo que sube en privado, luego actualiza la programación dos veces y luego fija una miniatura ha gastado 150 unidades en un vídeo antes de que nadie lo haya visto. Si esa aritmética empieza a apretar, la salida es una ampliación de cuota y la auditoría que lleva detrás, no más reintentos.
Preguntas frecuentes
¿Qué campo programa un vídeo de YouTube a través de la API?
status.publishAt en el recurso videos. Es un datetime que fijas mediante videos.insert en el momento de la subida o mediante videos.update después. No hay ningún método ni recurso de programación dedicado en la YouTube Data API.
¿Por qué rechazan mi actualización de publishAt?
La causa más habitual es la privacidad. La documentación de Google dice que cuando fijas publishAt mediante videos.update, "you must also set the status.privacyStatus property value to private even if the video is already private". Enviar publishAt sin privacyStatus en la misma petición no programa el vídeo.
¿Puedo programar un vídeo que ya es público?
No. La documentación afirma que publishAt "can only be set if the video's privacy status is private and the video has never been published". Una vez que un vídeo ha estado público, ese campo le queda cerrado para siempre.
¿Qué formato de hora acepta publishAt?
La página del recurso videos de Google describe el valor como ISO 8601. Envía una fecha y hora completas con un desplazamiento UTC explícito o una Z final, como 2026-10-01T14:30:00Z. Los valores sin hora o sin desplazamiento de zona son la fuente habitual de invalidPublishAt.
¿Qué pasa si publishAt está en el pasado?
El vídeo se publica de inmediato. Google lo documenta como equivalente a cambiar privacyStatus de privado a público. No se devuelve ningún error, así que valida la marca de tiempo antes de enviarla.
¿Cuánta cuota consume programar?
videos.insert cuesta 1 unidad de un compartimento de Video Uploads limitado a 100 llamadas al día. videos.update cuesta 50 unidades del fondo diario principal. Fijar publishAt durante el insert inicial no cuesta por tanto nada más allá de la subida; cada reprogramación posterior cuesta 50.
AdaptlyPost
Prueba gratis de 7 días
Analíticas multiplataforma
Bandeja Social
Asistente con IA
¿Puedo programar un vídeo con privacyStatus en unlisted?
status.privacyStatus acepta tres valores, private, public y unlisted, pero solo private admite una hora de publicación programada. Poner publishAt mientras privacyStatus está en unlisted o public no programa el vídeo. Envía privacyStatus como private en la misma solicitud que lleva publishAt.
¿Por qué desapareció la descripción de mi vídeo después de actualizar la programación?
videos.update sobrescribe cada propiedad mutable dentro de las partes que indiques, no solo los campos de tu cuerpo de solicitud. Una llamada con part=snippet,status que solo envía publishAt borra cualquier campo de snippet que omitas, incluida la descripción. Lee el recurso actual, conserva los campos que quieras mantener y devuelve la parte completa junto con el cambio de publishAt.
¿forbiddenPrivacySetting es un error 400 o un 403?
Es un 403, clasificado como forbidden y no como badRequest. Un manejador que solo revisa errores 400 alrededor de una llamada de programación deja pasar sin detectar un ajuste de privacidad rechazado. Revisa tanto 403 como 400 al validar una respuesta de videos.insert o videos.update.
¿Cuántos vídeos nuevos puedo programar por día a través de la API?
Hasta 100. videos.insert consume de un bucket de Video Uploads limitado a 100 llamadas por día, y cada llamada cuesta 1 unidad de ese límite diario, aparte del pool principal de 10.000 unidades. Reprogramar un vídeo ya subido pasa por videos.update, que cuesta 50 unidades del pool principal y no toca el límite de subidas.
Ponlo en práctica con AdaptlyPost
¿Te resultó útil este artículo?
¡Cuéntanos qué te parece!
Vernos más en Google
Un clic marca AdaptlyPost como fuente preferida y nuestros artículos aparecen más arriba en tus Noticias destacadas, el modo IA y los resúmenes con IA.
Antes de irte...
AdaptlyPost
Programa tu contenido en todas las plataformas
Gestiona todas tus cuentas de redes sociales en un solo lugar con AdaptlyPost.
Analíticas multiplataforma
Bandeja Social
Asistente con IA
Términos relacionados del glosario


Así funciona el límite de tasa de la API de Pinterest, por app y por usuario
El límite de tasa de la API de Pinterest va por categoría: Trial, 1,000 llamadas al día; Standard, 100 por minuto en org_write. Al 12 de septiembre de 2026.


Convertir el límite de tasa de la API de Bluesky en publicaciones por hora
El límite de tasa de la API de Bluesky en escrituras es un presupuesto de puntos, no de solicitudes: 5,000 puntos por hora, 3 por post, 1,666 al día.


Qué devuelve el endpoint content_publishing_limit de Instagram
El endpoint content_publishing_limit de Instagram devuelve quota_usage más un bloque config con quota_total 50 y quota_duration 86400 segundos.
Artículos Relacionados


Por qué un token de acceso de LinkedIn caduca a los 60 días
Cada token de acceso de LinkedIn dura 60 días y expires_in devuelve 5184000. Reglas del refresh token, qué lo mata antes y en qué difieren los 60 días de Meta.


Cómo initializeUpload de LinkedIn convierte un archivo en un URN de imagen
La acción initializeUpload de LinkedIn devuelve un URN de imagen y una URL de subida. El PUT, el post que referencia el URN y los errores de cada paso.


Cómo funciona el límite de 250 posts por día de la API de Threads
Meta cuenta el límite de 250 posts por día de la API de Threads en una ventana móvil de 24 horas. Los carruseles cuentan una vez y un endpoint da el restante.

