Статусы и события
Результат публикации можно узнать двумя способами: прочитать пост (GET /v1/posts/{id}) или читать ленту событий проекта
(GET /v1/events). Для интеграций удобнее лента: один запрос раз в минуту покрывает все посты проекта.
Статусы цели
У поста есть цель (targets[]) на каждый канал. Статус цели:
| Статус | Значение |
|---|---|
scheduled |
ждёт назначенного времени |
dispatched |
передана в Instagram, идёт публикация (загрузка и обработка медиа) |
deferred |
отложена: упёрлись в квоту или лимит запросов Instagram. retry_at — когда сервис попробует снова; повторять не нужно |
published |
опубликована: заполнены external_id и permalink |
failed |
не удалось, окончательно (error.code, error.message). Единственный статус, который можно повторить через :retry |
outcome_unknown |
неизвестно, вышел ли пост — см. ниже |
dry_run_ok |
теневой прогон (options.dry_run) дошёл до готового контейнера Instagram без публикации; container_id — идентификатор контейнера |
cancelled |
отменена до отправки |
Статус поста
Считается по целям:
| Статус | Когда |
|---|---|
scheduled |
все активные цели ещё ждут |
processing |
часть целей в работе или отложена |
published |
все цели опубликованы |
partially_published |
часть целей опубликована, остальные failed или outcome_unknown |
failed |
ни одна цель не опубликована (в том числе когда единственная цель в outcome_unknown) |
dry_run_ok |
теневой прогон завершён успешно (пост не публиковался) |
cancelled |
все цели отменены |
outcome_unknown: что это значит и почему не повторять вручную
Публикация в Instagram — два шага: создание контейнера с медиа и команда «опубликовать». Если сеть оборвалась или
процесс упал после команды «опубликовать», но до ответа, мы не знаем, вышел ли пост. Сервис сам сверяется с
Instagram по сохранённому контейнеру и в большинстве случаев выясняет исход (published или failed). Статус
outcome_unknown означает, что выяснить не удалось.
Не повторяйте такую публикацию вручную и не создавайте тот же пост заново: если пост на самом деле вышел, вы
получите дубль в ленте клиента, а Instagram дублей не отменяет. Сначала откройте профиль и проверьте, есть ли пост.
POST /v1/post-targets/{id}:retry для outcome_unknown нарочно не работает (409 target_not_failed).
Решение принимаете вы: нет поста — создайте новый (с новым Idempotency-Key).
Лента событий
GET /v1/events?after=<seq>&limit=<n> возвращает события проекта строго по порядку:
{
"data": [
{
"seq": 12,
"type": "post.published",
"created_at": "2026-11-05T09:10:41+00:00",
"data": {
"post_id": "01a1ab14-b9ae-7504-b304-8e6602f58395",
"target_id": "01a1ab14-b9af-7ab3-8e2b-4bb0ff2a1c03",
"channel_id": "01a1ab14-9628-798c-b1d0-77dbd5211c06",
"external_ref": "social_post:42",
"post_status": "published",
"target_status": "published",
"external_id": "17900000000000000",
"permalink": "https://www.instagram.com/p/XXXXXXXXXXX/",
"retry_at": null,
"error_code": null,
"error_message": null
}
}
],
"next_after": 12
}
seq — порядковый номер события в проекте. Храните последний обработанный seq и передавайте его как after:
получите только новые события. Пустой data — новых событий нет (next_after равен переданному after).
limit — до 500, по умолчанию 100. События хранятся по порядку и не пропадают между запросами, поэтому достаточно
опрашивать ленту раз в минуту.
# Лента событий проекта: храните next_after и передавайте его как after
curl -sS --fail-with-body -H "$AUTH" "$API_URL/v1/events?after=0&limit=50" \
| jq -r '(.data[] | "event: \(.seq) \(.type) \(.data.post_id // "")"), "next_after: \(.next_after)"'
# Лента событий проекта: храните next_after и передавайте его как after
feed = api("GET", "/v1/events?after=0&limit=50")
for event in feed["data"]:
print("event:", event["seq"], event["type"], event["data"].get("post_id", ""))
print("next_after:", feed["next_after"])
// Лента событий проекта: храните next_after и передавайте его как after
const feed = await api("GET", "/v1/events?after=0&limit=50");
for (const event of feed.data) {
console.log("event:", event.seq, event.type, event.data.post_id ?? "");
}
console.log("next_after:", feed.next_after);
// Лента событий проекта: храните next_after и передавайте его как after
$feed = api('GET', '/v1/events?after=0&limit=50');
foreach ($feed['data'] as $event) {
echo 'event: ', $event['seq'], ' ', $event['type'], ' ', $event['data']['post_id'] ?? '', "\n";
}
echo 'next_after: ', $feed['next_after'], "\n";
// Лента событий проекта: храните next_after и передавайте его как after
var feed struct {
Data []struct {
Seq int `json:"seq"`
Type string `json:"type"`
Data map[string]any `json:"data"`
} `json:"data"`
NextAfter int `json:"next_after"`
}
api("GET", "/v1/events?after=0&limit=50", nil, "", "", &feed)
for _, e := range feed.Data {
fmt.Println("event:", e.Seq, e.Type, e.Data["post_id"])
}
fmt.Println("next_after:", feed.NextAfter)
Типы событий
События post.* — по одному на смену статуса цели. Поля data у всех одинаковы (см. пример выше).
| Тип | Когда | Что смотреть в data |
|---|---|---|
post.published |
цель опубликована | external_id, permalink |
post.failed |
цель окончательно не удалась | error_code, error_message (каталог) |
post.deferred |
цель отложена из-за квоты или лимита Instagram | retry_at, error_code (quota_exhausted или rate_limited) |
post.outcome_unknown |
исход неизвестен (см. выше) | error_code, error_message |
post.dry_run_ok |
теневой прогон успешен, пост не опубликован | container_id |
channel.connected |
канал подключён или подключён заново | channel_id, username, external_account_id |
channel.reauth_required |
токен канала больше не работает, нужен новый | channel_id, reason_code, message |
Поле data |
Описание |
|---|---|
post_id, target_id, channel_id |
идентификаторы поста, цели и канала |
external_ref |
ваш external_ref, если передавали |
post_status, target_status |
статусы поста и цели на момент события |
external_id, permalink |
id и ссылка публикации в Instagram (у published) |
retry_at |
время следующей попытки (у deferred) |
container_id |
контейнер Instagram, созданный для публикации (во всех post.*, когда он уже создан) |
error_code, error_message |
причина (у failed, deferred, outcome_unknown) |
События статуса, который не поменялся, повторно не создаются. События канала не дублируются: channel.connected после
продления токена в ленте второй раз не появляется.
Ретраи
Сбои сети и временные ошибки Instagram сервис повторяет сам: до 6 попыток с нарастающей задержкой, не позже чем через
24 часа от publish_at. Если попытки закончились, цель становится failed (или outcome_unknown, если неясно, вышел ли пост).
Квоту публикаций Instagram и лимит запросов сервис учитывает заранее и откладывает цель (deferred), не тратя попытки.
Для упавшей цели, которую хотите повторить сами, есть POST /v1/post-targets/{id}:retry (только failed).