---
title: "Read background tasks with safe stage and saved asset progress."
method: GET
path: "/background-activity"
tags: ["Jobs"]
---

# Read background tasks with safe stage and saved asset progress.

`GET /background-activity`

## Request

- Base URL: `https://docs.sleeperhit.studio/api/v1`
- URL: `https://docs.sleeperhit.studio/api/v1/background-activity`
- Auth: HTTP bearer

Returns owned queued, running and retrying work plus jobs finished in the last ten minutes, each with `projectId` and `projectName` when it works for one of your projects. Optional episode context and completed/total asset progress enrich casting tasks. A deck's or a trailer's tasks are named with what they work on ("Stitching <deck> · 1:30", "Scoring <deck>'s plan (judgment 2 of up to 3)", "Watching <deck>'s preview cut"); an assembly carries its step as `detail` and the chapters or beats joined as `progress` (`unit`: `chapters` / `beats`). Renders, coverage and queued chat tasks are checked against their own owned record, so a render whose story job failed reads `failed` (with `queueState: completed` and the record's `failureReason`), never completed. A task the queue is holding for later (a provider backoff or retry delay) carries `nextAttemptAt`; it is scheduled, not stuck. The same list the app's activity indicator, MCP background_activity and the in-app assistant read. Read-only: never initializes workers, starts work, retries jobs, or exposes raw payloads and provider output.

## Response `200`

Owned background activity.

- object
  - `jobs` BackgroundActivity[], required
    - `id` string, required
    - `kind` string, required: The job's kind, its queue name (`story-plan-generate`, `series-bible-generate`). For code: show people `label`.
    - `label` string, required: What the task is doing, what is ready, or what failed, in plain words: "Planning the next episode" while it runs, "The next episode's plan is ready" once it finished, "Planning the next episode failed". Never names the project (that is `projectName`). The same words a story job carries as `label` on GET /story-jobs.
    - `summary` string, required: The task in one short line, the same line the app's activity bar shows: what is happening and how far along it is ("Stitching the trailer · 45%", "The Series Bible is ready"). The step and stage stay in `detail`.
    - `link` object: Present on a finished or failed task that has a place to go: the result, or where a failure is tried again. One link, never more.
      - `href` string, required: An app path on this site, such as `/dashboard/writing-lab/<project>/videos`.
      - `label` string, required: What the link says: "Open the project", "Open videos to try again".
    - `state` 'created' | 'active' | 'retry' | 'completed' | 'failed' | 'cancelled', required: The task's outcome. For renders (StoryJob), coverage and queued chat tasks it is checked against the task's own record: a render whose StoryJob FAILED reads failed even though the queue finished it, and one the queue finished while its record is still running reads active.
    - `retryCount` integer, required
    - `createdAt` string, date-time, required
    - `detail` string: Safe display stage from durable job state, when available. Never a provider error or raw payload.
    - `contextLabel` string: Ownership-checked episode title and version, the source label for a source task, or what a render makes, when available. The project is projectName.
    - `projectId` string: The owned, live project the task works for, when it works for one: read from the source, plan, render, coverage report, queued chat task, deck or trailer job, or screenplay it works on.
    - `projectName` string: That project's name, present with projectId, so a list shown on one project's page can say which tasks belong to another.
    - `progress` object
      - `completed` integer, required
      - `total` integer, required
      - `unit` 'assets' | 'sections' | 'chapters' | 'beats', required: assets for casting, sections for screenplay parsing, chapters or beats joined by a deck's or a trailer's assembly.
    - `percent` integer: How far along the whole task is, when it knows more than `progress` says: a deck's or a trailer's assembly across all its steps. Only climbs while the task runs.
    - `queueState` 'created' | 'active' | 'retry' | 'completed' | 'failed' | 'cancelled': The queue's own state, present only when the task's own record settled it otherwise.
    - `failureReason` string: Why the task failed, was cancelled or is retrying, from its own record (the same message the page that owns it shows), when the record gives one. Studio setup problems read as one plain statement. Never raw queue output.
    - `storyJobId` string: The owned story job a render works on.
    - `storyJobStatus` 'PENDING' | 'RESERVED' | 'RUNNING' | 'PARTIAL' | 'READY' | 'FAILED' | 'CANCELED': Lifecycle of a queued artifact-generation job. `RESERVED` means credits are held; when progress.stage is `provider_backoff`, Sleeper Hit has scheduled a delayed retry and clients should continue polling. `PARTIAL` means at least one artifact is READY while others are still running; `READY` is fully complete. Cancelable while `PENDING` or `RESERVED`, or `FAILED` before it ever started (canceling that one means it can no longer be resumed); a `RUNNING` job, and a `FAILED` job that had started generating, cannot be canceled. `CANCELED` is final.
    - `storyJobRunStale` boolean: Present with storyJobStatus: true when that story job is a RUNNING table read whose worker stopped answering (its `runStale`). POST /story-jobs/{jobId}/resume sends its run again from the last checkpoint at no new cost.
    - `chatToolJobId` string: The owned queued chat task, the id its chat tool answered with.
    - `toolName` string: The chat tool the queued task runs.
    - `toolJobStatus` string: The queued chat task's own status (pending, completed, failed).
    - `nextAttemptAt` string, date-time: Present while the queue is holding a queued or retrying task until a later time (a provider backoff, a retry delay, work scheduled for later): the earliest its next attempt can start. A task waiting for this time is scheduled, not stuck.
    - `providerRetryAttempt` integer: Which provider-backoff retry this run is (the fifth is 5), when the task was rescheduled because its model provider was unavailable.

## Other responses

- `401`: Missing, malformed, revoked, or expired API key.
- `403`: API key is valid but lacks the scope, is blocked by IP allowlist, or the account is disabled.
- `429`: Rate limit for this API key + IP + route family was exceeded.
- `500`: The API failed unexpectedly. Safe to retry with the same Idempotency-Key.

---

[API](https://skmtc.dev/sleeperhit/apis/sleeper-hit-studio-story-api.md) · [All operations](https://skmtc.dev/sleeperhit/apis/sleeper-hit-studio-story-api/llms.txt) · [OpenAPI document](https://skmtc.dev/sleeperhit/apis/sleeper-hit-studio-story-api/revisions/64c1102ccb2f?raw)
