Обход из пяти страниц занимает секунды, обход из двухсот — минуты. Держать соединение открытым всё это время бессмысленно: посредники рвут долгие запросы, а клиентские библиотеки закрывают их по своему таймауту. Поэтому режима два — и переключается он сам, по величине заказа.
Исполнитель в обоих случаях один и тот же. Синхронный обход — не «облегчённый режим»: то же задание, та же очередь, тот же счёт. Разница только в том, дожидаемся мы его в соединении или нет.
async: true просит идентификатор даже на маленьком обходе. Это удобно, когда обходы ставятся пачкой и ждать каждый по очереди незачем.

Что приходит

string
Идентификатор задания. По нему смотрят ход, забирают страницы и отменяют.
string
Где задание сейчас. Значения — в таблице ниже.
string
Машиночитаемая причина, когда задание закончилось не по-хорошему. У благополучного обхода — пустая строка.
string
То же самое человеческим языком: чего не хватило, где остановились, почему часть страниц не взялась.
integer
Заказанный потолок — то же число, что вы передали в pages. Не обещание: ссылки могут кончиться раньше.
integer
Сколько страниц вправду пройдено. Растёт по ходу и по нему же считается счёт.
integer
Сколько страниц не взялись. Обход из-за них не останавливается: чужой сайт время от времени отдаёт 502, и терять из-за одной страницы остальные девяносто девять было бы глупо.
integer
Списано на данный момент. По ходу задания растёт.
integer
Во сколько обойдётся обход, если пройдёт все pages_planned страниц. Именно эту сумму проверяют на балансе до старта — см. Цена обхода.
array
Срез результата. Каждый элемент — ровно ответ Fetch: {"fetch_metadata": {…}, "parsed": {…}}.
integer | null
Смещение следующего среза. null означает, что дальше ничего нет — на этот момент.

Статусы

Первые два — незавершённые, остальные четыре — окончательные: после них finished_at заполнен и pages_done больше не меняется.
Список статусов расширяется только добавлением. Ветвитесь на «закончено — это не queued и не running», а не перечислением четырёх окончательных: тогда новое значение не сломает ваш код.

Опрос

Тот же цикл, написанный за вас, — crawl_wait: он опрашивает задание сам и возвращается, когда статус стал окончательным.
Опрашивайте раз в несколько секунд, а не в цикле без паузы. Опрос — обычный запрос к API и считается в rpm; сотня опросов в минуту исчерпает частотный предел раньше, чем обход дойдёт до середины.

Забрать страницы

Двести страниц с разметкой — это десятки мегабайт, и отдавать их одним куском неразумно. Поэтому страницы приходят срезами: offset — с какой начинать, limit — сколько взять, до 200 за раз. GET /v1/crawl/{job_id} отдаёт метаданные вместе со срезом, GET /v1/crawl/{job_id}/pages — только страницы, без метаданных и эха правила. Второе удобнее в цикле выкачивания: ответ меньше и в нём нет повторяющегося.
Страницы доступны по мере готовности, а не только в конце: у идущего задания уже пройденное можно забирать и обрабатывать, не дожидаясь остальных. next_offset: null у running означает «на сейчас всё», а не «больше не будет».

Отмена

POST /v1/crawl/{job_id}/cancel останавливает задание.
Отмена срабатывает на границе страницы, а не мгновенно: начатую страницу не выбрасывают. Браузер за неё уже сходил, кредиты уже потрачены, и выкидывать готовый результат ради красивой мгновенности значило бы выкидывать ваши деньги. Поэтому между просьбой и статусом canceled может пройти несколько секунд, и pages_done за это время подрастёт на единицу. Всё, что успело пройти, остаётся доступным: отменённое задание читается и отдаёт страницы так же, как завершённое. Отмена уже законченного — 409 already_finished. Это не ошибка вашего кода, а обычная гонка: задание закончилось, пока просьба шла. Достаточно перечитать статус.

Список заданий

GET /v1/crawl?limit= показывает ваши задания, свежие сверху.
Нужно это чаще всего в одном случае: код упал, идентификатор потерялся, а задание идёт и тратит кредиты. Здесь его видно и отсюда его можно отменить.

Задание переживает перезапуск

Задания живут в хранилище, а не в памяти процесса. Перезапуск сервиса их не теряет: queued дождётся своей очереди, running продолжится с того места, где остановился. Брошенное задание — то, чей исполнитель не вернулся, — возвращается в очередь автоматически, без вашего участия. Обратная сторона: если хранилище заданий недоступно, обход не принимается вовсе — 503 service_unavailable. Принять задание и потерять его было бы хуже, чем честно отказать.

Дальше

Правило обхода

Из чего складывается маршрут и как его сузить.

Цена обхода

Откуда берётся credits_max и за что списывают по факту.

Ошибки

already_finished, not_found, service_unavailable и остальные.

Справочник

Ручки состояния, страниц и отмены.