SkyStream API

События

Как узнать, что запуск вышел на канал, заказ выполнен или срок подходит к концу.

Событие — запись о том, что случилось с объектом аккаунта: запуск вышел на канал, заказ выполнен, лимит подходит к концу. События позволяют не опрашивать API в ожидании перемен, а узнавать о них.

Получать события можно двумя способами: вебхуками — сразу на свой адрес, или списком GET /events, — и их удобно сочетать: вебхуки для скорости, список — чтобы догнать пропущенное.

События пишутся, только пока у аккаунта включён доступ к API. Хранятся 30 суток.

Типы

ТипОбъектКогда приходит
run.liveзапускНачался эфир, и запуск вышел на канал. Запуск, созданный во время эфира, сначала присылает run.waiting, а в течение минуты — run.live. Если в пуле сейчас нет места, у запуска status — waiting, пока место не освободится.
run.waitingзапускЗапуск создан или эфир закончился: запуск ждёт эфира. Зрители выйдут сами, когда эфир начнётся. У запуска status — waiting.
run.stoppedзапускЗапуск завершён. Причина — в stop_reason объекта: остановлен владельцем, вышло время, истёк лимит, остановлен поддержкой.
order.startedзаказЗаказ пошёл в работу, в том числе после паузы: заказ фолловеров «только в эфире» встаёт на паузу вне эфира и продолжается с его началом.
order.completedзаказЗаказ выполнен; у чат-ботов и чат-панели — истёк их срок.
order.failedзаказЗаказ не выполнен. Сумма возвращена на счёт.
order.cancelledзаказЗаказ отменён.
limit.expiringлимит (limit из аккаунта)До конца личного лимита зрителей осталось не больше срока предупреждения. Когда лимит истечёт, зрители на каналах остановятся.
api_key.expiringключ APIДо конца срока ключа API осталось не больше срока предупреждения. Когда срок выйдет, запросы с ключом перестанут приниматься.

Новые типы могут появляться в рамках версии. Событие незнакомого типа пропускайте.

Событие

{
  "id": "evt_1024",
  "type": "run.stopped",
  "object_type": "run",
  "created_at": "2026-09-30T12:00:00.000Z",
  "data": {
    "object": {
      "id": "run_345",
      "channel_id": "ch_12",
      "channel_name": "example_channel",
      "platform": "twitch",
      "status": "stopped",
      "stop_reason": "duration_elapsed",
      "viewers": 20,
      "started_at": "2026-09-30T08:00:00.000Z",
      "stopped_at": "2026-09-30T12:00:00.000Z",
      "duration_seconds": 14400
    }
  }
}
ПолеЧто содержит
idИдентификатор события. По нему повтор одного события отличают от нового
typeТип события
object_typeВид объекта в data.object: run, order, limit, api_key
created_atКогда событие случилось
data.objectОбъект в том же виде, что в ответе на его запрос: запуск — как в GET /runs, заказ — как в GET /orders/{id}

Статус объекта в событии — на момент события; прочие поля — на момент, когда событие появилось в списке, через несколько секунд после него. К тому времени, когда событие прочитано, объект мог измениться: например, запуск, вышедший на канал, уже ждёт следующего эфира. Текущее состояние возвращает запрос самого объекта.

Чтение списком

GET /events возвращает события от новых к старым в порядке их появления в списке, постранично; параметр type оставляет события одного типа. Одно событие — GET /events/{id}.

Событие, появившееся в списке позже, всегда стоит в нём раньше. Поэтому, чтобы обрабатывать события списком, достаточно запоминать id последнего обработанного события: читайте страницы от начала, пока не встретите его, и обрабатывайте прочитанное от старых к новым. Если это событие уже удалено по сроку хранения, starting_after с ним вернёт 404 resource_missing — читайте список с начала.

async function newEvents(lastSeenId) {
  const fresh = [];
  let after;
  while (true) {
    const url = new URL("https://api.skystream.su/app/v1/events");
    url.searchParams.set("limit", "100");
    if (after) url.searchParams.set("starting_after", after);
    const response = await fetch(url, {
      headers: { Authorization: `Bearer ${process.env.API_KEY}` },
    });
    const page = await response.json();
    for (const event of page.data) {
      if (event.id === lastSeenId) return fresh.reverse();
      fresh.push(event);
    }
    if (!page.has_more) return fresh.reverse();
    after = page.data[page.data.length - 1].id;
  }
}

Порядок и повторы

  • Событие появляется в списке через несколько секунд после того, что оно описывает.
  • События одного объекта идут в том порядке, в каком случились. События разных объектов, случившиеся почти одновременно, могут появиться в списке в другом порядке: время события — в created_at.
  • Обрабатывайте событие так, чтобы повторная обработка ничего не ломала: запоминайте id обработанных событий.

На этой странице