Publicar una publicación en Instagram desde tu aplicación, script o agente de IA parece que debería ser una única petición HTTP: enviar un pie de foto, adjuntar una imagen y recibir la URL de la publicación.
Bajo la Graph API oficial de Meta, la publicación programática funciona de forma distinta. Publicar en Instagram es un ciclo de vida de contenedores asíncrono. Creas un contenedor multimedia, consultas el estado hasta que Meta termina de descargar y procesar el archivo, y después lanzas una petición de publicación independiente. Además, tu código debe cumplir requisitos previos estrictos de cuenta, alojar archivos en servidores HTTPS públicos y gestionar flujos diferentes para imágenes, Reels y carruseles.
Este tutorial desglosa todo el proceso. Veremos cómo funcionan los puntos finales nativos de contenedores de Meta y cómo publicar de forma programática usando cURL, TypeScript o una API de publicación unificada.
Una API en lugar de la fontanería de la Graph API. InvisibleAPI es una sola API basada en jobs para Instagram y X. Conecta la cuenta, crea un job de publicación y consúltalo hasta que llegue a published.
Obtener clave APIQué es la API de Instagram
La API de Instagram es la interfaz oficial de Meta para el software que trabaja con cuentas profesionales de Instagram. Forma parte de la Graph API de Meta, por eso los desarrolladores también la llaman Instagram Graph API. Esto es lo que cubre en 2026:
| Pregunta | Respuesta |
|---|---|
| ¿Qué cuentas? | Solo cuentas profesionales (Business o Creator). Los perfiles personales no pueden publicar a través de la API |
| ¿Qué puede publicar? | Imágenes individuales, carruseles de hasta 10 elementos y vídeos, que se publican como Reels |
| ¿Qué más puede hacer? | Leer estadísticas de la cuenta y de las publicaciones, y gestionar comentarios |
| ¿Cómo se inicia sesión? | Dos vías: inicio de sesión de Instagram (sin página de Facebook) o inicio de sesión de Facebook (requiere una página de Facebook vinculada) |
| ¿Cuánto cuesta? | Meta no publica ninguna tarifa de uso. El coste es el trabajo de desarrollo y revisión, que explicamos en nuestra guía de precios de la API de Instagram |
| ¿Hay un límite de publicaciones? | 100 publicaciones mediante API por cuenta en una ventana móvil de 24 horas. Un carrusel cuenta como una |
| Versión actual | Graph API v26.0, publicada el 29 de julio de 2026 |
El resto de esta guía trata la parte de publicación: la configuración, el flujo de contenedores, las reglas de los archivos multimedia y código que funciona.
Meta cambia la plataforma a menudo. Nuestra página mensual de novedades de Instagram recoge cada cambio y si llega a la API.
Requisitos previos: Configuración de cuenta y tokens
Antes de escribir una sola línea de código de publicación, Meta requiere tres pasos de configuración administrativa. Omitir cualquiera de ellos provocará errores de permisos ((#100) Invalid parameter o (#200) Permission denied) durante las llamadas a la API.
1. El requisito de cuenta profesional
Los perfiles personales de Instagram no pueden publicar contenido a través de la API. La cuenta debe convertirse en una cuenta profesional de Instagram (Business o Creator). Puedes realizar este cambio dentro de la aplicación móvil de Instagram en Configuración > Tipo de cuenta y herramientas, o a través de Meta Business Suite.
2. Elegir una vía de inicio de sesión (y cuándo necesitas una página de Facebook)
Meta ofrece dos formas de acceder a los mismos endpoints de publicación:
- API de Instagram con inicio de sesión de Instagram: el titular de la cuenta inicia sesión directamente con Instagram. No se necesita ninguna página de Facebook. La publicación usa los permisos
instagram_business_basiceinstagram_business_content_publish. - API de Instagram con inicio de sesión de Facebook: el titular de la cuenta inicia sesión con Facebook, y la cuenta profesional de Instagram debe estar vinculada a una página de Facebook a la que tu aplicación tenga acceso.
Con el inicio de sesión de Facebook, vincula las cuentas desde la configuración de tu página de Facebook, en Cuentas vinculadas y después Instagram. Si ese vínculo falta o está incompleto, la Graph API no devolverá un identificador de usuario de Instagram (ig-user-id) para tu token. Los permisos del siguiente paso son los que usa la vía de inicio de sesión de Facebook.
3. Permisos de aplicación y tokens de acceso necesarios
Tu aplicación de desarrollador de Meta necesita los siguientes permisos para publicar contenido:
instagram_basic: Para leer el ID de la cuenta de Instagram conectada y los metadatos básicos del perfil.instagram_content_publish: Para crear contenedores y publicar posts.pages_show_listypages_read_engagement: Para localizar la página de Facebook asociada a la cuenta de Instagram.
Para desarrollo, puedes generar un token de corta duración con el Graph API Explorer. Para sistemas de producción, intercambia ese token por un token de acceso de usuario de larga duración de 60 días, o implementa Facebook Login con OAuth 2.0 para solicitar permisos dinámicamente.
Cómo funciona la publicación nativa en Meta: El flujo de contenedores en 3 pasos
Meta separa la publicación de contenido en tres pasos distintos porque el procesamiento multimedia requiere tiempo. En lugar de mantener una conexión HTTP abierta mientras Instagram descarga, valida y transcodifica un vídeo o imagen de alta resolución, la API utiliza un ciclo de contenedores.
| Paso | Método HTTP y Endpoint | Qué hace |
|---|---|---|
| 1. Crear contenedor | POST /{ig-user-id}/media |
Envía la URL del archivo y el pie de foto; crea un contenedor de subida |
| 2. Consultar estado | GET /{container-id}?fields=status_code |
Comprueba si Meta ha terminado de descargar y procesar |
| 3. Publicar contenedor | POST /{ig-user-id}/media_publish |
Publica el contenedor verificado en el perfil activo de Instagram |
Paso 1: Crear el contenedor multimedia
Comienzas enviando una petición POST al endpoint /media de la cuenta. Proporcionas la URL de la imagen, el pie de foto y tu token de acceso.
curl -X POST "https://graph.facebook.com/v21.0/$IG_USER_ID/media" \
-F "image_url=https://cdn.example.com/images/spring-launch.jpg" \
-F "caption=Spring collection is live. Shop the link in bio." \
-F "access_token=$META_ACCESS_TOKEN"
Si la carga útil es válida, Meta devuelve un ID de contenedor:
{
"id": "17895695634123456"
}
Este contenedor todavía no es visible en Instagram. Es un objeto de retención temporal en los servidores de Meta.
Paso 2: Consultar el estado del contenedor
Antes de publicar, debes verificar que Meta ha terminado de procesar el archivo. Consulta el campo status_code del contenedor:
curl -X GET "https://graph.facebook.com/v21.0/$CONTAINER_ID?fields=status_code&access_token=$META_ACCESS_TOKEN"
Meta devuelve uno de cuatro estados:
IN_PROGRESS: El archivo multimedia aún se está descargando o procesando. Espera unos segundos y vuelve a consultar.FINISHED: El contenedor está listo para ser publicado.ERROR: El procesamiento ha fallado (por ejemplo, el archivo no era accesible o estaba corrupto).EXPIRED: El contenedor no se publicó dentro de las 24 horas posteriores a su creación.
Para imágenes, el estado suele pasar a FINISHED en menos de dos segundos. Para vídeos, el procesamiento puede tardar entre 15 y 45 segundos según el tamaño del archivo y la carga del servidor.
Paso 3: Publicar el contenedor
Una vez que el estado alcanza FINISHED, activa la llamada final de publicación pasando el ID del contenedor como creation_id al endpoint /media_publish:
curl -X POST "https://graph.facebook.com/v21.0/$IG_USER_ID/media_publish" \
-F "creation_id=$CONTAINER_ID" \
-F "access_token=$META_ACCESS_TOKEN"
Meta devuelve el ID del objeto multimedia publicado en Instagram:
{
"id": "17923485729987654"
}
La publicación ya está activa en el perfil de Instagram de la cuenta.
Restricciones multimedia: URLs públicas, formatos y Reels
La API de publicación de contenido de Meta impone restricciones técnicas específicas en los archivos multimedia que suministras.
Solo URLs HTTPS públicas
Meta no acepta subidas directas de archivos binarios al crear contenedores multimedia. Tu aplicación debe subir la imagen o vídeo a un almacenamiento de objetos (como Amazon S3, Cloudflare R2 o una CDN pública) y pasar esa URL a Meta.
La URL debe cumplir tres requisitos:
- Debe ser accesible mediante HTTPS.
- No debe requerir encabezados de autenticación ni cookies privadas.
- El servidor debe devolver encabezados
Content-Typecorrectos (image/jpegovideo/mp4).
Especificaciones de imagen y relaciones de aspecto
- Formato: Se requiere formato JPEG para publicaciones en el feed. Aunque PNG funciona para historias en ciertos contextos, las publicaciones en el feed exigen JPEG.
- Tamaño máximo de archivo: 8 MB.
- Relación de aspecto: Debe situarse entre 4:5 (vertical, relación 0.8) y 1.91:1 (horizontal). Si tu imagen queda fuera de este rango, la llamada de creación de contenedor devuelve un error de relación de aspecto.
Los vídeos se publican como Reels
Cada subida de vídeo individual enviada a través de la API de publicación de contenido se publica como un Instagram Reel. El formato de vídeo clásico del feed se unificó con Reels en toda la plataforma.
- Formato: Contenedor MP4 o MOV con códec de vídeo H.264 y audio AAC.
- Duración: Entre 3 segundos y 15 minutos.
- Tamaño máximo de archivo: 1 GB.
- Relación de aspecto: Se recomienda 9:16 (1080x1920 píxeles), con una velocidad máxima de 60 fps.
Los carruseles requieren contenedores secundarios
Publicar un carrusel con múltiples imágenes o vídeos añade un nivel adicional de anidamiento de contenedores:
- Crea un contenedor secundario para cada imagen o vídeo individual indicando
is_carousel_item=true. - Consulta cada contenedor secundario hasta que todos ellos informen
FINISHED. - Crea un contenedor principal con
media_type=CAROUSELy pasa una matriz de IDs de contenedores secundarios en el parámetrochildren. - Publica el contenedor principal en
/media_publish.
Los carruseles admiten entre 2 y 10 elementos y pueden combinar imágenes y vídeos en la misma publicación.
La ruta de trabajo único: Publicar con InvisibleAPI
Construir y mantener el ciclo nativo de contenedores en múltiples cuentas introduce una sobrecarga considerable: almacenamiento de tokens, rutinas de renovación, asignación de páginas de Facebook, orquestación de contenedores secundarios y bucles de sondeo.
InvisibleAPI proporciona un motor de publicación social unificado. En lugar de coordinar flujos de contenedores de múltiples pasos por plataforma, envías un único trabajo de publicación asíncrono.
POST /api/v1/organizations/{organization}/publishing/jobs -> 202 Accepted
La plataforma valida la carga útil antes del envío, crea los contenedores necesarios, supervisa el progreso de procesamiento y gestiona los errores transitorios automáticamente.
El ciclo de vida del trabajo
Cuando envías una solicitud de publicación, InvisibleAPI devuelve un objeto de trabajo asíncrono inmediatamente:
{
"id": "job_01JH8M5V9W2Q4K7X1P0R",
"status": "processing",
"clientRequestId": "blog-announcement-2026-09-21",
"targets": ["acct_ig_8f29c41a"]
}
El trabajo avanza por estados documentados: pending, processing, submitted y polling, hasta que alcanza un estado terminal:
published: Publicado con éxito en Instagram.failed: Fallo permanente (por ejemplo, dimensiones de imagen no válidas).action_required: Credenciales de cuenta caducadas o desconectadas.partial_failure: El trabajo apuntaba a varias cuentas y algunas fallaron.canceled: El trabajo se canceló antes de publicarse.
Sobre los ejemplos de API. targets, mediaItems, caption, clientRequestId y los valores de estado del trabajo son campos documentados de la plataforma. Las estructuras exactas de respuesta y los encabezados de autenticación en estos ejemplos ilustran el flujo de integración. Consulta la Guía de inicio rápido para conocer los detalles completos del esquema.
Ejemplos de código: Imágenes, Reels y Carruseles
A continuación se muestra cómo publicar diferentes tipos de contenido multimedia utilizando TypeScript limpio y sin dependencias externas.
Ejemplo 1: Publicar una sola imagen (cURL y TypeScript)
En primer lugar, la petición cURL directa para enviar una publicación de imagen individual:
curl -X POST "https://api.invisibleapi.ai/api/v1/organizations/$ORG_ID/publishing/jobs" \
-H "Authorization: Bearer $INVISIBLE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"targets": ["acct_ig_8f29c41a"],
"caption": "Exploring the coast. Photo taken at sunset.",
"mediaItems": [
{
"mediaType": "image",
"sourceUrl": "https://cdn.example.com/photos/coast-sunset.jpg"
}
],
"clientRequestId": "sunset-post-001"
}'
En TypeScript, puedes encapsular el envío del trabajo y la consulta de estado en una función limpia:
interface PublishResult {
jobId: string;
status: string;
}
export async function publishInstagramImage(
orgId: string,
targetAccountId: string,
imageUrl: string,
caption: string,
clientRequestId: string
): Promise<PublishResult> {
const apiKey = process.env.INVISIBLE_API_KEY;
// 1. Submit the asynchronous publishing job
const response = await fetch(
`https://api.invisibleapi.ai/api/v1/organizations/${orgId}/publishing/jobs`,
{
method: "POST",
headers: {
"Authorization": `Bearer ${apiKey}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
targets: [targetAccountId],
caption,
mediaItems: [{ mediaType: "image", sourceUrl: imageUrl }],
clientRequestId,
}),
}
);
if (!response.ok) {
throw new Error(`Job creation failed: ${response.statusText}`);
}
const job = await response.json();
return { jobId: job.id, status: job.status };
}
Ejemplo 2: Publicar un Reel de vídeo
Publicar un Reel solo requiere cambiar mediaType a video y proporcionar una URL de MP4. Como el procesamiento de vídeo requiere más tiempo, el bucle de sondeo comprueba el estado del trabajo hasta que pasa a published:
export async function publishInstagramReel(
orgId: string,
targetAccountId: string,
videoUrl: string,
caption: string,
clientRequestId: string
) {
const apiKey = process.env.INVISIBLE_API_KEY;
const res = await fetch(
`https://api.invisibleapi.ai/api/v1/organizations/${orgId}/publishing/jobs`,
{
method: "POST",
headers: {
"Authorization": `Bearer ${apiKey}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
targets: [targetAccountId],
caption,
mediaItems: [{ mediaType: "video", sourceUrl: videoUrl }],
clientRequestId,
}),
}
);
if (!res.ok) {
throw new Error(`Job creation failed: ${res.status} ${await res.text()}`);
}
const job = await res.json();
return pollUntilComplete(orgId, job.id);
}
const TERMINAL_STATUSES = new Set([
"published",
"partial_failure",
"failed",
"action_required",
"canceled",
]);
async function pollUntilComplete(orgId: string, jobId: string, maxAttempts = 20) {
const apiKey = process.env.INVISIBLE_API_KEY;
for (let i = 0; i < maxAttempts; i++) {
await new Promise((resolve) => setTimeout(resolve, 3000));
const pollRes = await fetch(
`https://api.invisibleapi.ai/api/v1/organizations/${orgId}/publishing/jobs/${jobId}`,
{ headers: { "Authorization": `Bearer ${apiKey}` } }
);
if (!pollRes.ok) {
throw new Error(`Job lookup failed: ${pollRes.status}`);
}
const data = await pollRes.json();
if (TERMINAL_STATUSES.has(data.status)) {
return data;
}
}
throw new Error("Job polling timed out before reaching a terminal state.");
}
Ejemplo 3: Publicar un carrusel
Para publicar un carrusel, pasa varios objetos dentro de mediaItems. Puedes combinar imágenes y vídeos en la misma petición:
export async function publishInstagramCarousel(
orgId: string,
targetAccountId: string,
items: Array<{ type: "image" | "video"; url: string }>,
caption: string,
clientRequestId: string
) {
const apiKey = process.env.INVISIBLE_API_KEY;
const response = await fetch(
`https://api.invisibleapi.ai/api/v1/organizations/${orgId}/publishing/jobs`,
{
method: "POST",
headers: {
"Authorization": `Bearer ${apiKey}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
targets: [targetAccountId],
caption,
mediaItems: items.map((item) => ({
mediaType: item.type,
sourceUrl: item.url,
})),
clientRequestId,
}),
}
);
return response.json();
}
Internamente, la API genera de forma automática los contenedores secundarios para cada elemento, espera a que todos completen el procesamiento, crea el contenedor principal de carrusel y ejecuta la publicación final.
Fiabilidad en producción: Idempotencia, límites de frecuencia y fallos
Llevar la publicación social a entornos de producción exige protegerse contra interrupciones de red y agotamiento de límites.
Evitar publicaciones duplicadas con clientRequestId
Las conexiones de red fallan. Si una petición agota el tiempo de espera mientras espera la respuesta del servidor, un cliente básico reintentará la llamada. Sin una garantía de idempotencia, ese reintento crea una publicación duplicada en el feed del usuario.
InvisibleAPI admite un parámetro opcional clientRequestId (de hasta 128 caracteres). Si tu aplicación envía una petición con un clientRequestId que coincide con un trabajo recibido previamente, el servidor devuelve el registro del trabajo existente en lugar de enviar un duplicado:
# Safe retry with identical clientRequestId
curl -X POST "https://api.invisibleapi.ai/api/v1/organizations/$ORG_ID/publishing/jobs" \
-H "Authorization: Bearer $INVISIBLE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"targets": ["acct_ig_8f29c41a"],
"caption": "Product launch details.",
"mediaItems": [{"mediaType": "image", "sourceUrl": "https://cdn.example.com/p1.jpg"}],
"clientRequestId": "product-launch-v1"
}'
Si el contenido de la petición difiere para una clave existente, la API devuelve un error 409 publishing.idempotency_mismatch, alertándote de una discrepancia en la carga útil.
Límites de frecuencia y cuotas de la plataforma
Meta aplica un límite estricto en la publicación: 100 publicaciones mediante API en una ventana móvil de 24 horas por cuenta de Instagram.
- Una sola imagen o Reel cuenta como una publicación.
- Un carrusel con 10 elementos también cuenta como una sola publicación para esta cuota.
- Varios artículos antiguos mencionan un límite obsoleto de 25 publicaciones al día. Meta actualizó este límite a 100 publicaciones cada 24 horas.
Si tu aplicación supera este umbral, Meta devuelve el código 9 con el subcódigo 2207042, y su recomendación es reintentar al día siguiente. Controla tu volumen de envíos a nivel local para distribuir las publicaciones en varios días si gestionas flujos de trabajo de publicación frecuente.
Clasificación de fallos: Errores del emisor frente a caídas de la plataforma
Cuando una publicación falla, saber quién es responsable de la corrección determina cómo debe reaccionar tu sistema:
- Errores del emisor (
invalid_publish_data): Provocados por relaciones de aspecto no válidas, pies de foto de más de 2.200 caracteres o URLs de archivos no accesibles. Reintentar sin modificar la petición fallará indefinidamente. - Errores transitorios de plataforma (
retryable_provider_failure): La infraestructura de procesamiento de Meta experimentó un retraso temporal. El trabajo de publicación se reintenta automáticamente. - Problemas de credenciales (
provider_action_required): El usuario cambió su contraseña de Instagram, revocó los permisos de la aplicación o el token de 60 días caducó. Esto requiere volver a autenticar la cuenta.
Si implementas los reintentos tú mismo, nuestra guía de códigos de error de la API de Instagram clasifica cada código documentado en reintentar, corregir, escalar o detener. Para programar publicaciones desde tu propio código, descubre cómo automatizar publicaciones en Instagram con una cola y una política de fallos.
Para más detalles sobre los umbrales de la plataforma, revisa cómo funcionan los límites y restricciones de cuenta en Instagram o consulta cómo una plantilla de límites de publicación en redes sociales gestiona las esperas.
Pasos siguientes para tu integración
Publicar en Instagram de forma programática se reduce a gestionar el ciclo de vida de los contenedores. Si estás construyendo una integración personalizada para una sola cuenta, los endpoints de la Graph API de Meta proporcionan un control directo sobre las tres etapas de contenedores.
Si estás desarrollando una aplicación, herramienta interna o agente de IA que publica en múltiples cuentas, gestionar tokens, contenedores secundarios y clasificación de errores en tu propio código resulta complejo rápidamente, y ese es el trabajo del que se encarga la API de publicación en Instagram. A continuación, lee nuestra guía sobre cómo conectar una cuenta de Instagram o copia nuestra plantilla de calendario de publicación en redes sociales.
Publica en X y en Instagram desde una sola API.
Conecta las cuentas una vez, crea un job de publicación y consúltalo hasta que quede publicado. La validación previa detecta una publicación inválida antes de que llegue a la plataforma, y un clientRequestId hace que los reintentos sean seguros.
Fuentes
- Meta for Developers: Documentación de la Content Publishing API de Instagram (Graph API v21.0, verificado en septiembre de 2026).
- Meta for Developers: Referencia de contenedores multimedia y códigos de estado de Instagram.
- Condiciones de la plataforma de Meta: Políticas de publicación automatizada y estándares de seguridad de tokens.
- Referencia de InvisibleAPI: Documentación de la API de trabajos de publicación.