curl \
-H "Authorization: Bearer API_KEY" \
-X GET "https://api.ayrshare.com/api/automations/auto_9xKp2Lm4nQ/activity?limit=25"
curl \
-H "Authorization: Bearer API_KEY" \
-X GET "https://api.ayrshare.com/api/automations/auto_9xKp2Lm4nQ/activity?limit=25&next=eyJ0aW1lIjoiMjAyNi0wNS0xMlQw..."
const API_KEY = "API_KEY";
const id = "auto_9xKp2Lm4nQ";
// Paginate through every page
let next;
do {
const url = new URL(`https://api.ayrshare.com/api/automations/${id}/activity`);
url.searchParams.set("limit", "25");
if (next) url.searchParams.set("next", next);
const res = await fetch(url, {
headers: { "Authorization": `Bearer ${API_KEY}` },
});
const json = await res.json();
console.log(json.activity);
next = json.meta?.pagination?.hasMore ? json.meta.pagination.next : undefined;
} while (next);
import requests
headers = {"Authorization": "Bearer API_KEY"}
automation_id = "auto_9xKp2Lm4nQ"
params = {"limit": 25}
while True:
r = requests.get(
f"https://api.ayrshare.com/api/automations/{automation_id}/activity",
params=params,
headers=headers,
).json()
print(r["activity"])
pagination = r.get("meta", {}).get("pagination", {})
if not pagination.get("hasMore"):
break
params["next"] = pagination["next"]
$id = "auto_9xKp2Lm4nQ";
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.ayrshare.com/api/automations/" . $id . "/activity?limit=25",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => ["Authorization: Bearer API_KEY"],
]);
$response = curl_exec($curl);
curl_close($curl);
echo $response;
{
"status": "success",
"automationId": "auto_9xKp2Lm4nQ",
"activity": [
{
"id": "auto_9xKp2Lm4nQ:trg_a1b2c3:comment.received:18012345678901234",
"automationId": "auto_9xKp2Lm4nQ",
"triggerId": "trg_a1b2c3",
"triggerType": "comment_keyword",
"recipientId": "17841401234567890",
"recipientUsername": "jane_doe",
"eventId": "comment.received:18012345678901234",
"commentId": "18012345678901234",
"platform": "instagram",
"status": "sent",
"actionResults": [
{
"actionId": "act_d4e5f6",
"type": "send_dm",
"status": "sent",
"errorDetails": null,
"messageSource": "template",
"config": { "message": "Hi {{recipient_username}}, here's the link: https://example.com" },
"sent": { "message": "Hi jane_doe, here's the link: https://example.com" },
"completedAt": "2026-05-12T09:14:48.000Z"
}
],
"keyword": "LINK",
"commentText": "Send me the LINK please!",
"created": "2026-05-12T09:14:22.000Z",
"completedAt": "2026-05-12T09:14:48.000Z"
},
{
"id": "auto_9xKp2Lm4nQ:trg_a1b2c3:comment.received:18012345678905555",
"automationId": "auto_9xKp2Lm4nQ",
"triggerId": "trg_a1b2c3",
"triggerType": "comment_keyword",
"recipientId": "17841405555555555",
"recipientUsername": "late_commenter",
"eventId": "comment.received:18012345678905555",
"commentId": "18012345678905555",
"platform": "instagram",
"status": "failed",
"actionResults": [
{
"actionId": "act_d4e5f6",
"type": "send_dm",
"status": "failed",
"errorDetails": "Cannot send private reply: This comment is no longer eligible for a private reply.",
"completedAt": "2026-05-12T09:12:03.000Z"
}
],
"keyword": "LINK",
"commentText": "LINK please!",
"created": "2026-05-12T09:12:01.000Z",
"completedAt": "2026-05-12T09:12:03.000Z"
},
{
"id": "auto_9xKp2Lm4nQ:trg_a1b2c3:comment.received:18012345678900000",
"automationId": "auto_9xKp2Lm4nQ",
"triggerId": "trg_a1b2c3",
"triggerType": "comment_keyword",
"recipientId": "17841409876543210",
"recipientUsername": "repeat_user",
"eventId": "comment.received:18012345678900000",
"commentId": "18012345678900000",
"platform": "instagram",
"status": "deduplicated",
"actionResults": [],
"keyword": "LINK",
"commentText": "LINK again please",
"created": "2026-05-12T09:00:11.000Z",
"completedAt": "2026-05-12T09:00:34.000Z"
}
],
"meta": {
"pagination": {
"hasMore": true,
"limit": 25,
"next": "eyJ0aW1lIjoiMjAyNi0wNS0xMlQwOTowMDoxMS4wMDBaIiwiaWQiOiJhdXRvXzl4S3AyTG00blE6dHJnX2ExYjJjMzoxODAxMjM0NTY3ODkwMDAwMCJ9"
}
}
}
{
"status": "error",
"message": "limit must be a positive integer"
}
{
"status": "error",
"message": "'previous' pagination is not supported by this endpoint"
}
{
"action": "automation",
"status": "error",
"code": 469,
"message": "Automation not found"
}
Automations
Obtenir l'activité d'une automatisation
Journal d’audit paginé par curseur pour une automatisation
GET
/
automations
/
:id
/
activity
curl \
-H "Authorization: Bearer API_KEY" \
-X GET "https://api.ayrshare.com/api/automations/auto_9xKp2Lm4nQ/activity?limit=25"
curl \
-H "Authorization: Bearer API_KEY" \
-X GET "https://api.ayrshare.com/api/automations/auto_9xKp2Lm4nQ/activity?limit=25&next=eyJ0aW1lIjoiMjAyNi0wNS0xMlQw..."
const API_KEY = "API_KEY";
const id = "auto_9xKp2Lm4nQ";
// Paginate through every page
let next;
do {
const url = new URL(`https://api.ayrshare.com/api/automations/${id}/activity`);
url.searchParams.set("limit", "25");
if (next) url.searchParams.set("next", next);
const res = await fetch(url, {
headers: { "Authorization": `Bearer ${API_KEY}` },
});
const json = await res.json();
console.log(json.activity);
next = json.meta?.pagination?.hasMore ? json.meta.pagination.next : undefined;
} while (next);
import requests
headers = {"Authorization": "Bearer API_KEY"}
automation_id = "auto_9xKp2Lm4nQ"
params = {"limit": 25}
while True:
r = requests.get(
f"https://api.ayrshare.com/api/automations/{automation_id}/activity",
params=params,
headers=headers,
).json()
print(r["activity"])
pagination = r.get("meta", {}).get("pagination", {})
if not pagination.get("hasMore"):
break
params["next"] = pagination["next"]
$id = "auto_9xKp2Lm4nQ";
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.ayrshare.com/api/automations/" . $id . "/activity?limit=25",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => ["Authorization: Bearer API_KEY"],
]);
$response = curl_exec($curl);
curl_close($curl);
echo $response;
{
"status": "success",
"automationId": "auto_9xKp2Lm4nQ",
"activity": [
{
"id": "auto_9xKp2Lm4nQ:trg_a1b2c3:comment.received:18012345678901234",
"automationId": "auto_9xKp2Lm4nQ",
"triggerId": "trg_a1b2c3",
"triggerType": "comment_keyword",
"recipientId": "17841401234567890",
"recipientUsername": "jane_doe",
"eventId": "comment.received:18012345678901234",
"commentId": "18012345678901234",
"platform": "instagram",
"status": "sent",
"actionResults": [
{
"actionId": "act_d4e5f6",
"type": "send_dm",
"status": "sent",
"errorDetails": null,
"messageSource": "template",
"config": { "message": "Hi {{recipient_username}}, here's the link: https://example.com" },
"sent": { "message": "Hi jane_doe, here's the link: https://example.com" },
"completedAt": "2026-05-12T09:14:48.000Z"
}
],
"keyword": "LINK",
"commentText": "Send me the LINK please!",
"created": "2026-05-12T09:14:22.000Z",
"completedAt": "2026-05-12T09:14:48.000Z"
},
{
"id": "auto_9xKp2Lm4nQ:trg_a1b2c3:comment.received:18012345678905555",
"automationId": "auto_9xKp2Lm4nQ",
"triggerId": "trg_a1b2c3",
"triggerType": "comment_keyword",
"recipientId": "17841405555555555",
"recipientUsername": "late_commenter",
"eventId": "comment.received:18012345678905555",
"commentId": "18012345678905555",
"platform": "instagram",
"status": "failed",
"actionResults": [
{
"actionId": "act_d4e5f6",
"type": "send_dm",
"status": "failed",
"errorDetails": "Cannot send private reply: This comment is no longer eligible for a private reply.",
"completedAt": "2026-05-12T09:12:03.000Z"
}
],
"keyword": "LINK",
"commentText": "LINK please!",
"created": "2026-05-12T09:12:01.000Z",
"completedAt": "2026-05-12T09:12:03.000Z"
},
{
"id": "auto_9xKp2Lm4nQ:trg_a1b2c3:comment.received:18012345678900000",
"automationId": "auto_9xKp2Lm4nQ",
"triggerId": "trg_a1b2c3",
"triggerType": "comment_keyword",
"recipientId": "17841409876543210",
"recipientUsername": "repeat_user",
"eventId": "comment.received:18012345678900000",
"commentId": "18012345678900000",
"platform": "instagram",
"status": "deduplicated",
"actionResults": [],
"keyword": "LINK",
"commentText": "LINK again please",
"created": "2026-05-12T09:00:11.000Z",
"completedAt": "2026-05-12T09:00:34.000Z"
}
],
"meta": {
"pagination": {
"hasMore": true,
"limit": 25,
"next": "eyJ0aW1lIjoiMjAyNi0wNS0xMlQwOTowMDoxMS4wMDBaIiwiaWQiOiJhdXRvXzl4S3AyTG00blE6dHJnX2ExYjJjMzoxODAxMjM0NTY3ODkwMDAwMCJ9"
}
}
}
{
"status": "error",
"message": "limit must be a positive integer"
}
{
"status": "error",
"message": "'previous' pagination is not supported by this endpoint"
}
{
"action": "automation",
"status": "error",
"code": 469,
"message": "Automation not found"
}
Bêta. Voir la Vue d’ensemble des automatisations pour la description complète de la fonctionnalité.
Statut des lignes d’activité
Chaque ligne a unstatus de premier niveau plus un status par action à l’intérieur d’actionResults[].
| Statut | Quand il est enregistré |
|---|---|
pending | La ligne vient d’être écrite ; le worker ne l’a pas encore prise en charge |
in_flight | Le worker est en train d’envoyer |
sent | Au moins une action a été acceptée par la plateforme, et aucune n’a rencontré d’erreur d’auth. Pour send_dm, cela signifie que Meta a accepté le message — et non que le destinataire l’a reçu (voir la note ci-dessous) |
failed | Aucune action n’a été acceptée, et au moins une a été rejetée par la plateforme ou n’a pas pu s’exécuter (et aucune n’a rencontré d’erreur d’auth). La raison figure dans actionResults[].errorDetails |
auth_error | Les identifiants Instagram ou de Page Facebook du compte, ou ses autorisations de messagerie, n’ont pas pu être utilisés — par exemple un jeton d’accès expiré ou révoqué, une Facebook Page non sélectionnée, ou Messaging non activée pour le profil. Le DM n’a pas été retenté. Les échecs de livraison propres à un destinataire sont enregistrés comme failed, et non ici |
rate_limited | Le plafond quotidien de DM (par palier ou par profil) a été atteint. Aucun DM n’a été envoyé |
deduplicated | Cette action a déjà été déclenchée pour ce destinataire dans sa fenêtre de dédup (par défaut 7 jours, configurable par action) |
skipped | L’automatisation a été supprimée avant l’envoi — elle est devenue inactive ou a été supprimée entre le fan-out et l’envoi, elle n’a aucune action configurée, ou l’engagement qui l’a déclenchée provient du propre compte de l’automatisation — le plus souvent un commentaire sur votre propre publication. Dans ce dernier cas, aucune action ne s’exécute : pas de DM (un compte ne peut pas s’envoyer de message à lui-même), et pas de fire_webhook ni de send_email non plus. Une automatisation qui a activé automation.completed reçoit tout de même cet événement, avec ce statut |
pending et in_flight sont transitoires ; tout le reste est terminal.
Lorsqu’une automatisation comporte plus d’une action, le status de premier niveau est dérivé des résultats par action dans cet ordre : auth_error si une action a rencontré une erreur d’auth, puis sent si une action a été acceptée, puis deduplicated si chaque action a été dédupliquée, puis skipped si chaque action a été délibérément supprimée (skipped ou deduplicated), sinon failed. Consultez actionResults[] pour le détail par action.
sent confirme que Meta a accepté le message, pas que le destinataire l’a reçu. C’est vrai pour les DM Instagram comme pour les DM Messenger envoyés depuis une Page Facebook : l’automatisation enregistre uniquement l’acceptation et ne suit pas la livraison. Instagram n’expose aucun signal de livraison sur aucune surface d’API, et si le paramètre Message requests du destinataire bloque les inconnus, Meta accepte l’envoi et le supprime silencieusement. Voir Automation DM Sent but Not Delivered.Champs de résultat par action
Chaque entrée d’actionResults[] décrit le résultat d’une action :
| Champ | Type | Description |
|---|---|---|
actionId | string | L’ID stable de l’action au sein de l’automatisation |
type | string | Le type d’action (send_dm, fire_webhook, send_email) |
status | string | Statut par action, utilisant le même vocabulaire que le status de ligne ci-dessus |
errorDetails | string | null | Motif d’échec lisible par un humain lorsque l’action n’a pas abouti ; null (ou absent) en cas de succès. Pour un send_dm rejeté, ce champ contient le message d’erreur mappé (p. ex. la fenêtre de private reply est fermée, ou le commentaire a déjà reçu une réponse). Une exception au null en cas de succès : un send_dm avec messageSource: "fallback" est sent et contient la raison pour laquelle son callback n’a pas été utilisé. Un fallback dont l’envoi a ensuite échoué contient l’erreur d’envoi suivie de cette raison |
messageSource | string | send_dm uniquement. Le texte à partir duquel le DM a été construit : template (le message statique), callback (votre messageUrl a répondu et son texte a été utilisé) ou fallback (messageUrl était défini mais inutilisable, donc message a été utilisé à la place, avec la raison dans errorDetails). Il n’indique pas si le DM a été livré ; c’est le rôle de status. Présent dès que le texte du DM a été déterminé, y compris pour les envois qui ont ensuite échoué. Absent lorsque l’action s’est arrêtée avant (un DM skipped vers votre propre compte, une action deduplicated, ou une erreur de configuration failed telle qu’un identifiant de commentaire manquant), ainsi que pour les autres types d’action |
config | object (facultatif) | La configuration de l’action telle qu’elle était lors de ce déclenchement, par exemple le modèle message de send_dm. Elle reste identique si vous modifiez ensuite l’automatisation, de sorte que chaque ligne montre ce qui était configuré à ce moment-là. Absent des lignes écrites avant l’ajout de ce champ, et lorsqu’il a été retiré pour respecter la limite de taille (truncated vaut alors true) |
sent | object (facultatif) | Ce que l’action a envoyé, ou tenté d’envoyer, pour ce déclenchement. Enregistré dès que l’action a construit son message ou sa charge utile, y compris lorsque l’envoi a ensuite échoué : status indique s’il est parti. Absent lorsque l’action s’est arrêtée avant l’envoi, par exemple un résultat skipped pour un commentaire provenant de votre propre compte, ainsi que pour les résultats deduplicated. Voir ce que contient sent |
truncated | boolean (facultatif) | true lorsque l’entrée a été raccourcie pour respecter sa limite de taille : une longue valeur texte a été tronquée, ou config puis sent ont été entièrement omis. Absent sinon |
completedAt | string | Horodatage ISO 8601 auquel l’action s’est terminée |
Ce que contient sent
| Type d’action | Champs de sent |
|---|---|
send_dm | message : le texte avec lequel le DM a été envoyé. Il s’agit de votre modèle message avec ses placeholders remplis pour ce destinataire ou, lorsque messageSource vaut callback, du texte renvoyé par votre messageUrl. fallbackMessage : présent uniquement lorsque messageSource vaut callback ; votre modèle, rempli, tel qu’il aurait été envoyé sans le callback |
send_email | to, subject et message : l’e-mail tel qu’il a été mis en file d’attente, placeholders remplis |
fire_webhook | payload : les champs d’événement envoyés à votre webhook. Le corps livré contient également les champs webhook standard (action, created, hookId, refId, url, et timeStamp lorsque le webhook est signé). hookId : l’identifiant de la livraison, présent lorsque le webhook a été mis en file d’attente |
truncated est défini lorsque cela se produit. Les valeurs stockées sous des noms de clé qui ressemblent à des identifiants, tels que token, secret, password ou apiKey, sont enregistrées comme "[redacted]". Le messageUrl d’une action send_dm est lui aussi toujours enregistré comme "[redacted]", car une URL peut contenir un secret dans son chemin ou sa chaîne de requête.
Pour les automatisations déclenchées par un commentaire (comment_keyword), la ligne porte également un commentId de premier niveau — l’ID brut du commentaire Instagram sur lequel le DM était ancré. Il est null pour les déclencheurs pilotés par message (dm_keyword, story_reply, dm_reaction).
Les lignes portent également postId (la publication sur laquelle un commentaire comment_keyword a été laissé) et storyId (la story pour story_reply et story_comment). Chacun vaut null pour les autres déclencheurs, et est absent des lignes écrites avant l’ajout de ces champs.
Paramètres d’en-tête
Paramètres de chemin
string
requis
L’ID d’automatisation retourné par
POST /automations.Paramètres de requête
number
défaut:25
Taille de page. Par défaut
25, max 100. Les valeurs en dehors de [1, 100] sont ramenées à cette plage ; les valeurs non entières ou ≤0 retournent HTTP 400.string
Curseur opaque provenant de
meta.pagination.next d’une réponse précédente. Omettez-le à la première requête.Vers l’avant uniquement — passer ?previous= renvoie HTTP 400.Forme de la réponse
La réponse enveloppe la liste de résultats dansactivity[] et les infos du curseur dans meta.pagination :
{
"status": "success",
"automationId": "auto_9xKp2Lm4nQ",
"activity": [ /* …rows, newest first… */ ],
"meta": {
"pagination": {
"hasMore": true,
"limit": 25,
"next": "eyJ0aW1lIjoiMjAyNi0wNS0xMlQwOTowMDoxMS4wMDBaIiwiaWQiOiJhdXRvXzl4S3AyTG00blE6dHJnX2ExYjJjMzpjb21tZW50X3JlY2VpdmVkOjE4MDEyMzQ1Njc4OTAwMDAwIn0="
}
}
}
meta.pagination.next est un blob opaque encodé en base64 — traitez-le comme une boîte noire et repassez-le tel quel dans le ?next= de la requête suivante. meta.pagination.hasMore vaut true lorsqu’au moins une page supplémentaire existe.
curl \
-H "Authorization: Bearer API_KEY" \
-X GET "https://api.ayrshare.com/api/automations/auto_9xKp2Lm4nQ/activity?limit=25"
curl \
-H "Authorization: Bearer API_KEY" \
-X GET "https://api.ayrshare.com/api/automations/auto_9xKp2Lm4nQ/activity?limit=25&next=eyJ0aW1lIjoiMjAyNi0wNS0xMlQw..."
const API_KEY = "API_KEY";
const id = "auto_9xKp2Lm4nQ";
// Paginate through every page
let next;
do {
const url = new URL(`https://api.ayrshare.com/api/automations/${id}/activity`);
url.searchParams.set("limit", "25");
if (next) url.searchParams.set("next", next);
const res = await fetch(url, {
headers: { "Authorization": `Bearer ${API_KEY}` },
});
const json = await res.json();
console.log(json.activity);
next = json.meta?.pagination?.hasMore ? json.meta.pagination.next : undefined;
} while (next);
import requests
headers = {"Authorization": "Bearer API_KEY"}
automation_id = "auto_9xKp2Lm4nQ"
params = {"limit": 25}
while True:
r = requests.get(
f"https://api.ayrshare.com/api/automations/{automation_id}/activity",
params=params,
headers=headers,
).json()
print(r["activity"])
pagination = r.get("meta", {}).get("pagination", {})
if not pagination.get("hasMore"):
break
params["next"] = pagination["next"]
$id = "auto_9xKp2Lm4nQ";
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.ayrshare.com/api/automations/" . $id . "/activity?limit=25",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => ["Authorization: Bearer API_KEY"],
]);
$response = curl_exec($curl);
curl_close($curl);
echo $response;
{
"status": "success",
"automationId": "auto_9xKp2Lm4nQ",
"activity": [
{
"id": "auto_9xKp2Lm4nQ:trg_a1b2c3:comment.received:18012345678901234",
"automationId": "auto_9xKp2Lm4nQ",
"triggerId": "trg_a1b2c3",
"triggerType": "comment_keyword",
"recipientId": "17841401234567890",
"recipientUsername": "jane_doe",
"eventId": "comment.received:18012345678901234",
"commentId": "18012345678901234",
"platform": "instagram",
"status": "sent",
"actionResults": [
{
"actionId": "act_d4e5f6",
"type": "send_dm",
"status": "sent",
"errorDetails": null,
"messageSource": "template",
"config": { "message": "Hi {{recipient_username}}, here's the link: https://example.com" },
"sent": { "message": "Hi jane_doe, here's the link: https://example.com" },
"completedAt": "2026-05-12T09:14:48.000Z"
}
],
"keyword": "LINK",
"commentText": "Send me the LINK please!",
"created": "2026-05-12T09:14:22.000Z",
"completedAt": "2026-05-12T09:14:48.000Z"
},
{
"id": "auto_9xKp2Lm4nQ:trg_a1b2c3:comment.received:18012345678905555",
"automationId": "auto_9xKp2Lm4nQ",
"triggerId": "trg_a1b2c3",
"triggerType": "comment_keyword",
"recipientId": "17841405555555555",
"recipientUsername": "late_commenter",
"eventId": "comment.received:18012345678905555",
"commentId": "18012345678905555",
"platform": "instagram",
"status": "failed",
"actionResults": [
{
"actionId": "act_d4e5f6",
"type": "send_dm",
"status": "failed",
"errorDetails": "Cannot send private reply: This comment is no longer eligible for a private reply.",
"completedAt": "2026-05-12T09:12:03.000Z"
}
],
"keyword": "LINK",
"commentText": "LINK please!",
"created": "2026-05-12T09:12:01.000Z",
"completedAt": "2026-05-12T09:12:03.000Z"
},
{
"id": "auto_9xKp2Lm4nQ:trg_a1b2c3:comment.received:18012345678900000",
"automationId": "auto_9xKp2Lm4nQ",
"triggerId": "trg_a1b2c3",
"triggerType": "comment_keyword",
"recipientId": "17841409876543210",
"recipientUsername": "repeat_user",
"eventId": "comment.received:18012345678900000",
"commentId": "18012345678900000",
"platform": "instagram",
"status": "deduplicated",
"actionResults": [],
"keyword": "LINK",
"commentText": "LINK again please",
"created": "2026-05-12T09:00:11.000Z",
"completedAt": "2026-05-12T09:00:34.000Z"
}
],
"meta": {
"pagination": {
"hasMore": true,
"limit": 25,
"next": "eyJ0aW1lIjoiMjAyNi0wNS0xMlQwOTowMDoxMS4wMDBaIiwiaWQiOiJhdXRvXzl4S3AyTG00blE6dHJnX2ExYjJjMzoxODAxMjM0NTY3ODkwMDAwMCJ9"
}
}
}
{
"status": "error",
"message": "limit must be a positive integer"
}
{
"status": "error",
"message": "'previous' pagination is not supported by this endpoint"
}
{
"action": "automation",
"status": "error",
"code": 469,
"message": "Automation not found"
}