Layers
Partner APIAPI referenceContent

GET /v1/content/:containerId/progress

Fine-grained generation progress on a container. Prefer GET /v1/jobs/:id for most uses.

View as Markdown
GET/v1/content/:containerId/progress
Phase 1stable
Auth
Bearer
Scope
content:read

Returns the container's generation progress at a finer grain than GET /v1/content/:containerId. Meant for progress bars in end-customer UIs where you want to update a percentage or a status line every couple seconds without repeatedly pulling the whole container record.

For most programmatic work, GET /v1/jobs/:jobId is what you want. Use this endpoint when you don't have a jobId handy — for example, you're reading from a list of containers and need per-container status without a separate lookup.

Path parameters

  • containerId
    string (uuid)required
    The container id.

Request

terminal
curl https://api.layers.com/v1/content/{containerId}/progress \
  -H "X-Api-Key: $LAYERS_API_KEY"
progress.ts
const res = await fetch(
  `https://api.layers.com/v1/content/${containerId}/progress`,
  { headers: { 'X-Api-Key': process.env.LAYERS_API_KEY! } },
);
const progress = await res.json();
progress.py
import os, httpx

r = httpx.get(
    f"https://api.layers.com/v1/content/{container_id}/progress",
    headers={"X-Api-Key": os.environ["LAYERS_API_KEY"]},
)
progress = r.json()

Responses

200Current progress snapshot.
{
  "containerId": "cnt_01HXZ9...",
  "status": "generating",
  "stage": "generating_visuals",
  "stageProgress": 0.42,
  "etaSeconds": 38,
  "updatedAt": "2026-04-18T09:30:04Z"
}
200Terminal — completed.
{
  "containerId": "cnt_01HXZ9...",
  "status": "completed",
  "stage": "finalizing",
  "stageProgress": 1.0,
  "etaSeconds": null,
  "updatedAt": "2026-04-18T09:32:11Z"
}
200Terminal — failed. The container's lastError field has the code.
{
  "containerId": "cnt_01HXZ9...",
  "status": "failed",
  "stage": "generating_visuals",
  "stageProgress": 0.3,
  "etaSeconds": null,
  "updatedAt": "2026-04-18T09:30:41Z"
}

Field semantics

  • stageProgress is a 0.0–1.0 float. For multi-stage jobs, it resets to 0 at each stage transition rather than advancing monotonically across stages.
  • etaSeconds is a best-effort estimate. May be null when the stage doesn't have a historical baseline (fresh project, unusual format).
  • status mirrors the container status — queued, generating, completed, failed, or canceled.

Polling cadence

Two seconds is a sane default for user-facing progress bars. Back off to five seconds if the container sits on the same stage for more than 30 seconds — this is usually the generating_visuals stage, which can take minutes. Don't poll faster than once per second.

If you're running an agent that just needs to know "done or not", poll GET /v1/jobs/:jobId at the job level instead. It's the same data shape for every job kind, so one poll loop covers every async call in the API.

Errors

CodeWhen
NOT_FOUNDContainer id not in this org.
FORBIDDEN_SCOPEKey lacks content:read.

See also

On this page