---
title: "Publish a finished trailer: its public watch page goes live."
method: POST
path: "/trailers/{jobId}/publish"
tags: ["Trailer"]
---

# Publish a finished trailer: its public watch page goes live.

`POST /trailers/{jobId}/publish`

## Request

- Base URL: `https://docs.sleeperhit.studio/api/v1`
- URL: `https://docs.sleeperhit.studio/api/v1/trailers/{jobId}/publish`
- Auth: HTTP bearer

Publish a finished trailer: its public watch page goes live at the writer's public slug. ONLY A `complete` TRAILER PUBLISHES — anything else is refused and nothing is written. The watch page is screened for outbound safety first (a held account publishes nothing). A share token is minted when the trailer has none, and a master that is missing, idle, stale or failed is re-assembled. TWO PHASES: a body without `confirmed: true` changes NOTHING and answers a preview (`TrailerSharePreview`) naming the exact watch link a publish would mint; with `confirmed: true` it publishes and answers `TrailerPublish`. A finished trailer publishes to a public watch page at the writer's slug (/{writer}/trailers/{token}): the finished master, a title and a poster, nothing to edit, unlisted (never indexed). Only a `complete` trailer publishes; a share token is minted when the trailer has none and cleared on unpublish, which takes the link down to 404. Publishing and unpublishing are each two-phase — without `confirmed: true` the call changes nothing and answers a preview (the watch link a publish would mint, or the link an unpublish would darken) — and neither is metered. Requires `Idempotency-Key`. Scope: `story:write`.

## Headers

- `Idempotency-Key` string, required

## Request body

- TrailerShareConfirmBody: The publish or unpublish gate. Omit `confirmed` (or send false) for the preview — the call changes nothing and answers `TrailerSharePreview`. Send `confirmed: true` to act.
  - `confirmed` boolean: Omit (or false) to see what the act would do WITHOUT doing it. Pass true only after the writer has seen that and said so in their own words.

## Response `200`

With `confirmed: true`, the published trailer (relay its `shareUrl` verbatim); without it, the preview naming the link a publish would mint.

- TrailerPublish: A published trailer: its full watch link (relay it verbatim), its share token and slug, and the master's state after publishing. Answered only by a call that carried `confirmed: true`.
  - `shareToken` string, required: The trailer's share token — the `t` in its public watch link. `shareUrl` is the same link already assembled; use it, not this.
  - `writerSlug` string, required: The writer's public slug, where the shared trailer lives.
  - `shareUrl` string, required: The trailer's full public watch link, built server-side. Give it to the user verbatim — never rebuild it from the token and slug.
  - `renderedVideoStatus` string, required: The master's state after publishing: a missing, idle, stale or failed master is re-assembled.

## Other responses

- `400`: Request payload failed validation. The error message names the offending field.
- `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.
- `404`: The named project or source does not exist or is owned by another account.
- `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)
