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
取得自動化活動
單一自動化的游標分頁稽核紀錄
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"
}
Beta。 完整功能說明請見自動化概觀。
活動列狀態
每一列都有最外層的status,以及 actionResults[] 中每個動作的 status。
| 狀態 | 何時記錄 |
|---|---|
pending | 資料列剛寫入,Worker 尚未取用 |
in_flight | Worker 正在派送中 |
sent | 至少一個動作被平台接受,且沒有動作發生驗證錯誤。就 send_dm 而言,這表示 Meta 接受了該訊息 — 但不代表接收者收到了訊息(請見下方說明) |
failed | 沒有任何動作被接受,且至少一個動作被平台拒絕或無法執行(且沒有動作發生驗證錯誤)。原因會記在 actionResults[].errorDetails |
auth_error | 該帳號的 Instagram 或 Facebook 粉絲專頁憑證或訊息傳遞權限無法使用 — 例如已過期或已撤銷的存取權杖、未選擇 Facebook Page,或該 profile 未啟用 Messaging。DM 沒有被重試。每個接收者的送達失敗會記錄為 failed,而不會記在此處 |
rate_limited | 已達每日 DM 上限(方案層級或每個個人檔案)。DM 未被發送 |
deduplicated | 此動作已於去重視窗內對此接收者觸發過(預設 7 天,可依動作個別設定) |
skipped | 該自動化在派送前被抑制 — 在 fan-out 與派送之間被停用或已刪除、未設定任何動作,或觸發它的互動事件來自該自動化自己的帳號 — 最常見的情況是對自己的貼文留言。在最後這種情況下不會執行任何動作:不會發送 DM(帳號無法傳訊息給自己),fire_webhook 與 send_email 也不會執行。已選擇加入 automation.completed 的自動化仍會收到該事件,並帶有此狀態 |
pending 與 in_flight 為暫時狀態;其他皆為終態。
當自動化有多個動作時,最外層的 status 會依以下順序從每個動作的結果導出:若任一動作發生驗證錯誤則為 auth_error,接著若任一動作被接受則為 sent,接著若每個動作皆被去重則為 deduplicated,接著若每個動作皆被刻意抑制(skipped 或 deduplicated)則為 skipped,否則為 failed。請閱讀 actionResults[] 取得每個動作的詳細資訊。
sent 代表 Meta 接受了訊息,並非代表接收者收到了訊息。 這同樣適用於 Instagram DM 和透過 Messenger 從 Facebook 粉絲專頁發送的 DM:自動化只記錄接受結果,不會追蹤送達狀態。Instagram 在任何 API 層面都不提供訊息送達的訊號,若接收者的 Message requests 設定阻擋陌生人,Meta 會照常接受發送但靜默地將訊息捨棄。請參閱 Automation DM Sent but Not Delivered。每個動作的結果欄位
actionResults[] 中每個項目描述一個動作的結果:
| 欄位 | 類型 | 說明 |
|---|---|---|
actionId | string | 該動作在自動化內的穩定 ID |
type | string | 動作類型(send_dm、fire_webhook、send_email) |
status | string | 每個動作的狀態,使用與上方資料列 status 相同的詞彙 |
errorDetails | string | null | 動作未成功時的人類可讀失敗原因;成功時為 null(或不存在)。若 send_dm 遭拒,這裡會帶對應的錯誤訊息(例如 private reply 視窗已關閉,或該留言已收到回覆)。成功時為 null 的一個例外:messageSource: "fallback" 的 send_dm 狀態為 sent,並帶有未使用其回呼的原因。若 fallback 之後發送失敗,則帶有發送錯誤,後接該原因 |
messageSource | string | 僅限 send_dm。DM 以哪段文字建立:template(靜態的 message)、callback(你的 messageUrl 已回應,並使用了它的文字)或 fallback(已設定 messageUrl 但無法使用,因此改用 message,原因記在 errorDetails)。它不代表 DM 是否已送達;送達與否請看 status。在 DM 文字確定後就會出現,包括之後發送失敗的情況。若動作在那之前就已停止(發給你自己帳號而被 skipped 的 DM、deduplicated 的動作,或缺少留言 id 等 failed 設定錯誤),以及其他動作類型,則不會出現 |
config | object(選填) | 本次觸發執行時該動作的設定,例如 send_dm 的 message 模板。即使你之後編輯了自動化,這裡也會維持不變,因此每個資料列都會顯示當時的設定。在此欄位加入之前寫入的資料列上不存在,且為符合大小限制而被移除時也不存在(此時 truncated 為 true) |
sent | object(選填) | 該動作在本次觸發中發送或嘗試發送的內容。在動作建立好其訊息或 payload 後就會記錄,包括之後發送失敗的情況:是否已送出請看 status。若動作在發送之前就已停止(例如針對你自己帳號的留言而產生的 skipped 結果),以及 deduplicated 結果,則不會出現。請參閱 sent 包含的內容 |
truncated | boolean(選填) | 當該項目為符合大小限制而被截短時為 true:過長的文字值被縮短,或 config 以及接著 sent 被整個省略。其他情況下不存在 |
completedAt | string | 動作完成時的 ISO 8601 時間戳 |
sent 包含的內容
| 動作類型 | sent 欄位 |
|---|---|
send_dm | message:DM 實際發送的文字。也就是針對此接收者填入預留變數後的 message 模板;或當 messageSource 為 callback 時,你的 messageUrl 所回傳的文字。fallbackMessage:僅在 messageSource 為 callback 時出現;即填入預留變數後的模板,也就是未使用 callback 時原本會發送的內容 |
send_email | to、subject 與 message:排入佇列時的電子郵件內容,已填入預留變數 |
fire_webhook | payload:發送到你 webhook 的事件欄位。實際送達的內容還會帶有標準的 webhook 欄位(action、created、hookId、refId、url,以及 webhook 有簽署時的 timeStamp)。hookId:該次送達的 id,在 webhook 已排入佇列時出現 |
truncated。儲存在看起來像憑證的鍵名(例如 token、secret、password 或 apiKey)下的值,會記錄為 "[redacted]"。send_dm 動作的 messageUrl 也一律記錄為 "[redacted]",因為 URL 的路徑或查詢字串中可能帶有機密資訊。
對於由留言觸發的自動化(comment_keyword),該資料列還會攜帶一個最外層的 commentId — 該 DM 所錨定的原始 Instagram 留言 ID。對於由訊息驅動的觸發條件(dm_keyword、story_reply、dm_reaction)則為 null。
資料列也會攜帶 postId(comment_keyword 留言所在的貼文)與 storyId(story_reply 與 story_comment 對應的限時動態)。兩者在其他觸發條件時皆為 null,且在這些欄位加入之前寫入的資料列上不存在。
標頭參數
路徑參數
string
必填
由
POST /automations 回傳的自動化 ID。查詢參數
number
預設值:25
每頁大小。預設
25,最大 100。[1, 100] 以外的值會被夾限(clamp);非整數或 ≤0 會回傳 HTTP 400。string
來自上一次回應
meta.pagination.next 的不透明游標。第一次請求時省略。僅支援向前分頁 — 傳入 ?previous= 會回傳 HTTP 400。回應格式
回應會將結果清單包在activity[] 中,並將游標資訊包在 meta.pagination 中:
{
"status": "success",
"automationId": "auto_9xKp2Lm4nQ",
"activity": [ /* …rows, newest first… */ ],
"meta": {
"pagination": {
"hasMore": true,
"limit": 25,
"next": "eyJ0aW1lIjoiMjAyNi0wNS0xMlQwOTowMDoxMS4wMDBaIiwiaWQiOiJhdXRvXzl4S3AyTG00blE6dHJnX2ExYjJjMzpjb21tZW50X3JlY2VpdmVkOjE4MDEyMzQ1Njc4OTAwMDAwIn0="
}
}
}
meta.pagination.next 是 base64 編碼的不透明字串 — 請將其視為黑盒,並在下一次請求的 ?next= 中原樣傳回。當至少還有一頁時,meta.pagination.hasMore 為 true。
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"
}