Статусы и события

Результат публикации можно узнать двумя способами: прочитать пост (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)"'

Типы событий

События 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).