---
title: "Re-render against an existing renderJob's snapshot"
method: POST
path: "/v1/projects/{id}/renders/{renderId}/retry"
tags: ["renders"]
---

# Re-render against an existing renderJob's snapshot

`POST /v1/projects/{id}/renders/{renderId}/retry`

## Request

- Base URL: `https://api.cueframe.ai`
- URL: `https://api.cueframe.ai/v1/projects/{id}/renders/{renderId}/retry`
- Auth: one of:
  - HTTP bearer
  - OAuth 2 (authorization code, authorization URL `https://api.cueframe.ai/api/auth/mcp/authorize`, token URL `https://api.cueframe.ai/api/auth/mcp/token`, scopes: `renders:write`)
  - API key in header `PAYMENT-SIGNATURE`

Required permission: renders:write

## Path parameters

- `id` string, required
- `renderId` string, required

## Response `201`

Retry queued — returns a NEW renderJob with status=queued.

- RenderResponse: Render job response per §Renders.
  - `id` string, required
  - `status` 'queued' | 'pending' | 'rendering' | 'complete' | 'error' | 'cancelled', required
  - `progress` RenderProgress: Non-terminal render progress; phase is one of the worker's emitted stages.
    - `phase` 'queued' | 'validating' | 'presigning' | 'collecting-artifacts' | 'resolving' | 'detecting' | 'baking-matte' | 'translating' | 'spawning' | 'encoding' | 'uploading', required
    - `percent` number, required
    - `scenesCompleted` integer
    - `scenesTotal` integer
  - `outputUrl` string, nullable, required
  - `outputExpiresAt` string, nullable, required
  - `error` string, nullable, required: Human-readable failure message. Pair with `errorCode` for a stable, machine-readable code an agent runner can branch on.
  - `errorCode` string, nullable, required: Stable, machine-readable error code (e.g. `render_pipeline_unavailable`, `render_route_missing`, `render_pipeline_failed`). Null when status is not `error` or unavailable for an older render.
  - `errorDetails` object, nullable, required: Structured failure context — `{ targetUrl?, upstreamStatus?, upstreamCode?, attemptedAt? }`. Surfaced so agent runners can distinguish operator-config issues from upstream-down vs route-missing without parsing `error`.
  - `category` 'authoring' | 'transient' | 'internal', nullable, required: `authoring` = deterministic defect in YOUR composition/request — fix it, retrying is futile; `transient` = temporary pipeline/infra failure — safe to retry; `internal` = unexpected server fault — retry once then escalate.
  - `retryable` boolean, nullable, required: Whether re-attempting the SAME render can succeed (status `error`); null otherwise. true → call retry_render. false → deterministic (category authoring/internal); fix the composition first — retry_render alone reproduces it. Mirrors the render.failed webhook's `retryable`.
  - `createdAt` string, required
  - `updatedAt` string, required: ISO-8601 timestamp of the render's most recent progress update. Compute staleness = now − updatedAt to distinguish a wedged render from a slow one and decide whether to wait, cancel, or retry.
  - `compositionId` string, nullable, required: The composition this render froze at create time (the project's active one, or the compositionId the request named). Null on renders minted before this was recorded.
  - `format` Format, required
    - `aspectRatio` '16:9' | '9:16' | '1:1' | '4:5', required
    - `fps` union
      - 24
      - 25
      - 30
      - 60
    - `resolution` 'hd' | 'fhd' | '4k'
    - `platform` string
  - `engine` 'hyperframes' | 'remotion', nullable, required: The render engine the row was minted for. Null on rows minted before the engine was recorded.
  - `completedAt` string, nullable, required: ISO-8601 instant the render reached its terminal status (complete, error or cancelled); null while it runs. Pair with createdAt for the wall time.
  - `outputDurationSec` number, nullable, required: The output's length in seconds (the composition timeline's, or the preview window's), as billed. Null on legacy rows.
  - `preview` object, nullable, required: The scoped preview window when this is a preview_clip render; null for a full deliverable.
    - `fromSec` number, required
    - `toSec` number, required
  - `listUsd` number: A2 money stamp: the metered event's LIST price (USD), stamped at the success terminal (exports for deliverable renders, compose_capture for A8 previews). A plan allowance may zero the actual invoice line — this is the list price, never a Stripe charge. Absent while running, on failure, and for x402 orgs (on-chain receipts). Mirrors the get_usage ledger.
  - `warnings` string[]: Non-fatal advisories surfaced at render-CREATE (omitted when none, and on GET — create-time only).

## Other responses

- `400`: Bad request — validation_error / invalid_cursor / invalid_query.
- `401`: Missing or invalid Authorization header.
- `402`: Payment required. Returned when the caller presents no API key on a priced operation: the body AND the `Payment-Required` header carry the x402 v2 challenge (accepted scheme, network, USDC asset, amount, payTo). Sign the EIP-3009 authorization and retry with a `PAYMENT-SIGNATURE` header. A KEYED caller sees this status instead when their plan lacks or has exhausted the feature (`billing_required`).
- `403`: Forbidden — permission insufficient.
- `404`: Resource not found.
- `409`: Conflict — stale_etag / idempotency_conflict / suggestions_already_complete.
- `422`: Unprocessable — invalid_composition / media_in_use / session_in_use / render_not_cancellable.
- `429`: Rate limited. Retry-After header present.
- `500`: Internal error.
- `503`: Service unavailable — billing_unavailable / honest-503 for runtime deps.

---

[API](https://skmtc.dev/cueframe/apis/cueframe-api.md) · [All operations](https://skmtc.dev/cueframe/apis/cueframe-api/llms.txt) · [OpenAPI document](https://skmtc.dev/cueframe/apis/cueframe-api/revisions/8f9bfe362b4a?raw)
