Genie
Documentation

Async jobs & polling

Universal async pattern: submit with mode='async', get a job id back, poll /v1/jobs/:id (or receive a webhook on completion). Same shape across chat, image, and video generation.

Why async

  • Long jobs. Reasoning model on a 100K-token corpus, large image batches, video gen. Sync exhausts HTTP timeouts.
  • Batch fans. Submit 1000 jobs in 1000 requests, poll in parallel. No connection-holding cost.
  • Pipelines. Fire-and-forget with a webhook on terminal status — no client-side polling at all.

Mode by endpoint

Endpoint                                 Modes supported              Default
POST /v1/chat/completions                sync · stream · async        sync
POST /v1/images/generations              sync · async                 sync
POST /v1/videos/generations              async (only)                 async
                                         (sync would always
                                          time out — gen takes
                                          10–60s wall-clock)

Submit + poll

# Submit async
JOB_ID=$(curl https://api.genie.tech/v1/chat/completions \
  -H "Authorization: Bearer $GENIE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"mode":"async","model":"qwen3:14b","messages":[...]}' \
  | jq -r .id)

# Poll until terminal
while true; do
  STATUS=$(curl -s "https://api.genie.tech/v1/jobs/${JOB_ID#chatcmpl-}" \
    -H "Authorization: Bearer $GENIE_API_KEY" | jq -r .status)
  case "$STATUS" in
    completed) echo "done"; break ;;
    failed) echo "failed"; exit 1 ;;
    *) sleep 2 ;;
  esac
done

Async response shape

Every async submission returns 202 with the same shape:

{
  "id": "chatcmpl-cmoz...",
  "object": "chat.completion.async",
  "status": "queued",
  "polling_url": "/api/v1/jobs/cmoz...",
  "created": 1731020000
}

Job poll endpoint

GET /v1/jobs/:id returns the job's current status + result if terminal:

{
  "id": "chatcmpl-cmoz...",
  "status": "completed",
  "result": {
    "id": "chatcmpl-cmoz...",
    "object": "chat.completion",
    "choices": [{ "message": { "role": "assistant", "content": "..." } }],
    "usage": { "prompt_tokens": 12, "completion_tokens": 28, "total_tokens": 40 }
  }
}

Status values: queued · running · completed · failed · cancelled · timeout.

Webhook delivery

Supply webhook: { url, secret } in the submit body and Genie POSTs the completed-job body to your URL when it hits a terminal state. Signed with HMAC-SHA256 inX-Genie-Signature. See Webhooks.

Idempotency. The job id is stable across retries. If your client crashes mid-poll, resume by calling GET /v1/jobs/:id with the same id — no duplicate billing, no duplicate work.