sent significa que Meta aceptó el mensaje, no que el destinatario lo haya recibido. En Instagram, la entrega está en última instancia dictada por la configuración de Message requests del destinatario: si no permite solicitudes de mensajes de todos, Meta devuelve una respuesta de éxito y descarta silenciosamente el mensaje, y esto es invisible en cada capa de la API. Incluso un DM activado por un comentario y entregado correctamente llega como una solicitud de mensaje que el destinatario debe aceptar (a menos que ya exista una conversación entre las dos cuentas). Consulta DM de automatización enviado pero no entregado para la explicación completa.Cómo funciona
Crea una automatización
POST /automations con los disparadores y las acciones que deseas. La automatización se activa de inmediato.Un usuario final interactúa
Ayrshare hace coincidir y despacha
Inspecciona qué se activó
GET /automations/:id/activity devuelve el registro de auditoría: cada intento de envío, los resultados por acción y cualquier error.Disparadores
Puedes adjuntar hasta 50 disparadores a una sola automatización. Cada disparador es una unión discriminada por el campotype; los campos específicos del tipo están al mismo nivel. La columna Plataformas muestra dónde está disponible cada disparador; consulta Páginas de Facebook para ver lo que necesita Facebook.
Reglas perennes con "all"
Establece postId (o storyId) en la cadena literal en minúsculas "all" para que se active en todas las publicaciones, reels o historias de la cuenta conectada en lugar de en una pieza de contenido específica. Esto es lo que quieres para una regla que deba seguir funcionando a medida que se publica contenido nuevo, sin una llamada a la API por cada publicación:
"all". Una variante como "ALL" o " all" se rechaza con un error de validación en lugar de guardarse como un ID de publicación que nunca coincidiría.
"all" nunca se amplía más allá de la cuenta conectada — una regla en un perfil no puede activarse con el contenido de otro perfil. Tu tope diario de DM y las reglas de envío ancladas a la interacción se aplican exactamente igual que en una regla de publicación única.
storyId se comporta igual que "all". Prefiere "all" — expresa la intención de forma explícita, y la omisión se retirará en una versión futura con aviso anticipado en Próximos cambios de la API.Páginas de Facebook
Estableceplatform en facebook para ejecutar una automatización en la página de Facebook vinculada al perfil. Los DMs se envían desde la página a través de Messenger.
- Disparadores:
dm_keywordydm_reaction. Por ahora, los disparadores de comentarios y de historias son solo para Instagram, y una automatización de Facebook que use uno de ellos se rechaza con un error de validación. - Mensajería: el perfil necesita tener Messaging activado para Facebook, igual que para enviar un DM de Facebook con la Messages API.
- Destinatario:
{{recipient_id}}es el ID del usuario con ámbito de página (PSID).{{recipient_username}}está vacío, porque los webhooks de Messenger no incluyen un nombre de usuario.
Acciones
Puedes adjuntar hasta 50 acciones a una sola automatización. Se ejecutan secuencialmente; cada resultado se registra en la fila de actividad.Ventana de desduplicación por acción
Cada acción, sin importar el tipo, acepta adicionalmente un campodedupWindowMinutes opcional de nivel superior que sobrescribe la ventana de desduplicación por destinatario predeterminada de 7 días solo para esa acción.
- Establécelo en
0para deshabilitar la desduplicación por completo para esa acción (típico parafire_webhook/send_emaildonde el receptor espera cada evento). - Limitado a
525600(un año).
Contenido dinámico del mensaje
De forma predeterminada,send_dm envía el mismo message a todas las personas que activan la regla. Los placeholders como {{recipient_username}} son lo único que cambia de una persona a otra. Establece messageUrl en la acción y, en su lugar, tu propio servidor escribe el DM para cada persona: cada vez que la regla coincide, le preguntamos a tu endpoint qué decir y luego enviamos su respuesta como el DM.
Ejemplo. Tu regla responde a cualquiera que comente “LINK” en una publicación, y messageUrl apunta a tu servidor. Cuando Ava comenta “LINK please!”:
- Hacemos un
POSTcon los detalles a tumessageUrl: quién comentó ("recipientUsername": "ava"), qué escribió y en qué publicación. - Tu servidor escribe una respuesta para Ava, por ejemplo con un enlace de seguimiento creado solo para ella, y responde
{ "message": "Hi ava, here's your link: https://example.com/r/12345" }. - Enviamos ese texto a Ava como el DM, exactamente como lo escribiste.
timeoutMs, devuelve un error o devuelve algo que no podemos usar, enviamos a Ava el message habitual de la acción, para que igualmente reciba una respuesta.
Agrégalo a una acción send_dm así:
messageUrl es donde pedimos el texto. message sigue siendo requerido y es la alternativa: nunca se envía a tu servidor, y lo enviamos por DM en su lugar siempre que tu servidor no responda a tiempo, devuelva un error o devuelva algo que no podemos usar (consulta la advertencia a continuación). timeoutMs es opcional (predeterminado 3000, máximo 5000).
Qué enviamos a tu endpoint. Un POST con este cuerpo JSON:
automations, de la misma manera: X-Authorization-Content-SHA256 es el HMAC-SHA256 del cuerpo sin procesar, y X-Authorization-Timestamp lleva el timeStamp del cuerpo. El código de verificación que ya usas para nuestros webhooks funciona sin cambios. Si hay un secreto registrado pero no podemos leerlo en ese momento, no enviamos el callback sin firmar; en su lugar enviamos tu plantilla message.
A dónde puede apuntar. messageUrl debe ser una dirección HTTPS pública. Se rechaza una URL que se resuelva a una dirección privada, de loopback, link-local o de metadatos de la nube, y no se siguen las redirecciones — una respuesta 3xx cuenta como un fallo. En cualquier caso, se envía la plantilla en su lugar.
Qué devuelve tu endpoint. Devuelve 200 con un cuerpo JSON, de 16 KB como máximo, que contenga una cadena message de 1 a 1000 caracteres:
{{placeholder}}, por lo que un {{ literal en tu texto generado llega al destinatario tal como está escrito.
timeoutMs es 3000 de forma predeterminada. El máximo es 5000: un valor mayor se rechaza con un error de validación al crear o actualizar la automatización. Cubre todo el intercambio, incluida la lectura del cuerpo de tu respuesta. Tenlo en cuenta: el DM se envía después de que tu endpoint responde, así que un endpoint lento retrasa el mensaje.
Comprueba qué camino tomó un disparo en GET /automations/:id/activity. Una entrada send_dm en actionResults[] lleva messageSource una vez que se ha determinado el texto del DM, incluso cuando el envío falla después. Está ausente cuando la acción se detuvo antes de eso, por ejemplo un DM skipped a tu propia cuenta o una acción deduplicated:
messageSource indica a partir de qué texto se construyó el DM, no si se entregó. Para eso, lee el status de la entrada.
Una alternativa por sí sola no hace fallar la acción: cuando el DM de la plantilla se entrega, la entrada es sent, con el motivo por el que no se usó el callback en errorDetails. Si el DM de la plantilla también falla, la entrada es failed y errorDetails da el error de envío seguido del motivo del callback. Vigílalo: de lo contrario, un callback que falla en cada disparo se ve exactamente igual que uno que funciona.
Mantén tu message enviable por sí solo. Si se renderiza vacío para un destinatario, por ejemplo {{recipient_username}} solo en un disparador de DM que no incluye nombre de usuario, y no se usa el texto de tu callback, no se envía ningún DM y la acción es failed con el motivo en errorDetails.
Eventos de webhook
Se entregan dos eventos a la acción de webhookautomations que registras con POST /hook/webhook. Ambos llevan un campo type — ramifica en él antes de leer cualquier otra cosa.
automation.completed está desactivado de forma predeterminada. Actívalo para una automatización estableciendo "sendCompletedEvent": true en su acción fire_webhook. De lo contrario permanece desactivado, para que un receptor construido para una carga útil por disparo siga recibiendo exactamente una. automation.triggered no es un registro de cada coincidencia: se envía solo cuando fire_webhook en sí se ejecuta, por lo que una coincidencia que termina en rate_limited o deduplicated produce únicamente automation.completed. Ninguno de los dos eventos se envía para una automatización que fue desactivada o eliminada antes de que se ejecutara el envío.automation.triggered
activityId es la fila que devuelve GET /automations/:id/activity, para que puedas unir los dos con exactitud en lugar de hacer coincidir recipientId + triggerId + keyword — lo cual es ambiguo cuando varias personas comentan la misma palabra clave a la vez. actionId es la acción fire_webhook que envió el evento, y coincide con actionResults[].actionId; distingue entre dos acciones fire_webhook en la misma regla.
Los campos que un disparador no completa son null en lugar de omitirse, para que la forma sea estable. recipientUsername es null para dm_keyword, dm_reaction y story_reply, porque la carga útil de Meta no incluye uno. commentId se establece solo para comment_keyword y story_comment, postId solo para comment_keyword, y storyId solo para los disparadores de historia. story_reply no tiene keyword. Para dm_keyword, commentText es el texto del DM; para dm_reaction, commentText y keyword son ambos el emoji de la reacción.
automation.completed
Se envía solo cuando la automatización lo activa en su acción fire_webhook:
status y cada actionResults[].status usan los mismos valores que el registro de actividad — sent, failed, rate_limited, deduplicated, skipped, auth_error — por lo que en el caso normal sabes cómo terminó un envío sin hacer polling. Sin embargo, la entrega de este evento es de mejor esfuerzo: si el proceso se detiene entre registrar el resultado y encolar el evento, no se envía. El registro de actividad es la fuente de verdad, así que si necesitas todos los resultados, reconcilia contra GET /automations/:id/activity para cualquier activityId que no haya reportado uno. Un resultado de send_dm también lleva messageSource, como en el registro de actividad: template, callback o fallback, para que puedas detectar un messageUrl que recurre repetidamente a la alternativa sin hacer polling. Haz coincidir los resultados con tus acciones configuradas por actionId, no por posición — dos acciones del mismo tipo solo se distinguen de esa manera. actionResults está vacío en tres casos, cada uno con el motivo en el errorDetails de nivel superior cuando lo hay: rate_limited (se alcanzó tu tope diario), deduplicated (todas las acciones estaban dentro de su ventana de desduplicación), y failed después de que el envío se reintentara el número máximo de veces sin terminar. En este último caso, algunas acciones pueden haberse ejecutado ya, por lo que un DM puede haber salido y automation.triggered puede haberse enviado ya.
La entrega de webhooks es al menos una vez, por lo que el mismo evento puede llegar ocasionalmente dos veces, y un envío que se reintenta puede enviar automation.triggered de nuevo con un nuevo hookId. Nunca desdupliques por hookId. Usa una clave distinta para cada tipo de evento, de modo que procesar uno nunca suprima el otro: automation.completed por activityId (cada actividad tiene un solo resultado), y automation.triggered por activityId más actionId (uno por cada acción fire_webhook). Los dos eventos se entregan de forma independiente, por lo que automation.completed puede llegar ocasionalmente antes que automation.triggered.
Si no hay ningún webhook registrado
fire_webhook publica en la acción automations registrada en el perfil, con tu Primary Profile como respaldo. No hay respaldo a otra acción como messages. Si no existe ninguno de los dos registros, automation.triggered no se descarta silenciosamente: la acción se registra en la fila de actividad como failed, con el motivo en actionResults[].errorDetails. (automation.completed tampoco tiene adónde ir, y no se registra.) El estado general del envío sigue entonces la precedencia habitual: auth_error si alguna acción tuvo un error de autenticación, en caso contrario sent si alguna acción fue aceptada, en caso contrario failed. Así que el webhook faltante cuenta para las estadísticas de fallos de la automatización solo cuando nada más en la regla envió; cuando otra acción sí envió (y ninguna tuvo un error de autenticación), el envío termina en sent y el webhook fallido aparece solo en actionResults[].
Un resultado sent de fire_webhook significa que el evento se encoló para su entrega a tu URL, no que tu endpoint lo haya aceptado. La entrega se reintenta después según su propio calendario.
Variables de plantilla
send_dm.message, send_email.subject y send_email.message admiten sustitución con {{placeholder}}. Los placeholders desconocidos se rechazan en el momento de creación/actualización (como un error de validación 473) para que un error tipográfico nunca deje pasar el literal {{foo}} a un mensaje visible para el cliente.
sender_email / recipient_email. Estos no se exponen deliberadamente: tu correo electrónico de facturación no tiene lugar legítimo en un DM a un desconocido, y Meta no proporciona el correo electrónico del destinatario en ningún webhook de IG. Evitar los placeholders previene divulgaciones accidentales.Límites de tasa y topes
POST (crear) como en la reactivación con PUT (active: false → true), cada una arrojando el código de error 470. ¿Necesitas un límite por perfil más alto? Contacta a soporte para que se aumente en tu cuenta.
El tope diario de DM se aplica por cuenta principal de Ayrshare, se comparte entre todos tus perfiles y tiene un sub-tope por perfil para que un perfil muy activo no consuma toda la cuota de la cuenta. Cuando se alcanza un tope de DM, la fila de actividad registra el estado rate_limited y no se envía ningún DM.
El límite de conversaciones de mensajería también se aplica. send_dm requiere el complemento Messaging en el perfil, y cada DM que envía cuenta para el límite de conversaciones mensual de ese perfil, igual que un DM que envías tú mismo. Cuando se alcanza el límite, un send_dm a un nuevo destinatario no se envía y la fila de actividad registra el estado failed, con el mensaje del límite en actionResults[].errorDetails. Los DM activados por un comentario (comment_keyword y story_comment) son la excepción: se siguen enviando al alcanzar el límite, y se siguen contando.
Topes estructurales en una sola automatización: 1–50 disparadores, 1–50 acciones.
Instagram por sí mismo limita los DMs a aproximadamente 200/hora por cuenta. El motor regula el envío con un jitter de 20 a 60 segundos para mantenerse con seguridad por debajo de este.
Estados de actividad
Una fila enGET /automations/:id/activity lleva un status de nivel superior más un status por acción dentro de actionResults[]:
pending e in_flight son transitorios; todo lo demás es terminal.
Cuando una automatización tiene más de una acción, el status de nivel superior se deriva de los resultados por acción en este orden: auth_error si alguna acción tuvo un error de autenticación, luego sent si alguna acción fue aceptada, luego deduplicated si todas las acciones fueron desduplicadas, luego skipped si todas las acciones fueron suprimidas deliberadamente (skipped o deduplicated), en caso contrario failed. Consulta actionResults[] para el detalle por acción.
sent es un acuse de recepción de aceptación por parte de la plataforma, no un acuse de entrega. Una acción send_dm se marca como sent en el momento en que Meta acepta el mensaje, ya se envíe desde tu cuenta de Instagram o por Messenger desde tu página de Facebook. La automatización solo registra esa aceptación; no hace seguimiento de la entrega. Instagram no expone la entrega de mensajes a ninguna API, y que el destinatario lo reciba realmente depende de su configuración de Message requests de Instagram, que Ayrshare no puede leer ni modificar. Consulta DM de automatización enviado pero no entregado.Códigos de error
La API devuelve dos formas de error:- Errores de regla de negocio llevan un
codenumerado de automatización (por ejemplo,{ "action": "automation", "code": 469, ... }). - Errores de validación — cualquier cuerpo de solicitud mal formado (campos faltantes o inválidos, variables de plantilla desconocidas, claves no reconocidas) — se devuelven como una única respuesta
473con un objetodetailsque lista los campos ofensivos.detailses la salida del validador (formErrorsmásfieldErrors). Ramifica endetails, no en un código por condición. EnfieldErrors, las claves son los campos de nivel superior de la solicitud (triggers,actions): un problema dentro de una entrada específica, como un disparador al que le faltakeywords, se reporta bajo ese campo (por ejemplo,triggers), mientras queformErrorscontiene problemas de nivel de objeto, como claves no reconocidas.
468 solo se devuelve a
los planes que no incluyen automatizaciones.Lo que Meta NO permite
Algunas capacidades comúnmente solicitadas no se admiten porque Meta no las permite en la API pública de Instagram:- Auto-DM en nuevos seguidores. Instagram no publica un webhook de seguimiento.
- Primeros DMs a desconocidos. Meta requiere que el destinatario haya interactuado primero (comentario, respuesta, DM, reacción) antes de que una cuenta comercial pueda enviarle un mensaje. Cada disparador admitido está anclado a esa interacción, pero ten en cuenta que estar autorizado a enviar no es lo mismo que el mensaje sea entregado: la configuración de Message requests de Instagram del destinatario aún puede provocar que Meta acepte y después descarte silenciosamente el mensaje (consulta DM de automatización enviado pero no entregado).
- Campañas masivas de salida. Los topes de DM por hora y las heurísticas anti-abuso se aplican a nivel de plataforma.
Uso multi-perfil
Los endpoints respetan el encabezadoprofileKey. Pasa la clave de un perfil secundario y la automatización se crea/gestiona bajo ese perfil. Los límites de tasa se dividen entre perfiles mediante un sub-tope por perfil, para que un perfil muy conversador no drene la cuota de la cuenta principal.
Preguntas frecuentes
¿Puedo activar en un nuevo seguidor?
¿Puedo activar en un nuevo seguidor?
comment_keyword, story_reply, dm_reaction, dm_keyword) está anclado a una interacción de ese tipo, que es lo que hace admisible el envío.¿Por qué una actividad dice sent pero el destinatario nunca recibió el DM?
¿Por qué una actividad dice sent pero el destinatario nunca recibió el DM?
sent significa que Meta aceptó el mensaje, no que se haya entregado. Esto aplica tanto en Instagram como en Facebook (Messenger desde tu página): la automatización solo registra la aceptación y no hace seguimiento de la entrega. En Instagram, la entrega depende de la configuración de Message requests de Instagram del destinatario — si no permite solicitudes de mensajes de todos, Meta devuelve una respuesta de éxito y descarta silenciosamente el mensaje, sin error, webhook ni ninguna otra señal en ninguna superficie de la API. Un DM activado por un comentario y entregado correctamente también llega como una solicitud de mensaje que el destinatario debe aceptar (a menos que ya exista una conversación). Esta es una limitación permanente de la plataforma Instagram. Consulta DM de automatización enviado pero no entregado.¿Qué sucede si mi token de acceso no es válido cuando se activa una automatización?
¿Qué sucede si mi token de acceso no es válido cuando se activa una automatización?
auth_error y el DM no se reintenta. Al resolver el estado de la cuenta (volviendo a vincularla, seleccionando una Page o activando Messaging), la siguiente interacción coincidente se activará normalmente. Esto solo se aplica a fallos reales de credenciales y permisos: si un DM concreto no se pudo entregar por otro motivo — por ejemplo, no se pudo encontrar al destinatario, o la interacción que activó la regla provino de la cuenta que enviaría el DM — la fila se registra como failed o skipped con el motivo en actionResults[].errorDetails, y volver a vincular no cambiará el resultado.¿Por qué hay un retraso antes de que se envíe el DM?
¿Por qué hay un retraso antes de que se envíe el DM?
fire_webhook y send_email: tu webhook llegará entre 20 y 60 segundos después del comentario, no de inmediato. La marca de tiempo created de la fila de actividad es cuando coincidió el disparador; completedAt es cuando terminó el envío.¿Las filas de actividad se conservan para siempre?
¿Las filas de actividad se conservan para siempre?
GET /automations/:id/activity devuelve las filas de los últimos 30 días por rendimiento. (La protección de desduplicación usa su propia ventana por acción — con un valor predeterminado de 7 días — que no está relacionada con el retroactivo de actividad.)¿Eliminar una automatización elimina su historial de actividad?
¿Eliminar una automatización elimina su historial de actividad?
deleted, no se producen nuevos envíos, pero las filas de actividad históricas siguen siendo legibles a través del endpoint de actividad.Endpoints
POST /automations— crea una nueva automatizaciónGET /automations— lista tus automatizacionesGET /automations/:id— obtén una automatización con sus disparadores y accionesPUT /automations/:id— actualización parcial; pausa conactive: falseDELETE /automations/:id— borrado lógicoGET /automations/:id/activity— registro de auditoría de envíos paginado por cursor