Batch API job finished
The Batch API (OpenAI, Anthropic) is cheaper than a regular call but runs
asynchronously — from minutes to 24 hours. All that time the job hangs in
in_progress, and refreshing the dashboard by hand is pointless. It’s far
handier to get a push exactly when it becomes completed or failed, and with
a “how many requests passed, how many failed” breakdown.
Option 1: poll status → push
Section titled “Option 1: poll status → push”A small worker polls the status once a minute and sends an alert on transition to a terminal state:
import os, time, requestsimport openai
NOTIFLY_URL = os.environ["NOTIFLY_URL"]NOTIFLY_TOKEN = os.environ["NOTIFLY_TOKEN"]POLL_SEC = 60
client = openai.OpenAI()
def notify(title, msg, prio): requests.post(f"{NOTIFLY_URL}/message", params={"token": NOTIFLY_TOKEN}, json={"title": title, "message": msg, "priority": prio}, timeout=5)
def watch_batch(batch_id): """Poll the job until it finishes; then push a summary.""" while True: b = client.batches.retrieve(batch_id) if b.status in ("completed", "failed", "expired", "cancelled"): counts = b.request_counts # .completed / .failed / .total if b.status == "completed" and counts.failed == 0: notify( f"✅ Batch готов: {counts.completed} запросов", f"Джоба {batch_id} завершилась без ошибок.", priority=5, ) else: notify( f"⚠️ Batch {b.status}: {counts.failed} ошибок", f"Готово {counts.completed}/{counts.total}, " f"ошибок {counts.failed}. Проверьте error_file_id.", priority=8, ) return b.status time.sleep(POLL_SEC)
# usage: submitted a batch and watching itbatch = client.batches.create( input_file_id="file-abc", endpoint="/v1/chat/completions", completion_window="24h")watch_batch(batch.id)Success with no errors is a quiet priority=5 (look at it when convenient);
any failed or a failed/expired status is a loud priority=8, because part
of the data came up short. request_counts saves you from downloading the
result just to gauge the scale.
Option 2: don’t hold a process — cron/YC function
Section titled “Option 2: don’t hold a process — cron/YC function”If you don’t want to keep a worker alive for a day, move the polling into a
scheduled function on Yandex Cloud with a timer-trigger. Keep the list of
active batch_ids in a file/YDB, check statuses on each tick, and cross off
the finished ones. A ready skeleton is in the recipe
Custom cloud function for integrity checks:
the same handler, only instead of /health it calls client.batches.retrieve.
Option 3: provider webhook → Webhook Router
Section titled “Option 3: provider webhook → Webhook Router”If the provider can send a webhook on batch completion (OpenAI supports this),
you don’t need polling at all. Point the webhook at the
Webhook Router — it will turn the batch.completed
event into a push instantly, without a single status poll.
What to put in the alert text
Section titled “What to put in the alert text”- the
batch_idand final status (completed/failed/expired); - the
completed/failed/totalbreakdown; - the
error_file_idif there were errors — to go straight for details; - how long the job ran (useful for planning the next one).