Jobs

Long-running work — whole-book writes, batch narration, audiobook export — runs as a background job. Poll these endpoints, or register a webhook for job.succeeded / job.failed instead. PDF renders have their own poll endpoint (/books/{bookId}/production-jobs/{jobId}, see Production).

List jobs

GET/v1/jobsscope: account:read

Newest first. Query parameters:

ParamTypeNotes
statusall | active | finishedactive = queued or running; finished = succeeded, failed or cancelled. Default all.
bookIduuidOnly this book’s jobs.
limit1–50Default 20.

A book-scoped key only sees jobs on its allowlisted books; asking for another book returns an empty list rather than a 403.

{
  "data": [
    { "id": "6c1e…", "kind": "narrateBook", "status": "running", "bookId": "8f1c…",
      "progress": "Narrating chapter 4 of 12…", "startedAt": "2026-11-02T09:01:00.000Z",
      "finishedAt": null, "error": null }
  ]
}

Poll one job

GET/v1/jobs/{jobId}scope: account:read

Same fields as the list, plus result (kind-specific, e.g. { audiobookUrl, sizeBytes }). Unknown ids — and jobs on books a scoped key can’t see — return 404.

Cancel a book-generation run

POST/v1/books/{bookId}/cancelscope: books:write

Cancels the active whole-book generation workflow for the book, reverts its status, and refunds the credits for chapters that were not yet written. Idempotent: returns ok: true even when nothing was running.

{ "data": { "ok": true, "cancelled": true, "refundedCredits": 14 } }