{"manifestVersion":1,"name":"Sleeper Hit Studio","summary":"A story-creation and production workspace for developing, writing, performing, packaging, and publishing narrative work.","ideaFirstPrompt":"Start from an initial premise, notes, research, or an existing screenplay. An existing screenplay is not required.","api":{"version":"v1","status":"foundation"},"canonicalUrl":"https://sleeperhit.studio/capabilities.json","access":{"accountRequired":true,"signupMode":"open","signupUrl":"https://sleeperhit.studio/signup","loginUrl":"https://sleeperhit.studio/login","intents":[{"id":"business","label":"Business and brand storytelling","audience":"Companies, agencies, and brand or marketing teams producing narrative work.","url":"https://sleeperhit.studio/signup?intent=business"},{"id":"creator","label":"Independent creator","audience":"Solo creators and small studios publishing their own shows, podcasts, and short-form video.","url":"https://sleeperhit.studio/signup?intent=creator"},{"id":"writer","label":"Screenwriter","audience":"Screenwriters developing scripts, pilots, features, and pitch material.","url":"https://sleeperhit.studio/signup?intent=writer"}],"withoutAccount":["Search opted-in creator profiles, project summaries, and creator-approved public assets through the public MCP server or the public discovery API.","Read every published contract: the capability manifest, OpenAPI spec, docs site, llms.txt, and the CLI and MCP tool maps.","Open public share links (table reads, pitch decks, trailers) a creator has already published."],"withAccount":["Create story projects, attach source material, and develop a project Series Bible.","Plan, generate, and revise screenplay installments, table reads, pitch decks, and trailers.","Spend Studio Credits on generation, rendering, casting, scoring, and finalization.","Publish durable releases to the first-party RSS feed and connected destinations."],"publicMcpUrl":"https://sleeperhit.studio/api/mcp","authenticatedMcpUrl":"https://sleeperhit.studio/mcp","capabilityManifestUrl":"https://sleeperhit.studio/capabilities.json","legal":{"termsUrl":"https://sleeperhit.studio/terms","privacyUrl":"https://sleeperhit.studio/privacy","minimumAge":18,"statement":"I am 18 or older, and I agree to the Terms of Service and Privacy Policy."},"note":"Anyone 18 or older can create a Sleeper Hit account at the signup link, where they confirm their age and accept the Terms of Service and Privacy Policy. An email-and-password signup then confirms its address from the link emailed to it before it can sign in (a Google signup needs no extra step). An agent cannot create an account or accept the Terms on a user's behalf: hand the human the signup link that matches their intent and stop there.","agentSetup":{"heading":"If you are an agent setting this up","steps":["Never run the OAuth login (for example `codex mcp login`) inside a sandboxed shell. The browser cannot reach the sandbox's localhost callback, so the person approves and no token ever arrives.","When you are sandboxed, use a Sleeper Hit API key as a bearer token instead. The writer creates the key at https://sleeperhit.studio/dashboard/api (Developers → API Keys) and sets it as SLEEPERHIT_API_KEY. Then run: `codex mcp add sleeperhit --url https://sleeperhit.studio/mcp --bearer-token-env-var SLEEPERHIT_API_KEY`","Verify with the `whoami` tool. It answers `source: \"api_key\"` and the key's scopes; to create and generate, the key needs story:write and source:write."],"apiKeyUrl":"https://sleeperhit.studio/dashboard/api","apiKeyGuideUrl":"https://sleeperhit.studio/mcp#api-key","apiKeyEnvVar":"SLEEPERHIT_API_KEY","bearerTokenCommands":{"codex":"codex mcp add sleeperhit --url https://sleeperhit.studio/mcp --bearer-token-env-var SLEEPERHIT_API_KEY","claudeCode":"claude mcp add --transport http sleeperhit https://sleeperhit.studio/mcp --header \"Authorization: Bearer $SLEEPERHIT_API_KEY\""},"verifyTool":"whoami"}},"surfaces":{"mcpAuthenticated":{"role":"Full story-development and production access","transport":"streamable-http","url":"https://sleeperhit.studio/mcp","auth":{"accountRequired":true,"type":"oauth2.1","scopes":["story:read","story:write","source:read","source:write","artifact:read","artifact:publish","publishing:read","publishing:write","publishing:publish","publishing:connect","publishing:analytics","credits:read","webhook:write","account:read","account:write"],"discoveryScopes":["openid","profile","email","offline_access","story:read","story:write","source:read","source:write","artifact:read","artifact:publish","publishing:read","publishing:write","publishing:publish","publishing:connect","publishing:analytics","credits:read","webhook:write","account:read","account:write"],"protectedResourceMetadataUrl":"https://sleeperhit.studio/.well-known/oauth-protected-resource","authorizationServerMetadataUrl":"https://sleeperhit.studio/.well-known/oauth-authorization-server"},"recommendedStartTools":["whoami","get_agent_guidance","get_credits"],"workflowGroups":[{"id":"orientation-account","title":"Orientation and account","summary":"Confirm the connected identity and load live backend guidance before choosing a workflow.","startWith":["whoami","get_agent_guidance"],"cost":"none","intent":"routine"},{"id":"credits-usage","title":"Credits and usage","summary":"Check the available Studio Credit balance before any generation or rendering work.","startWith":["get_credits"],"cost":"none","intent":"routine"},{"id":"account-data","title":"Your data: download it, or delete the account","summary":"Only when the writer asks: build \"Download my data\" and hand them the link; or show what deleting removes and the credit balance, schedule the deletion, or cancel it.","startWith":["get_account_export","get_account_deletion"],"cost":"none","intent":"explicit-user-intent"},{"id":"projects-sources","title":"Projects and source material","summary":"Create or resume a project and ground it in notes, URLs, PDFs, research, or an existing script.","startWith":["list_projects","create_project"],"cost":"inspect-first","intent":"explicit-user-intent"},{"id":"series-bible-development","title":"Series Bible and development","summary":"Establish canon, format, characters, world, episode architecture, and foundational coverage.","startWith":["get_series_bible","get_mood_board","get_cast_canon"],"cost":"credits","intent":"confirm-expensive-work"},{"id":"planning-screenwriting","title":"Planning and screenwriting","summary":"Create a reviewable plan, generate an installment, inspect real pages, and revise the same artifact.","startWith":["create_plan","get_plan"],"cost":"credits","intent":"confirm-expensive-work"},{"id":"pitch-deck-rendering","title":"Pitch deck rendering","summary":"Approve a pitch deck plan into a priced 480p render, review and choose takes chapter by chapter, then finish the deck at 720p (or 1080p) and export it.","startWith":["get_pitch_deck_chapters","approve_pitch_deck_plan"],"cost":"credits","intent":"confirm-expensive-work"},{"id":"trailer-rendering","title":"Trailer rendering","summary":"Approve a trailer plan into a priced 480p render, review and choose takes, then finish the cut at 720p (or 1080p) and export it.","startWith":["get_trailer_beats","approve_trailer_plan"],"cost":"credits","intent":"confirm-expensive-work"},{"id":"table-reads-audio","title":"Table reads and audio","summary":"Cast, perform, score, add effects, and create durable audio from a screenplay-backed table read.","startWith":["get_cast","get_table_read_script"],"cost":"credits","intent":"confirm-expensive-work"},{"id":"video-rendering","title":"Video rendering","summary":"Direct theater motion and render a durable video from a reviewed artifact.","startWith":["get_artifact","direct_theater_motion_beat"],"cost":"credits","intent":"confirm-expensive-work"},{"id":"coverage-revision","title":"Coverage and revision","summary":"Read existing coverage first, request analysis when needed, and revise before final packaging.","startWith":["get_coverage","get_brand_coverage"],"cost":"credits","intent":"confirm-expensive-work"},{"id":"seasons-automation","title":"Seasons and automation","summary":"Operate controlled multi-installment season workflows.","startWith":["list_season_runs"],"cost":"credits","intent":"explicit-user-intent"},{"id":"recurring-shows","title":"Recurring shows","summary":"Set up and run a recurring podcast or show: a cast and format, a source it reads (a feed, a site, a repository, Hacker News), a schedule, spending caps the user agrees, one preview episode the user hears, then live — each episode made unattended from new source material and credited in its show notes. The user owns the show, its episodes and its feed.","startWith":["create_project","save_series_bible","create_publishing_series","preview_show_sources","get_show_quote","produce_show_episode","update_publishing_series"],"cost":"credits","intent":"confirm-expensive-work"},{"id":"publishing-analytics","title":"Publishing and analytics","summary":"Prepare destinations and releases, then publish only after the user approves the exact externally visible action.","startWith":["list_publishing_series","list_publishing_releases"],"cost":"inspect-first","intent":"explicit-user-intent"}]},"mcpPublic":{"role":"Read-only public discovery","transport":"streamable-http","url":"https://sleeperhit.studio/api/mcp","auth":{"accountRequired":false,"type":"none"},"tools":["search","fetch","find_writers","get_writer_profile","find_projects","get_project_summary","list_writer_assets","list_project_assets","get_public_pitch_assets","get_access_info"]},"storyApi":{"role":"HTTP Story API for creation, generation, and publishing","baseUrl":"https://sleeperhit.studio/api/v1","auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:read","story:write","source:read","source:write","artifact:read","artifact:publish","publishing:read","publishing:write","publishing:publish","publishing:connect","publishing:analytics","credits:read","webhook:write","account:read","account:write"],"header":"Authorization: Bearer <oauth-access-token | sh_<prefix>_<secret>>","idempotency":"Idempotency-Key is required on every credit-reserving or mutating POST."},"openapiUrl":"https://sleeperhit.studio/api/v1/openapi.json","capabilitiesUrl":"https://sleeperhit.studio/api/v1/capabilities","agentGuidanceUrl":"https://sleeperhit.studio/api/v1/agent-guidance","examplesUrl":"https://sleeperhit.studio/api/v1/examples","errorCodes":["authentication_required","invalid_api_key","api_key_revoked","api_key_expired","account_disabled","ip_not_allowed","insufficient_scope","rate_limited","idempotency_key_required","idempotency_conflict","validation_failed","project_not_found","source_not_found","source_type_unsupported","source_too_large","source_incomplete","source_fetch_failed","story_plan_not_found","story_plan_state_invalid","story_plan_failed","season_run_not_found","season_run_state_invalid","story_job_not_found","story_job_state_invalid","artifact_not_found","artifact_not_ready","artifact_generation_failed","publishing_series_not_found","publishing_destination_not_found","publishing_release_not_found","publishing_release_state_invalid","publishing_asset_not_ready","publishing_asset_stale","project_precondition_failed","spend_subject_unresolved","insufficient_credits","internal_error","trailer_not_found","trailer_state_invalid","pitch_deck_not_found","pitch_deck_state_invalid","pitch_deck_version_not_found","story_job_not_resumable","script_not_found","cast_precondition_failed","table_read_not_prepared","voice_clone_not_found","mood_board_full","fal_account_locked","location_plate_not_found","location_plate_precondition_failed","voice_not_found","voice_design_not_found","voice_in_use","cast_voice_precondition_failed","script_in_use","script_state_invalid","plan_limit_reached","cast_voice_casting_coverage_failed","cast_portrait_casting_coverage_failed","voice_retired","voice_consent_required","voice_consent_revoked","account_email_mismatch","account_deletion_refused","project_not_restorable","content_refused","safety_hold","safety_check_unavailable","likeness_consent_required","reference_image_not_owned","likeness_consent_not_found","character_not_found","portrait_design_not_found","series_bible_version_conflict","show_cap_reached","not_found","method_not_allowed"]},"cli":{"role":"Terminal and script client over the same Story API","package":"@sleeperhit/cli","install":"npm install -g @sleeperhit/cli","auth":"sleeperhit login (device flow) or SLEEPERHIT_API_KEY with an sh_ key.","commandCount":298,"commandsUrl":"https://sleeperhit.studio/docs/cli-commands.json","docsUrl":"https://docs.sleeperhit.studio/cli"}},"scopes":[{"name":"story:read","description":"View your scripts, projects, story plans, and coverage","write":false},{"name":"story:write","description":"Create and edit scripts, projects, and story plans","write":true},{"name":"source:read","description":"Read the full text of your uploaded scripts","write":false},{"name":"source:write","description":"Upload and modify script source text","write":true},{"name":"artifact:read","description":"View generated artifacts — table reads, pitch decks, trailers","write":false},{"name":"artifact:publish","description":"Publish and render generated artifacts","write":true},{"name":"publishing:read","description":"View your shows, their episodes and where they publish","write":false},{"name":"publishing:write","description":"Create and edit your shows and episodes, including a recurring show's schedule and spending limits","write":true},{"name":"publishing:publish","description":"Publish your shows' episodes, including on a schedule you turn on","write":true},{"name":"publishing:connect","description":"Connect and manage publishing destinations","write":true},{"name":"publishing:analytics","description":"View your publishing analytics","write":false},{"name":"credits:read","description":"View your Studio Credit balance and usage","write":false},{"name":"webhook:write","description":"Create and manage webhooks","write":true},{"name":"account:read","description":"See whether your account is scheduled for deletion, and your credit balance","write":false},{"name":"account:write","description":"Schedule or cancel the deletion of your account (it needs your email address, and can be cancelled for 7 days)","write":true}],"capabilities":[{"id":"capabilities","title":"Discover live capabilities","description":"Read the feature manifest before integrating a flow.","availability":"available","tags":["discovery"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:read"]},"api":{"method":"GET","path":"/capabilities","operationId":"getCapabilities","idempotent":false},"cli":{"command":"sleeperhit capabilities"},"mcp":{"tool":null,"resource":"sleeperhit://capabilities","workflowId":null},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"agent-guidance","title":"Read agent guidance","description":"Read the backend-managed workflow guidance for Story API, CLI, and MCP agents.","availability":"available","tags":["discovery"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:read"]},"api":{"method":"GET","path":"/agent-guidance","operationId":"getAgentGuidance","idempotent":false},"cli":{"command":"sleeperhit guidance"},"mcp":{"tool":"get_agent_guidance","resource":"sleeperhit://agent-guidance","workflowId":"orientation-account"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"credits.read","title":"Read Studio Credit balance","description":"Read available credits, and what each operation costs (`costs`, the list the Billing page shows), before starting generation work. A pitch deck is priced by the second: 1 credit a second to render at 480p, plus 1 credit a second to finish at 720p (2 credits a second in all; a 1080p finish is 4 credits a second instead). Planning is free. The exact price is quoted per shot once the plan is ready, before anything renders; location plates and on-screen text are itemized in the same quotes. A trailer is priced by the second: 1 credit a second to render at 480p, plus 1 credit a second to finish at 720p (2 credits a second in all; a 1080p finish is 4 credits a second instead). Planning is free. The exact price is quoted per shot once the plan is ready, before anything renders; location plates and on-screen text are itemized in the same quotes.","availability":"available","tags":["credits"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["credits:read"]},"api":{"method":"GET","path":"/credits","operationId":"getCredits","idempotent":false},"cli":{"command":"sleeperhit credits"},"mcp":{"tool":"get_credits","resource":null,"workflowId":"credits-usage"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"account.export.get","title":"Read the \"Download my data\" archive","description":"Where the latest archive of everything the account holds stands (`queued`, `building`, `ready`, `failed`, `expired`). When ready, `download.url` is a signed link that works for an hour (read again for a new one); the archive is deleted 7 days after it is built. Free.","availability":"available","tags":["account"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["account:read"]},"api":{"method":"GET","path":"/account/export","operationId":"getAccountExport","idempotent":false},"cli":{"command":"sleeperhit account export --status"},"mcp":{"tool":"get_account_export","resource":null,"workflowId":"account-data"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"account.export.request","title":"Download my data","description":"Build one zip of everything the account holds: scripts (Fountain and Final Draft), projects' Series Bibles, outlines and documents (JSON and Markdown), coverage (JSON, Markdown and PDF), links to every audio and video master, shows with their feeds, voice consent records, the credit ledger and payments, voices, chats, forum posts and comments. Built in the background; read the status for the download link. One at a time. Free.","availability":"available","tags":["account"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["account:read"]},"api":{"method":"POST","path":"/account/export","operationId":"requestAccountExport","idempotent":true},"cli":{"command":"sleeperhit account export [--wait] [--download <dir>]"},"mcp":{"tool":"request_account_export","resource":null,"workflowId":"account-data"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"account.deletion.get","title":"Read where the account's deletion stands","description":"Where the account's deletion stands (`none`, `scheduled` with its date, `purging`, `blocked`), with the Studio Credit balance, any top-up still inside its 14-day refund window (request the refund first), what deleting removes and what is kept. Free.","availability":"available","tags":["account"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["account:read"]},"api":{"method":"GET","path":"/account/deletion","operationId":"getAccountDeletion","idempotent":false},"cli":{"command":"sleeperhit account deletion"},"mcp":{"tool":"get_account_deletion","resource":null,"workflowId":"account-data"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"account.deletion.request","title":"Delete the account","description":"Schedule the deletion of the account and everything it made (scripts, projects, reads, decks, trailers, shows and their feeds, voices here and at the voice provider, stored files, keys and connected apps), 7 days out. `confirmEmail` must be the account's email address. It can be cancelled until the purge starts; unused credits are forfeited at the purge. Payment records are kept without a name or email, as tax law requires. Free.","availability":"available","tags":["account"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["account:write"]},"api":{"method":"POST","path":"/account/deletion","operationId":"requestAccountDeletion","idempotent":true},"cli":{"command":"sleeperhit account delete --confirm-email <email>"},"mcp":{"tool":"request_account_deletion","resource":null,"workflowId":"account-data"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"account.deletion.cancel","title":"Cancel the account's deletion","description":"Cancel a scheduled account deletion, any time before its purge starts. Nothing was removed before then. Free.","availability":"available","tags":["account"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["account:write"]},"api":{"method":"DELETE","path":"/account/deletion","operationId":"cancelAccountDeletion","idempotent":false},"cli":{"command":"sleeperhit account cancel-deletion"},"mcp":{"tool":"cancel_account_deletion","resource":null,"workflowId":"account-data"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"generation.health","title":"Check generation health","description":"See whether the writing pipeline can reach a healthy model provider before blaming a failed job on your request.","availability":"available","tags":["health"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:read"]},"api":{"method":"GET","path":"/generation-health","operationId":"getGenerationHealth","idempotent":false},"cli":{"command":"sleeperhit generation-health"},"mcp":{"tool":"get_generation_health","resource":null,"workflowId":"credits-usage"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"projects.create","title":"Create a story project","description":"Create a workspace that groups sources, plans, jobs, and artifacts.","availability":"available","tags":["projects"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:write"]},"api":{"method":"POST","path":"/story-projects","operationId":"createStoryProject","idempotent":true},"cli":{"command":"sleeperhit projects create --name <name>"},"mcp":{"tool":"create_project","resource":null,"workflowId":"projects-sources"},"docsUrl":"https://docs.sleeperhit.studio/quickstart"},{"id":"projects.createFromScript","title":"Create a project around a script","description":"Put a script that belongs to no project into a new one, named after the script, so its Series Bible, seasons, videos and publishing become reachable. Pass the script id (or the id in its Writers Lab URL) or any of its scriptUploadIds. A script already in a project returns that project with created: false. Reading a script never puts it in a project; this does. Costs no credits.","availability":"available","tags":["projects","script_project"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:write"]},"api":{"method":"POST","path":"/story-projects/from-script","operationId":"createStoryProjectFromScript","idempotent":true},"cli":{"command":"sleeperhit projects from-script <scriptId> | --script <scriptUploadId>"},"mcp":{"tool":"create_project_from_script","resource":null,"workflowId":"projects-sources"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"projects.list","title":"List story projects","description":"Cursor-paginated project list.","availability":"available","tags":["projects"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:read"]},"api":{"method":"GET","path":"/story-projects","operationId":"listStoryProjects","idempotent":false},"cli":{"command":"sleeperhit projects list"},"mcp":{"tool":"list_projects","resource":null,"workflowId":"projects-sources"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"projects.get","title":"Read a story project","description":"Fetch one project by id, with `workspaceGate` — the readiness preflight (`ready`, `stage`, `reason`, `missingFields`, `canPlan`, `canStartEpisode`, and `fullCoverage`: `advisory` for a recurring show, which premise coverage alone opens, with `fullCoverageNotice` saying so) — and `tableReadReadiness` (`ready`, `audioOnly`, `reason`, `narratorVoice`, `members`): whether the cast canon lets a table read start from a plan. A recurring caller reads it before fetching or uploading anything: when it cannot plan or start an episode, finish `stage` instead of attempting a call that refuses with 409 `project_precondition_failed`; when the cast is not ready, complete the members named instead of a job that refuses with 409 `cast_precondition_failed`. Read-only; it never queues coverage.","availability":"available","tags":["projects"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:read"]},"api":{"method":"GET","path":"/story-projects/{projectId}","operationId":"getStoryProject","idempotent":false},"cli":{"command":"sleeperhit projects get <projectId>"},"mcp":{"tool":"get_project","resource":null,"workflowId":"projects-sources"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"projects.update","title":"Update a story project","description":"Rename a project or patch its description, metadata, archived state, or season cadence (monthly: new episodes are filed by the month their source was made) from the API, CLI, or MCP. The season cadence is also set on the project's seasons page.","availability":"available","tags":["projects"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:write"]},"api":{"method":"PATCH","path":"/story-projects/{projectId}","operationId":"updateStoryProject","idempotent":false},"cli":{"command":"sleeperhit projects update <projectId> [--name <text>] [--description <text>] [--metadata <json>] [--archived true|false] [--season-cadence monthly|numbered]"},"mcp":{"tool":"update_project","resource":null,"workflowId":"projects-sources"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"projects.delete","title":"Delete a story project","description":"Delete a project: hidden at once (its feed, show page, decks and share links stop answering) and restorable for 30 days (`restorableUntil`), then purged with its Series Bible, cast, mood board, sources, plans, season runs, show, decks and trailers. Its episodes are not deleted: they stay in the library as private scripts (`episodesKept`). Archiving (PATCH archived: true) only hides it.","availability":"available","tags":["projects"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:write"]},"api":{"method":"DELETE","path":"/story-projects/{projectId}","operationId":"deleteStoryProject","idempotent":false},"cli":{"command":"sleeperhit projects delete <projectId>"},"mcp":{"tool":"delete_project","resource":null,"workflowId":"projects-sources"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"projects.deleted.list","title":"List deleted projects that can still be restored","description":"Deleted projects still inside their 30-day restore window, newest first, each with `restorableUntil` and `episodesKept`. Free.","availability":"available","tags":["projects"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:read"]},"api":{"method":"GET","path":"/story-projects/deleted","operationId":"listDeletedStoryProjects","idempotent":false},"cli":{"command":"sleeperhit projects deleted"},"mcp":{"tool":"list_deleted_projects","resource":null,"workflowId":"projects-sources"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"projects.restore","title":"Restore a deleted project","description":"Restore a deleted project within its 30-day window: it comes back with the episodes its delete took out (and their share links), except any deleted since or moved to another project. 409 `project_not_restorable` after the window or once the purge has started. Free.","availability":"available","tags":["projects"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:write"]},"api":{"method":"POST","path":"/story-projects/{projectId}/restore","operationId":"restoreStoryProject","idempotent":true},"cli":{"command":"sleeperhit projects restore <projectId>"},"mcp":{"tool":"restore_project","resource":null,"workflowId":"projects-sources"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"projects.series-bible.get","title":"Read a project Series Bible","description":"Fetch the durable project-level canon and continuity document; use it as the preferred first gate before screenplay generation. Its renderContext.periodNegatives shows, read-only, the Bible's period world: what every video render of the series is told the world is (indoors, outdoors), and what it never has (negatives).","availability":"available","tags":["projects","documents"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:read"]},"api":{"method":"GET","path":"/story-projects/{projectId}/series-bible","operationId":"getProjectSeriesBible","idempotent":false},"cli":{"command":"sleeperhit bible get <projectId>"},"mcp":{"tool":"get_series_bible","resource":null,"workflowId":"series-bible-development"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"projects.series-bible.save","title":"Save a project Series Bible","description":"Persist full project canon, episode map, characters, and style/audio direction before planning or generating screenplay pages.","availability":"available","tags":["projects","documents"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:write"]},"api":{"method":"PATCH","path":"/story-projects/{projectId}/series-bible","operationId":"saveProjectSeriesBible","idempotent":false},"cli":{"command":"sleeperhit bible save <projectId> --json <object>"},"mcp":{"tool":"save_series_bible","resource":null,"workflowId":"series-bible-development"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"projects.series-bible.generate","title":"Generate a project Series Bible","description":"Use the backend sidecar to synthesize or refresh full project-level canon from project context before screenplay generation.","availability":"available","tags":["projects","documents"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:write"]},"api":{"method":"POST","path":"/story-projects/{projectId}/series-bible","operationId":"generateProjectSeriesBible","idempotent":true},"cli":{"command":"sleeperhit bible generate <projectId>"},"mcp":{"tool":"generate_series_bible","resource":null,"workflowId":"series-bible-development"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"projects.series-bible.coverage.get","title":"Read Series Bible coverage","description":"Read premise or full-Bible coverage with ?phase=premise|full (premise by default). Develop the Bible foundation and canon before premise coverage. The premise pass unlocks planning and the optional Mood board. The full pass unlocks episode work and new project media.","availability":"available","tags":["projects","documents","coverage"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:read"]},"api":{"method":"GET","path":"/story-projects/{projectId}/series-bible/coverage","operationId":"getProjectSeriesBibleCoverage","idempotent":false},"cli":{"command":"sleeperhit bible coverage <projectId> [--phase premise|full]"},"mcp":{"tool":"get_series_bible_coverage","resource":null,"workflowId":"series-bible-development"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"projects.series-bible.coverage.generate","title":"Generate Series Bible coverage","description":"Queue premise or full-Bible coverage with body phase=premise|full (premise by default), calibrated against 72 provenance-backed series craft profiles.","availability":"available","tags":["projects","documents","coverage"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:write"]},"api":{"method":"POST","path":"/story-projects/{projectId}/series-bible/coverage","operationId":"generateProjectSeriesBibleCoverage","idempotent":true},"cli":{"command":"sleeperhit bible coverage <projectId> --generate [--phase premise|full]"},"mcp":{"tool":"generate_series_bible_coverage","resource":null,"workflowId":"series-bible-development"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"projects.outline-map.get","title":"Read episode outlines","description":"Every planned episode's outline in season-map order, with where it came from (`outline_map`: written for the episode; `season_map`: its season-map note, standing in because it lays the episode out act by act or scene by scene) and `readiness`: what outline coverage can score. Read-only.","availability":"available","tags":["projects","documents","outline"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:read"]},"api":{"method":"GET","path":"/story-projects/{projectId}/outline-map","operationId":"getProjectOutlineMap","idempotent":false},"cli":{"command":"sleeperhit outline get <projectId>"},"mcp":{"tool":"get_outline_map","resource":null,"workflowId":"series-bible-development"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"projects.outline-map.episode.save","title":"Save an episode outline","description":"Replace one season-map episode's outline (every other episode stays as stored) — the same writer as its Outline tab and Slug, so it is what outline coverage scores and the season planner hands the writer. Free.","availability":"available","tags":["projects","documents","outline"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:write"]},"api":{"method":"PATCH","path":"/story-projects/{projectId}/outline-map","operationId":"saveProjectEpisodeOutline","idempotent":false},"cli":{"command":"sleeperhit outline save <projectId> <episodeId> --json <outline>"},"mcp":{"tool":"save_episode_outline","resource":null,"workflowId":"series-bible-development"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"projects.outline-map.coverage.get","title":"Read outline coverage","description":"Read the structural report for the current-or-stale outline-map revision, and `readiness`: whether the outlines can be scored now and, when not, exactly what is missing. Report-only: it scores act turns, causality, escalation and season momentum, and gates nothing.","availability":"available","tags":["projects","documents","coverage","outline"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:read"]},"api":{"method":"GET","path":"/story-projects/{projectId}/outline-map/coverage","operationId":"getProjectOutlineCoverage","idempotent":false},"cli":{"command":"sleeperhit outline coverage <projectId>"},"mcp":{"tool":"get_outline_coverage","resource":null,"workflowId":"series-bible-development"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"projects.outline-map.coverage.generate","title":"Generate outline coverage","description":"Queue a structural report for one exact outline-map revision. Refuses with `readiness.reason` when no planned episode has an outline. Unlike Series Bible coverage this sets no gate, so it never blocks script coverage or season generation.","availability":"available","tags":["projects","documents","coverage","outline"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:write"]},"api":{"method":"POST","path":"/story-projects/{projectId}/outline-map/coverage","operationId":"generateProjectOutlineCoverage","idempotent":true},"cli":{"command":"sleeperhit outline coverage <projectId> --generate"},"mcp":{"tool":"generate_outline_coverage","resource":null,"workflowId":"series-bible-development"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"seasons.create","title":"Create a conversational season run","description":"Create a durable runner from the Series Bible episode map; every episode remains in a conversational mapping gate until the user confirms it.","availability":"available","tags":["publishing","seasons"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:write","publishing:write"]},"api":{"method":"POST","path":"/story-projects/{projectId}/season-runs","operationId":"createStorySeasonRun","idempotent":true},"cli":{"command":"sleeperhit seasons create <projectId>"},"mcp":{"tool":"create_season_run","resource":null,"workflowId":"seasons-automation"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"seasons.list","title":"List season runs","description":"List persisted season maps and their coverage, finalization, and publishing progress.","availability":"available","tags":["publishing","seasons"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:read"]},"api":{"method":"GET","path":"/story-projects/{projectId}/season-runs","operationId":"listStorySeasonRuns","idempotent":false},"cli":{"command":"sleeperhit seasons list <projectId>"},"mcp":{"tool":"list_season_runs","resource":null,"workflowId":"seasons-automation"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"seasons.get","title":"Read a season run","description":"Read the complete persisted runner state, episode coverage scores, and the next human or automated action.","availability":"available","tags":["publishing","seasons"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:read"]},"api":{"method":"GET","path":"/season-runs/{runId}","operationId":"getStorySeasonRun","idempotent":false},"cli":{"command":"sleeperhit seasons get <runId>"},"mcp":{"tool":"get_season_run","resource":null,"workflowId":"seasons-automation"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"seasons.episodes.map","title":"Map one season episode","description":"Save one episode brief agreed in conversation using the latest required mapVersion; confirmed=true is reserved for explicit user agreement.","availability":"available","tags":["publishing","seasons"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:write"]},"api":{"method":"PATCH","path":"/season-runs/{runId}/episodes/{episodeId}","operationId":"updateStorySeasonEpisode","idempotent":false},"cli":{"command":"sleeperhit seasons map <runId> <episodeId> --expected-map-version <n> --patch <json> [--confirm]"},"mcp":{"tool":"map_season_episode","resource":null,"workflowId":"seasons-automation"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"seasons.approve","title":"Approve a complete season map","description":"Lock the exact mapVersion the user reviewed; stale versions are rejected. Episode plans retain a separate human approval hold.","availability":"available","tags":["publishing","seasons"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:write"]},"api":{"method":"POST","path":"/season-runs/{runId}/approve","operationId":"approveStorySeasonMap","idempotent":true},"cli":{"command":"sleeperhit seasons approve <runId> --expected-map-version <n> --confirm"},"mcp":{"tool":"approve_season_map","resource":null,"workflowId":"seasons-automation"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"seasons.advance","title":"Advance a coverage-gated season episode","description":"Take one durable generation step, or submit an explicitly confirmed replan, same-report coverage retry, revision, exact screenplay replacement, or publish action. Replans can carry a durable correction brief, defaulting to a rejected plan's persisted reason. The runner never approves an episode plan and cannot publish before the configured coverage gate and durable MP3 pass. Producing an episode needs only story:write, artifact:publish and publishing:write; `action=publish` additionally requires publishing:publish, enforced per-action so a produce-only connector never has to hold publish rights.","availability":"available","tags":["publishing","seasons","coverage"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:write","artifact:publish","publishing:write"]},"api":{"method":"POST","path":"/season-runs/{runId}/advance","operationId":"advanceStorySeasonRun","idempotent":true},"cli":{"command":"sleeperhit seasons advance <runId> | replan <runId> [--instruction <text>] --confirm | retry-coverage <runId> --confirm | revise <runId> (--instruction <text> | --screenplay-file <path>) --confirm | publish <runId> --confirm"},"mcp":{"tool":"advance_season_run","resource":null,"workflowId":"seasons-automation"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"projects.series-bible.character.get","title":"Read one Series Bible character","description":"One Series Bible character, by id or any name the Bible or the cast canon knows them by, with the Bible's `currentVersion` to send back as `expectedVersion`. Free.","availability":"available","tags":["projects","documents"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:read"]},"api":{"method":"GET","path":"/story-projects/{projectId}/series-bible/characters","operationId":"getSeriesBibleCharacter","idempotent":false},"cli":{"command":"sleeperhit bible character <projectId> <character>"},"mcp":{"tool":"get_series_bible_character","resource":null,"workflowId":"series-bible-development"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"projects.series-bible.character.update","title":"Edit one Series Bible character","description":"Change only the fields sent on ONE Series Bible character and leave every other character as stored (`bible save` sends whole arrays). `expectedVersion` makes it a compare-and-swap (409 `series_bible_version_conflict` when the Bible changed since); `create` adds the character when nobody answers to the name. Free.","availability":"available","tags":["projects","documents"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:write"]},"api":{"method":"PATCH","path":"/story-projects/{projectId}/series-bible/characters","operationId":"updateSeriesBibleCharacter","idempotent":false},"cli":{"command":"sleeperhit bible character <projectId> <character> --json '<fields>' [--expected-version <n>] [--create]"},"mcp":{"tool":"update_series_bible_character","resource":null,"workflowId":"series-bible-development"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"projects.cast-canon.get","title":"Read a project cast canon","description":"Fetch the project-level canonical portrait, body, character-sheet, voice, alias and signature-item canon every new episode inherits, with identity warnings (one name reaching two people, a shared body figure, no Series Bible appearance). Visual direction lives in the Series Bible.","availability":"available","tags":["projects","documents"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:read"]},"api":{"method":"GET","path":"/story-projects/{projectId}/cast-canon","operationId":"getProjectCastCanon","idempotent":false},"cli":{"command":"sleeperhit cast-canon get <projectId>"},"mcp":{"tool":"get_cast_canon","resource":null,"workflowId":"series-bible-development"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"projects.cast-canon.save","title":"Save a project cast canon","description":"Pin per-character portrait, body, character-sheet, voice, aliases and signature items for a project; new episodes reuse these instead of rendering replacements (characters merge by name or alias). Free; returns the identity warnings.","availability":"available","tags":["projects","documents"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:write"]},"api":{"method":"PATCH","path":"/story-projects/{projectId}/cast-canon","operationId":"saveProjectCastCanon","idempotent":false},"cli":{"command":"sleeperhit cast-canon save <projectId> --json '<object>' | --file <json> [--replace]"},"mcp":{"tool":"save_cast_canon","resource":null,"workflowId":"series-bible-development"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"projects.cast-voice.design","title":"Design a cast member's voice","description":"Draw up to four candidate voices for one named cast member from a description (or the Series Bible's voice line for them) on the voice designer (ElevenLabs Voice Design), each one take of the character's own screenplay lines. A KEY character's candidates are then judged by casting coverage by themselves, free (`coverage` on the result; read it with the design's coverage). METERED: TWO CALLS — without `confirmed` it prices the design (one casting voice per candidate; `quotedOnly: true`, `credits`, `balanceAfter`, `sufficient`, `note`, and the description and lines it will use) and draws nothing; with `confirmed: true` it draws and answers with `designId` and the candidates' take urls and preview ids. Every candidate drawn is charged, chosen or not. Anyone on the project cast is reached, in an episode or not: a person with no screenplay lines (someone only a deck or trailer gives a line) is designed on `sampleText`, else on a passage the designer writes for the description (`designLine: null` on the price). Refused before the price (409 `cast_voice_precondition_failed`) with no description and no Bible voice line, or no voice designer configured.","availability":"available","tags":["projects","casting"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["artifact:publish"]},"api":{"method":"POST","path":"/story-projects/{projectId}/cast-voice/design","operationId":"designProjectCastVoice","idempotent":true},"cli":{"command":"sleeperhit cast-voice design <projectId> --character <c> [--description <text>] [--candidates <n>] [--preview-lines <n>] [--sample-text <line>] [--confirm]"},"mcp":{"tool":"design_cast_voice","resource":null,"workflowId":"series-bible-development"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"projects.cast-voice.choose","title":"Choose a designed cast voice","description":"Keep one candidate of a cast voice design: its take is cloned into the provider that speaks every designed voice (Cartesia) and added to the voice library with its lineage (description, preview id, new voice), then pinned to the cast canon (every new episode, deck, trailer and showcase speaks with it); lists the finished reads that still speak with the old voice (re-voice them, priced). Free; choosing it again reuses the voice. A candidate its casting coverage FAILED is refused (409 `cast_voice_casting_coverage_failed`, `details.castingCoverage` with the score, the bar, why and the candidate it recommends instead) unless `acknowledgeCastingCoverage: true` — only once the writer has heard it and chosen it anyway; a report still running or one that could not run never holds a choice (`castingCoverageWarning` says so).","availability":"available","tags":["projects","casting"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:write"]},"api":{"method":"POST","path":"/story-projects/{projectId}/cast-voice/choose","operationId":"chooseProjectCastVoice","idempotent":true},"cli":{"command":"sleeperhit cast-voice choose <projectId> --design <designId> --candidate <n> [--name <voiceName>] [--acknowledge-coverage]"},"mcp":{"tool":"choose_cast_voice","resource":null,"workflowId":"series-bible-development"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"projects.cast-voice.set","title":"Set a cast member's voice","description":"Pin an EXISTING voice on one person's cast canon entry — anyone on the project cast, in an episode or not (a person no screenplay names yet, whom a deck or trailer gives a line). Every new episode, deck, trailer and showcase speaks them with it, and an episode that later names them inherits it instead of casting a second one. A Series Bible character the canon does not hold yet is added. Free, one call; answers `previous` (the canon voice it replaced: set it again to go back) and `reads` (finished reads that still speak them with another voice: re-voice them, priced). Never changes a read. A voice on a provider that is retiring its voices is refused (409 `voice_retired`); nobody by that name is a 404 `character_not_found`. A NEW voice is designed (`projects.cast-voice.design`) and chosen instead.","availability":"available","tags":["projects","casting"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:write"]},"api":{"method":"PATCH","path":"/story-projects/{projectId}/cast-voice","operationId":"setProjectCastVoice","idempotent":false},"cli":{"command":"sleeperhit cast-voice set <projectId> --character <c> --voice-id <id> [--voice-name <n>] [--provider <p>] [--gender <g>]"},"mcp":{"tool":"set_cast_voice","resource":null,"workflowId":"series-bible-development"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"projects.cast-voice.designs","title":"List cast voice designs","description":"A project's cast voice designs, newest first, with each candidate's preview urls, the one chosen, and each design's casting coverage (`coverage`: the ranking, every candidate's scores and flags, and the recommendation). Free.","availability":"available","tags":["projects","casting"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:read"]},"api":{"method":"GET","path":"/story-projects/{projectId}/cast-voice/designs","operationId":"listProjectCastVoiceDesigns","idempotent":false},"cli":{"command":"sleeperhit cast-voice designs <projectId> [--character <c>]"},"mcp":{"tool":"list_cast_voice_designs","resource":null,"workflowId":"series-bible-development"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"projects.cast-voice.coverage.get","title":"Read a voice design's casting coverage","description":"Read a cast voice design's CASTING COVERAGE: a model listened to every candidate take blind (shuffled and relabelled every run), beside the voices already cast in the project, and scored each against the brief and the Series Bible — emblematic fit, truthful performance, period register, accent honesty, clean audio, word accuracy (a blind transcript compared with the lines) and distinctness from the cast — heard, and MEASURED by speaker embedding against every chosen voice (at or above `distinctnessThreshold`, 0.88 by default, a candidate fails on its own). Answers the ranking, every candidate's score, flags and best 15–20 s, the candidate it RECOMMENDS (the best that cleared the bar), the runner-up and whether the race was close, `cast` — the candidate the CAST PLAN picks for this design so that no two of the project's voices measure as the same speaker — `failingCandidates` (choosing one needs `acknowledgeCastingCoverage: true`), and — when every candidate failed — `report.redesign` with why and a revised brief to design again from. `report.judging` says how it was reached: near the bar or in a close race the takes are judged again (a third time when two runs disagree) and every score is the median; identical takes against an identical cast carry an earlier report. A design with no report reads back as `missing`, not as a 404.","availability":"available","tags":["projects","casting","casting_coverage"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:read"]},"api":{"method":"GET","path":"/story-projects/{projectId}/cast-voice/designs/{designId}/coverage","operationId":"getProjectCastVoiceCoverage","idempotent":false},"cli":{"command":"sleeperhit cast-voice coverage <projectId> --design <designId>"},"mcp":{"tool":"get_casting_coverage","resource":null,"workflowId":"series-bible-development"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"projects.cast-voice.coverage.generate","title":"Judge a voice design again","description":"Listen to a cast voice design's candidates again as a new casting coverage report, with the cast as it stands now (the voices other characters have chosen since, and the leading candidates of their open designs). Free — the listening costs the writer nothing — so there is no price and no `confirmed`. Coverage already runs by itself once per key character's design; a report already running is returned as it is. Optional `focusPrompt`: what to listen for hardest. Refused for a design with no hosted takes, or when no provider can listen right now (which never holds a choice).","availability":"available","tags":["projects","casting","casting_coverage"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:write"]},"api":{"method":"POST","path":"/story-projects/{projectId}/cast-voice/designs/{designId}/coverage","operationId":"generateProjectCastVoiceCoverage","idempotent":true},"cli":{"command":"sleeperhit cast-voice judge <projectId> --design <designId> [--focus <text>]"},"mcp":{"tool":"generate_casting_coverage","resource":null,"workflowId":"series-bible-development"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"projects.cast-portraits.design","title":"Draw headshot candidates for a cast member","description":"Draw N headshot candidates (default 3, at most 4) for one named cast member, each from the Series Bible's appearance and wardrobe with the person's LOOK after it — `direction`, else their look direction on the cast canon — which outranks the Bible. METERED: TWO CALLS — without `confirmed` it prices the candidates (one cast headshot each; `quotedOnly: true`, `credits`, `balanceAfter`, `sufficient`, `note`, and the direction it will draw from) and draws nothing; with `confirmed: true` it reserves them and queues the draw, answering with `designId` (poll the designs until `status` is `complete`). Every candidate drawn is charged, chosen or not; one that cannot be drawn is not. Each candidate has a stable `candidateId` and its `imageUrl`. `keepFace: true` restyles the person KEEPING THEIR FACE: each candidate is their current headshot edited to the look on the model that keeps a face (`restyledFrom`), at the same price, judged and chosen the same. Refused before the price: 404 `character_not_found`, 409 `cast_precondition_failed` (nothing to draw from, no image model, or with `keepFace` no headshot yet: `cast_face_missing`), 409 `project_precondition_failed`.","availability":"available","tags":["projects","casting"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["artifact:publish"]},"api":{"method":"POST","path":"/story-projects/{projectId}/cast-portraits/design","operationId":"designProjectCastPortraits","idempotent":true},"cli":{"command":"sleeperhit cast-portrait design <projectId> --character <c> [--direction <text>] [--age <a>] [--candidates <n>] [--keep-face] [--confirm]"},"mcp":{"tool":"design_cast_portraits","resource":null,"workflowId":"series-bible-development"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"projects.cast-portraits.choose","title":"Choose a headshot candidate","description":"Pin one drawn headshot candidate as the person's face on the cast canon (with the prompt it was drawn from): every new episode, deck, trailer and showcase draws them from it. A new face clears the canon body shot and sheet drawn from the old one (`cleared`, `previous`); the project cast draws them again from the new face. Free. A headshot its casting coverage FAILED is refused (409 `cast_portrait_casting_coverage_failed`, `details.castingCoverage` with the score, the bar, why and the headshot it recommends instead) unless `acknowledgeCastingCoverage: true` — only once the writer has seen it and chosen it anyway; coverage still running or one that could not run never holds a choice (`castingCoverageWarning` says so).","availability":"available","tags":["projects","casting"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:write"]},"api":{"method":"POST","path":"/story-projects/{projectId}/cast-portraits/choose","operationId":"chooseProjectCastPortrait","idempotent":true},"cli":{"command":"sleeperhit cast-portrait choose <projectId> --design <designId> --candidate <n> [--acknowledge-coverage]"},"mcp":{"tool":"choose_cast_portrait","resource":null,"workflowId":"series-bible-development"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"projects.cast-portraits.coverage.get","title":"Read a portrait design's casting coverage","description":"Read a portrait design's CASTING COVERAGE: a model looked at every drawn headshot blind (shuffled and relabelled every run), beside the faces already chosen for the cast, and scored each against the look and the Series Bible — emblematic fit, period truth (no modern faces or styling), naturalness (a photograph, not a generated image: no waxy skin, uncanny symmetry or costume too clean to have been worn) and distinctness from the cast. Answers the ranking, every headshot's score, flags and problems, the headshot it RECOMMENDS, the runner-up, `failingCandidates` (choosing one needs `acknowledgeCastingCoverage: true`), and — when every headshot failed — `report.redesign` with why and a revised look to draw again from. Near the bar or in a close race it looks again and every score is the median; identical faces against an identical cast carry an earlier report. A design with no report reads back as `missing`, not as a 404.","availability":"available","tags":["projects","casting","casting_coverage"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:read"]},"api":{"method":"GET","path":"/story-projects/{projectId}/cast-portraits/designs/{designId}/coverage","operationId":"getProjectCastPortraitCoverage","idempotent":false},"cli":{"command":"sleeperhit cast-portrait coverage <projectId> --design <designId>"},"mcp":{"tool":"get_portrait_coverage","resource":null,"workflowId":"series-bible-development"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"projects.cast-portraits.coverage.generate","title":"Judge a portrait design again","description":"Look at a portrait design's headshots again as a new casting coverage report, with the cast as it stands now. Free — the look costs the writer nothing — so there is no price and no `confirmed`. Coverage already runs by itself once a key character's headshots are drawn; a report already running is returned as it is. Optional `focusPrompt`. Refused for a design with no drawn headshot, or when no provider can look right now (which never holds a choice).","availability":"available","tags":["projects","casting","casting_coverage"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:write"]},"api":{"method":"POST","path":"/story-projects/{projectId}/cast-portraits/designs/{designId}/coverage","operationId":"generateProjectCastPortraitCoverage","idempotent":true},"cli":{"command":"sleeperhit cast-portrait judge <projectId> --design <designId> [--focus <text>]"},"mcp":{"tool":"generate_portrait_coverage","resource":null,"workflowId":"series-bible-development"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"projects.cast-portraits.designs","title":"List headshot candidate designs","description":"A project's portrait designs, newest first: status, the person (`character`, `castPersonId`), the direction drawn from, each candidate's `candidateId`, index and `imageUrl`, and the one chosen. One design by `designId`, or one person by `character`. Free.","availability":"available","tags":["projects","casting"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:read"]},"api":{"method":"GET","path":"/story-projects/{projectId}/cast-portraits/designs","operationId":"listProjectCastPortraitDesigns","idempotent":false},"cli":{"command":"sleeperhit cast-portrait designs <projectId> [--character <c>] [--design <designId>] [--watch]"},"mcp":{"tool":"list_cast_portrait_designs","resource":null,"workflowId":"series-bible-development"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"projects.cast-look.get","title":"Read cast look directions","description":"Every cast member's LOOK at project level — the writer's look direction and the age they are played at, on the cast canon — beside what the Series Bible says they look like; Bible characters the canon does not hold yet are listed with no look. One person by `character`. Free.","availability":"available","tags":["projects","casting"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:read"]},"api":{"method":"GET","path":"/story-projects/{projectId}/cast-look","operationId":"getProjectCastLook","idempotent":false},"cli":{"command":"sleeperhit cast direction <projectId> [--character <c>]"},"mcp":{"tool":"get_cast_look_direction","resource":null,"workflowId":"series-bible-development"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"projects.cast-look.set","title":"Set a cast member's look direction","description":"Set or clear one person's look direction and age on the cast canon, without an episode. Every headshot and portrait candidate drawn for them reads it, outranking the Series Bible's appearance; body shots and sheets carry it through the headshot. A field not sent is left alone; null clears it. Free: nothing is drawn.","availability":"available","tags":["projects","casting"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:write"]},"api":{"method":"PATCH","path":"/story-projects/{projectId}/cast-look","operationId":"setProjectCastLook","idempotent":false},"cli":{"command":"sleeperhit cast direction <projectId> --character <c> [--look <text>] [--age <a>] [--clear-look] [--clear-age]"},"mcp":{"tool":"set_cast_look_direction","resource":null,"workflowId":"series-bible-development"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"projects.mood-board.get","title":"Read a project mood board","description":"Read the kept frames that are this project's agreed look — the pictures every new character render is made in. Costs no credits. A project that has agreed no look yet returns an empty board rather than an error, and `content.frames` is capped at four because four is the most that can bind a render. It also answers with `candidates` — frames this project has RENDERED and not kept, which is where the urls `keepProjectMoodBoardFrame` needs come from — and `renders`, the recent batches and where each one got to, so a poll after a render terminates instead of waiting forever on a batch that failed.","availability":"available","tags":["projects","documents"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:read"]},"api":{"method":"GET","path":"/story-projects/{projectId}/mood-board","operationId":"getProjectMoodBoard","idempotent":false},"cli":{"command":"sleeperhit mood-board get <projectId>"},"mcp":{"tool":"get_mood_board","resource":null,"workflowId":"series-bible-development"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"projects.mood-board.keepFrame","title":"Keep a frame on the mood board","description":"After premise coverage passes and project canon is complete, pin one frame as part of the project's agreed look, so every character render afterwards is made in it. Costs no credits and generates nothing — the picture already exists and this writes it into canon. Keeping a frame whose `id` is already kept renews its approval time after premise changes; keeping a fifth distinct frame is REFUSED by name, never silently trimmed, because a frame beyond the fourth could not bind a render and the writer would never learn it had no effect.","availability":"available","tags":["projects","documents"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:write"]},"api":{"method":"POST","path":"/story-projects/{projectId}/mood-board/frames","operationId":"keepProjectMoodBoardFrame","idempotent":true},"cli":{"command":"sleeperhit mood-board keep <projectId> --json '<frame>' | --file <json>"},"mcp":{"tool":"keep_mood_board_frame","resource":null,"workflowId":"series-bible-development"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"projects.mood-board.renderFrames","title":"Render candidate mood board frames","description":"After premise coverage passes and project canon is complete, draw candidate frames for this project's look from a brief — a place, a light, a texture, a weather, in the show's medium. METERED: one still image per frame. TWO CALLS: sent without `confirmed` it PRICES the batch and renders nothing (`quotedOnly: true`, `credits`, `balanceAfter` — what the writer would have left — `sufficient`, and a `note` to show the writer; when `sufficient` is false the note says they are short and names the top-up link, and the caller must not confirm); sent again with `confirmed: true` it reserves the credit lines and queues the batch. Not a required `confirmed: true` literal — a field that must be true to validate cannot tell a confirmed call from an unconfirmed one, and it would force the price to be announced after the money moved. EVERY CANDIDATE COSTS, KEPT OR NOT: rendering proposes frames, keeping them is the free act that agrees the look, and the frames the writer drops were still drawn and still charged. The quote says so — repeat it. Preconditions run above the price: a project that is not yours, a project that has not passed premise coverage, and no image model bound for frames (409 `project_precondition_failed`, with `details.stage`), are refused with no quote at all. A confirmed call answers with a `chatToolJobId` because the render is queued — poll `getProjectMoodBoard` until the batch leaves `renders` and its frames appear in `candidates`, then keep the ones that are right.","availability":"available","tags":["projects","documents"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["artifact:publish"]},"api":{"method":"POST","path":"/story-projects/{projectId}/mood-board/render-frames","operationId":"renderProjectMoodBoardFrames","idempotent":true},"cli":{"command":"sleeperhit mood-board render <projectId> --brief <text> [--count <n>] [--aspect <ratio>] [--confirm]"},"mcp":{"tool":"render_mood_board_frames","resource":null,"workflowId":"series-bible-development"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"projects.mood-board.dropFrame","title":"Drop a frame from the mood board","description":"Take one frame back out of the agreed look. Costs no credits and refunds none: the picture stays where it is hosted, and what changes is that it stops binding renders. Dropping the last kept frame returns the project to having agreed no look, which the cast step reads. Returns the whole board after the change.","availability":"available","tags":["projects","documents"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:write"]},"api":{"method":"DELETE","path":"/story-projects/{projectId}/mood-board/frames/{frameId}","operationId":"dropProjectMoodBoardFrame","idempotent":false},"cli":{"command":"sleeperhit mood-board drop <projectId> <frameId>"},"mcp":{"tool":"drop_mood_board_frame","resource":null,"workflowId":"series-bible-development"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"projects.cast.generate","title":"Generate the project cast","description":"Cast a finalized episode after screenplay coverage: character and narrator voices, headshots, body shots, and character sheets. First call with scriptUploadId quotes Studio Credits, with what it would leave the writer (`balanceAfter`) and whether they can afford it (`sufficient`; when false the note names the top-up link and the caller must not confirm); confirm with confirmed: true and that quoteId to enqueue durable work. Poll the cast with scriptUploadId for progress and readiness. Table Read remains locked until the complete cast is ready. Omit scriptUploadId for the separate project-level Bible visual cast before screenplay writing. Every body shot and sheet drawn from a headshot is checked against it (the same person, age, build and wardrobe); one that does not match is drawn once more at our cost and the closer kept, never blocking the cast — a project cast's `members[].artChecks` and `note` say what was redrawn or is still off. `images` (with scriptUploadId) narrows an episode's cast to those pictures and no voices — `face`, `body`, `sheet` — and with `force` redraws them: the Cast page's Redraw on a body shot or sheet, drawn from the chosen headshot and priced per picture; the job's progressDetail says what each check found. `images` WITHOUT scriptUploadId is the project cast canon's Redraw: `body` and/or `sheet` for canon people, including people no episode names, the chosen headshot kept and each picture written onto the canon; priced per picture, confirmed with the quote's quoteId; the cast read's `redraw` names each new picture and its check.","availability":"available","tags":["projects","casting"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["artifact:publish"]},"api":{"method":"POST","path":"/story-projects/{projectId}/cast","operationId":"generateProjectCast","idempotent":true},"cli":{"command":"sleeperhit cast generate <projectId> [--script <scriptUploadId>] [--character <name>] [--force] [--image face|body|sheet] [--confirm --quote <quoteId>]"},"mcp":{"tool":"generate_cast","resource":null,"workflowId":"series-bible-development"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"projects.cast.direction","title":"Save episode character direction","description":"Save approved avatarPrompt (headshot and sheet), figurePrompt (body), age, gender, personality, speechStyle, backstory, and relationships for one episode character, and signatureItems on the project cast canon. A person on the project cast canon whom the episode does not name (a deck or trailer draws them from the canon) takes signatureItems alone here, saved on their canon entry (`projectCast: true` in the answer); anything else sent for them is refused by name. When the canon cannot tell who the character is, nothing is saved and the answer names the candidates; the writer says who they are with sameAs (that canon person; the script name becomes their alias) or newPersonName (someone else), and the Cast page offers the same choice as buttons. Requires scriptUploadId. No generation or credit charge; existing assets remain until a separately quoted and confirmed cast generation.","availability":"available","tags":["projects","casting"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:write"]},"api":{"method":"PATCH","path":"/story-projects/{projectId}/cast","operationId":"updateEpisodeCharacterDirection","idempotent":false},"cli":{"command":"sleeperhit cast direction <projectId> --script <scriptUploadId> --character <name> --json <direction>"},"mcp":{"tool":"update_character_direction","resource":null,"workflowId":"series-bible-development"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"projects.cast.get","title":"Read casting progress","description":"Read project cast assets and, with scriptUploadId, the episode casting job (with the pictures it draws), readiness, and the finished table read: `episode.read.behindCanon` names each character the read still speaks with another voice than the cast canon voice the Cast page plays, which a priced re-voice in that read fixes. This read-only operation never submits generation or spends credits.","availability":"available","tags":["projects","casting"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:read"]},"api":{"method":"GET","path":"/story-projects/{projectId}/cast","operationId":"getProjectCast","idempotent":false},"cli":{"command":"sleeperhit cast status <projectId> [--script <scriptUploadId>]"},"mcp":{"tool":"get_project_cast","resource":null,"workflowId":"series-bible-development"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"scripts.tableRead.prepare","title":"Prepare an episode's table read","description":"Prepare an episode's table read once its cast is complete: it charges the read's table-read credit (priced by the screenplay's pages: the short or long table-read price GET /credits lists), once per screenplay version, and adds the read's scene sound effects and music. METERED, PRICED FIRST: TWO CALLS on the API and the CLI — without `confirmed` it only prices it; with `confirmed: true` it charges and starts — and two tools on MCP and in chat (quote_prepare_table_read, then prepare_table_read with `confirmed: true`). A read already prepared, or being prepared, answers prepared / preparing and costs nothing, so a retry never charges twice. The Writers Lab's \"Continue to Table Read\" on Cast is the same operation. Answers `status`: `quoted` (`credits`, `balanceAfter`, `sufficient`, `note`; nothing spent — when `sufficient` is false the caller must not confirm), `queued` (charged and started: `charged`, `credits`, `tableReadJobId`), or `prepared` / `preparing` (nothing charged). Refused before the price: 404 `script_not_found`, 409 `cast_precondition_failed` (a draft, or an episode cast that is not complete — `details.missing`), 409 `project_precondition_failed`, 409 `voice_retired`. A confirmed call the balance cannot cover is 402 `insufficient_credits` and changes nothing.","availability":"available","tags":["casting","table_read"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["artifact:publish"]},"api":{"method":"POST","path":"/scripts/{scriptUploadId}/table-read/prepare","operationId":"prepareScriptTableRead","idempotent":true},"cli":{"command":"sleeperhit script table-read prepare <scriptUploadId> [--confirm]"},"mcp":{"tool":"prepare_table_read","resource":null,"workflowId":"series-bible-development"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"sources.create","title":"Attach a source","description":"Attach text, markdown, URL, or PDF source material to a project. A producer names each item with producer + externalId; a repeat of an item the project holds returns that source (deduplicated) instead of storing it again. originatedAt says when the material itself was made; a monthly project files the episode by it.","availability":"available","tags":["sources"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["source:write"]},"api":{"method":"POST","path":"/story-projects/{projectId}/sources","operationId":"createStorySource","idempotent":true},"cli":{"command":"sleeperhit sources add <projectId> --type text|markdown|url|pdf [--producer <name> --external-id <id>] [--originated-at <iso>]"},"mcp":{"tool":"add_source","resource":null,"workflowId":"projects-sources"},"docsUrl":"https://docs.sleeperhit.studio/quickstart"},{"id":"sources.list","title":"List sources","description":"List sources attached to a project.","availability":"available","tags":["sources"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["source:read"]},"api":{"method":"GET","path":"/story-projects/{projectId}/sources","operationId":"listStorySources","idempotent":false},"cli":{"command":"sleeperhit sources list <projectId>"},"mcp":{"tool":"list_sources","resource":null,"workflowId":"projects-sources"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"sources.get","title":"Read a source","description":"Poll one source until extraction and digest states are terminal.","availability":"available","tags":["sources"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["source:read"]},"api":{"method":"GET","path":"/story-projects/{projectId}/sources/{sourceId}","operationId":"getStorySource","idempotent":false},"cli":{"command":"sleeperhit sources get <projectId> <sourceId>"},"mcp":{"tool":"get_source","resource":null,"workflowId":"projects-sources"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"sources.delete","title":"Delete a source","description":"Soft-delete one source and clear extracted preview data.","availability":"available","tags":["sources"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["source:write"]},"api":{"method":"DELETE","path":"/story-projects/{projectId}/sources/{sourceId}","operationId":"deleteStorySource","idempotent":false},"cli":{"command":"sleeperhit sources delete <projectId> <sourceId>"},"mcp":{"tool":"delete_source","resource":null,"workflowId":"projects-sources"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"plans.create","title":"Generate a StoryPlan","description":"Generate the source-grounded plan that drives artifact jobs; for screenplay/table_read work, the planner auto-loads the saved Series Bible and the user should review the plan against it. A pitch_deck request's `deckMode` picks a pitch (the default) or a showcase (an epic sizzle of the show's world), with `showcaseCharacters` naming who it must feature.","availability":"available","tags":["plans"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:write"]},"api":{"method":"POST","path":"/story-projects/{projectId}/story-plans","operationId":"createStoryPlan","idempotent":true},"cli":{"command":"sleeperhit plans create <projectId> --target ... --artifact ..."},"mcp":{"tool":"create_plan","resource":null,"workflowId":"planning-screenwriting"},"docsUrl":"https://docs.sleeperhit.studio/quickstart"},{"id":"plans.list","title":"List StoryPlans","description":"List generated plans for a project.","availability":"available","tags":["plans"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:read"]},"api":{"method":"GET","path":"/story-projects/{projectId}/story-plans","operationId":"listStoryPlans","idempotent":false},"cli":{"command":"sleeperhit plans list <projectId>"},"mcp":{"tool":"list_plans","resource":null,"workflowId":"planning-screenwriting"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"plans.get","title":"Read a StoryPlan","description":"Poll a StoryPlan until it is ready, approved, rejected, or failed; provider backoff remains PENDING and is retried by Sleeper Hit without a client-side recovery loop. Its `quote` carries the price (`total`); while the plan still awaits its spend (READY or REQUIRES_APPROVAL, or APPROVED with no job yet) and the caller holds credits:read, it also carries what it would leave the writer (`balanceAfter`) and whether they can afford it (`sufficient`), with that sentence first in `notes` — show it before creating the job, and when `sufficient` is false the writer must top up first. Once a job exists the plan is paid for and those fields are absent.","availability":"available","tags":["plans"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:read"]},"api":{"method":"GET","path":"/story-plans/{planId}","operationId":"getStoryPlan","idempotent":false},"cli":{"command":"sleeperhit plans get <planId>"},"mcp":{"tool":"get_plan","resource":null,"workflowId":"planning-screenwriting"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"plans.resume","title":"Resume a StoryPlan","description":"Requeue pre-output failures or stale planning under the same durable plan id; active and review-ready plans are replay-safe no-ops.","availability":"available","tags":["plans","recovery"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:write"]},"api":{"method":"POST","path":"/story-plans/{planId}/resume","operationId":"resumeStoryPlan","idempotent":true},"cli":{"command":"sleeperhit plans resume <planId>"},"mcp":{"tool":"resume_story_plan","resource":null,"workflowId":"planning-screenwriting"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"plans.approve","title":"Approve a StoryPlan","description":"Move a reviewed plan out of the human approval hold only with explicit user confirmation — or, for a table-read plan made after the grant, under a show's standing approval by the one API key it is bound to.","availability":"available","tags":["plans"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:write"]},"api":{"method":"POST","path":"/story-plans/{planId}/approve","operationId":"approveStoryPlan","idempotent":true},"cli":{"command":"sleeperhit plans approve <planId> --confirm"},"mcp":{"tool":"approve_plan","resource":null,"workflowId":"planning-screenwriting"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"plans.reject","title":"Reject a StoryPlan","description":"Reject a plan with an optional reason.","availability":"available","tags":["plans"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:write"]},"api":{"method":"POST","path":"/story-plans/{planId}/reject","operationId":"rejectStoryPlan","idempotent":true},"cli":{"command":"sleeperhit plans reject <planId>"},"mcp":{"tool":"reject_plan","resource":null,"workflowId":"planning-screenwriting"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"activity.get","title":"Read background activity","description":"Read your queued, running, retrying and recently finished background tasks, with safe stage details, episode context, the project each task is for, and completed/total progress when available. A deck's or a trailer's tasks are named with what they work on (\"Stitching <deck> · 1:30\", \"Scoring <deck>'s plan\", \"Watching <deck>'s preview cut\"), and an assembly says the step it is on. Read-only: never starts, retries or cancels work.","availability":"available","tags":["jobs","activity"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:read"]},"api":{"method":"GET","path":"/background-activity","operationId":"getBackgroundActivity","idempotent":false},"cli":{"command":"sleeperhit activity"},"mcp":{"tool":"background_activity","resource":null,"workflowId":"planning-screenwriting"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"screenplay-drafts.get","title":"Read screenplay drafting progress","description":"Read scene-by-scene drafting progress for one draft: status (interrupted when a writing lease expired), completed/total scenes, current act, the saved screenplay so far, and the coverage started when drafting completes. Null when drafting was never started.","availability":"available","tags":["jobs","screenplay_draft"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:read"]},"api":{"method":"GET","path":"/screenplay-drafts/{scriptUploadId}","operationId":"getScreenplayDraft","idempotent":false},"cli":{"command":"sleeperhit screenplay-draft status <scriptUploadId>"},"mcp":{"tool":"screenplay_draft_status","resource":null,"workflowId":"planning-screenwriting"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"screenplay-drafts.start","title":"Draft or resume an episode scene by scene","description":"Queue an approved, act-ordered scene plan against an EMPTY editable draft once project setup is approved (use throughAct to write Act 1 first), or resume from the next unfinished scene with action=resume, preserving the writer's current edits. Each completed scene is saved as it lands; screenplay coverage starts when the draft completes.","availability":"available","tags":["jobs","screenplay_draft"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:write"]},"api":{"method":"POST","path":"/screenplay-drafts/{scriptUploadId}","operationId":"startScreenplayDraft","idempotent":true},"cli":{"command":"sleeperhit screenplay-draft start|resume <scriptUploadId> [--file <scene-plan.json>]"},"mcp":{"tool":"draft_episode/resume_screenplay_draft","resource":null,"workflowId":null},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"scripts.delete","title":"Delete a whole script","description":"Permanently delete a script: every version and everything scoped to them (character avatars, table reads and their share links, coverage reports, conversations, drafts), through the same core as the Writers Lab's delete. The id is the script's own or any of its versions' (`scriptUploadId`). Requires `confirmed: true` (`?confirmed=true` or a JSON body). Refused with 409 `script_in_use` (`details.uses`) while a published or scheduled release, a running job, a season-run slot, a pitch deck or a trailer still depends on it. Banked audio stays in My Library; the plan, job and artifact rows that generated it are kept. Irreversible; costs no credits.","availability":"available","tags":["scripts","script_delete"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:write"]},"api":{"method":"DELETE","path":"/scripts/{scriptUploadId}","operationId":"deleteScript","idempotent":false},"cli":{"command":"sleeperhit script delete <scriptId> --confirm"},"mcp":{"tool":"delete_script","resource":null,"workflowId":"projects-sources"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"scripts.overrides.get","title":"Read an episode's overrides","description":"Read the five episode overrides on one script version (scriptUploadId): `avatar` (character portraits), `theater` (theater presentation), `soundscape` (adaptive scene music and beat cues), `pitchDeck` (pitch deck generation) and `locations` (this episode's location plates). Each is the writer's direction layered over the Series Bible's visual canon, or for the soundscape over the studio default (`soundscapeDefault`). All five keys always come back; null means none is set for this episode. Works for any Writers Lab episode, with or without a Story API artifact. Read-only; costs no credits.","availability":"available","tags":["episode_overrides"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:read"]},"api":{"method":"GET","path":"/scripts/{scriptUploadId}/overrides","operationId":"getScriptOverrides","idempotent":false},"cli":{"command":"sleeperhit script overrides get <scriptUploadId>"},"mcp":{"tool":"get_script_overrides","resource":null,"workflowId":"series-bible-development"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"scripts.overrides.update","title":"Set or clear an episode's overrides","description":"Change any of the five episode overrides (`avatar`, `theater`, `soundscape`, `pitchDeck`, `locations`) in one partial update: text sets one (at most 8000 characters), null or blank text clears it back to the Series Bible canon (the soundscape to the studio default), and keys left out are untouched. An unknown key, a non-text value or an over-long one is refused with 400 `validation_failed`, the same refusal the Writers Lab shows. Answers all five as they now stand. Costs no credits and renders nothing: the next render of that kind uses it (to restyle existing cast portraits now, the cast update's metered `avatarStyle` does that).","availability":"available","tags":["episode_overrides"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:write"]},"api":{"method":"PATCH","path":"/scripts/{scriptUploadId}/overrides","operationId":"updateScriptOverrides","idempotent":false},"cli":{"command":"sleeperhit script overrides set <scriptUploadId> [--avatar <text>] [--theater <text>] [--soundscape <text>] [--pitch-deck <text>] [--locations <text>] [--clear <override>]"},"mcp":{"tool":"update_script_overrides","resource":null,"workflowId":"series-bible-development"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"projects.episodes.list","title":"List a project's episodes, versions and videos","description":"Read what the Writers Lab's Seasons & episodes and Videos pages show for one project: its seasons (named, with their episode counts), every episode — the ones uploaded, started from the Series Bible or written in the app included — with its logline, format, genre, season, feed release and every version (with what has been made from it), the Series Bible's planned episodes joined against what is written, and the project's videos. An earlier attempt at an episode is included and marked `supersededBy`. `season` narrows it to one season. Read-only; costs no credits.","availability":"available","tags":["projects","project_episodes"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:read"]},"api":{"method":"GET","path":"/story-projects/{projectId}/episodes","operationId":"listProjectEpisodes","idempotent":false},"cli":{"command":"sleeperhit projects episodes <projectId> [--season N]"},"mcp":{"tool":"list_project_episodes","resource":null,"workflowId":"projects-sources"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"projects.seasons.create","title":"Name a new season","description":"Add a season to a project: the lowest free season number, named as given (at most 80 characters) or \"Season N\". Move an episode into it with the script update's `seasonNumber`. Refused with 409 `project_precondition_failed` until the project can plan. Costs no credits.","availability":"available","tags":["projects","project_seasons"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:write"]},"api":{"method":"POST","path":"/story-projects/{projectId}/seasons","operationId":"createProjectSeason","idempotent":true},"cli":{"command":"sleeperhit projects seasons add <projectId> [--name <text>]"},"mcp":{"tool":"create_project_season","resource":null,"workflowId":"projects-sources"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"scripts.upload","title":"Upload a screenplay","description":"Upload a screenplay the writer already has as a new script in no project, with its first version parsed and its characters analysed in the background; put it in a project with the from-script project create. Refused with 403 `plan_limit_reached` past the plan's page allowance. Costs no credits.","availability":"available","tags":["scripts","script_upload"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:write"]},"api":{"method":"POST","path":"/scripts","operationId":"uploadScript","idempotent":true},"cli":{"command":"sleeperhit script upload --title <title> --file <path> [--format text|fountain|fdx]"},"mcp":{"tool":"upload_script","resource":null,"workflowId":"projects-sources"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"scripts.get","title":"Read a script","description":"Read one script the writer owns, however it was made: its title, URL slug, logline, format, genre, season, project and every version with what has been made from it. The id is the script's own, the id in its Writers Lab URL, or any version's (`scriptUploadId`). Read-only; costs no credits.","availability":"available","tags":["scripts","script_metadata"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:read"]},"api":{"method":"GET","path":"/scripts/{scriptUploadId}","operationId":"getScript","idempotent":false},"cli":{"command":"sleeperhit script show <scriptId>"},"mcp":{"tool":"get_script","resource":null,"workflowId":"projects-sources"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"scripts.update","title":"Change a script's title, logline, format, genre or season","description":"Change a script's own fields in one partial update: `title` (renames the latest version too), `slug`, `logline` (at most 500 characters — the writer's own, the one Slug reads; coverage keeps its own reading), `mediaType` (film or tv), `genre` (free text up to 80 characters) and `seasonNumber` (1–99: moves an episode into that season of its project, adding the season when it is new). A bad value is refused with 400 `validation_failed`, the same sentence the Writers Lab shows. Costs no credits.","availability":"available","tags":["scripts","script_metadata"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:write"]},"api":{"method":"PATCH","path":"/scripts/{scriptUploadId}","operationId":"updateScript","idempotent":false},"cli":{"command":"sleeperhit script update <scriptId> [--title <t>] [--slug <s>] [--logline <text>] [--media-type film|tv] [--genre <text>] [--season N] [--clear logline|genre|media-type]"},"mcp":{"tool":"update_script","resource":null,"workflowId":"projects-sources"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"scripts.versions.upload","title":"Upload a new version of a script","description":"Upload the next version of a script, parsed and analysed in the background, with the previous version's episode overrides copied forward; earlier versions are kept. Refused with 403 `plan_limit_reached` on the free plan (one version per script) or past the page allowance. Costs no credits.","availability":"available","tags":["scripts","script_versions"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:write"]},"api":{"method":"POST","path":"/scripts/{scriptUploadId}/versions","operationId":"uploadScriptVersion","idempotent":true},"cli":{"command":"sleeperhit script versions add <scriptId> --file <path> [--format text|fountain|fdx]"},"mcp":{"tool":"upload_script_version","resource":null,"workflowId":"projects-sources"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"scripts.versions.delete","title":"Delete one version of a script","description":"Permanently delete ONE version of a script and what is scoped to it (character art, table reads and their share links, coverage, conversations); the other versions stay. Requires `confirmed: true`. Refused with 409 `script_in_use` (`details.uses`) while something live depends on this version — a release in the feed whose read performs it, a running job, an episode draft, a season-run slot, a pitch deck or a trailer — and with 409 `script_state_invalid` for the only version (delete the whole script instead). Banked audio stays in My Library. Irreversible; costs no credits.","availability":"available","tags":["scripts","script_versions"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:write"]},"api":{"method":"DELETE","path":"/scripts/{scriptUploadId}/versions/{versionId}","operationId":"deleteScriptVersion","idempotent":false},"cli":{"command":"sleeperhit script versions delete <scriptId> <scriptUploadId> --confirm"},"mcp":{"tool":"delete_script_version","resource":null,"workflowId":"projects-sources"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"scripts.export","title":"Export a screenplay as Fountain, Final Draft or PDF","description":"Export one version (or a script's latest) as Fountain, Final Draft (`fdx`) or a PDF, with or without its title page, for a page range, and in a chosen PDF typeface. Fountain and fdx come back as text, a PDF base64-encoded. Refused with 409 `script_state_invalid` for a version not parsed yet. Read-only; costs no credits.","availability":"available","tags":["scripts","script_export"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:read"]},"api":{"method":"GET","path":"/scripts/{scriptUploadId}/export","operationId":"exportScript","idempotent":false},"cli":{"command":"sleeperhit script export <scriptUploadId> --format fountain|fdx|pdf [--out <path>] [--no-title-page] [--from-page N] [--to-page N] [--font <font>]"},"mcp":{"tool":"export_script","resource":null,"workflowId":"projects-sources"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"projects.episodes.start","title":"Start a Series Bible episode as a draft","description":"Start a planned episode from the Series Bible's episode map: its empty draft, titled, summarized, in its label's season and linked to the plan entry — or the script that already covers it (`created: false`), never a second draft. Write into the returned `scriptUploadId` scene by scene with screenplay drafting, or whole with the content write, then finish it. Refused with 409 `project_precondition_failed` until the project can start an episode. Costs no credits.","availability":"available","tags":["projects","episode_start"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:write"]},"api":{"method":"POST","path":"/story-projects/{projectId}/episodes","operationId":"startPlannedEpisode","idempotent":true},"cli":{"command":"sleeperhit projects episodes start <projectId> <episodeId>"},"mcp":{"tool":"start_planned_episode","resource":null,"workflowId":"planning-screenwriting"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"scripts.content.write","title":"Write a version's text","description":"Write the whole screenplay text of a draft or a locked version, as the Writers Lab's editor saves it. With `expectedContent` it is a compare-and-swap: the write lands only if the version still holds exactly that text, else 409 `script_state_invalid`. A version a season run wrote is not edited here. Costs no credits.","availability":"available","tags":["scripts","script_editor"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:write"]},"api":{"method":"PATCH","path":"/scripts/{scriptUploadId}/content","operationId":"writeScriptContent","idempotent":false},"cli":{"command":"sleeperhit script write <scriptUploadId> --file <path> [--expected-file <path>]"},"mcp":{"tool":"write_script_content","resource":null,"workflowId":"planning-screenwriting"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"scripts.finish","title":"Finish a draft into a locked version","description":"Finalize a draft in two steps, as the editor does: without `coverage`, Slug's judgment of whether the last passing coverage can be carried forward (nothing locked); with `coverage: adopt`, that report is copied onto the version, the draft locked and the screenplay prepared; with `coverage: fresh`, the draft is locked and new coverage runs first (refused while the project gate holds paid work). Only a draft can be finished (409 `script_state_invalid`). Adopting costs no credits; fresh coverage is the coverage run.","availability":"available","tags":["scripts","script_editor"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:write"]},"api":{"method":"POST","path":"/scripts/{scriptUploadId}/finish","operationId":"finishDraft","idempotent":true},"cli":{"command":"sleeperhit script finish <scriptUploadId> [--coverage adopt|fresh]"},"mcp":{"tool":"finish_draft","resource":null,"workflowId":"planning-screenwriting"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"artifacts.coverage.versions","title":"List a screenplay's coverage history","description":"List every coverage report across every version of the screenplay, newest first — its id, status, score, which version it covers and whether that is the current one — for a table-read artifact or a writer's own episode. Read one with the coverage read's `reportId`. Read-only; costs no credits.","availability":"available","tags":["artifacts","coverage"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["artifact:read"]},"api":{"method":"GET","path":"/artifacts/{artifactId}/coverage/versions","operationId":"listCoverageVersions","idempotent":false},"cli":{"command":"sleeperhit coverage versions <artifactId>"},"mcp":{"tool":"list_coverage_versions","resource":null,"workflowId":"coverage-revision"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"artifacts.coverage.blacklist","title":"Read a Black List analysis","description":"Read the Black List analysis of a coverage report (`reportId`, else the latest complete one) for a table-read artifact or a writer's own episode. It runs by itself after coverage completes; null until then, or when professional coverage add-ons are not available for the episode. Read-only; costs no credits.","availability":"available","tags":["artifacts","coverage"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["artifact:read"]},"api":{"method":"GET","path":"/artifacts/{artifactId}/coverage/blacklist","operationId":"getBlackListAnalysis","idempotent":false},"cli":{"command":"sleeperhit coverage blacklist <artifactId> [--report <reportId>]"},"mcp":{"tool":"get_blacklist_analysis","resource":null,"workflowId":"coverage-revision"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"jobs.create","title":"Create a story job","description":"Reserve credits and enqueue artifact generation for an approved plan; if this creates screenplay pages, the adapter auto-loads the saved Series Bible, and coverage should run after the artifact is ready. A table read performs the project cast: from a plan it starts when the cast canon (+ voiceMap) covers every character (voices only for an audio project), or it adopts a finalized, cast-ready screenplay with `scriptUploadId`. A table_read request's `punchUp` adds a guarded punch-up pass over the written draft, one scene at a time, before it is scored (`neverSay` names the hard lines it may never introduce, and `firstLineClean` keeps the episode's first spoken line free of swearing). A pitch_deck request's `deckMode` picks a pitch (the default) or a showcase (an epic sizzle of the show's world), with `showcaseCharacters` naming who it must feature. A trailer job always stops at its plan: it plans the beats onto a `draft` trailer (the job's `progress.trailerJobId`) and renders and reserves nothing, so planning is free. The next step is approve_trailer_plan (POST /trailers/{jobId}/plan/approve; CLI: trailer approve-plan <jobId>), priced first: its quote (quote_approve_trailer_plan, or the route without `confirmed`) returns the 480p render quote and reserves nothing; with `confirmed: true` it reserves exactly the quoted calls and renders them. A pitch deck job always stops at its plan: it plans the chapters onto a `draft` deck (the job's `progress.pitchDeckJobId`) and renders and reserves nothing, so planning is free. The next step is approve_pitch_deck_plan (POST /pitch-decks/{jobId}/plan/approve; CLI: pitch-deck approve-plan <jobId>), priced first: its quote (quote_approve_pitch_deck_plan, or the route without `confirmed`) returns the 480p render quote and reserves nothing; with `confirmed: true` it reserves exactly the quoted calls and renders them.","availability":"available","tags":["jobs"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:write"]},"api":{"method":"POST","path":"/story-jobs","operationId":"createStoryJob","idempotent":true},"cli":{"command":"sleeperhit jobs create <planId> [--script <scriptUploadId>]"},"mcp":{"tool":"create_job","resource":null,"workflowId":"planning-screenwriting"},"docsUrl":"https://docs.sleeperhit.studio/quickstart"},{"id":"jobs.list","title":"List story jobs","description":"List queued and completed jobs.","availability":"available","tags":["jobs"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:read"]},"api":{"method":"GET","path":"/story-jobs","operationId":"listStoryJobs","idempotent":false},"cli":{"command":"sleeperhit jobs list"},"mcp":{"tool":"list_jobs","resource":null,"workflowId":"planning-screenwriting"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"jobs.get","title":"Read a story job","description":"Poll job status and artifact readiness; a RESERVED job with progress.stage=provider_backoff already has a centralized delayed retry.","availability":"available","tags":["jobs"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:read"]},"api":{"method":"GET","path":"/story-jobs/{jobId}","operationId":"getStoryJob","idempotent":false},"cli":{"command":"sleeperhit jobs get <jobId>"},"mcp":{"tool":"get_job","resource":null,"workflowId":"planning-screenwriting"},"docsUrl":"https://docs.sleeperhit.studio/quickstart"},{"id":"jobs.cancel","title":"Cancel a story job","description":"Cancel a job that has not started (PENDING, RESERVED, or FAILED before it started, which also stops it being resumed) and release unsettled credits.","availability":"available","tags":["jobs"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:write"]},"api":{"method":"POST","path":"/story-jobs/{jobId}/cancel","operationId":"cancelStoryJob","idempotent":true},"cli":{"command":"sleeperhit jobs cancel <jobId>"},"mcp":{"tool":"cancel_job","resource":null,"workflowId":"planning-screenwriting"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"jobs.resume","title":"Resume a story job","description":"Recover terminal legacy/pre-worker failures or continue a failed artifact finalize; active provider backoff is already scheduled centrally and is a replay-safe no-op.","availability":"available","tags":["jobs","recovery"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:write"]},"api":{"method":"POST","path":"/story-jobs/{jobId}/resume","operationId":"resumeStoryJob","idempotent":true},"cli":{"command":"sleeperhit jobs resume <jobId>"},"mcp":{"tool":"resume_story_job","resource":null,"workflowId":"planning-screenwriting"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"artifacts.list","title":"List job artifacts","description":"List artifacts produced by a job.","availability":"available","tags":["artifacts"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["artifact:read"]},"api":{"method":"GET","path":"/story-jobs/{jobId}/artifacts","operationId":"listStoryJobArtifacts","idempotent":false},"cli":{"command":"sleeperhit jobs artifacts <jobId>"},"mcp":{"tool":"list_artifacts","resource":null,"workflowId":"planning-screenwriting"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"artifacts.get","title":"Read an artifact","description":"Read a generated artifact, manifest URLs, and revision state.","availability":"available","tags":["artifacts"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["artifact:read"]},"api":{"method":"GET","path":"/artifacts/{artifactId}","operationId":"getStoryArtifact","idempotent":false},"cli":{"command":"sleeperhit artifacts get <artifactId>"},"mcp":{"tool":"get_artifact","resource":null,"workflowId":"planning-screenwriting"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"artifacts.renderVideo","title":"Render a table-read video","description":"Queue the opt-in MP4 render for a ready table-read artifact.","availability":"available","tags":["artifacts","video"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["artifact:publish"]},"api":{"method":"POST","path":"/artifacts/{artifactId}/render-video","operationId":"renderArtifactVideo","idempotent":true},"cli":{"command":"sleeperhit artifacts render-video <artifactId>"},"mcp":{"tool":"render_artifact_video","resource":null,"workflowId":"video-rendering"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"artifacts.renderVideo.status","title":"Read render status + share link","description":"Poll the durable render (theater MP4 / full-mix MP3) status for an artifact and get the shareable link to watch or listen.","availability":"available","tags":["artifacts","video"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["artifact:read"]},"api":{"method":"GET","path":"/artifacts/{artifactId}/render-video","operationId":"getArtifactRenderStatus","idempotent":false},"cli":{"command":"sleeperhit artifacts render-status <artifactId>"},"mcp":{"tool":"get_artifact_share","resource":null,"workflowId":"publishing-analytics"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"artifacts.theaterMotion.direct","title":"Direct a theater motion graphic","description":"Add or refine a motion beat (kinetic text, a lower-third, or a title card) in a table-read theater scene, baked into the durable theater video. Returns a shareable link to the enhanced video.","availability":"available","tags":["artifacts","theater"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["artifact:publish"]},"api":{"method":"POST","path":"/artifacts/{artifactId}/theater-motion","operationId":"directTheaterMotionBeat","idempotent":true},"cli":{"command":"sleeperhit artifacts theater-motion <artifactId> --scene <n> --entry <n> --composition motion-only|motion-over-clip|performance-motion-overlay [--caption <text>] [--direction <text>] [--duration <0.5..30>] [--clip-prompt <text>]"},"mcp":{"tool":"direct_theater_motion_beat","resource":null,"workflowId":"video-rendering"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"artifacts.theaterMotion.clip","title":"Generate a theater motion background clip","description":"Generate the background clip a \"motion-over-clip\" theater motion beat plays its text over (author the beat first). Returns a shareable link to the enhanced theater video.","availability":"available","tags":["artifacts","theater"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["artifact:publish"]},"api":{"method":"POST","path":"/artifacts/{artifactId}/theater-motion-clip","operationId":"generateTheaterMotionClip","idempotent":true},"cli":{"command":"sleeperhit artifacts theater-motion-clip <artifactId> --scene <n> --entry <n> [--prompt <text>] [--duration <4..30>]"},"mcp":{"tool":"generate_theater_motion_clip","resource":null,"workflowId":"video-rendering"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"artifacts.theaterCanvas.apply","title":"Design a theater scene canvas","description":"Commit a whole theater scene as one immersive canvas — an ordered list of full-canvas motion-graphic beats baked into the durable theater video. Returns a shareable link to the enhanced video.","availability":"available","tags":["artifacts","theater"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["artifact:publish"]},"api":{"method":"POST","path":"/artifacts/{artifactId}/theater-canvas","operationId":"applyTheaterCanvas","idempotent":true},"cli":{"command":"sleeperhit artifacts theater-canvas <artifactId> --scene <n> --beats <json-array>"},"mcp":{"tool":"apply_theater_canvas","resource":null,"workflowId":"video-rendering"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"artifacts.theater.get","title":"Read the theater presentation","description":"Read the table read's whole theater presentation (theater mode default, backgrounds, scene visuals, the active style set, the scene theme and transitions, the script pane, fonts, the title screen, fullscreen chrome, noun imagery), every style set it can take, and each scene's theater (text reveal, look, transition, backdrop prompt and media, FX cues). Free.","availability":"available","tags":["artifacts","table_read","theater"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["artifact:read"]},"api":{"method":"GET","path":"/artifacts/{artifactId}/theater","operationId":"getArtifactTheater","idempotent":false},"cli":{"command":"sleeperhit theater get <artifactId>"},"mcp":{"tool":"get_theater_settings","resource":null,"workflowId":"video-rendering"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"artifacts.theater.update","title":"Change the theater presentation","description":"Change the whole read's presentation in one partial update: theater mode default, moving backgrounds, scene visuals, a style set (`applyStyleSetId`), the scene theme and transitions, the script pane, fonts, the title screen, fullscreen chrome, and how noun images appear. Keys left out are untouched. The same save as the Table Read page's theater settings. Free: renders nothing.","availability":"available","tags":["artifacts","table_read","theater"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["artifact:publish"]},"api":{"method":"POST","path":"/artifacts/{artifactId}/theater","operationId":"updateArtifactTheater","idempotent":true},"cli":{"command":"sleeperhit theater update <artifactId> [--theater-mode on|off] [--backgrounds on|off] [--scene-visuals on|off] [--style-set <id>] [--transition <type>] [--transition-duration <ms>] [--heading-font <id>] [--dialogue-font <id>] [--layout <mode>] [--dialogue <presentation>] [--title <text>] [--subtitle <text>] [--title-layout <layout>] [--noun-imagery insets|replace_backdrop|off] [--json <presentation>]"},"mcp":{"tool":"update_theater_settings","resource":null,"workflowId":"video-rendering"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"artifacts.theater.scene","title":"Change one scene's theater","description":"Set one scene's text reveal, look, transition, backdrop prompt and media, and atmospheric FX cues (a list replaces the scene's cues; an empty list clears them). Fields left out are kept. The same save as the Table Read page's per-scene controls and Slug. Free: renders nothing.","availability":"available","tags":["artifacts","table_read","theater"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["artifact:publish"]},"api":{"method":"POST","path":"/artifacts/{artifactId}/theater-scene","operationId":"updateArtifactTheaterScene","idempotent":true},"cli":{"command":"sleeperhit theater scene <artifactId> --scene <n> [--text-reveal fade|drift|spotlight] [--backdrop-prompt <text>] [--media image|video] [--transition <type>] [--transition-duration <ms>] [--transition-prompt <text>] [--summary <text>] [--fx-cues <json-array> | --clear-fx-cues]"},"mcp":{"tool":"update_scene_theater","resource":null,"workflowId":"video-rendering"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"artifacts.theater.fxCues","title":"Write a scene's atmospheric FX cues","description":"Write a bounded set of atmospheric, non-text FX cues (light bursts, washes, weather, darkness) for one scene from its lines and mood, replacing the cues it had. Waits on the project gate.","availability":"available","tags":["artifacts","table_read","theater"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["artifact:publish"]},"api":{"method":"POST","path":"/artifacts/{artifactId}/theater-fx-cues","operationId":"generateArtifactTheaterFxCues","idempotent":true},"cli":{"command":"sleeperhit theater fx-cues <artifactId> --scene <n>"},"mcp":{"tool":"generate_scene_fx_cues","resource":null,"workflowId":"video-rendering"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"artifacts.theater.backdropPrompts","title":"Write scene backdrop prompts","description":"Write a backdrop prompt (the setting only) for every scene that has none, or for the named scenes; `force` writes over a scene's prompt. Each comes from the scene's heading, lines and mood in the show's look. Waits on the project gate.","availability":"available","tags":["artifacts","table_read","theater"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["artifact:publish"]},"api":{"method":"POST","path":"/artifacts/{artifactId}/theater-backdrop-prompts","operationId":"writeArtifactTheaterBackdropPrompts","idempotent":true},"cli":{"command":"sleeperhit theater backdrop-prompts <artifactId> [--scenes 0,2,5] [--force]"},"mcp":{"tool":"write_scene_backdrop_prompts","resource":null,"workflowId":"video-rendering"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"artifacts.nounImagery.get","title":"Read the noun imagery","description":"Read the noun-imagery library: how spoken-noun images appear in the live read (insets, replace_backdrop, off), how many lines name a depictable noun, and each noun's image and status. Free.","availability":"available","tags":["artifacts","table_read","theater"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["artifact:read"]},"api":{"method":"GET","path":"/artifacts/{artifactId}/noun-imagery","operationId":"getArtifactNounImagery","idempotent":false},"cli":{"command":"sleeperhit noun-imagery get <artifactId>"},"mcp":{"tool":"get_noun_imagery","resource":null,"workflowId":"video-rendering"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"artifacts.nounImagery.generate","title":"Build the noun imagery","description":"Find the depictable nouns on every spoken line and draw one image per noun, reused on every later mention (`force` draws every noun again), or draw ONE noun again (`noun`). Queued: poll the read. Waits on the project gate, the same as the Table Read page and Slug.","availability":"available","tags":["artifacts","table_read","theater"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["artifact:publish"]},"api":{"method":"POST","path":"/artifacts/{artifactId}/noun-imagery","operationId":"generateArtifactNounImagery","idempotent":true},"cli":{"command":"sleeperhit noun-imagery generate <artifactId> [--force] [--noun <key> [--label <text>] [--kind object|location|entity]]"},"mcp":{"tool":"generate_noun_imagery","resource":null,"workflowId":"video-rendering"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"artifacts.soundscapes.list","title":"List soundscape beds and regions","description":"List every scene's soundscape bed (over the lines it spans) and every custom region, in script order, with each one's sound, level, fades and play mode. Free.","availability":"available","tags":["artifacts","table_read","soundscape"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["artifact:read"]},"api":{"method":"GET","path":"/artifacts/{artifactId}/soundscapes","operationId":"listArtifactSoundscapes","idempotent":false},"cli":{"command":"sleeperhit soundscapes list <artifactId>"},"mcp":{"tool":"get_soundscapes","resource":null,"workflowId":"table-reads-audio"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"artifacts.soundscapes.manage","title":"Edit soundscape beds and regions","description":"Tune a scene's bed (label, line offsets, level, fades, loop or stretch), add, move or re-level a custom region, give a bed or region library audio, or take one off. Free; a finalized MP3/MP4 is marked stale.","availability":"available","tags":["artifacts","table_read","soundscape"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["artifact:publish"]},"api":{"method":"POST","path":"/artifacts/{artifactId}/soundscapes","operationId":"manageArtifactSoundscapes","idempotent":true},"cli":{"command":"sleeperhit soundscapes update-bed|add|update|attach|remove <artifactId>"},"mcp":{"tool":"update_soundscape/remove_soundscape","resource":null,"workflowId":null},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"artifacts.avatarVideo","title":"Animate a character's portrait","description":"Make a short animated talking portrait from one character's portrait (never the narrator). Queued: read the cast until `avatarVideoUrl` is set. Waits on the project gate, the same as the Table Read page and Slug.","availability":"available","tags":["artifacts","table_read","avatar"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["artifact:publish"]},"api":{"method":"POST","path":"/artifacts/{artifactId}/avatar-video","operationId":"animateArtifactAvatar","idempotent":true},"cli":{"command":"sleeperhit cast animate <artifactId> --character <name> [--description <text>]"},"mcp":{"tool":"animate_avatar","resource":null,"workflowId":"table-reads-audio"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"artifacts.refine","title":"Refine a table read","description":"Revise a table read in place while keeping the artifact id and share URLs stable.","availability":"available","tags":["artifacts","table_read"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["artifact:publish"]},"api":{"method":"POST","path":"/artifacts/{artifactId}/refine","operationId":"refineArtifact","idempotent":true},"cli":{"command":"sleeperhit refine <artifactId> <instruction...>"},"mcp":{"tool":"refine_artifact","resource":null,"workflowId":"coverage-revision"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"artifacts.finalize","title":"Finalize a durable MP3 or MP4","description":"Render a durable audio or video file for a table-read artifact. A finished MP3 the read's mix moved past renders again; `refresh` also updates one whose mix is unknown (the app's \"Update the recording\").","availability":"available","tags":["artifacts","table_read"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["artifact:publish"]},"api":{"method":"POST","path":"/artifacts/{artifactId}/finalize","operationId":"finalizeArtifact","idempotent":true},"cli":{"command":"sleeperhit finalize <artifactId> --mode audio|video [--refresh]"},"mcp":{"tool":"finalize_artifact","resource":null,"workflowId":"table-reads-audio"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"artifacts.finalize.retry","title":"Retry a failed durable MP3 finalize","description":"Resume a failed audio render from the existing artifact without regenerating its performance.","availability":"available","tags":["artifacts","table_read","recovery"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["artifact:publish"]},"api":{"method":"POST","path":"/artifacts/{artifactId}/finalize/retry","operationId":"retryArtifactFinalize","idempotent":true},"cli":{"command":"sleeperhit finalize <artifactId> --retry"},"mcp":{"tool":"retry_artifact_finalize","resource":null,"workflowId":"table-reads-audio"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"artifacts.cast","title":"Read a table-read cast","description":"Read voice assignments from the artifact manifest.","availability":"available","tags":["artifacts","voice"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["artifact:read"]},"api":{"method":"GET","path":"/artifacts/{artifactId}","operationId":"getStoryArtifact","idempotent":false},"cli":{"command":"sleeperhit cast <artifactId>"},"mcp":{"tool":"get_cast","resource":null,"workflowId":"table-reads-audio"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"artifacts.script.get","title":"Read table-read script content","description":"Read the backing script entries for a table-read artifact, or for a writer's own episode with no artifact (its script id, Writers Lab URL id or a version's scriptUploadId).","availability":"available","tags":["artifacts","table_read","script"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["artifact:read"]},"api":{"method":"GET","path":"/artifacts/{artifactId}/script","operationId":"getArtifactScript","idempotent":false},"cli":{"command":"sleeperhit script get <artifactId>"},"mcp":{"tool":"get_table_read_script","resource":null,"workflowId":"planning-screenwriting"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"artifacts.script.replace","title":"Replace a table-read screenplay exactly","description":"Version customer-authored screenplay content without an AI rewrite, optionally deferring automatic music and the durable audio render for exact clip production, while preserving stable artifact URLs.","availability":"available","tags":["artifacts","table_read","script"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["artifact:publish"]},"api":{"method":"POST","path":"/artifacts/{artifactId}/script","operationId":"replaceArtifactScript","idempotent":true},"cli":{"command":"sleeperhit script replace <artifactId> --file <path> [--instruction <text>] [--narration-policy include|suppress] [--defer-music] [--defer-audio-render]"},"mcp":{"tool":"replace_artifact_script","resource":null,"workflowId":"planning-screenwriting"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"artifacts.script.page","title":"Read script content by page","description":"Read actual script entries on one rendered page.","availability":"available","tags":["artifacts","table_read","script"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["artifact:read"]},"api":{"method":"GET","path":"/artifacts/{artifactId}/script","operationId":"getArtifactScript","idempotent":false},"cli":{"command":"sleeperhit script page <artifactId> <page>"},"mcp":{"tool":"get_script_page","resource":null,"workflowId":"planning-screenwriting"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"artifacts.script.scene","title":"Read script content by scene","description":"Read actual script entries in one scene window.","availability":"available","tags":["artifacts","table_read","script"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["artifact:read"]},"api":{"method":"GET","path":"/artifacts/{artifactId}/script","operationId":"getArtifactScript","idempotent":false},"cli":{"command":"sleeperhit script scene <artifactId> <sceneIndex>"},"mcp":{"tool":"get_script_scene","resource":null,"workflowId":"planning-screenwriting"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"artifacts.script.character","title":"Read character lines","description":"Read actual dialogue entries for one character.","availability":"available","tags":["artifacts","table_read","script"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["artifact:read"]},"api":{"method":"GET","path":"/artifacts/{artifactId}/script","operationId":"getArtifactScript","idempotent":false},"cli":{"command":"sleeperhit script character <artifactId> <character...>"},"mcp":{"tool":"get_character_lines","resource":null,"workflowId":"planning-screenwriting"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"artifacts.recastVoice","title":"Recast a character voice","description":"Reassign one character voice on a table read without changing share URLs. The cast canon person follows (unless pinToCanon is false), and the previous voice and recording stay restorable.","availability":"available","tags":["artifacts","voice"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["artifact:publish"]},"api":{"method":"POST","path":"/artifacts/{artifactId}/voice","operationId":"recastArtifactVoice","idempotent":true},"cli":{"command":"sleeperhit voice set <artifactId> --character <c> --voice-id <id> --voice-name <name> [--no-canon]"},"mcp":{"tool":"recast_voice","resource":null,"workflowId":"table-reads-audio"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"artifacts.restoreVoice","title":"Restore a character's previous voice","description":"Undo the newest recast of a character on a table read: the previous voice comes back with the recording the read had before it (and the canon voice while the canon still holds the recast one). Free; restoring again flips back.","availability":"available","tags":["artifacts","voice"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["artifact:publish"]},"api":{"method":"POST","path":"/artifacts/{artifactId}/voice/restore","operationId":"restoreArtifactVoice","idempotent":true},"cli":{"command":"sleeperhit voice restore <artifactId> [--character <c>]"},"mcp":{"tool":"restore_voice","resource":null,"workflowId":"table-reads-audio"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"artifacts.revoiceCharacter","title":"Re-voice one character in a finished read","description":"Speak one character's lines again in a new voice (or their cast canon voice) and keep every other line of the finished read as recorded, then mix it again. METERED: TWO CALLS — without `confirmed` it prices the re-voice (`quotedOnly: true`, `credits`, `lines`, `keptLines`, `balanceAfter`, `sufficient`, `note`) and changes nothing; with `confirmed: true` it reserves, recasts (previous voice and recording stay restorable) and queues the finalize. Refused before the price (409 `cast_voice_precondition_failed`) for a read with no finished recording, a character with no lines, a voice it already speaks with, a finalize running, or a recording whose lines overlap.","availability":"available","tags":["artifacts","voice"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["artifact:publish"]},"api":{"method":"POST","path":"/artifacts/{artifactId}/revoice","operationId":"revoiceArtifactCharacter","idempotent":true},"cli":{"command":"sleeperhit voice revoice <artifactId> --character <c> [--voice-id <id> --voice-name <name>] [--confirm]"},"mcp":{"tool":"revoice_character","resource":null,"workflowId":"table-reads-audio"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"artifacts.revoiceLine","title":"Re-voice one line at a new speed","description":"Speak one line of a table read again from its voice's provider at a new speed — the provider's own speed parameter (Cartesia 0.6–1.5, ElevenLabs 0.7–1.2, Deepgram 0.7–1.5), never a time-stretch — keeping every other line as recorded, then mix it again. FREE (0 credits), still TWO CALLS — without `confirmed` it quotes (`quotedOnly: true`, `credits` 0, `mode`, `speed`, `range`, `note`) and changes nothing; with `confirmed: true` it does it. `mode` says what it does: `revoice` (the line spoken again), `restore_take` (a take the line had at that speed comes back) or `save` (a read with no recording yet). Refused before the quote (409 `cast_voice_precondition_failed`) for an OpenAI or Hume voice, or a model or voice with no speed setting (Eleven v3, Cartesia before sonic-3, a Deepgram Aura-1 voice or a Cartesia professional clone), a speed it already has, a modified take, a finalize running, or a recording that cannot be cut line by line.","availability":"available","tags":["artifacts","voice"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["artifact:publish"]},"api":{"method":"POST","path":"/artifacts/{artifactId}/revoice-line","operationId":"revoiceArtifactLine","idempotent":true},"cli":{"command":"sleeperhit voice revoice-line <artifactId> --entry <index> --speed <x> [--confirm]"},"mcp":{"tool":"revoice_line","resource":null,"workflowId":"table-reads-audio"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"artifacts.recastAvatar","title":"Regenerate a character avatar","description":"Re-render one character avatar portrait on a table read in place (async, queue-backed) without changing share URLs.","availability":"available","tags":["artifacts","cast","avatar"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["artifact:publish"]},"api":{"method":"POST","path":"/artifacts/{artifactId}/avatar","operationId":"recastArtifactAvatar","idempotent":true},"cli":{"command":"sleeperhit avatar set <artifactId> --character <c> [--refine <text>] [--style <style>] [--confirm]"},"mcp":{"tool":"recast_avatar","resource":null,"workflowId":"table-reads-audio"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"artifacts.recastFigure","title":"Regenerate a character figure","description":"Re-render one character full-body figure — the cutout a render uses for that character — seeded from that character avatar so the two keep depicting the same person.","availability":"available","tags":["artifacts","cast","figure"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["artifact:publish"]},"api":{"method":"POST","path":"/artifacts/{artifactId}/figure","operationId":"recastArtifactFigure","idempotent":true},"cli":{"command":"sleeperhit figure set <artifactId> --character <c> [--refine <text>] [--reference <url>] [--confirm]"},"mcp":{"tool":"recast_figure","resource":null,"workflowId":"table-reads-audio"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"artifacts.updateCast","title":"Update the cast (voices + avatars)","description":"Batch-reassign voices and/or queue per-character avatar renders (with an optional cast-wide restyle) on a table read in place.","availability":"available","tags":["artifacts","cast","voice","avatar"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["artifact:publish"]},"api":{"method":"POST","path":"/artifacts/{artifactId}/cast","operationId":"updateArtifactCast","idempotent":true},"cli":{"command":"sleeperhit cast update <artifactId> --json '<entries-or-{entries,avatarStyle}>' [--confirm]  (cast-wide restyle: sleeperhit cast restyle <artifactId> --style <s> [--confirm])"},"mcp":{"tool":"update_cast","resource":null,"workflowId":"table-reads-audio"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"artifacts.getCast","title":"Read the enriched cast","description":"Read each character voice merged with its avatar (url, style, render status) for a table read, with identity warnings; poll after avatar renders.","availability":"available","tags":["artifacts","cast","voice","avatar"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["artifact:read"]},"api":{"method":"GET","path":"/artifacts/{artifactId}/cast","operationId":"getArtifactCast","idempotent":false},"cli":{"command":"sleeperhit cast <artifactId>"},"mcp":{"tool":"get_cast","resource":null,"workflowId":"table-reads-audio"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"artifacts.coverage.generate","title":"Generate script coverage","description":"Generate the recommended first development coverage round for the screenplay backing a table read — or a writer's own episode, by its script or version id — before finalization, pitch packaging, or later-installment work.","availability":"available","tags":["artifacts","coverage"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:write"]},"api":{"method":"POST","path":"/artifacts/{artifactId}/coverage","operationId":"generateArtifactCoverage","idempotent":true},"cli":{"command":"sleeperhit coverage generate <artifactId>"},"mcp":{"tool":"generate_coverage","resource":null,"workflowId":"coverage-revision"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"artifacts.coverage.get","title":"Read script coverage","description":"Poll or read the latest screenplay-rubric report from the shared coverage lifecycle for a table-read artifact, or for a writer's own episode by its script or version id. `overallScore` is the gated score: near the bar the script is judged up to three times and it is the MEDIAN of the judgments — `summary` says \"the median of N judgments\" and `judging` records each one, which gave the median and why.","availability":"available","tags":["artifacts","coverage"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["artifact:read"]},"api":{"method":"GET","path":"/artifacts/{artifactId}/coverage","operationId":"getArtifactCoverage","idempotent":false},"cli":{"command":"sleeperhit coverage get <artifactId>"},"mcp":{"tool":"get_coverage","resource":null,"workflowId":"coverage-revision"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"brand.coverage.analyze","title":"Analyze brand storytelling coverage","description":"Queue a brand-rubric report in the shared coverage lifecycle for marketing narrative (copy, a brand film, a founder pitch, a case study) across eight craft dimensions. Async — returns `{ reportId, status }`; poll the brand coverage read until complete.","availability":"available","tags":["brand","coverage"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:write"]},"api":{"method":"POST","path":"/brand-coverage","operationId":"analyzeBrandCoverage","idempotent":true},"cli":{"command":"sleeperhit brand-coverage generate <content|-> [--type <text>] [--audience <text>] [--industry <text>] [--channel <text>] [--voice <text>]"},"mcp":{"tool":"analyze_brand_coverage","resource":null,"workflowId":"coverage-revision"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"brand.coverage.get","title":"Read brand coverage report","description":"Poll or read a brand-rubric report from the shared coverage lifecycle by id.","availability":"available","tags":["brand","coverage"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:read"]},"api":{"method":"GET","path":"/brand-coverage/{reportId}","operationId":"getBrandCoverage","idempotent":false},"cli":{"command":"sleeperhit brand-coverage get <reportId>"},"mcp":{"tool":"get_brand_coverage","resource":null,"workflowId":"coverage-revision"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"brand.narrative.generate","title":"Generate brand storytelling","description":"Turn a brief (+ optional source facts) into a finished piece of brand storytelling held to the studio craft bar. Synchronous — returns `{ narrative, modelId }`. Will not invent claims beyond the supplied facts.","availability":"available","tags":["brand"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:write"]},"api":{"method":"POST","path":"/brand-narrative","operationId":"generateBrandNarrative","idempotent":true},"cli":{"command":"sleeperhit brand-narrative generate <brief|-> [--type <text>] [--audience <text>] [--industry <text>] [--channel <text>] [--voice <text>] [--length <text>] [--facts <file>]"},"mcp":{"tool":"generate_brand_narrative","resource":null,"workflowId":"coverage-revision"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"artifacts.music.generate","title":"Generate scene music","description":"Render scene music for a table-read artifact: durable per-scene music clips on defined-clip scripts (pass scene indexes to re-render specific clips), or regenerate adaptive soundtrack directions on realtime scripts. Clips render instrumental unless vocals are explicitly enabled per scene.","availability":"available","tags":["artifacts","music"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["artifact:publish"]},"api":{"method":"POST","path":"/artifacts/{artifactId}/music","operationId":"generateArtifactMusic","idempotent":true},"cli":{"command":"sleeperhit music generate <artifactId> [--coverage <0..1|0..100>] [--scenes 0,2,5]"},"mcp":{"tool":"generate_music","resource":null,"workflowId":"table-reads-audio"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"artifacts.music.update","title":"Update scene music","description":"Edit one scene's defined music clip (prompt, explicit vocals opt-in, disable, volume, fades, play-once vs loop, banked audio with start/end anchoring, or a final music-only post-roll), re-render clips, tune soundtrack direction for a whole read, one scene, or one entry, or change one scene's music direction field by field (`direction`: end transition, mix, ducking, tempo, density, brightness, instruments and the rest; the same save as the Table Read page's scene console, which drops the scene's rendered bed so the next render plays the new direction). `defined_clips` is the only music mode (realtime streaming is deprecated).","availability":"available","tags":["artifacts","music"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["artifact:publish"]},"api":{"method":"POST","path":"/artifacts/{artifactId}/music","operationId":"generateArtifactMusic","idempotent":true},"cli":{"command":"sleeperhit music update <artifactId> [--scene <n> --clip-prompt <text> --clip-volume <0..1> --clip-fade-in <ms> --clip-fade-out <ms> --clip-play-mode once|loop --clip-sound-url <url> --clip-duration-ms <ms> --clip-anchor start|end --clip-post-roll-ms <ms>] [--scene <n> --end-transition fadeOut|cut --mix <0..1> --ducking <0.1..1> --bpm <60..180> --density <0..1> --brightness <0..1> --instruments \"Cello:1.2,Piano:0.8\"] [--scope screenplay|scene|entry] [--mode merge|replace]"},"mcp":{"tool":"update_music","resource":null,"workflowId":"table-reads-audio"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"artifacts.music.get","title":"Read scene music status","description":"Poll scene-music readiness for a table-read artifact — music mode, status, per-scene defined clips (prompt, vocals, render status, audio URL), and each scene's music direction (`sceneDirections`: end transition, mix, ducking, tempo, instruments).","availability":"available","tags":["artifacts","music"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["artifact:read"]},"api":{"method":"GET","path":"/artifacts/{artifactId}/music","operationId":"getArtifactMusic","idempotent":false},"cli":{"command":"sleeperhit music get <artifactId>"},"mcp":{"tool":"get_music","resource":null,"workflowId":"table-reads-audio"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"artifacts.voiceModification","title":"Modify voices over a range","description":"Apply a voice effect (autotune) to a contiguous range of dialogue entries on a table-read artifact.","availability":"available","tags":["artifacts","voice"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["artifact:publish"]},"api":{"method":"POST","path":"/artifacts/{artifactId}/voice-modification","operationId":"modifyArtifactVoice","idempotent":true},"cli":{"command":"sleeperhit modify-voice <artifactId> --start <n> --end <n>"},"mcp":{"tool":"modify_voice","resource":null,"workflowId":"table-reads-audio"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"artifacts.performance","title":"Refine character performance","description":"Adjust emotion, speed (absolute or relative %), volume, and cadence across ALL of one character's lines — including the NARRATOR or ALL voiced lines — on a table-read artifact. A prompt-driven delivery refine, e.g. \"make the narration flatter and 20% faster\".","availability":"available","tags":["artifacts","performance","voice"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["artifact:publish"]},"api":{"method":"POST","path":"/artifacts/{artifactId}/performance","operationId":"updateArtifactPerformance","idempotent":true},"cli":{"command":"sleeperhit performance <artifactId> --character <name|NARRATOR|ALL> [--speed-factor 1.2] [--emotions a,b]"},"mcp":{"tool":"refine_performance","resource":null,"workflowId":"table-reads-audio"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"voices.list","title":"List my studio voices","description":"List the caller's reusable studio voices — designed (text-description) and cloned (recorded sample) — with provider and source tagging.","availability":"available","tags":["voices"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:read"]},"api":{"method":"GET","path":"/voices","operationId":"listStudioVoices","idempotent":false},"cli":{"command":"sleeperhit voices list"},"mcp":{"tool":"list_voices","resource":null,"workflowId":"table-reads-audio"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"voices.preview","title":"Hear a voice say a line","description":"Audition any voice — yours or a catalog voice — on given words or a character's own first line in a read, before assigning it. Free; the same words in the same voice are voiced once and cached.","availability":"available","tags":["voices"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:write"]},"api":{"method":"POST","path":"/voices/preview","operationId":"previewStudioVoice","idempotent":true},"cli":{"command":"sleeperhit voices preview <voiceId> (--text <line> | --artifact <artifactId> --character <c>) [--provider <p>]"},"mcp":{"tool":"preview_voice","resource":null,"workflowId":"table-reads-audio"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"voices.rename","title":"Rename a library voice","description":"Rename one of your library voices; cast canon people pinned to it carry the new name. Free.","availability":"available","tags":["voices"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:write"]},"api":{"method":"PATCH","path":"/voices/{voiceId}","operationId":"renameStudioVoice","idempotent":false},"cli":{"command":"sleeperhit voices rename <voiceId> --name <name>"},"mcp":{"tool":"rename_voice","resource":null,"workflowId":"table-reads-audio"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"voices.delete","title":"Delete a library voice","description":"Delete one of your library voices. A voice still pinned in a cast canon or spoken in a read is refused (409 `voice_in_use`, naming every use) until confirmed. Free.","availability":"available","tags":["voices"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:write"]},"api":{"method":"DELETE","path":"/voices/{voiceId}","operationId":"deleteStudioVoice","idempotent":false},"cli":{"command":"sleeperhit voices delete <voiceId> [--confirm]"},"mcp":{"tool":"delete_voice","resource":null,"workflowId":"table-reads-audio"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"voices.migrate","title":"Migrate a voice everywhere it is used","description":"Re-point every use of one voice — the cast canon (and so a recurring show's pinned voices), trailer and deck narrators, and every read with no finished recording — to a replacement, optionally within one project and one character. Free, two calls: without `confirmed` it shows what would change; with `confirmed: true` it migrates and records it, so it can be undone. Finished reads keep their recording and are listed in `skipped`. Refused (409 `voice_retired`) when the replacement's provider is retiring or retired.","availability":"available","tags":["voices"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:write"]},"api":{"method":"POST","path":"/voice-migrations","operationId":"migrateVoice","idempotent":true},"cli":{"command":"sleeperhit voices migrate <fromVoiceId> --to <toVoiceId> [--to-provider <p>] [--to-name <n>] [--project <projectId>] [--character <c>] [--confirm]"},"mcp":{"tool":"migrate_voice","resource":null,"workflowId":"table-reads-audio"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"voices.migrations","title":"List voice migrations","description":"Your recorded voice migrations, newest first, each with what it re-pointed, the finished reads it left on the old voice, and whether it was undone; optionally only those from or to one voice.","availability":"available","tags":["voices"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:read"]},"api":{"method":"GET","path":"/voice-migrations","operationId":"listVoiceMigrations","idempotent":false},"cli":{"command":"sleeperhit voices migrations [--voice <voiceId>]"},"mcp":{"tool":"list_voice_migrations","resource":null,"workflowId":"table-reads-audio"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"voices.migrationUndo","title":"Undo a voice migration","description":"Put every use a migration re-pointed back on the old voice, where it still holds the replacement; a use changed again since is kept. Free. Refused (409 `voice_retired`) once the old voice's provider has retired it.","availability":"available","tags":["voices"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:write"]},"api":{"method":"POST","path":"/voice-migrations/{migrationId}/undo","operationId":"undoVoiceMigration","idempotent":true},"cli":{"command":"sleeperhit voices migration-undo <migrationId>"},"mcp":{"tool":"undo_voice_migration","resource":null,"workflowId":"table-reads-audio"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"voices.cloneLink","title":"Mint a voice-clone recording link","description":"Mint a short-lived browser URL (My Library with the recorder ready) where the user records a 15-60s sample; the clone lands in their library as a reusable voice (tagged \"cloned\"). Headless surfaces hand this URL to the human — recording needs a microphone.","availability":"available","tags":["voices"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:write"]},"api":{"method":"POST","path":"/voices/clone-link","operationId":"createVoiceCloneLink","idempotent":true},"cli":{"command":"sleeperhit voices clone"},"mcp":{"tool":"create_voice_clone_link","resource":null,"workflowId":"table-reads-audio"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"voices.consentLink","title":"Mint a voice consent link","description":"Mint a 7-day browser link the person whose voice a CLONE is opens to confirm their consent: a clone cloned before consent records began (`consent.status: \"required\"` in GET /voices) is refused everywhere until they do. The link is the auth; hand it to them. Free. A cloned voice speaks only with its subject's recorded consent: the recorder asks the person speaking (not the account that sent the link) to say whose voice it is, confirm they are 18 or older, read a consent statement aloud and agree to it, and records who, when, the words and the link or session used; a recently deceased person's voice needs their estate's approval. A clone made before consent records began is listed with `consent.status: \"required\"` and refused (409 `voice_consent_required`) until its subject confirms through a consent link. Withdrawing consent stops every new use of the voice at once (409 `voice_consent_revoked`) and deletes it at the provider within 7 days; work already published stays up.","availability":"available","tags":["voices"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:write"]},"api":{"method":"POST","path":"/voices/{voiceId}/consent-link","operationId":"createVoiceConsentLink","idempotent":true},"cli":{"command":"sleeperhit voices consent <voiceId>"},"mcp":{"tool":"create_voice_consent_link","resource":null,"workflowId":"table-reads-audio"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"voices.revokeConsent","title":"Withdraw a cloned voice's consent","description":"Withdraw every consent on record for one of your cloned voices: from now on it is never used for anything new (409 `voice_consent_revoked`), and its copy at the voice provider is deleted within 7 days. Work already published stays up. Final. Free.","availability":"available","tags":["voices"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:write"]},"api":{"method":"POST","path":"/voices/{voiceId}/revoke-consent","operationId":"revokeVoiceConsent","idempotent":true},"cli":{"command":"sleeperhit voices revoke-consent <voiceId> --confirm"},"mcp":{"tool":"revoke_voice_consent","resource":null,"workflowId":"table-reads-audio"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"likeness.list","title":"List likeness approvals","description":"Every likeness approval the account holds: whose, who approved (the account holder, the person, or their estate), when, and whether it is active or revoked. A picture or video that would show a real, identifiable person who is living, or who died within the last 70 years, is made only with their recorded approval: the account holder approves their own likeness in one step from the dashboard, and anyone else approves through a link the account holder hands them, whose page asks the person (or a recently deceased person's estate) to confirm who they are, that they are 18 or older, and to agree to the exact words. Without it the request is refused (422 `likeness_consent_required`, naming the person). Approved likenesses are never shown in a sexual or intimate way. Withdrawing stops every new picture or video at once; work already published stays up.","availability":"available","tags":["likeness"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:read"]},"api":{"method":"GET","path":"/likeness-consents","operationId":"listLikenessConsents","idempotent":false},"cli":{"command":"sleeperhit likeness list"},"mcp":{"tool":"list_likeness_consents","resource":null,"workflowId":"table-reads-audio"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"likeness.link","title":"Mint a likeness approval link","description":"Mint a 7-day, single-use browser link for a real person (or, for someone who died within the last 70 years, their estate) to approve pictures and videos of them for this account. The link is the auth; hand it to them. An agent cannot approve on anyone's behalf; the account holder approves their own likeness in the dashboard. Free.","availability":"available","tags":["likeness"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:write"]},"api":{"method":"POST","path":"/likeness-consents/links","operationId":"createLikenessConsentLink","idempotent":true},"cli":{"command":"sleeperhit likeness link <name> [--email <email>]"},"mcp":{"tool":"create_likeness_consent_link","resource":null,"workflowId":"table-reads-audio"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"likeness.revoke","title":"Withdraw a likeness approval","description":"Withdraw a likeness approval the account holds: from now on a picture or video that would show that person is refused (422 `likeness_consent_required`). Work already published stays up. Final. Free.","availability":"available","tags":["likeness"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:write"]},"api":{"method":"POST","path":"/likeness-consents/{consentId}/revoke","operationId":"revokeLikenessConsent","idempotent":true},"cli":{"command":"sleeperhit likeness revoke <consentId> --confirm"},"mcp":{"tool":"revoke_likeness_consent","resource":null,"workflowId":"table-reads-audio"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"tableRead.performanceBooth.start","title":"Mint a Performance Booth recording link","description":"Audio Acting is ADDITIVE: a performed line keeps the writer's own timing and intonation in the assigned character voice, and every line NOT performed stays on TTS exactly as today. This mints a 7-day browser recording link bound to one table-read job — the link IS the auth, so hand it to the person doing the performing. Capture spans many lines and sessions; poll the status operation to see which lines have a ready take.","availability":"available","tags":["table-read","audio"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:write"]},"api":{"method":"POST","path":"/table-read/performance-booth","operationId":"startPerformanceBoothSession","idempotent":true},"cli":{"command":"sleeperhit performance-booth <jobId>"},"mcp":{"tool":"create_performance_booth_link","resource":null,"workflowId":"table-reads-audio"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"tableRead.performanceBooth.status","title":"Read which table-read lines have a performed take","description":"Which lines of a table read now carry a human performance, and which are still on TTS. Poll after handing out a recording link; a line with no take is not an error, it is the default.","availability":"available","tags":["table-read","audio"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:read"]},"api":{"method":"GET","path":"/table-read/performance-booth","operationId":"getPerformanceBoothStatus","idempotent":false},"cli":{"command":"sleeperhit performance-booth <jobId> --status"},"mcp":{"tool":"get_performance_booth_status","resource":null,"workflowId":"table-reads-audio"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"voices.pro.start","title":"Start a Pro voice clone","description":"Start a studio-grade (professional) voice clone fine-tuned on 30 min–2 hr of the speaker's audio; mints a long-lived browser recording link bound to the clone job. Premium, metered, async (~3 hr train, 250 credits on success).","availability":"available","tags":["voices"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:write"]},"api":{"method":"POST","path":"/voices/pro/start","operationId":"startProVoiceClone","idempotent":true},"cli":{"command":"sleeperhit voices clone --pro --name <name> [--language <iso>] [--upgrade-from <voiceId>]"},"mcp":{"tool":"create_pro_voice_clone_link","resource":null,"workflowId":"table-reads-audio"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"voices.pro.script","title":"Read the Pro voice clone recording script","description":"The ~30-minute mixed-register script the user reads aloud to collect Pro-clone audio. Returns `{ title, intro, totalEstSeconds, passages }`.","availability":"available","tags":["voices"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:read"]},"api":{"method":"GET","path":"/voices/pro/script","operationId":"getProVoiceCloneScript","idempotent":false},"cli":{"command":"sleeperhit voices pro script"},"mcp":{"tool":"get_pro_voice_clone_script","resource":null,"workflowId":"table-reads-audio"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"voices.pro.train","title":"Start Pro voice clone training","description":"Kick off the ~3 hour fine-tune for a Pro voice clone once enough audio is recorded. Charges 250 credits, settled only if training succeeds.","availability":"available","tags":["voices"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:write"]},"api":{"method":"POST","path":"/voices/pro/train","operationId":"startProVoiceCloneTraining","idempotent":true},"cli":{"command":"sleeperhit voices pro train <jobId>"},"mcp":{"tool":"start_pro_voice_clone_training","resource":null,"workflowId":"table-reads-audio"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"voices.pro.get","title":"Poll a Pro voice clone","description":"Poll a Pro voice clone job: status (collecting → training → ready | failed), audio collected vs required, whether it is trainable yet, and the resulting voiceId once ready.","availability":"available","tags":["voices"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:read"]},"api":{"method":"GET","path":"/voices/pro/{jobId}","operationId":"getProVoiceClone","idempotent":false},"cli":{"command":"sleeperhit voices pro status <jobId>"},"mcp":{"tool":"get_pro_voice_clone","resource":null,"workflowId":"table-reads-audio"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"pitchDeck.chapters.get","title":"Read a pitch deck's chapters","description":"Read the deck's chapters as they render. Each chapter carries its key and its number — `chapterIndex`, what every chapter edit takes, and `chapterNumber`: The chapter's place in the deck, counted from 1: the number a person says (\"chapter 2\") and every sentence uses. Never an input; chapter edits take `chapterIndex`. — its plan (what it delivers and shows, its words, who speaks its line — a cast member in their own voice, on camera when the chapter shows them and as a voice-over when it does not, or the narrator — its cast and the location key it is set in) and its render calls (at most 10s each): duration, audio mode, the location plate the render opens on, who is on camera, the shots and the lines spoken in them, the speech track, and every take — whether it played the cast's recorded lines, whether it opened on its planned framing, whether it was the call's one automatic retake at our cost, whether it was not checked for a person shown twice (`duplicateNotChecked`: never a pass, ranked below checked takes), whether its lip sync was not checked (`mouthNotChecked`: no on-camera speaker's mouth could be read — never a pass, never a retake, ranked below a take whose lips were measured passing), whether its checks have not completed (`checksPending`: its QA, its mouth or duplicate check, or its watch was interrupted — nothing proves it clean yet, it is never selected over a checked take, and the worker runs them again), whether it is a take that never finished (`abandoned`: the job holding its claim died before anything was sent, so the claim was released, any credits reserved for it went back, and the shot's next take was decided again — say \"a take that never finished (released)\"), every line the wrong person speaks (`identitySwaps`: the line's speaker found nowhere on camera and another cast member's face, matched by their identity image, following it — a miss that earns the automatic retake, told whose face must say it), whether it is uncertain (`mouthUncertain`: measured, but a reading sat inside the band around its limit — never a pass, never a retake, ranked below a measured pass and above a miss), every criterion missed or uncertain with its number and limit (`mouthFindings`: correlation, lag or trailing motion after the line for a speaker; open run, open share or openings for a still face), a content refusal (released, never retried; `reference_render_provider_ip_refused` is a shot refused as possibly someone else's intellectual property, whose notice names what to edit before it renders again), which take is selected, and what a priced retake would cost. Also the chapter's cut and poster frame, whether the plan changed since it rendered (`stale`), the master (a 480p preview in review, finished once the finish completes), the delivery class, the warnings the finish and export carry, `reassembly` (a failed deck: the stage it failed in, and whether the free re-assembly would put it back together now; a deck in review or complete: whether its master would be rebuilt now with the current sound rules, or why not), the asset preflight in draft and review (`videoModelPreflight`: what each chapter's render needs and what is missing, a missing location plate reported as made at render), and a browser `reviewUrl`. A read: it never compiles, renders, voices or makes a plate. `assembly` is the master being put together right now, null when nothing is being assembled: `stage` (the 480p `preview` or the `finished` cut), the `step` it is on (`cutting`: joining each chapter's or beat's chosen takes, with `unit` the one being joined and `done` of `total` joined so far; `text`: laying the on-screen text (the finished cut only); `sound`: laying the voices, music and sound under the cut; `finish_look`: laying the finish look on the picture (only when one is set); `stitching`: stitching everything into one video, with `percent` from the renderer's own frame count; `delivering`: levelling the sound and saving the file), `steps` in order, `startedAt`, and `sentence`, which says it in words. Nothing renders and nothing is charged while a cut is assembled, and it cannot be stopped: it is free and ends on its own. `verdict` is the review in the writer's words — lead with it: `progress` (one line: rendering, fixing N shots the review flagged, ready to watch), `verdict` (one paragraph naming the problems that are left, by chapter or beat), `working` (true while the engine works: nothing to do but wait), and `choices` (at most two, only once it has stopped: `finish`, `finish_anyway` — the finish with `acknowledgeVideoCoverage` — or `more_fixes` with its `credits`). The scores, findings, takes and checks stay in `videoCoverage`, the chapters' calls and `autoFix` for anyone who wants to step in. `autoFix` is the AUTOMATIC FIXES the render approval paid for up front: the approval quote carries an automatic-fix allowance beside the 480p render (`autoFixAllowance`), reserved with it. After the preview is stitched the engine watches it (video coverage) and retakes the shots the review flags — each new take told what the review saw, a shot at most twice, re-staged as a voice-over where the take rules allow — and renders flagged on-screen text again, all inside that allowance; then it stitches and watches the preview again. It stops at a clean 480p preview (`state: clean`), when the allowance is spent, when the review flags nothing a fix can clear, or after `maxRounds` rounds (`state: stopped`, `stopReason`, `stoppedBecause`). `state` is `waiting` (first pass rendering), `reviewing` or `fixing` while it works — do not retake or finish then, just poll. `allowanceCredits` is the ceiling, `drawnCredits` what fixes took from it (each charged only when its take lands), `heldCredits` what is still reserved (released when it stops); `rounds[]` lists each round's fixes with `why`. When it stopped short, `moreFixes` (if not null) offers one more grant of `credits` (the more-fixes op, priced first); otherwise the writer finishes anyway. The 720p finish is always the writer's own approval. `earlyLook` (while the first pass renders; null once the preview exists) lists every chapter or beat whose shots all have a take, with each take's clip in shot order (`units[].clips[].url`), and `roughCut` once two have landed: they can be watched as they land, nothing to do. `musicPlan` is the music the cut will carry, known before the stitch: the beds on its timeline (`source: timeline`), or for a deck with none the table read's score as the assembly will lay it (`table_read_score`), each bed with the chapters or beats it plays under and a `url` to listen to — say it early, so a music change is made before the finish. A score to picture asked for (`score`, from a draft on) leads with its direction and, once its sketch to the planned cut is composed, `score.sketchUrl` to listen to; while one is asked for, the table read's beds are not laid or projected. When a score asked for with a direction could not be composed (`score.status: failed`), the beds are not laid in its place either: the sentence says so plainly (\"The score couldn't be composed (reason in Details). The bell plays alone. Score to picture to try again.\") — say it to the writer.","availability":"available","tags":["pitch-deck","storyboard"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:read"]},"api":{"method":"GET","path":"/pitch-decks/{jobId}/chapters","operationId":"getPitchDeckChapters","idempotent":false},"cli":{"command":"sleeperhit pitch-deck chapters <jobId>"},"mcp":{"tool":"get_pitch_deck_chapters","resource":null,"workflowId":"pitch-deck-rendering"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"pitchDeck.storyboard.coverage.get","title":"Read pitch deck plan coverage","description":"Read the pre-render report for the exact pitch-deck journey plan that would render right now — current/stale, overall score, the 8.0 gate, seven dimensions, machine-checked plan defects, per-chapter notes, and priority fixes. A plan with no report yet reads back as `missing`, not as a 404; the latest draft edit's coverage, waiting to start, reads back as `queued` (a burst of edits is one run, started once the plan has been left alone for three minutes); a run that failed, or a draft edit whose coverage could not be queued at all (no Series Bible, no reachable coverage provider), reads back as `failed` with the reason in `failureMessage`. Near the bar the same revision is judged again and the gate decides on the median of each score: `judging` lists every judgment with its score, the medians, and whether another is pending. The report's `opening` is the judge's note on the deck's opening title sequence (`present`, `whatItSays`, `servesIntent`, `nextMove`).","availability":"available","tags":["pitch-deck","storyboard","coverage"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:read"]},"api":{"method":"GET","path":"/pitch-decks/{jobId}/storyboard/coverage","operationId":"getPitchDeckStoryboardCoverage","idempotent":false},"cli":{"command":"sleeperhit pitch-deck coverage <jobId>"},"mcp":{"tool":"get_storyboard_coverage","resource":null,"workflowId":"pitch-deck-rendering"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"pitchDeck.storyboard.coverage.generate","title":"Generate pitch deck plan coverage","description":"Queue a pre-render report for the current pitch-deck journey plan. It grades the PLAN, never a rendered frame, so it spends no render credits. The gate is 8.0 — stricter than the 7.0 foundational Bible gate — because a plan that renders wrong spends real money.","availability":"available","tags":["pitch-deck","storyboard","coverage"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:write"]},"api":{"method":"POST","path":"/pitch-decks/{jobId}/storyboard/coverage","operationId":"generatePitchDeckStoryboardCoverage","idempotent":true},"cli":{"command":"sleeperhit pitch-deck coverage <jobId> --generate"},"mcp":{"tool":"generate_storyboard_coverage","resource":null,"workflowId":"pitch-deck-rendering"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"pitchDeck.intent.get","title":"Read a pitch deck's intent","description":"Read what the pitch deck is FOR beside what its plan says: its intent, each chapter's arc stage and how it advances the central question, where the chapters break the arc, and plan coverage's first-time-viewer takeaway — written before the judge saw the intent — with the story checks. Every deck and trailer is planned from an explicit intent — what the video is for, its logline, theme, central question, stakes, what a first-time viewer is promised, a four-stage arc (setup, escalation, turn, closing question) and how the ending lands the question. Every chapter or beat names the arc stage it serves (`arcStage`), how it advances the central question (`advancesQuestion`) and, after the first, why it follows the one before it (`whyItFollows`: the visible link — a cause, an answer, a contrast, a match cut, a look, an object, a sound — and what it moves forward; one line, never shown on screen). Plan coverage first writes what a first-time viewer would take away from the plan without seeing the intent (`viewerTakeaway`, with how much of the story the words recited rather than let them work out: `toldVersusShown`, and where they lost the thread: `lostTheThread`), then compares it with the intent: intent clarity, the central question, the buildup and whether the theme is carried each fail the plan on their own, and so do subtext — a plan that recites its plot instead of posing its question — and transitions — a part that follows the one before it for no reason a first-time viewer can feel (`weakTransitions` names the weakest, each with its fix); voices (do the characters speak, rather than the narrator carrying everything) is scored beside them. A read.","availability":"available","tags":["pitch-deck","intent"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:read"]},"api":{"method":"GET","path":"/pitch-decks/{jobId}/intent","operationId":"getPitchDeckIntent","idempotent":false},"cli":{"command":"sleeperhit pitch-deck intent <jobId>"},"mcp":{"tool":"get_video_intent","resource":null,"workflowId":"pitch-deck-rendering"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"pitchDeck.intent.update","title":"Edit a draft pitch deck's intent","description":"Edit a DRAFT pitch deck's intent — its purpose, audience, logline, theme, central question, stakes, viewer promise, ending, or its whole four-stage arc (each stage's purpose, temperature and a 1–10 intensity that rises to the turn). Editing the intent is free and only while the plan is a draft (approving the plan approves its intent): it saves the new intent and queues plan coverage again for the latest revision — a burst of edits is one coverage run, started once the plan has been left alone for three minutes. The chapters or beats are not re-planned; edit them (their `arcStage`, `advancesQuestion` and `whyItFollows` included) to follow the new intent. Answers the saved intent, `planCoverage`, and `arcProblems` — where the chapters now break the new arc; fix them with the chapter refine's `arcStage` and `advancesQuestion`.","availability":"available","tags":["pitch-deck","intent"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:write"]},"api":{"method":"POST","path":"/pitch-decks/{jobId}/intent","operationId":"updatePitchDeckIntent","idempotent":true},"cli":{"command":"sleeperhit pitch-deck intent <jobId> [--purpose <text>] [--audience <text>] [--logline <text>] [--theme <text>] [--central-question <text>] [--stakes <text>] [--viewer-promise <text>] [--ending <text>] [--arc <json>]"},"mcp":{"tool":"update_video_intent","resource":null,"workflowId":"pitch-deck-rendering"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"pitchDeck.chapters.refine","title":"Refine one pitch deck chapter","description":"Edit one chapter's plan while the deck is a draft plan, in review or complete: its title (`title`, plan words that never make a take stale), what it delivers (`storyBeat`), what it shows on screen (`visualPlan`), its shot size (`shotType`: it must name a scale on the shot ladder — establishing, wide, medium or close, the scale word deciding, so \"medium close\" is a medium — or it is refused; the render is told it, so it stales a rendered chapter's takes; the answer's `shotLadderRung` names the rung), what its people physically do (`motionPlan`, the business its shots stage, and what the camera does where the chapter wants it), where it is set (`location`, a canonical location key; `null` clears it), the camera direction of its text layer (`motionPrompt`) and the hand-off into the next chapter, its words (narration and who speaks it, caption, text mode and treatment), its composition (image / text / both), what it is of (`chapterFocus`: `world` — the place itself, no cast on camera — or `cast`), the stage of the deck's intent it serves (`arcStage`: setup, escalation, turn or closing_question), how it advances the central question (`advancesQuestion`) and why it follows the chapter before it (`whyItFollows`: the link a viewer sees or hears, never on screen; \"\" clears it) — plan words that never make a take stale — its length, who is in the picture (`visibleCharacters`, the named characters on camera — each needs an identity reference; unnamed people need no listing; `featuredCharacter`), and its continuity (`propContinuity`, `wardrobeContinuity` and `screenDirection`, which the render is told as \"Props: …\", so a prop the writer is steering away from must leave them too; `continuityNotes`, which it never is; '' clears any of them). There is no image prompt and no cast reference mode: a chapter has no still, and its cast reaches the render as body figures. Free: it saves the plan. On a DRAFT plan nothing has rendered, so nothing goes stale: the next plan approval recompiles just this chapter, and the changed plan is queued for plan coverage again (`planCoverage` in the answer: `queued` for the latest edit — one run per burst of edits, started once the plan has been left alone for three minutes; the plan approval starts it at once and waits for its score). This is how a chapter the plan approval refused (`pitch_deck_render_blocked`, for example a sentence too long for one render) is fixed: refine that chapter, then price the approval again — the deck is not planned again. In review or complete an edit to what the chapter films marks its takes out of date (they stay playable) and a caption edit marks only its text layer; render the chapter again with the priced render-clip op. `chapterIndex`: The chapter's `chapterIndex`, exactly as the chapters read returns it: a key, not a position — a plan may key its chapters from 0 or from 1. A person's \"chapter 2\" is the chapter whose `chapterNumber` is 2; pass that chapter's `chapterIndex`. Answers `{ success, needsRerender, chapterIndex, chapterNumber, planCoverage, edited, jobId, status }` and a shareable `previewUrl` for the chapter: `edited` names the version the edit changed (`draft_plan` or `rendered_deck`), and every surface tells the writer which. A chapter can be added or removed on a draft plan too.","availability":"available","tags":["pitch-deck","storyboard"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:write"]},"api":{"method":"POST","path":"/pitch-decks/{jobId}/chapters/refine","operationId":"refinePitchDeckChapter","idempotent":true},"cli":{"command":"sleeperhit pitch-deck refine-chapter <jobId> --chapter <chapterIndex> [--title <text>] [--story-beat <text>] [--visual-plan <text>] [--shot-type <text>] [--motion-plan <text>] [--location <key> | --clear-location] [--transition-prompt <text>] [--motion-prompt <text>] [--caption <text>] [--text-treatment <text>] [--text-mode voiceover|caption] [--narration <text>] [--narration-voice <id> | --clear-narration-voice] [--composition image|text|both] [--chapter-focus world|cast] [--arc-stage setup|escalation|turn|closing_question] [--advances-question <text>] [--montage | --no-montage] [--keep-scene-sound | --no-scene-sound] [--line-delivery <text>] [--cut-into-next cut|dip] [--duration <4..30>] [--visible-characters <a,b>] [--featured-character <name>] [--prop-continuity <text>] [--wardrobe-continuity <text>] [--screen-direction <text>] [--continuity-notes <text>]"},"mcp":{"tool":"refine_pitch_deck_chapter","resource":null,"workflowId":"pitch-deck-rendering"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"pitchDeck.narrator.get","title":"Read the pitch deck narrator","description":"Read who narrates the deck: the voice every narrated line (chapter narration, lines over black) is spoken in, and where it comes from — `override` (cast for this deck), `cast_canon` (the cast canon's NARRATOR), `table_read_voice_map` (the table read's NARRATOR) or `default`. A deck's narrator speaks every line the narrator carries (chapter narration and lines over black). It resolves in one order: the voice cast for THIS deck (`set_pitch_deck_narrator`), else the cast canon's NARRATOR, else the table read's NARRATOR, else the default narrator. Casting or clearing it is free; on a rendered deck the narrated lines are voiced again in the new voice and the master is re-assembled, at no charge.","availability":"available","tags":["pitch-deck","audio","voice"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:read"]},"api":{"method":"GET","path":"/pitch-decks/{jobId}/narrator","operationId":"getPitchDeckNarrator","idempotent":false},"cli":{"command":"sleeperhit pitch-deck narrator <jobId>"},"mcp":{"tool":"get_pitch_deck_narrator","resource":null,"workflowId":"pitch-deck-rendering"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"pitchDeck.narrator.set","title":"Cast the pitch deck narrator","description":"Cast the voice that narrates THIS deck, or pass `voiceId: null` to drop back to the default (the cast canon's NARRATOR, else the table read's, else the default narrator). A deck's narrator speaks every line the narrator carries (chapter narration and lines over black). It resolves in one order: the voice cast for THIS deck (`set_pitch_deck_narrator`), else the cast canon's NARRATOR, else the table read's NARRATOR, else the default narrator. Casting or clearing it is free; on a rendered deck the narrated lines are voiced again in the new voice and the master is re-assembled, at no charge.","availability":"available","tags":["pitch-deck","audio","voice"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:write"]},"api":{"method":"POST","path":"/pitch-decks/{jobId}/narrator","operationId":"setPitchDeckNarrator","idempotent":true},"cli":{"command":"sleeperhit pitch-deck narrator <jobId> --voice-id <voiceId> [--provider <name>] | --clear"},"mcp":{"tool":"set_pitch_deck_narrator","resource":null,"workflowId":"pitch-deck-rendering"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"pitchDeck.interludes.update","title":"Set a pitch deck's black interludes","description":"Replace the deck's black interludes with the list given (an empty list removes them all; the chapters read returns them as `interludes`). A black interlude is a beat of pure black between two chapters (0.5 to 2 seconds), keyed by the chapter it follows (`afterChapterIndex`), that may carry one sound (a breath, a bell) or one short line heard over the dark, the narrator's or a character's own, always as a voice-over. It costs no render: the master draws the black and voices its line and its sound at no charge. Free: on a draft plan the changed plan is queued for coverage again; in review or complete the master is re-assembled.","availability":"available","tags":["pitch-deck","storyboard"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:write"]},"api":{"method":"POST","path":"/pitch-decks/{jobId}/interludes","operationId":"updatePitchDeckInterludes","idempotent":true},"cli":{"command":"sleeperhit pitch-deck interludes <jobId> --json <list> | --file <path> | --clear"},"mcp":{"tool":"update_pitch_deck_interludes","resource":null,"workflowId":"pitch-deck-rendering"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"pitchDeck.titleSequence.update","title":"Set a pitch deck's title sequence","description":"Set the deck's title sequence whole, or pass `titleSequence: null` to remove it (the chapters read returns it as `titleSequence`, with what each flash cut resolved to, each person's name super, `supers`, and on the bell beat grid where each intro and the title land, `beatTimeline`). A deck's title sequence opens its master, before the first chapter: optionally an epigraph (`epigraph`: its words and where they are from) and a source credit (`sourceCredit`), each quiet on black and held long enough to read; then flash cuts of six to ten frames to the people it names (`cast`, in order; `inShadow` darkens one), each the person's LIVING PORTRAIT — looking into the lens, still, breathing, rendered for the flash (priced first, its own step) — and until it is made a still, silent close from the deck's own takes or another rendered deck of the project (free), never one in which anyone speaks or moves; a still canon portrait image only when the writer asks for one (`flashSource: 'portrait'`); then the title (`title`, one word, in capitals) in a bold sans on black. The flash cuts and the title run `seconds` (3 to 5). With `nameSupers: true` each flash cut carries the person's NAME in the TITLE'S LOOK — the face and colour the title is drawn in (blood red, the heavy condensed sans, when the title is directed so), uppercase, large enough to read at 480p — on the bell beat with the face, set in the black BESIDE the picture (or over the top of it), never over the face: LABEL is the first word of the person's canon name in capitals unless their cast entry sets `label`, and `role` (up to 40 characters, optional) is a smaller line under it; a person `inShadow` gets no name unless their `label` is set (the shadow withholds who they are); how the names look and where they sit is directed with `titleElement: nameSupers`. With `beatGrid: true` the intros cut on the bell's beat: from the sequence's first frame a beat every `beatSeconds` (0.5 to 4; 2 when left out), each flash cut starting on a beat and holding exactly one beat (the one in shadow too), the title on the next beat for `titleBeats` beats (1 to 8; 2 when left out) — their seconds are then derived (beats × beatSeconds), and a score composed to the deck strikes its bell on every intro and on the title. Saving it is free: nothing is rendered for it (a motion close is its own priced step). `enabled: false` keeps it without playing it. How its words look and move is directed separately (`titleElement` on the direct-text-motion call; read back as `textMotion`), and a save keeps those directions. Free: on a draft plan the changed plan is queued for coverage again; in review or complete the master is re-assembled.","availability":"available","tags":["pitch-deck","storyboard"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:write"]},"api":{"method":"POST","path":"/pitch-decks/{jobId}/title-sequence","operationId":"updatePitchDeckTitleSequence","idempotent":true},"cli":{"command":"sleeperhit pitch-deck title-sequence <jobId> --title <WORD> --cast <names> [--shadow <name>] [--seconds <3-5>] [--epigraph <text> [--epigraph-attribution <text>]] [--source-credit <text>] [--name-supers on|off] [--role \"<name>=<role>\"]… [--label \"<name>=<LABEL>\"]… [--beat-grid on|off] [--beat-seconds <0.5-4>] [--title-beats <1-8>] [--flash-source \"<name>=deck|project|motion|portrait|auto\"]… [--on|--off] | --clear"},"mcp":{"tool":"update_pitch_deck_title_sequence","resource":null,"workflowId":"pitch-deck-rendering"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"pitchDeck.closingSequence.update","title":"Set a pitch deck's closing sequence","description":"Set the deck's closing sequence whole, or pass `closingSequence: null` to remove it (the chapters read returns it as `closingSequence`, with each card's length, where it starts in the master, its bell beat, the look it wears, and where the music and the bell fade out, `fadeOut`). A deck's closing sequence ends its master, after the last chapter, and mirrors its title sequence: optionally a closing quote (`quote`: its words, quoted exactly, and where they are from, cited exactly — one that answers the opening's epigraph, often from the same source), then \"Coming Soon\" (`comingSoon`, up to 40 characters; \"Coming Soon\" when left out), then the production credit (`productionCredit`; \"Sleeper Hit Studio\" when left out), each quiet on black, faded in and out and held long enough to read. It ADDS to the deck's length: no chapter is shortened for it. When the title sequence cuts on its bell beat grid, each card starts on a beat of that same grid and the bell lane accents it. Across it the music (the score or the beds) and the bell lane fade out smoothly to silence on the master's last frame: what still sounds at the last chapter's cut plays on under the cards. A card with no direction of its own wears the opening's look (the quote the epigraph's, the credit the source credit's, \"Coming Soon\" the title's or the epigraph's background), so the deck is sandwiched by one style. It is free: nothing is rendered for it, and a rendered deck's master is stitched again with it. `enabled: false` keeps it without playing it. How its words look and move is directed separately (`closingElement` on the direct-text-motion call; read back as `textMotion`), and a save keeps those directions. Free: on a draft plan it is saved on the plan; in review or complete the master is re-assembled.","availability":"available","tags":["pitch-deck","storyboard"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:write"]},"api":{"method":"POST","path":"/pitch-decks/{jobId}/closing-sequence","operationId":"updatePitchDeckClosingSequence","idempotent":true},"cli":{"command":"sleeperhit pitch-deck closing-sequence <jobId> [--quote <text> [--quote-attribution <source>] | --no-quote] [--coming-soon <text>] [--production-credit <text>] [--on|--off] | --clear"},"mcp":{"tool":"update_pitch_deck_closing_sequence","resource":null,"workflowId":"pitch-deck-rendering"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"pitchDeck.visualGrammar.update","title":"Set a pitch deck's visual grammar","description":"Replace the deck's visual grammar, at most 2000 characters (the chapters read returns the current one as `visualGrammar`). The visual grammar is the deck's one camera language across every chapter: how its world is lit and framed, how the camera moves or holds, and how chapters hand off. It is plan words: plan coverage judges every chapter against it, and nothing rendered reads it, so changing it never makes a take out of date. Free: on a draft plan the changed plan is queued for coverage again; in review or complete it is saved on the plan and nothing else happens. Refused while a render or finish pass runs.","availability":"available","tags":["pitch-deck","storyboard"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:write"]},"api":{"method":"POST","path":"/pitch-decks/{jobId}/visual-grammar","operationId":"updatePitchDeckVisualGrammar","idempotent":true},"cli":{"command":"sleeperhit pitch-deck visual-grammar <jobId> [--text <words> | --file <path>]"},"mcp":{"tool":"update_pitch_deck_visual_grammar","resource":null,"workflowId":"pitch-deck-rendering"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"pitchDeck.titleSequence.motionCloses","title":"Make living portraits for a pitch deck's title intros","description":"Price, then make, each person's living portrait for the title intros — looking into the lens, still, breathing (the chapters read lists whose is not made yet as `titleSequence.motionClosesNeeded`, and every one made as `titleSequence.motionCloses`). Every intro is a LIVING PORTRAIT (owner, 2026-10-07: \"They should just be looking at the camera and breathing but not in motion … we don't want them to be speaking unless we're using words\"). Each person's flash is, in order: their living portrait (`source: motion`: one short WAN shot rendered for the flash from their cast portrait, the person looking straight into the lens, still, breathing, an occasional blink, lips closed, lit and graded like the deck, 480p, a few seconds, PRICED FIRST through the motion-close step and never spent silently; one another deck of the project made is reused free); until one is made, a STILL, SILENT close of them from the deck's own cut (`source: cut`, free) or another rendered deck of the project (`source: reuse`, free; `fromDeck` names it), with `needsMotionClose: true` while their living portrait is not made. A close stands in only when nobody speaks on camera in its shot, the mouth check and the take watcher saw no mouth move there, the person is alone, and its picture measured still (no walk, gesture, turn or camera move) — in motion means speaking with words, and a flash plays the score, never a line, so a close in which anyone speaks or moves never opens an intro. A person `inShadow` stays in shadow, as still. A cast entry's `flashSource` (`motion`, `deck`, `project` or `portrait`) puts that source first; `portrait` is their still canon portrait image, used only when asked for. With neither, `source` is `missing` with `needsMotionClose: true`: their beat stays black, and `motionClosesNeeded` prices the living portrait that would fill it. A motion close is a person's LIVING PORTRAIT for their title intro: one WAN shot of their face and shoulders from their cast portrait, the person looking straight into the lens and holding still — breath, an occasional blink, lips closed — lit and graded like the deck (its Series Bible's look), at 480p, silent, 3 seconds on the 2 s bell (the flash's beat plus room), in shadow when the sequence keeps them in shadow. PRICED FIRST — TWO CALLS on the API and the CLI, two tools on MCP and in chat (quote_render_pitch_deck_title_motion_closes, then render_pitch_deck_title_motion_closes): without `confirmed` it prices every person whose intro is not yet their living portrait (`motionClosesNeeded` in the read: about 6 people × 3 s at 480p for a father and his sons), or the people named in `names` (a new take of someone who has one is priced again), and spends nothing; with `confirmed: true` it reserves exactly those lines and renders them. Allowed while the deck is in review or complete. When each lands it is checked like a take (a file that decodes, silent, its length) and the master is re-assembled with it, free; a render that fails or is refused is released (nothing charged). Read each one back as `titleSequence.motionCloses` (`livingPortrait` false: a moving close made before 2026-10-07, which no longer opens an intro).","availability":"available","tags":["pitch-deck","storyboard"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["artifact:publish"]},"api":{"method":"POST","path":"/pitch-decks/{jobId}/title-sequence/motion-closes","operationId":"renderPitchDeckTitleMotionCloses","idempotent":true},"cli":{"command":"sleeperhit pitch-deck title-motion-closes <jobId> [--name <name>]… [--confirm]"},"mcp":{"tool":"render_pitch_deck_title_motion_closes","resource":null,"workflowId":"pitch-deck-rendering"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"pitchDeck.look.get","title":"Read the pitch deck finish","description":"Read the film finish laid on the deck's picture at master assembly (`finish`: its look, intensity and adjustments), each effect's level in it, and every look and intensity there is. The finish is a film look laid on the picture when the master is assembled: a look (camera, period-35mm, night-interior, none), an intensity (light, standard, strong; standard by default) and, optionally, single effects set to a level (adjust: { effect: off | subtle | medium | strong }; effects: steady-light, match-shots, halation, mist, shoulder, colour, vignette, weave, grain, soften). New decks and trailers start on camera. Titles and captions are laid after it, so type stays crisp, and the sound and timing are never touched. Setting it is free; on a rendered deck or trailer the master is assembled again with it (free), and setting the same finish again changes nothing.","availability":"available","tags":["pitch-deck","render"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:read"]},"api":{"method":"GET","path":"/pitch-decks/{jobId}/look","operationId":"getPitchDeckLook","idempotent":false},"cli":{"command":"sleeperhit pitch-deck look <jobId>"},"mcp":{"tool":"get_pitch_deck_look","resource":null,"workflowId":"pitch-deck-rendering"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"pitchDeck.look.set","title":"Set the pitch deck finish","description":"Set the film finish laid on the deck's picture at master assembly — the whole finish: a look (camera, period-35mm, night-interior, none), an intensity and optional per-effect adjustments. The finish is a film look laid on the picture when the master is assembled: a look (camera, period-35mm, night-interior, none), an intensity (light, standard, strong; standard by default) and, optionally, single effects set to a level (adjust: { effect: off | subtle | medium | strong }; effects: steady-light, match-shots, halation, mist, shoulder, colour, vignette, weave, grain, soften). New decks and trailers start on camera. Titles and captions are laid after it, so type stays crisp, and the sound and timing are never touched. Setting it is free; on a rendered deck or trailer the master is assembled again with it (free), and setting the same finish again changes nothing.","availability":"available","tags":["pitch-deck","render"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:write"]},"api":{"method":"POST","path":"/pitch-decks/{jobId}/look","operationId":"setPitchDeckLook","idempotent":true},"cli":{"command":"sleeperhit pitch-deck look <jobId> <camera|period-35mm|night-interior|none> [--intensity light|standard|strong] [--adjust <effect>=<level>,…]"},"mcp":{"tool":"set_pitch_deck_look","resource":null,"workflowId":"pitch-deck-rendering"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"pitchDeck.motionBlur.get","title":"Read the pitch deck motion blur","description":"Read the deck's motion blur: every chapter's shots, numbered as its cut plays them (with who speaks on camera), which are chosen, the strength, the seconds chosen against the cap, and, chapter by chapter, whether the last master laid the blur or why not, with the sentence the review shows. Motion blur makes chosen shots move like film: what moves in them blurs the way a camera's shutter blurs it, while still frames, faces held in frame and straight edges stay sharp. It is chosen per shot (or per chapter or beat: its moving shots, never a shot where someone speaks on camera unless that shot is named), at one of two strengths (standard, subtle; standard by default). It is free, up to 300 seconds of blurred picture per deck or trailer, and it is laid when the master is assembled, before the film finish. The sound and timing are never touched.","availability":"available","tags":["pitch-deck","render"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:read"]},"api":{"method":"GET","path":"/pitch-decks/{jobId}/motion-blur","operationId":"getPitchDeckMotionBlur","idempotent":false},"cli":{"command":"sleeperhit pitch-deck motion-blur <jobId>"},"mcp":{"tool":"get_pitch_deck_motion_blur","resource":null,"workflowId":"pitch-deck-rendering"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"pitchDeck.motionBlur.set","title":"Set the pitch deck motion blur","description":"Choose the shots of a chapter to blur — `{ units: [{ unit, shots? }], strength?, off? }`: `unit` is the chapter's `chapterIndex`, `shots` its shot numbers from the read, `moving` (the default: every shot where nobody speaks on camera) or [] to clear it; chapters not listed keep their choice; strengths standard, subtle. Motion blur makes chosen shots move like film: what moves in them blurs the way a camera's shutter blurs it, while still frames, faces held in frame and straight edges stay sharp. It is chosen per shot (or per chapter or beat: its moving shots, never a shot where someone speaks on camera unless that shot is named), at one of two strengths (standard, subtle; standard by default). It is free, up to 300 seconds of blurred picture per deck or trailer, and it is laid when the master is assembled, before the film finish. The sound and timing are never touched. On a rendered deck the master is assembled again with it (`reassembling`); free.","availability":"available","tags":["pitch-deck","render"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:write"]},"api":{"method":"POST","path":"/pitch-decks/{jobId}/motion-blur","operationId":"setPitchDeckMotionBlur","idempotent":true},"cli":{"command":"sleeperhit pitch-deck motion-blur <jobId> [--chapter <chapterIndex>[:<shot>,…|moving|none]]… [--strength standard|subtle] [--off]"},"mcp":{"tool":"set_pitch_deck_motion_blur","resource":null,"workflowId":"pitch-deck-rendering"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"pitchDeck.quietTrack.get","title":"Read the pitch deck quiet track","description":"Read what the deck's renders with no spoken line are sent as their voice track: `quietTrack` (silence, room_tone, or null: none, the default), `quietCalls` (the renders it reaches), `tooLong` (quiet renders over 15 s, never sent one), and `takesWithTrack` (takes already rendered with each). The quiet track sends every render of the deck that has no spoken line a voice track with nobody speaking in it (silence, or a soft room tone), the way a spoken render is sent the cast's lines, to test whether quiet faces keep their lips closed when the render hears a track. It is off by default and free, and it changes only the takes rendered after it is set: each take records the track it was sent, and a take already made keeps what it had. A render with a spoken line, and a chapter that keeps its own sound (bells, singers, a crowd), never gets one. A chapter that played its render's own room tone plays the track (silence, or the hush) instead.","availability":"available","tags":["pitch-deck","render"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:read"]},"api":{"method":"GET","path":"/pitch-decks/{jobId}/quiet-track","operationId":"getPitchDeckQuietTrack","idempotent":false},"cli":{"command":"sleeperhit pitch-deck quiet-track <jobId>"},"mcp":{"tool":"get_pitch_deck_quiet_track","resource":null,"workflowId":"pitch-deck-rendering"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"pitchDeck.quietTrack.set","title":"Set the pitch deck quiet track","description":"Set what the deck's renders with no spoken line are sent as their voice track — `{ quietTrack }`: silence or room_tone, or null to send none again (the field is required). The quiet track sends every render of the deck that has no spoken line a voice track with nobody speaking in it (silence, or a soft room tone), the way a spoken render is sent the cast's lines, to test whether quiet faces keep their lips closed when the render hears a track. It is off by default and free, and it changes only the takes rendered after it is set: each take records the track it was sent, and a take already made keeps what it had. A render with a spoken line, and a chapter that keeps its own sound (bells, singers, a crowd), never gets one. A chapter that played its render's own room tone plays the track (silence, or the hush) instead. Free; nothing is rendered by setting it — render or retake a chapter to use it.","availability":"available","tags":["pitch-deck","render"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:write"]},"api":{"method":"POST","path":"/pitch-decks/{jobId}/quiet-track","operationId":"setPitchDeckQuietTrack","idempotent":true},"cli":{"command":"sleeperhit pitch-deck quiet-track <jobId> --track silence|room_tone | --off"},"mcp":{"tool":"set_pitch_deck_quiet_track","resource":null,"workflowId":"pitch-deck-rendering"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"pitchDeck.videoModel.get","title":"Read the pitch deck video model","description":"Read which video model renders every chapter of the deck: `videoModel` (wan3-prime or vidu-q4; wan3-prime is the default), `chaptersOnAnotherModel` (rendered chapters made on the other model: out of date) and `renderedChapters`. The video model renders every chapter of the deck: WAN 3 (the default) or Vidu Q4. Changing it keeps the plan and every edit, and marks every rendered chapter out of date: the next render of the deck is quoted again and re-renders them on the new model. Takes already made are kept as they are. A render is priced in Studio Credits per second exactly as before; the quote states the model's own cost per second.","availability":"available","tags":["pitch-deck","render"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:read"]},"api":{"method":"GET","path":"/pitch-decks/{jobId}/video-model","operationId":"getPitchDeckVideoModel","idempotent":false},"cli":{"command":"sleeperhit pitch-deck video-model <jobId>"},"mcp":{"tool":"get_pitch_deck_video_model","resource":null,"workflowId":"pitch-deck-rendering"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"pitchDeck.videoModel.set","title":"Set the pitch deck video model","description":"Set which video model renders every chapter of the deck — `{ videoModel }`: wan3-prime or vidu-q4 (the field is required). The video model renders every chapter of the deck: WAN 3 (the default) or Vidu Q4. Changing it keeps the plan and every edit, and marks every rendered chapter out of date: the next render of the deck is quoted again and re-renders them on the new model. Takes already made are kept as they are. A render is priced in Studio Credits per second exactly as before; the quote states the model's own cost per second. Free; nothing is rendered by setting it — approve the plan or render the out-of-date chapters, each priced first.","availability":"available","tags":["pitch-deck","render"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:write"]},"api":{"method":"POST","path":"/pitch-decks/{jobId}/video-model","operationId":"setPitchDeckVideoModel","idempotent":true},"cli":{"command":"sleeperhit pitch-deck video-model <jobId> --model wan3-prime|vidu-q4"},"mcp":{"tool":"set_pitch_deck_video_model","resource":null,"workflowId":"pitch-deck-rendering"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"pitchDeck.versions.list","title":"List the pitch deck versions","description":"List the deck's versions, newest first: each published master's number, stage, date and link, the chapters and takes it played, its folder of raw clips and where that copy stands, and its zip. Every time a deck's master is published (a preview, an early look or the finished deck) it is kept as a numbered version: the master, and for every chapter in order the take each shot played (with its trim, and its finished copy on a finished deck), the chapter's cut before the film finish, its narration, speech, music, sound effects and text layer, and the finish it was laid with. Each version's cuts and takes are copied, untouched, into a folder of their own, one per chapter (pitch-decks/<deck>/versions/<n>-<YYYYMMDD-HHMM>/chapters/<NN>-<title>/), with a manifest.json, so a later re-render never loses the clips an earlier version played. Reading versions is free, and a zip of a version's clips is made on request, free.","availability":"available","tags":["pitch-deck","video"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:read"]},"api":{"method":"GET","path":"/pitch-decks/{jobId}/versions","operationId":"listPitchDeckVersions","idempotent":false},"cli":{"command":"sleeperhit pitch-deck versions <jobId>"},"mcp":{"tool":"list_pitch_deck_versions","resource":null,"workflowId":"pitch-deck-rendering"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"pitchDeck.versions.get","title":"Read a pitch deck version","description":"Read one version: every chapter in order with its cut before the film finish and the take each shot played (its trim, its finished copy), where each sits in the version's folder, its narration, speech, music, sound effects and text layer, the finish it was laid with, and every file of the folder. Every time a deck's master is published (a preview, an early look or the finished deck) it is kept as a numbered version: the master, and for every chapter in order the take each shot played (with its trim, and its finished copy on a finished deck), the chapter's cut before the film finish, its narration, speech, music, sound effects and text layer, and the finish it was laid with. Each version's cuts and takes are copied, untouched, into a folder of their own, one per chapter (pitch-decks/<deck>/versions/<n>-<YYYYMMDD-HHMM>/chapters/<NN>-<title>/), with a manifest.json, so a later re-render never loses the clips an earlier version played. Reading versions is free, and a zip of a version's clips is made on request, free.","availability":"available","tags":["pitch-deck","video"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:read"]},"api":{"method":"GET","path":"/pitch-decks/{jobId}/versions/{number}","operationId":"getPitchDeckVersion","idempotent":false},"cli":{"command":"sleeperhit pitch-deck version-clips <jobId> <number> [--download <dir>]"},"mcp":{"tool":"get_pitch_deck_version","resource":null,"workflowId":"pitch-deck-rendering"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"pitchDeck.versions.zip","title":"Ask for a pitch deck version zip","description":"Ask for a zip of a version's folder (its manifest.json and every clip, stored as they are). Made once off the request path, then kept: a ready zip answers its signed link (an hour); otherwise it is queued — read the version again until `zip.status` is `ready`. Free.","availability":"available","tags":["pitch-deck","video"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:write"]},"api":{"method":"POST","path":"/pitch-decks/{jobId}/versions/{number}/zip","operationId":"requestPitchDeckVersionZip","idempotent":true},"cli":{"command":"sleeperhit pitch-deck version-clips <jobId> <number> --zip"},"mcp":{"tool":"request_pitch_deck_version_zip","resource":null,"workflowId":"pitch-deck-rendering"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"pitchDeck.camera.get","title":"Read the pitch deck camera motion","description":"Read the deck's camera motion: every chapter's shots, numbered as its cut plays them, each with its camera (`held` — the render held it still, so it can take the handheld sway and a move —, `moving` or `handheld`) and who speaks on camera; the handheld strength; each chapter's move (a snap zoom onto a reaction or a slow reframe, with its shot and faces); and, chapter by chapter, what the last master laid or why a move was left out, with the sentence the review shows. Camera motion gives the held shots an operator, the way a documentary camera moves: a handheld sway on the shots that were rendered still (off, subtle, medium; never on a shot whose camera already moves or was filmed handheld, and never so far that a speaking mouth leaves the frame), and at most one move per chapter or beat, on a held shot where nobody speaks on camera: a snap zoom onto a reaction (up to 1.5×, right after a line) or a slow reframe from one face to another already in the frame. It is free, and laid when the master is assembled, as the first step of the film finish and before any type. The sound and timing are never touched.","availability":"available","tags":["pitch-deck","render"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:read"]},"api":{"method":"GET","path":"/pitch-decks/{jobId}/camera","operationId":"getPitchDeckCamera","idempotent":false},"cli":{"command":"sleeperhit pitch-deck camera <jobId>"},"mcp":{"tool":"get_pitch_deck_camera","resource":null,"workflowId":"pitch-deck-rendering"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"pitchDeck.camera.set","title":"Set the pitch deck camera motion","description":"Set the camera motion — `{ handheld?, moves?: [{ unit, move, shot?, target?, from?, zoom? }], off? }`: `handheld` (off, subtle, medium) sways every held shot; each move names its chapter by `unit` (the chapter's `chapterIndex`), its shot by number from the read, `move` `snap` (a snap zoom onto `target`, `zoom` 1.15–1.5, default 1.4) or `reframe` (from the face `from` to `target`), or `none` to clear the chapter; one move per chapter; chapters not listed keep theirs; `off: true` turns it all off. Refused, with the fix named: a shot whose camera already moves or is handheld, a shot where someone speaks on camera, a shot too short for the move, a face not in the shot's cast. Camera motion gives the held shots an operator, the way a documentary camera moves: a handheld sway on the shots that were rendered still (off, subtle, medium; never on a shot whose camera already moves or was filmed handheld, and never so far that a speaking mouth leaves the frame), and at most one move per chapter or beat, on a held shot where nobody speaks on camera: a snap zoom onto a reaction (up to 1.5×, right after a line) or a slow reframe from one face to another already in the frame. It is free, and laid when the master is assembled, as the first step of the film finish and before any type. The sound and timing are never touched. On a rendered deck the master is assembled again with it (`reassembling`); free.","availability":"available","tags":["pitch-deck","render"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:write"]},"api":{"method":"POST","path":"/pitch-decks/{jobId}/camera","operationId":"setPitchDeckCamera","idempotent":true},"cli":{"command":"sleeperhit pitch-deck camera <jobId> [--handheld off|subtle|medium] [--snap <chapterIndex>:<shot>:<NAME>[@<zoom>]]… [--reframe <chapterIndex>:<shot>:<FROM>><TARGET>]… [--clear <chapterIndex>]… [--off]"},"mcp":{"tool":"set_pitch_deck_camera","resource":null,"workflowId":"pitch-deck-rendering"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"pitchDeck.chapters.renderClip","title":"Render one pitch deck chapter again","description":"Render one chapter again at 480p — the writer's priced retake: a new take of one call (`callId`) or of every call of the chapter. A chapter whose plan changed since it rendered (or that never rendered, such as one inserted in review) is recompiled first (free) and its new calls are priced. Each new take is checked like every take and may earn the call's one automatic retake at our cost (a re-voiced line, or an opening off its planned framing); a moderation refusal is released and never retried. TWO CALLS: sent without `confirmed` it PRICES the render and reserves nothing (`quotedOnly: true`, `credits`, the `lines`, `balanceAfter` — what the writer would have left — `sufficient`, and a `note` to show the writer; when `sufficient` is false the note names the top-up link, and the caller must not confirm); sent again with `confirmed: true` it reserves exactly the quoted lines and queues the takes. Not a required `confirmed: true` literal — a field that must be true to validate cannot tell a confirmed call from an unconfirmed one. Refused before the price: a text-only chapter, a chapter that is not in the deck, a call id the chapter does not have, a changed chapter asked for one call, and a cast member with no body figure (the refusal names the action that fixes it in `error.details.refusal` / `error.details.blocked`). Review or complete only. Name the chapter by its `chapterIndex` from the chapters read — a key, not its place in the deck. Returns a shareable per-chapter `previewUrl`.","availability":"available","tags":["pitch-deck","storyboard"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["artifact:publish"]},"api":{"method":"POST","path":"/pitch-decks/{jobId}/chapters/render-clip","operationId":"renderPitchDeckChapterClip","idempotent":true},"cli":{"command":"sleeperhit pitch-deck render-clip <jobId> --chapter <chapterIndex> [--call <callId>] [--confirm]"},"mcp":{"tool":"render_pitch_deck_chapter_clip","resource":null,"workflowId":"pitch-deck-rendering"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"pitchDeck.chapters.selectTake","title":"Select a take of one pitch deck call","description":"Choose which take of one of a chapter's calls the cut plays and the finish delivers. Free and reversible — select another take to change it — so there is no price and nothing to confirm; the chapter's preview cut is re-assembled from the new selection. A take that replaced an on-camera line with its own reading (re-voiced) is never selected, by default or here: the refusal names the lines — stage the line as a voice-over, or render a new take. The answer's `warning` names anything else the chosen take was flagged for, and the finish quote and the export carry it too. In a complete deck a new selection sends the deck back to review, and the next finish quotes just that take. A call of another chapter is refused. Review or complete only. The path `{chapterIndex}` is the chapter's key from the chapters read — not its place in the deck. Answers `{ jobId, chapterIndex, callId, take, warning }`.","availability":"available","tags":["pitch-deck","storyboard"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:write"]},"api":{"method":"POST","path":"/pitch-decks/{jobId}/chapters/{chapterIndex}/select-take","operationId":"selectPitchDeckTake","idempotent":true},"cli":{"command":"sleeperhit pitch-deck select-take <jobId> --chapter <chapterIndex> --call <callId> --take <n>"},"mcp":{"tool":"select_pitch_deck_take","resource":null,"workflowId":"pitch-deck-rendering"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"pitchDeck.chapters.repairTake","title":"Repair one take of a pitch deck call in place","description":"Every rendered take is watched with its sound after its checks. A cut nobody asked for at the start or end of an otherwise good take is trimmed off first, before any new take: free, frame for frame, only where the cut is measured in the file, outside every spoken line (each kept whole with a breath after it), and only when what is left keeps its chapter or beat within a quarter of its planned length. When the shot's automatic new take is spent and the take it plays still has such a cut outside its line, that end is trimmed as a last resort: past the quarter, as long as the line stays whole, at least 2 seconds are left and the chapter or beat keeps half its planned length. A cut inside a spoken line is never trimmed. A speaker whose lips keep moving past the take's last line, where nothing is heard, is trimmed half a second after the line, free and frame for frame. Lips moving where no line is heard are never retaken on their own: the same staging brings them back, so the shot is offered for restaging (one face, framed closer), a trim, or your call. Any other defect is remedied by rule during processing, at our cost: first a new take told what to avoid; a repair in place when the same problem comes back after a new take, or when the take passed every other check and only something removable (a period anachronism, garbled lettering, a stray or doubled person) or the light is wrong. Camera movement and its speed (a move that rushes, or dies into a hold at the end), timing, cuts and a crowd moving as one (extras in step, everyone turning or looking down at once, repeated faces) are only ever fixed by a new take, or by the free trim when they sit only at an end of the take; spoken shots are not repaired in place. A line the speaker's mouth did not speak on two takes is no longer retaken on camera: the next take stages it as a voice-over, the speaker seen from behind, the line heard over the picture. Every take plays its own sound under its own picture, so the lips follow what is heard: a line said in the take's own reading is kept, and only a line not heard, or said in a voice too like another character's, is a defect (a new take). Where a speaker's mouth cannot be measured (or the face is too small to trust a miss), the watcher's own judgment of the lips decides the line: a mouth it saw not speak is a miss, one it saw speak is uncertain. Each shot gets at most one automatic new take, one automatic repair in place and one automatic voice-over re-stage, so a new take whose removable defect came back is repaired in the same pass; a repaired or trimmed take is never remedied again on its own. A repair that fails on the repair service's own side (never one declined at its content check) and cost nothing is sent again once; if that fails too, a new take instead. A repaired take keeps the take's own sound, is judged again, and is kept as a new take linked to the one it repairs; it plays only when it passes. A trimmed take plays over the take it came from when it passes, or when it shows only part of what that take showed, with the same speech and faces: it is judged by time window, so anything seen inside the span it keeps counts as that take's own footage too, and it wins when the trim cut something off. This is the writer's own repair of one take. TWO CALLS: sent without `confirmed` it PRICES the repair and reserves nothing (`quotedOnly: true`, `credits` for the seconds it sends — the whole take, or only the shots its defect sits in, two seconds at least — `summary`, `balanceAfter`, `sufficient` and a `note` to show the writer; when `sufficient` is false the caller must not confirm); sent again with `confirmed: true` it reserves exactly that line and queues the repair as a new take linked to the one it repairs (`repairTake`). The repaired take keeps the take's own sound, is checked again and plays only if it passes; a repair that does not land is released (nothing charged). Refused before anything is reserved: the project's spend gate, a take that is not an accepted take of the call, a repair of a repair, a take whose repair was declined at the content check (never sent again unchanged), a spoken shot (not repaired in place yet), repair not set up, and a length the repair cannot take. To render a new take instead, use render-clip with `callId`: a new take is told what the watcher saw on the takes before it. Review or complete only. The path `{chapterIndex}` is the chapter's key from the chapters read.","availability":"available","tags":["pitch-deck","storyboard"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["artifact:publish"]},"api":{"method":"POST","path":"/pitch-decks/{jobId}/chapters/{chapterIndex}/repair-take","operationId":"repairPitchDeckTake","idempotent":true},"cli":{"command":"sleeperhit pitch-deck repair-take <jobId> --chapter <chapterIndex> --call <callId> --take <n> [--confirm]"},"mcp":{"tool":"repair_pitch_deck_take","resource":null,"workflowId":"pitch-deck-rendering"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"pitchDeck.chapters.overrideTakeRepair","title":"Override the repair decision on one pitch deck take","description":"Override the repair engine on one take of a chapter's call. Free, so there is no price and nothing to confirm. `keep` keeps the take as it is: what was found on it no longer ranks it down or warns, and the engine never acts on it. `restore` lets the engine's decision stand again. The call's default selection re-runs unless the writer chose its take explicitly, and the cut re-assembles when the take it plays changed. `rewatch` watches again, at our cost, a take whose watch could not finish (its decision `unwatched`: never clean, never remedied on its own): its checks are queued and it is decided when the watch lands; a take already watched is refused. Review or complete only. Answers `{ jobId, callId, take, decision, repair, selectedTake, message }`. The path `{chapterIndex}` is the chapter's key from the chapters read.","availability":"available","tags":["pitch-deck","storyboard"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:write"]},"api":{"method":"POST","path":"/pitch-decks/{jobId}/chapters/{chapterIndex}/take-repair-override","operationId":"overridePitchDeckTakeRepair","idempotent":true},"cli":{"command":"sleeperhit pitch-deck override-repair <jobId> --chapter <chapterIndex> --call <callId> --take <n> --keep|--restore|--rewatch"},"mcp":{"tool":"override_pitch_deck_take_repair","resource":null,"workflowId":"pitch-deck-rendering"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"pitchDeck.chapters.trimTake","title":"Trim one take of a pitch deck call","description":"Trim one take of a chapter's call to a span: \"trim this take to <start>–<end>\". Free: one call, nothing priced, reserved or confirmed. The span `[keepStartSeconds, keepEndSeconds)` is snapped to the take's frames and kept as a NEW take linked to the one it trims (`trimTake`); the take itself stays. Never into a spoken line: the span must keep every line placed on the take's speech track whole (`trim_cuts_speech`), lie inside the take, keep at least the shortest a take is trimmed to, and not be the whole take (`trim_span_invalid`) — refused before anything is queued. The trimmed take is checked again and plays over the take it came from only if it passes; its cut then plays its real, shorter length. The repair engine trims on its own, first and for free, when a cut nobody asked for sits at the start or end of an otherwise good take (rule `trim_edge`), or a speaker's lips run on past the take's last line where nothing is heard (rule `trim_overrun`: cut half a second after the line as the take says it); each take's `trimBounds` says what it may keep. Review or complete only. Answers `{ jobId, callId, take, trimTake, keepStartSeconds, keepEndSeconds, queued, message }`. The path `{chapterIndex}` is the chapter's key from the chapters read.","availability":"available","tags":["pitch-deck","storyboard"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:write"]},"api":{"method":"POST","path":"/pitch-decks/{jobId}/chapters/{chapterIndex}/trim-take","operationId":"trimPitchDeckTake","idempotent":true},"cli":{"command":"sleeperhit pitch-deck trim-take <jobId> --chapter <chapterIndex> --call <callId> --take <n> --keep <start>-<end>"},"mcp":{"tool":"trim_pitch_deck_take","resource":null,"workflowId":"pitch-deck-rendering"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"pitchDeck.chapters.dropLine","title":"Cut a pitch deck chapter's line out, keep the rest of its footage","description":"Cut the line, keep the rest (free, one step): the chapter's spoken line leaves its plan (its words, its voice and how it is said), and each take that says it is trimmed to the footage on one side of it — after the line when the line opens the take, before it when it closes it — measured where the take says it, with a small pad, so nothing of the line is heard. The trimmed take is the same footage, so the chapter stays current: nothing is rendered or charged, the trimmed take plays as soon as it lands, and its sound is the take's own sound with the line cut out. A line with footage on both sides is refused until you choose keep before or keep after; so is a side shorter than 1.5 s, and a trim that would leave another chapter of its scene group with no shot. Name a chapter to move the line to and its words, speaker and delivery go there, to be rendered with that chapter's own staging; otherwise add it there with a refine. Free: one call, nothing priced, reserved or confirmed. `keep` (`before` | `after`) chooses the side of the line each take keeps (a line in the middle needs it); `toChapterIndex` moves the line's words, speaker and delivery into that chapter. The chapters read's `lineDrop` says what it would do now and `droppedLine` shows a line already cut out. Review or complete only. Answers `{ jobId, chapterIndex, chapterNumber, line, movedTo, trims, queued, resumed, current, message }`. The path `{chapterIndex}` is the chapter's key from the chapters read.","availability":"available","tags":["pitch-deck","storyboard"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:write"]},"api":{"method":"POST","path":"/pitch-decks/{jobId}/chapters/{chapterIndex}/drop-line","operationId":"dropPitchDeckChapterLine","idempotent":true},"cli":{"command":"sleeperhit pitch-deck drop-line <jobId> --chapter <chapterIndex> [--keep before|after] [--to <chapterIndex>]"},"mcp":{"tool":"drop_pitch_deck_chapter_line","resource":null,"workflowId":"pitch-deck-rendering"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"pitchDeck.chapters.stageVoiceOver","title":"Stage one pitch deck take's line as a voice-over","description":"Stage the line of one take of a chapter's call as a VOICE-OVER in a new take of the call: the speaker seen from behind, the cast's own voice laid over the picture, so no mouth has to follow the line. The lines staged are the call's on-camera lines that a take of it replaced with its own reading (a re-voiced take is never played), else every line it says on camera (each take's `voiceOverRestage` shows them, with the price). The engine does this on its own, at our cost, once the same line is re-voiced on two takes of a call. Metered like a new take of the call, TWO CALLS: sent without `confirmed` it PRICES the new take and reserves nothing (`quotedOnly: true`, `credits`, `voiceOverTake`, `lineRefs`, `summary`, `balanceAfter`, `sufficient` and a `note` to show the writer; when `sufficient` is false the caller must not confirm); sent again with `confirmed: true` it reserves exactly that line, records the request on the take and queues the new take (`voiceOverTake`), which is checked like every take and plays only when it is the best take of the call. Refused before anything is reserved: the project's spend gate, a take that is not an accepted take of the call (`pitch_deck_take_not_accepted`), and a call that says nothing on camera (`voice_over_nothing_to_stage`). Review or complete only. The path `{chapterIndex}` is the chapter's key from the chapters read.","availability":"available","tags":["pitch-deck","storyboard"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["artifact:publish"]},"api":{"method":"POST","path":"/pitch-decks/{jobId}/chapters/{chapterIndex}/stage-voice-over","operationId":"stageVoiceOverPitchDeckTake","idempotent":true},"cli":{"command":"sleeperhit pitch-deck stage-voice-over <jobId> --chapter <chapterIndex> --call <callId> --take <n> [--confirm]"},"mcp":{"tool":"stage_pitch_deck_take_as_voice_over","resource":null,"workflowId":"pitch-deck-rendering"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"pitchDeck.chapters.insert","title":"Insert a blank pitch deck chapter","description":"Insert a new blank chapter — `atIndex` is the position it takes (a position, not a key: 0 puts it first), `afterChapterIndex` puts it just after the chapter with that `chapterIndex` (its key from the chapters read), and omitting both appends it. Costs no credits and renders nothing: the new chapter arrives with no footage — direct it with the refine op, then render it with the priced render-clip op. Every other chapter keeps its takes, and a complete deck goes back to review. A draft plan, review or complete. On a draft plan nothing has rendered: the plan is renumbered (its black interludes follow their chapters) and the changed plan is queued for plan coverage again (`planCoverage`). Returns `insertedChapterIndex` and the new `chapterCount`; the chapters are renumbered from 0, so the new chapter is chapter `insertedChapterIndex + 1`.","availability":"available","tags":["pitch-deck","storyboard"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:write"]},"api":{"method":"POST","path":"/pitch-decks/{jobId}/chapters/insert","operationId":"insertPitchDeckChapter","idempotent":true},"cli":{"command":"sleeperhit pitch-deck add-chapter <jobId> [--at <position> | --after <chapterIndex>]"},"mcp":{"tool":"add_pitch_deck_chapter","resource":null,"workflowId":"pitch-deck-rendering"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"pitchDeck.chapters.remove","title":"Remove a pitch deck chapter","description":"Remove one chapter from the deck, with everything already rendered on it. Costs no credits — and refunds none: what that chapter bought is gone, and a deck keeps at least one chapter. The remaining chapters are renumbered and keep their takes. A draft plan, review or complete. On a draft plan nothing has rendered: the plan is renumbered (its black interludes follow their chapters) and the changed plan is queued for plan coverage again (`planCoverage`). Name the chapter by its `chapterIndex` from the chapters read — a key, not its place in the deck. Returns the new `chapterCount`.","availability":"available","tags":["pitch-deck","storyboard"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:write"]},"api":{"method":"POST","path":"/pitch-decks/{jobId}/chapters/remove","operationId":"removePitchDeckChapter","idempotent":true},"cli":{"command":"sleeperhit pitch-deck remove-chapter <jobId> --chapter <chapterIndex>"},"mcp":{"tool":"remove_pitch_deck_chapter","resource":null,"workflowId":"pitch-deck-rendering"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"pitchDeck.chapters.reorder","title":"Put the pitch deck chapters in a new order","description":"Puts the deck's chapters in a new order: `order` names every chapter's chapterIndex once, in the order they will play, or `move` puts one chapter just after another (`afterChapterIndex`) or first (`afterChapterIndex: null`). Free: nothing renders and every chapter keeps its takes; a rendered deck's video is stitched again in the new order. Chapters filmed in one render (a scene group: a chapter whose `renderedWith` names another, and that chapter) move as one block, side by side in their order; an order that pulls them apart is refused (`pitch_deck_scene_group_split`) and a move of one of them moves the whole group. The chapters are renumbered from 0 in their new order (each answer chapter's `previousChapterIndex` is its key before). How a chapter hands into the next and the black after it travel with it (a black whose chapter now ends the deck is taken out and named in `droppedInterludes`); music and sound laid on one chapter move with it, and a score composed to the old order keeps playing but no longer lands on the chapters (`score: no_longer_fits`) until it is scored again, priced. A draft plan, review or complete; on a draft the changed plan is queued for plan coverage again (`planCoverage`). A rendered deck waits while its video is being put together or its automatic fixes are running (409 `pitch_deck_reorder_assembly_running`, `pitch_deck_reorder_auto_fix_running`).","availability":"available","tags":["pitch-deck","storyboard"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:write"]},"api":{"method":"POST","path":"/pitch-decks/{jobId}/chapters/reorder","operationId":"reorderPitchDeckChapters","idempotent":true},"cli":{"command":"sleeperhit pitch-deck reorder-chapters <jobId> (--order <chapterIndex,...> | --move <chapterIndex> --after <chapterIndex|first>)"},"mcp":{"tool":"reorder_pitch_deck_chapters","resource":null,"workflowId":"pitch-deck-rendering"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"pitchDeck.storyboard.regenerateText","title":"Render one chapter's text layer","description":"Render one chapter's on-screen text / motion-graphic layer with its current caption + treatment (metered — one per-text credit; a text-only chapter renders on its own, a text-over-footage chapter composites over its cut). TWO CALLS: sent without `confirmed` it PRICES the render and reserves nothing (`quotedOnly: true`, `credits`, `balanceAfter` — what the writer would have left — `sufficient`, and a `note` to show the writer; when `sufficient` is false the note says they are short and names the top-up link, and the caller must not confirm); sent again with `confirmed: true` it reserves the one credit line and queues the render. Not a required `confirmed: true` literal — a field that must be true to validate cannot tell a confirmed call from an unconfirmed one, and it would force the price to be announced after the money moved. Preconditions run above the price: a footage-only chapter carries no on-screen text and is refused with no quote at all. Review or complete only. Name the chapter by its `chapterIndex` from the chapters read — a key, not its place in the deck. A confirmed call returns `reviewUrl` + a shareable per-chapter `previewUrl`.","availability":"available","tags":["pitch-deck","storyboard"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["artifact:publish"]},"api":{"method":"POST","path":"/pitch-decks/{jobId}/storyboard/regenerate-text","operationId":"regeneratePitchDeckText","idempotent":true},"cli":{"command":"sleeperhit pitch-deck regenerate-text <jobId> --chapter <chapterIndex> [--confirm]"},"mcp":{"tool":"regenerate_pitch_deck_text","resource":null,"workflowId":"pitch-deck-rendering"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"pitchDeck.storyboard.directTextMotion","title":"Direct how a deck's text looks and moves","description":"Say in plain words how one chapter's on-screen text should move — \"type it out letter by letter, then draw an underline\" — and it is compiled into the motion spec the text layer executes. Costs no credits and renders nothing: it writes the spec and keeps your own words beside it, so the next direction is not authored blind. Re-directing REPLACES the treatment rather than adding to it, which is why there is no price and nothing to confirm. Render the text layer afterwards to see it. Refused before anything is compiled when the chapter has nothing to move: a chapter that is footage only, or one with no caption written yet. Name the chapter by its `chapterIndex` from the chapters read — a key, not its place in the deck. With a `titleElement` instead (title, epigraph, sourceCredit, nameSupers) it directs one of the deck's TITLE SEQUENCE's words. The title sequence's words are directed like a chapter's text, in the writer's own words, through the same direct-text-motion call with a `titleElement` instead of a `chapterIndex`: `title` (\"KARAMAZOV huge, blood red, a stark sans, the ends cut off by the frame\"), `epigraph` (\"a subtle background behind the verse: grain, a candle's flicker, a few falling seeds\"), `sourceCredit`, or `nameSupers` (every name alike: its face, its colour, and where it sits — beside the face on the left or the right, over the top of the picture, or under it; never over a face). The director compiles the sentence into a motion-text spec — the face (the show's, or a bundled grotesque or condensed grotesque), the colour, the size (up to edge to edge, wider than the frame so the frame cuts the first and last letters), how it moves, and a seeded background behind it (film grain, a breathing vignette, a flickering warm light, banks of fog rolling across the frame, slowly falling motes), as quiet or as strong and moving as asked (\"the same fog as the verse, but stronger\"), held under the words' own brightness (behind the blood-red title it is a haze of the same red) — and saves it with the sentence on the title sequence (`textMotion`). The words stay the sequence's: a direction says how they look, never what they say. `clear: true` puts an element back in the sequence's own type. Free: an LLM call, no credits; a rendered deck's master is stitched again with it, and nothing else renders (no chapter, no shot). A save of the title sequence keeps every direction (an element whose words are removed loses its own). With a `closingElement` (quote, comingSoon, productionCredit) it directs one of the deck's CLOSING SEQUENCE's cards. The closing sequence's words are directed like the title sequence's, in the writer's own words, through the same direct-text-motion call with a `closingElement` instead of a `chapterIndex`: `quote`, `comingSoon` or `productionCredit` (\"the same candlelight and grain as the epigraph\", \"Coming Soon wide and slow, a faint vignette breathing behind it\"). The same director compiles the sentence into a motion-text spec (face, colour, size, motion and a quiet background) and saves it with the sentence on the closing sequence (`textMotion`). The words stay the closing's: a direction says how they look, never what they say. `clear: true` puts a card back in the opening's look (or its own type). Free: an LLM call, no credits; a rendered deck's master is stitched again with it, and nothing else renders.","availability":"available","tags":["pitch-deck","storyboard"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:write"]},"api":{"method":"POST","path":"/pitch-decks/{jobId}/storyboard/direct-text-motion","operationId":"directPitchDeckTextMotion","idempotent":true},"cli":{"command":"sleeperhit pitch-deck direct-text-motion <jobId> (--chapter <chapterIndex> | --title-element title|epigraph|source-credit|name-supers | --closing-element quote|coming-soon|production-credit) (--direction <text> | --clear)"},"mcp":{"tool":"direct_pitch_deck_text_motion","resource":null,"workflowId":"pitch-deck-rendering"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"pitchDeck.video.export","title":"Re-stitch the finished deck master from its current chapters and audio","description":"Rebuild the finished pitch-deck MP4 from the finished chapter cuts, narration and music already on the job. Generates nothing and costs no render credits — it re-runs the composition over EXISTING assets, so it is the supported way to fold in a music bed or a narration track that landed after the finish. Only a complete deck exports: a 480p preview is never the deliverable, so a deck in review is finished first (the priced finish op). A queued or rendering export short-circuits rather than stacking.","availability":"available","tags":["pitch-deck","render"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:write"]},"api":{"method":"POST","path":"/pitch-decks/{jobId}/video-export","operationId":"exportPitchDeckVideo","idempotent":true},"cli":{"command":"sleeperhit pitch-deck export <jobId>"},"mcp":{"tool":"export_pitch_deck_video","resource":null,"workflowId":"pitch-deck-rendering"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"pitchDeck.plan.approve","title":"Approve the pitch deck plan into the render","description":"Approve a draft deck's chapter plan into the render — the next step of EVERY deck job, which stops at its plan (a story job's `progress.pitchDeckJobId`, `progress.nextStep: approve_pitch_deck_plan`): approving THIS job renders the deck that was scored, while creating a new plan re-runs the stochastic planner and renders an ungraded draw. TWO CALLS: sent without `confirmed` it runs the coverage gate, compiles and voices every footage chapter (free to the writer) and PRICES the 480p render — a line per call at its voiced seconds and a line per location plate the renders make first, the `calls`, advisory `warnings`, `balanceAfter`, `sufficient`, and a `note` to show the writer — reserving nothing; sent again with `confirmed: true` it reserves exactly the quoted calls and starts the render (`rendering`, then `review`). The quote also carries the AUTOMATIC-FIX ALLOWANCE (`autoFixAllowance: { credits, note }`, and a `lines` entry of kind `allowance`): a ceiling, sized from the render, that the engine may draw on to retake the shots the review of the 480p preview flags (and render flagged on-screen text again), reserved with the render — only what the fixes draw is charged and the rest comes back when the loop stops (0 when the balance covers only the render: the preview is still reviewed). Follow it on the read's `autoFix`. The 720p finish stays a separate approval. A chapter's line is spoken by a cast member in their own voice when its `narrationVoice` names one, otherwise by the narrator over the cut; a take that re-voices a line, has lips out of step with its lines, or misses its opening framing is retaken once automatically at our cost. Refused before the price, with the action that fixes it (`error.details.refusal`, and `error.details.blocked` per chapter): an unscored or failing plan, a chapter whose cast has no body figure or whose speaker has no cast voice, a chapter whose words one render cannot carry. Each blocked chapter carries its `chapterIndex` and `chapterNumber`; fix it with the refine op (free, on the draft) and price the approval again — the deck is not planned again. A plan the gate refuses on the judge's scores alone (`error.details.overridable: true`) may be rendered anyway on the writer's explicit choice with `acknowledgePlanCoverage: { reason }` — never over a blocking defect decided in code, or a missing, running, failed, stale or old-rubric report; the confirmed approval records it on the report (the coverage read's `writerOverride`). Draft only. A pitch deck is priced by the second: 1 credit a second to render at 480p, plus 1 credit a second to finish at 720p (2 credits a second in all; a 1080p finish is 4 credits a second instead). Planning is free. The exact price is quoted per shot once the plan is ready, before anything renders; location plates and on-screen text are itemized in the same quotes.","availability":"available","tags":["pitch-deck","plan"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:write"]},"api":{"method":"POST","path":"/pitch-decks/{jobId}/plan/approve","operationId":"approvePitchDeckPlan","idempotent":true},"cli":{"command":"sleeperhit pitch-deck approve-plan <jobId> [--confirm] [--acknowledge-plan-coverage \"<reason>\"]"},"mcp":{"tool":"approve_pitch_deck_plan","resource":null,"workflowId":"pitch-deck-rendering"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"pitchDeck.finish","title":"Finish the pitch deck","description":"Finish the deck: every selected take is upscaled from its 480p render to the delivery class — 720p unless the writer chose 1080p (`deliveryResolution` here, or the deck's stored choice; the plan never raises it) — the on-screen text layers are laid over the finished cuts, the finished master is stitched, and the deck's artifact and PDF (laid out from poster frames of the finished takes) follow. Nothing is generated again, and a take already finished at the class is reused, not charged twice. TWO CALLS: sent without `confirmed` it PRICES the finish and reserves nothing (`quotedOnly: true`, `credits`, the `lines` — one per selected take and one per text layer — a `warnings` entry per flagged take the writer kept, `balanceAfter`, `sufficient`, and a `note` to show the writer); sent again with `confirmed: true` it reserves exactly those lines and starts the finish (`finishing`, then `complete`). Refused before the price while any call has no selected take (a call whose every take re-voiced a line: stage the line as a voice-over, or render a new take) or any footage chapter has not rendered, and while the deck's master FAILED its video coverage (`pitch_deck_video_coverage_failed`, with the findings and their fixes) unless `acknowledgeVideoCoverage: true` — only once the writer has seen the findings and chosen to finish anyway. Coverage still running, one that could not run, or one of an earlier master never holds the finish; the quote's `warnings` say so. While the read's `autoFix.state` is `reviewing` or `fixing` the engine is retaking what the review flagged by itself — wait for it rather than retaking by hand; once it has stopped short (`verdict.state: your_call`), the writer either finishes anyway or lets it try more fixes (the more-fixes op). Review or complete (finishing again at a new class) only.","availability":"available","tags":["pitch-deck","render"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["artifact:publish"]},"api":{"method":"POST","path":"/pitch-decks/{jobId}/finish","operationId":"finishPitchDeck","idempotent":true},"cli":{"command":"sleeperhit pitch-deck finish <jobId> [--resolution 720p|1080p] [--confirm] [--acknowledge-video-coverage]"},"mcp":{"tool":"finish_pitch_deck","resource":null,"workflowId":"pitch-deck-rendering"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"pitchDeck.reassemble","title":"Re-assemble a pitch deck whose assembly failed, or rebuild its master","description":"Put a FAILED deck back together from the takes it already has. A deck whose assembly failed for good — `assemble`, the 480p preview, or `finish_assemble`, the finished master — lost nothing it paid for: every call's takes (and their finished upscales) are kept. This re-runs THAT stage: the deck goes back to `rendering` (then `review`) or `finishing` (then `complete`). Free — nothing is rendered, upscaled or reserved — so there is no price and nothing to confirm. Refused (409, with the reason) for a deck that is not failed, one that failed while its shots were being sent to render or to be finished (nothing to assemble), a finished master missing a finished take, or a preview with no footage chapter whose takes are all in hand; the chapters read's `reassembly` says whether it applies (`available`), why not (`refusal`) and what it leaves out (`leftOut`) before you call. The preview follows the master's rule: a chapter with no accepted take is LEFT OUT of the master and named, never a refusal. A deck in `review` or `complete` has its master REBUILT, free and fresh, with the current sound rules: in review the preview assembly runs (`assemble`, older-recipe cuts re-cut) and the deck stays in review; complete, the finished master is stitched again at its class (`restitch`) and the deck STAYS complete. Never changes the selected takes. Refused while a master is already being assembled for the deck (`pitch_deck_reassemble_assembly_in_flight`) or a shot has a take in flight (`pitch_deck_reassemble_take_in_flight`). Answers `{ jobId, queued, stage, status, credits: 0, message, leftOut }`.","availability":"available","tags":["pitch-deck","render"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:write"]},"api":{"method":"POST","path":"/pitch-decks/{jobId}/reassemble","operationId":"reassemblePitchDeck","idempotent":true},"cli":{"command":"sleeperhit pitch-deck reassemble <jobId>"},"mcp":{"tool":"reassemble_pitch_deck","resource":null,"workflowId":"pitch-deck-rendering"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"pitchDeck.cancelRender","title":"Stop a pitch deck's render","description":"Stop the deck's render in flight — its first pass, its finish, or a retake or repair still running. Nothing more is sent to a provider: its queued and running render jobs are cancelled, and a job already running stops at its next step. The writer's reservations for work that had not run are released (`released`, `releasedCredits`); every accepted take, selection, cut, finished take and master is kept (`keptTakes`). A shot already out at the provider is stopped and recorded on its chapter (`abandoned`): not charged to the writer (the provider may still bill it, at our cost), and never resumed. It lands in `review` with what rendered, back at `draft` when nothing did (approving again quotes the same shots), back in `review` after a stopped finish, or as it was after a stopped retake. Free: no price and nothing to confirm. With nothing rendering it answers `stopped: false` and changes nothing. Answers `{ jobId, surface, stopped, previousStatus, status, cancelledJobs, abandoned, released, releasedCredits, keptTakes, note }`; read `pitch-deck chapters` after it.","availability":"available","tags":["pitch-deck","render"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["artifact:publish"]},"api":{"method":"POST","path":"/pitch-decks/{jobId}/cancel-render","operationId":"cancelPitchDeckRender","idempotent":true},"cli":{"command":"sleeperhit pitch-deck cancel-render <jobId>"},"mcp":{"tool":"cancel_pitch_deck_render","resource":null,"workflowId":"pitch-deck-rendering"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"pitchDeck.moreFixes","title":"Let the deck's automatic fixes try more","description":"The render approval carries an automatic-fix allowance: the engine watches the 480p preview and retakes the shots its review flags, inside that ceiling, until the preview is clean or it stops short (the chapters read's `autoFix`: `state: stopped`, `stopReason`, `stoppedBecause`). When it stopped for want of credits or rounds, or because a flagged shot reached its tries, `autoFix.moreFixes` offers ONE MORE GRANT of `credits` and `verdict.choices` carries `more_fixes`; this op takes it. Metered, TWO CALLS: sent without `confirmed` it PRICES the grant and reserves nothing (`quotedOnly: true`, `credits`, `costLabel`, `balanceAfter`, `sufficient`, and a `note` to show the writer; when `sufficient` is false the caller must not confirm); sent again with `confirmed: true` it reserves the grant, raises the loop's caps (a round of fixes and a try per shot more) and answers the same review again (`quotedOnly: false`, `queued: true`, `credits`, `message`, `autoFix`). Only what the fixes draw is charged; the rest comes back when the loop stops. Refused (409, `details.refusal.code`): `auto_fix_not_in_review`, `auto_fix_nothing_more` (still fixing, or nothing a new take or a text render would fix — finish anyway instead), `auto_fix_already_running`; 402 when the balance cannot hold it. Review only.","availability":"available","tags":["pitch-deck","render"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["artifact:publish"]},"api":{"method":"POST","path":"/pitch-decks/{jobId}/more-fixes","operationId":"allowMorePitchDeckFixes","idempotent":true},"cli":{"command":"sleeperhit pitch-deck more-fixes <jobId> [--confirm]"},"mcp":{"tool":"allow_more_pitch_deck_fixes","resource":null,"workflowId":"pitch-deck-rendering"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"pitchDeck.videoCoverage.get","title":"Read pitch deck video coverage","description":"Read the deck's VIDEO COVERAGE: its stitched master (the 480p preview, then the finished master) watched with its sound and scored on its quality and its adherence to the shot list — lip sync, prompt adherence, visual fidelity, motion naturalness, identity continuity, text placement, audio sync — never its story. Answers which master it watched and whether that is the current one, the score against the bar with the dimensions that fail it on their own, every finding with its timecode located on chapters, calls and shots and its remedy (retake that call, or render the text again), and `blocksFinish` — while true the finish is refused (`pitch_deck_video_coverage_failed`) unless the writer chooses to finish anyway. `report.judging` says how the verdict was reached: near the bar the master is watched again (a third time when two watches disagree) and every score is the median of its watches; a master whose picture is frame-identical to an earlier judged one carries that report's picture scores and judges only lip sync, audio sync and transitions again. `report.lipSync` is the MEASURED lip sync: every spoken line, what the mouth check measured on the take it plays from (missed, uncertain, in sync, not measured) and why; each miss is also a `measured` lip-sync finding that holds lip sync under the bar whatever the judge scored, fixed by a new take of its call. A deck with no report reads back as `missing`, not as a 404.","availability":"available","tags":["pitch-deck","render","video_coverage"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:read"]},"api":{"method":"GET","path":"/pitch-decks/{jobId}/video-coverage","operationId":"getPitchDeckVideoCoverage","idempotent":false},"cli":{"command":"sleeperhit pitch-deck video-coverage <jobId>"},"mcp":{"tool":"get_video_coverage","resource":null,"workflowId":"pitch-deck-rendering"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"pitchDeck.videoCoverage.generate","title":"Cover the pitch deck video again","description":"Watch the deck's CURRENT master again as a new video coverage report. Free — the watch costs the writer nothing — so there is no price and no `confirmed`. Coverage already runs by itself, once per master, when the preview is stitched and again when the finished master is; a report already running on this master is returned as it is. Refused for a deck with no stitched master, one not in review or complete, or when no provider can watch a video right now (which never holds the finish).","availability":"available","tags":["pitch-deck","render","video_coverage"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:write"]},"api":{"method":"POST","path":"/pitch-decks/{jobId}/video-coverage","operationId":"generatePitchDeckVideoCoverage","idempotent":true},"cli":{"command":"sleeperhit pitch-deck video-coverage <jobId> --generate"},"mcp":{"tool":"generate_video_coverage","resource":null,"workflowId":"pitch-deck-rendering"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"pitchDeck.resolution.get","title":"Read the pitch deck delivery class","description":"Read the class the finish delivers the deck at: `deliveryResolution` (720p unless the writer chose 1080p — the plan never raises it), `isDefault` (true when nobody chose on the deck, so the 720p default applies — say so rather than reporting it as a decision), `renderResolution` (every take renders at 480p first, whatever the class), `options`, and `editable` (false while a render or finish pass is running). Raising the class upscales the selected takes at finish: it quotes a finish, never a render.","availability":"available","tags":["pitch-deck","render"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:read"]},"api":{"method":"GET","path":"/pitch-decks/{jobId}/resolution","operationId":"getPitchDeckResolution","idempotent":false},"cli":{"command":"sleeperhit pitch-deck resolution <jobId>"},"mcp":{"tool":"get_pitch_deck_resolution","resource":null,"workflowId":"pitch-deck-rendering"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"pitchDeck.resolution.set","title":"Choose the pitch deck delivery class","description":"Choose the class the finish delivers the deck at — 720p (the default) or 1080p — or pass `resolution: null` to clear the choice back to the default. Storing it is free and changes no render: every shot renders at 480p first, and raising the class upscales the selected takes at finish, so it quotes a finish of the takes you keep, never a render. A finished deck goes back to review so it can be finished again at the new class. Every class renders its first pass at 480p, finished by upscaling: about $0.068/s at 480p, $0.078/s at 720p and $0.088/s at 1080p (the 480p first pass plus $0.01/s or $0.02/s to upscale; confirmed rates), so a 90-second cut comes to about $6.12, $7.02 or $7.92. Refused while a render or finish pass is running.","availability":"available","tags":["pitch-deck","render"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:write"]},"api":{"method":"POST","path":"/pitch-decks/{jobId}/resolution","operationId":"setPitchDeckResolution","idempotent":true},"cli":{"command":"sleeperhit pitch-deck resolution <jobId> --resolution <720p|1080p> | --default"},"mcp":{"tool":"set_pitch_deck_resolution","resource":null,"workflowId":"pitch-deck-rendering"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"trailer.beats.get","title":"Read a trailer's beats","description":"Read the trailer's beats as they render. Each beat carries its plan (what it delivers, framing, cut list, cast, room, caption) and its render calls (at most 10s each): duration, audio mode, the location plate rung the render opens on, who is on camera, the shots and the lines spoken in them, the cast's speech track, and every take — whether it played the cast's recorded lines, whether it opened on its planned framing, whether it was the call's one automatic retake at our cost, whether it was not checked for a person shown twice (`duplicateNotChecked`: never a pass, ranked below checked takes), whether its lip sync was not checked (`mouthNotChecked`: no on-camera speaker's mouth could be read — never a pass, never a retake, ranked below a take whose lips were measured passing), whether its checks have not completed (`checksPending`: its QA, its mouth or duplicate check, or its watch was interrupted — nothing proves it clean yet, it is never selected over a checked take, and the worker runs them again), whether it is a take that never finished (`abandoned`: the job holding its claim died before anything was sent, so the claim was released, any credits reserved for it went back, and the shot's next take was decided again — say \"a take that never finished (released)\"), every line the wrong person speaks (`identitySwaps`: the line's speaker found nowhere on camera and another cast member's face, matched by their identity image, following it — a miss that earns the automatic retake, told whose face must say it), whether it is uncertain (`mouthUncertain`: measured, but a reading sat inside the band around its limit — never a pass, never a retake, ranked below a measured pass and above a miss), every criterion missed or uncertain with its number and limit (`mouthFindings`: correlation, lag or trailing motion after the line for a speaker; open run, open share or openings for a still face), a content refusal (released, never retried; `reference_render_provider_ip_refused` is a shot refused as possibly someone else's intellectual property, whose notice names what to edit before it renders again), which take is selected, and what a priced retake would cost. Also the beat's cut and poster, whether the plan changed since it rendered (`stale`), the master (a 480p preview in review, finished once the finish completes), the delivery class, the warnings the finish and export carry, `reassembly` (a failed trailer: the stage it failed in, and whether the free re-assembly would put it back together now; a trailer in review or complete: whether its master would be rebuilt now with the current sound rules, or why not), and a browser `reviewUrl`. A read: it never compiles, renders or makes a plate. `assembly` is the master being put together right now, null when nothing is being assembled: `stage` (the 480p `preview` or the `finished` cut), the `step` it is on (`cutting`: joining each chapter's or beat's chosen takes, with `unit` the one being joined and `done` of `total` joined so far; `text`: laying the on-screen text (the finished cut only); `sound`: laying the voices, music and sound under the cut; `finish_look`: laying the finish look on the picture (only when one is set); `stitching`: stitching everything into one video, with `percent` from the renderer's own frame count; `delivering`: levelling the sound and saving the file), `steps` in order, `startedAt`, and `sentence`, which says it in words. Nothing renders and nothing is charged while a cut is assembled, and it cannot be stopped: it is free and ends on its own. `verdict` is the review in the writer's words — lead with it: `progress` (one line: rendering, fixing N shots the review flagged, ready to watch), `verdict` (one paragraph naming the problems that are left, by chapter or beat), `working` (true while the engine works: nothing to do but wait), and `choices` (at most two, only once it has stopped: `finish`, `finish_anyway` — the finish with `acknowledgeVideoCoverage` — or `more_fixes` with its `credits`). The scores, findings, takes and checks stay in `videoCoverage`, the chapters' calls and `autoFix` for anyone who wants to step in. `autoFix` is the AUTOMATIC FIXES the render approval paid for up front: the approval quote carries an automatic-fix allowance beside the 480p render (`autoFixAllowance`), reserved with it. After the preview is stitched the engine watches it (video coverage) and retakes the shots the review flags — each new take told what the review saw, a shot at most twice, re-staged as a voice-over where the take rules allow — and renders flagged on-screen text again, all inside that allowance; then it stitches and watches the preview again. It stops at a clean 480p preview (`state: clean`), when the allowance is spent, when the review flags nothing a fix can clear, or after `maxRounds` rounds (`state: stopped`, `stopReason`, `stoppedBecause`). `state` is `waiting` (first pass rendering), `reviewing` or `fixing` while it works — do not retake or finish then, just poll. `allowanceCredits` is the ceiling, `drawnCredits` what fixes took from it (each charged only when its take lands), `heldCredits` what is still reserved (released when it stops); `rounds[]` lists each round's fixes with `why`. When it stopped short, `moreFixes` (if not null) offers one more grant of `credits` (the more-fixes op, priced first); otherwise the writer finishes anyway. The 720p finish is always the writer's own approval. `earlyLook` (while the first pass renders; null once the preview exists) lists every chapter or beat whose shots all have a take, with each take's clip in shot order (`units[].clips[].url`), and `roughCut` once two have landed: they can be watched as they land, nothing to do. `musicPlan` is the music the cut will carry, known before the stitch: the beds on its timeline (`source: timeline`), or for a deck with none the table read's score as the assembly will lay it (`table_read_score`), each bed with the chapters or beats it plays under and a `url` to listen to — say it early, so a music change is made before the finish. A score to picture asked for (`score`, from a draft on) leads with its direction and, once its sketch to the planned cut is composed, `score.sketchUrl` to listen to; while one is asked for, the table read's beds are not laid or projected. When a score asked for with a direction could not be composed (`score.status: failed`), the beds are not laid in its place either: the sentence says so plainly (\"The score couldn't be composed (reason in Details). The bell plays alone. Score to picture to try again.\") — say it to the writer.","availability":"available","tags":["trailer","storyboard"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:read"]},"api":{"method":"GET","path":"/trailers/{jobId}/beats","operationId":"getTrailerBeats","idempotent":false},"cli":{"command":"sleeperhit trailer beats <jobId>"},"mcp":{"tool":"get_trailer_beats","resource":null,"workflowId":"trailer-rendering"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"trailer.narrator.get","title":"Read the trailer narrator","description":"Read which voice narrates this cut, and the cut's audio policy. A `narrate` trailer speaks its beats' `narrationText` in ONE chosen voice, rendered as a separate per-beat track and mixed over the finished picture. The narrator is the voice cast for this cut, else — by default — the cast canon's NARRATOR (`source`). `voiceId: null` means neither exists — which is correct for a caption-beat (`suppress`) cut and a blocking problem for a narrated one.","availability":"available","tags":["trailer","audio","voice"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:read"]},"api":{"method":"GET","path":"/trailers/{jobId}/narrator","operationId":"getTrailerNarrator","idempotent":false},"cli":{"command":"sleeperhit trailer narrator <jobId>"},"mcp":{"tool":"get_trailer_narrator","resource":null,"workflowId":"trailer-rendering"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"trailer.narrator.set","title":"Cast the trailer narrator","description":"Choose the voice that narrates this cut, or pass `voiceId: null` to clear it (the cut then narrates in the cast canon's NARRATOR when the canon casts one). The narrator is a casting decision belonging to the TRAILER: it need not be a cast member, and need not match the table read's narrator. Costs nothing — it stores a choice, and the voice is spoken at render. Audition candidates with the studio voice preview first, and re-cast freely: narration is a separate track mixed over the finished cut, so changing the voice re-renders audio, never a frame.","availability":"available","tags":["trailer","audio","voice"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:write"]},"api":{"method":"POST","path":"/trailers/{jobId}/narrator","operationId":"setTrailerNarrator","idempotent":true},"cli":{"command":"sleeperhit trailer narrator <jobId> --voice <voiceId> [--provider <name>] | --clear"},"mcp":{"tool":"set_trailer_narrator","resource":null,"workflowId":"trailer-rendering"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"trailer.resolution.get","title":"Read the trailer delivery class","description":"Read the class the finish delivers the cut at: `deliveryResolution` (720p unless the writer asked for 1080p), `isDefault` (true when nobody has chosen, so the 720p default applies — say so rather than reporting it as a decision), `renderResolution` (every take renders at 480p first, whatever the class), `options`, and `editable` (false while a render or finish pass is running). Raising the class upscales the approved takes at finish: it quotes a finish, never a render.","availability":"available","tags":["trailer","video"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:read"]},"api":{"method":"GET","path":"/trailers/{jobId}/resolution","operationId":"getTrailerResolution","idempotent":false},"cli":{"command":"sleeperhit trailer resolution <jobId>"},"mcp":{"tool":"get_trailer_resolution","resource":null,"workflowId":"trailer-rendering"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"trailer.resolution.set","title":"Choose the trailer delivery class","description":"Choose the class the finish delivers the cut at — 720p (the default) or 1080p — or pass `resolution: null` to clear the choice back to 720p. Storing it is free and changes no render: every shot renders at 480p first, and raising the class upscales the approved takes at finish, so it quotes a finish of the takes you keep, never a render. A finished cut goes back to review so it can be finished again at the new class. Every class renders its first pass at 480p, finished by upscaling: about $0.068/s at 480p, $0.078/s at 720p and $0.088/s at 1080p (the 480p first pass plus $0.01/s or $0.02/s to upscale; confirmed rates), so a 90-second cut comes to about $6.12, $7.02 or $7.92. Refused while a render or finish pass is running.","availability":"available","tags":["trailer","video"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:write"]},"api":{"method":"POST","path":"/trailers/{jobId}/resolution","operationId":"setTrailerResolution","idempotent":true},"cli":{"command":"sleeperhit trailer resolution <jobId> --resolution <720p|1080p> | --default"},"mcp":{"tool":"set_trailer_resolution","resource":null,"workflowId":"trailer-rendering"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"trailer.look.get","title":"Read the trailer finish","description":"Read the film finish laid on the trailer's picture at master assembly (`finish`: its look, intensity and adjustments), each effect's level in it, and every look and intensity there is. The finish is a film look laid on the picture when the master is assembled: a look (camera, period-35mm, night-interior, none), an intensity (light, standard, strong; standard by default) and, optionally, single effects set to a level (adjust: { effect: off | subtle | medium | strong }; effects: steady-light, match-shots, halation, mist, shoulder, colour, vignette, weave, grain, soften). New decks and trailers start on camera. Titles and captions are laid after it, so type stays crisp, and the sound and timing are never touched. Setting it is free; on a rendered deck or trailer the master is assembled again with it (free), and setting the same finish again changes nothing.","availability":"available","tags":["trailer","video"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:read"]},"api":{"method":"GET","path":"/trailers/{jobId}/look","operationId":"getTrailerLook","idempotent":false},"cli":{"command":"sleeperhit trailer look <jobId>"},"mcp":{"tool":"get_trailer_look","resource":null,"workflowId":"trailer-rendering"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"trailer.look.set","title":"Set the trailer finish","description":"Set the film finish laid on the trailer's picture at master assembly — the whole finish: a look (camera, period-35mm, night-interior, none), an intensity and optional per-effect adjustments. The finish is a film look laid on the picture when the master is assembled: a look (camera, period-35mm, night-interior, none), an intensity (light, standard, strong; standard by default) and, optionally, single effects set to a level (adjust: { effect: off | subtle | medium | strong }; effects: steady-light, match-shots, halation, mist, shoulder, colour, vignette, weave, grain, soften). New decks and trailers start on camera. Titles and captions are laid after it, so type stays crisp, and the sound and timing are never touched. Setting it is free; on a rendered deck or trailer the master is assembled again with it (free), and setting the same finish again changes nothing.","availability":"available","tags":["trailer","video"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:write"]},"api":{"method":"POST","path":"/trailers/{jobId}/look","operationId":"setTrailerLook","idempotent":true},"cli":{"command":"sleeperhit trailer look <jobId> <camera|period-35mm|night-interior|none> [--intensity light|standard|strong] [--adjust <effect>=<level>,…]"},"mcp":{"tool":"set_trailer_look","resource":null,"workflowId":"trailer-rendering"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"trailer.motionBlur.get","title":"Read the trailer motion blur","description":"Read the trailer's motion blur: every beat's shots, numbered as its cut plays them (with who speaks on camera), which are chosen, the strength, the seconds chosen against the cap, and, beat by beat, whether the last master laid the blur or why not, with the sentence the review shows. Motion blur makes chosen shots move like film: what moves in them blurs the way a camera's shutter blurs it, while still frames, faces held in frame and straight edges stay sharp. It is chosen per shot (or per chapter or beat: its moving shots, never a shot where someone speaks on camera unless that shot is named), at one of two strengths (standard, subtle; standard by default). It is free, up to 300 seconds of blurred picture per deck or trailer, and it is laid when the master is assembled, before the film finish. The sound and timing are never touched.","availability":"available","tags":["trailer","video"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:read"]},"api":{"method":"GET","path":"/trailers/{jobId}/motion-blur","operationId":"getTrailerMotionBlur","idempotent":false},"cli":{"command":"sleeperhit trailer motion-blur <jobId>"},"mcp":{"tool":"get_trailer_motion_blur","resource":null,"workflowId":"trailer-rendering"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"trailer.motionBlur.set","title":"Set the trailer motion blur","description":"Choose the shots of a beat to blur — `{ units: [{ unit, shots? }], strength?, off? }`: `unit` is the beat's `beatIndex`, `shots` its shot numbers from the read, `moving` (the default: every shot where nobody speaks on camera) or [] to clear it; beats not listed keep their choice; strengths standard, subtle. Motion blur makes chosen shots move like film: what moves in them blurs the way a camera's shutter blurs it, while still frames, faces held in frame and straight edges stay sharp. It is chosen per shot (or per chapter or beat: its moving shots, never a shot where someone speaks on camera unless that shot is named), at one of two strengths (standard, subtle; standard by default). It is free, up to 300 seconds of blurred picture per deck or trailer, and it is laid when the master is assembled, before the film finish. The sound and timing are never touched. On a rendered trailer the master is assembled again with it (`reassembling`); free.","availability":"available","tags":["trailer","video"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:write"]},"api":{"method":"POST","path":"/trailers/{jobId}/motion-blur","operationId":"setTrailerMotionBlur","idempotent":true},"cli":{"command":"sleeperhit trailer motion-blur <jobId> [--beat <beatIndex>[:<shot>,…|moving|none]]… [--strength standard|subtle] [--off]"},"mcp":{"tool":"set_trailer_motion_blur","resource":null,"workflowId":"trailer-rendering"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"trailer.camera.get","title":"Read the trailer camera motion","description":"Read the trailer's camera motion: every beat's shots, numbered as its cut plays them, each with its camera (`held` — the render held it still, so it can take the handheld sway and a move —, `moving` or `handheld`) and who speaks on camera; the handheld strength; each beat's move (a snap zoom onto a reaction or a slow reframe, with its shot and faces); and, beat by beat, what the last master laid or why a move was left out, with the sentence the review shows. Camera motion gives the held shots an operator, the way a documentary camera moves: a handheld sway on the shots that were rendered still (off, subtle, medium; never on a shot whose camera already moves or was filmed handheld, and never so far that a speaking mouth leaves the frame), and at most one move per chapter or beat, on a held shot where nobody speaks on camera: a snap zoom onto a reaction (up to 1.5×, right after a line) or a slow reframe from one face to another already in the frame. It is free, and laid when the master is assembled, as the first step of the film finish and before any type. The sound and timing are never touched.","availability":"available","tags":["trailer","video"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:read"]},"api":{"method":"GET","path":"/trailers/{jobId}/camera","operationId":"getTrailerCamera","idempotent":false},"cli":{"command":"sleeperhit trailer camera <jobId>"},"mcp":{"tool":"get_trailer_camera","resource":null,"workflowId":"trailer-rendering"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"trailer.camera.set","title":"Set the trailer camera motion","description":"Set the camera motion — `{ handheld?, moves?: [{ unit, move, shot?, target?, from?, zoom? }], off? }`: `handheld` (off, subtle, medium) sways every held shot; each move names its beat by `unit` (the beat's `beatIndex`), its shot by number from the read, `move` `snap` (a snap zoom onto `target`, `zoom` 1.15–1.5, default 1.4) or `reframe` (from the face `from` to `target`), or `none` to clear the beat; one move per beat; beats not listed keep theirs; `off: true` turns it all off. Refused, with the fix named: a shot whose camera already moves or is handheld, a shot where someone speaks on camera, a shot too short for the move, a face not in the shot's cast. Camera motion gives the held shots an operator, the way a documentary camera moves: a handheld sway on the shots that were rendered still (off, subtle, medium; never on a shot whose camera already moves or was filmed handheld, and never so far that a speaking mouth leaves the frame), and at most one move per chapter or beat, on a held shot where nobody speaks on camera: a snap zoom onto a reaction (up to 1.5×, right after a line) or a slow reframe from one face to another already in the frame. It is free, and laid when the master is assembled, as the first step of the film finish and before any type. The sound and timing are never touched. On a rendered trailer the master is assembled again with it (`reassembling`); free.","availability":"available","tags":["trailer","video"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:write"]},"api":{"method":"POST","path":"/trailers/{jobId}/camera","operationId":"setTrailerCamera","idempotent":true},"cli":{"command":"sleeperhit trailer camera <jobId> [--handheld off|subtle|medium] [--snap <beatIndex>:<shot>:<NAME>[@<zoom>]]… [--reframe <beatIndex>:<shot>:<FROM>><TARGET>]… [--clear <beatIndex>]… [--off]"},"mcp":{"tool":"set_trailer_camera","resource":null,"workflowId":"trailer-rendering"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"trailer.delete","title":"Delete a trailer","description":"Delete a trailer job you own — a failed or abandoned attempt, or a draft you will not pursue. Irreversible. A PUBLISHED trailer is refused: unpublish it first, its share link is live. Pairs with the Videos library, where failed and stale trailer attempts fold behind a count and can be deleted one at a time or together.","availability":"available","tags":["trailer"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:write"]},"api":{"method":"DELETE","path":"/trailers/{jobId}","operationId":"deleteTrailer","idempotent":false},"cli":{"command":"sleeperhit trailer delete <jobId>"},"mcp":{"tool":"delete_trailer","resource":null,"workflowId":"trailer-rendering"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"pitchDeck.delete","title":"Delete a pitch deck","description":"Delete a pitch-deck job you own — a failed or abandoned attempt, or a draft you will not pursue. Irreversible. A PUBLISHED deck is refused: unpublish it first, its share link is live. Pairs with the deck list, where failed and stale attempts fold behind a count and can be deleted one at a time or together.","availability":"available","tags":["pitch-deck"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:write"]},"api":{"method":"DELETE","path":"/pitch-decks/{jobId}","operationId":"deletePitchDeck","idempotent":false},"cli":{"command":"sleeperhit pitch-deck delete <jobId>"},"mcp":{"tool":"delete_pitch_deck","resource":null,"workflowId":"pitch-deck-rendering"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"pitchDeck.duplicate","title":"Duplicate a pitch deck from its plan","description":"Duplicating a deck makes a NEW `draft` deck that carries the source deck's CURRENT plan — every chapter with its edits, the deck's intent, its black interludes and montage marks — and the choices made on the deck itself (the narrator cast for it, its delivery class, its strategic target), and leaves the source deck untouched. Nothing rendered rides along: no takes, cuts, masters, share links or coverage reports. It is free and renders and reserves nothing; the copy's plan is queued for coverage, and its next step is approve_pitch_deck_plan on the NEW deck's jobId (CLI: pitch-deck approve-plan <newJobId>). Any status may be duplicated (a draft, a deck in review or complete, a failed deck) as long as its plan reads as a plan today; one that does not is refused (409 `pitch_deck_state_invalid`, `details.refusal.code: pitch_deck_duplicate_no_plan`) and nothing is created. Optional `title` renames the copy (its plan's title). Answers the NEW deck's `jobId`, `chapters`, `interludes`, the carried `narrator` and `deliveryResolution`, `planCoverage` (`queued` / `current` / `failed`), `nextStep: approve_pitch_deck_plan`, `reviewUrl` and a `note` to read out. Pairs with the deck list's Duplicate action.","availability":"available","tags":["pitch-deck"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:write"]},"api":{"method":"POST","path":"/pitch-decks/{jobId}/duplicate","operationId":"duplicatePitchDeck","idempotent":true},"cli":{"command":"sleeperhit pitch-deck duplicate <jobId> [--title <text>]"},"mcp":{"tool":"duplicate_pitch_deck","resource":null,"workflowId":"pitch-deck-rendering"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"trailer.sceneAudio.get","title":"Read per-beat music and sound effects","description":"Read every beat's music bed and its placed sound-effect cues for a trailer. This is the per-beat view: each bed is generated for one beat on its own. Read the audio timeline instead when you need to know what a clip does ACROSS beats — a per-beat bed cannot span or crossfade. A fully-scored cut normally shows `music: null` on every beat here: most cuts are scored on the project TIMELINE rather than beat by beat, because a per-beat bed is generated on its own and so shares no tempo, key or phrase with its neighbours. Read `audioTimeline.musicClips` in the response before concluding a cut is silent.","availability":"available","tags":["trailer","audio","music","sfx"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:read"]},"api":{"method":"GET","path":"/trailers/{jobId}/storyboard/audio","operationId":"getTrailerSceneAudio","idempotent":false},"cli":{"command":"sleeperhit trailer audio <jobId>"},"mcp":{"tool":"get_trailer_scene_audio","resource":null,"workflowId":"trailer-rendering"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"trailer.sceneMusic.mutate","title":"Score one beat's music","description":"Set, replace or clear ONE beat's music bed. `action` selects the operation: `score` generates a new bed from a prompt, `apply-library` reuses a track already saved in My Library (no generation, and the way several beats come to share a tempo and key), `update` relevels or retimes the existing bed, `remove` clears it. Music generation uses the Lyria engine, so it is never blocked by the fal balance. Returns the bed and a shareable per-beat preview link.","availability":"available","tags":["trailer","audio","music"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:write"]},"api":{"method":"POST","path":"/trailers/{jobId}/storyboard/music","operationId":"editTrailerSceneMusic","idempotent":true},"cli":{"command":"sleeperhit trailer music <score|update|remove|apply-library> <jobId> --beat <n> [flags]"},"mcp":{"tool":"score_trailer_scene_music","resource":null,"workflowId":"trailer-rendering"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"trailer.sceneSfx.mutate","title":"Place sound effects on one beat","description":"Place, adjust or remove a sound-effect cue within ONE beat, at an exact offset from that beat's start. `action` selects the operation: `add` generates a new cue from a prompt, `apply-library` places a track already saved in My Library (no generation, and the only way a recurring motif sounds IDENTICAL each time), `update` moves/relevels/disables a placed cue, `remove` deletes it. Returns the cue and a shareable per-beat preview link.","availability":"available","tags":["trailer","audio","sfx"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:write"]},"api":{"method":"POST","path":"/trailers/{jobId}/storyboard/sfx","operationId":"editTrailerSceneSfx","idempotent":true},"cli":{"command":"sleeperhit trailer sfx <add|update|remove|apply-library> <jobId> --beat <n> [flags]"},"mcp":{"tool":"add_trailer_scene_sfx","resource":null,"workflowId":"trailer-rendering"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"pitch-deck.sceneAudio.get","title":"Read per-scene music and sound effects","description":"Read every scene's music bed and its placed sound-effect cues for a pitch-deck. This is the per-scene view: each bed is generated for one scene on its own. Read the audio timeline instead when you need to know what a clip does ACROSS scenes — a per-scene bed cannot span or crossfade. A fully-scored cut normally shows `music: null` on every scene here: most cuts are scored on the project TIMELINE rather than scene by scene, because a per-scene bed is generated on its own and so shares no tempo, key or phrase with its neighbours. Read `audioTimeline.musicClips` in the response before concluding a cut is silent.","availability":"available","tags":["pitch-deck","audio","music","sfx"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:read"]},"api":{"method":"GET","path":"/pitch-decks/{jobId}/storyboard/audio","operationId":"getPitchDeckSceneAudio","idempotent":false},"cli":{"command":"sleeperhit pitch-deck audio <jobId>"},"mcp":{"tool":"get_pitch_deck_scene_audio","resource":null,"workflowId":"pitch-deck-rendering"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"pitch-deck.sceneMusic.mutate","title":"Score one scene's music","description":"Set, replace or clear ONE scene's music bed. `action` selects the operation: `score` generates a new bed from a prompt, `apply-library` reuses a track already saved in My Library (no generation, and the way several scenes come to share a tempo and key), `update` relevels or retimes the existing bed, `remove` clears it. Music generation uses the Lyria engine, so it is never blocked by the fal balance. Returns the bed and a shareable per-scene preview link.","availability":"available","tags":["pitch-deck","audio","music"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:write"]},"api":{"method":"POST","path":"/pitch-decks/{jobId}/storyboard/music","operationId":"editPitchDeckSceneMusic","idempotent":true},"cli":{"command":"sleeperhit pitch-deck music <score|update|remove|apply-library> <jobId> --chapter <chapterIndex> [flags]"},"mcp":{"tool":"score_pitch_deck_scene_music","resource":null,"workflowId":"pitch-deck-rendering"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"pitch-deck.sceneSfx.mutate","title":"Place sound effects on one scene","description":"Place, adjust or remove a sound-effect cue within ONE scene, at an exact offset from that scene's start. `action` selects the operation: `add` generates a new cue from a prompt, `apply-library` places a track already saved in My Library (no generation, and the only way a recurring motif sounds IDENTICAL each time), `update` moves/relevels/disables a placed cue, `remove` deletes it. Returns the cue and a shareable per-scene preview link.","availability":"available","tags":["pitch-deck","audio","sfx"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:write"]},"api":{"method":"POST","path":"/pitch-decks/{jobId}/storyboard/sfx","operationId":"editPitchDeckSceneSfx","idempotent":true},"cli":{"command":"sleeperhit pitch-deck sfx <add|update|remove|apply-library> <jobId> --chapter <chapterIndex> [flags]"},"mcp":{"tool":"add_pitch_deck_scene_sfx","resource":null,"workflowId":"pitch-deck-rendering"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"trailer.audioTimeline.get","title":"Read the trailer audio timeline","description":"Read the project-level multi-track audio timeline: music layers with their clips (a clip may span several beats and crossfade into the next) plus absolutely-positioned sound-effect cues, together with the beat axis they are placed against. This is the through-composed alternative to per-beat beds, which are generated independently of one another and so share no tempo, key or phrase.","availability":"available","tags":["trailer","audio","music"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:read"]},"api":{"method":"GET","path":"/trailers/{jobId}/storyboard/audio-timeline","operationId":"getTrailerAudioTimeline","idempotent":false},"cli":{"command":"sleeperhit trailer timeline <jobId> show"},"mcp":{"tool":"get_trailer_audio_timeline","resource":null,"workflowId":"trailer-rendering"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"trailer.audioTimeline.mutate","title":"Edit the trailer audio timeline","description":"Add or remove music layers, generate a Lyria music clip or place a durable library asset onto a layer at an absolute position (optionally spanning beats and crossfading into the next clip), retime/move/relevel a clip, and generate or place sound-effect cues at an exact offset within a beat: a spot effect (`kind: spot`, its own length) or an ambience bed under the picture (`kind: ambience`: with no `lengthMs` it fills its beat from the offset, or through `endSceneIndex`, repeating the effect crossfaded, at 0.2 with short fades unless set). A cue takes `lengthMs` (how long it sounds; longer than the effect repeats it), `fadeInMs` / `fadeOutMs`, and on an update `muted` (silent, kept on the lane) and null `lengthMs` / `endSceneIndex` (back to its default span). `update-sfx-cues` changes or removes several cues in one write (`cues`: each entry update-sfx-cue's fields, or `remove: true`; per-entry `results`). Every cue's file is measured and levelled before its level, so a level is a place in the mix (the sound map's `suggestedLevels` and `targetLevel` put a bed 10–14 dB and a spot 3–8 dB under its scene's own mix), and each cue an answer shows carries `assetLufs`, `normGainDb`, `mixLufs`, a bed's `continuity` and `loudnessFlag`. Music generation uses the Lyria engine, so it is never blocked by the fal balance.","availability":"available","tags":["trailer","audio","music","sfx"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:write"]},"api":{"method":"POST","path":"/trailers/{jobId}/storyboard/audio-timeline","operationId":"editTrailerAudioTimeline","idempotent":true},"cli":{"command":"sleeperhit trailer timeline <jobId> <add-layer|remove-layer|generate-music|add-music-from-library|update-music|remove-music|generate-sfx|add-sfx-from-library|update-sfx|update-sfx-cues|remove-sfx> [flags] (sfx: --kind spot|ambience --length-ms N --fade-in-ms N --fade-out-ms N; update-sfx --muted|--unmuted --clear-length; update-sfx-cues --cues '<json>')"},"mcp":{"tool":"generate_trailer_timeline_music","resource":null,"workflowId":"trailer-rendering"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"pitch-deck.audioTimeline.get","title":"Read the pitch-deck audio timeline","description":"Read the project-level multi-track audio timeline: music layers with their clips (a clip may span several scenes and crossfade into the next) plus absolutely-positioned sound-effect cues, together with the scene axis they are placed against. This is the through-composed alternative to per-scene beds, which are generated independently of one another and so share no tempo, key or phrase.","availability":"available","tags":["pitch-deck","audio","music"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:read"]},"api":{"method":"GET","path":"/pitch-decks/{jobId}/storyboard/audio-timeline","operationId":"getPitchDeckAudioTimeline","idempotent":false},"cli":{"command":"sleeperhit pitch-deck timeline <jobId> show"},"mcp":{"tool":"get_pitch_deck_audio_timeline","resource":null,"workflowId":"pitch-deck-rendering"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"pitch-deck.audioTimeline.mutate","title":"Edit the pitch-deck audio timeline","description":"Add or remove music layers, generate a Lyria music clip or place a durable library asset onto a layer at an absolute position (optionally spanning scenes and crossfading into the next clip), retime/move/relevel a clip, and generate or place sound-effect cues at an exact offset within a scene: a spot effect (`kind: spot`, its own length) or an ambience bed under the picture (`kind: ambience`: with no `lengthMs` it fills its scene from the offset, or through `endSceneIndex`, repeating the effect crossfaded, at 0.2 with short fades unless set). A cue takes `lengthMs` (how long it sounds; longer than the effect repeats it), `fadeInMs` / `fadeOutMs`, and on an update `muted` (silent, kept on the lane) and null `lengthMs` / `endSceneIndex` (back to its default span). `update-sfx-cues` changes or removes several cues in one write (`cues`: each entry update-sfx-cue's fields, or `remove: true`; per-entry `results`). Every cue's file is measured and levelled before its level, so a level is a place in the mix (the sound map's `suggestedLevels` and `targetLevel` put a bed 10–14 dB and a spot 3–8 dB under its scene's own mix), and each cue an answer shows carries `assetLufs`, `normGainDb`, `mixLufs`, a bed's `continuity` and `loudnessFlag`. Music generation uses the Lyria engine, so it is never blocked by the fal balance.","availability":"available","tags":["pitch-deck","audio","music","sfx"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:write"]},"api":{"method":"POST","path":"/pitch-decks/{jobId}/storyboard/audio-timeline","operationId":"editPitchDeckAudioTimeline","idempotent":true},"cli":{"command":"sleeperhit pitch-deck timeline <jobId> <add-layer|remove-layer|generate-music|add-music-from-library|update-music|remove-music|generate-sfx|add-sfx-from-library|update-sfx|update-sfx-cues|remove-sfx> [flags] (sfx: --kind spot|ambience --length-ms N --fade-in-ms N --fade-out-ms N; update-sfx --muted|--unmuted --clear-length; update-sfx-cues --cues '<json>')"},"mcp":{"tool":"generate_pitch_deck_timeline_music","resource":null,"workflowId":"pitch-deck-rendering"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"trailer.soundMap.get","title":"Read the trailer sound map","description":"Read what a sound pass is placed from, for every beat or one (`?sceneIndex=`): its length in the master (the window a cue's offset is measured in), every shot's seconds with its framing, who is on camera and what happens, every spoken line's speaker and seconds, what the cut already carries under each call (`heard`: silence, cast_lines, room_tone or scene_sound) and the room tone it was made with, its own mix (`chapterMixLufs`: voice, kept scene sound and score, no sound effects, measured on the master at its last stitch; `chapterHeardLufs` with them) and the levels a new bed and spot take under it (`suggestedLevels`), the sound-effect cues already placed (cueId, kind, offset, length, level, fades, muted; how loud each really is: assetLufs, normGainDb, mixLufs; where it sits against its own mix: underChapterMixDb and targetLevel, against the map's targets of a bed 10–14 dB and a spot 3–8 dB under; a bed's continuity; insideLine for a spot inside a spoken line; loudnessFlag too_quiet, clipped, gappy or unmeasured) and the music over it. Read-only.","availability":"available","tags":["trailer","audio","sfx"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:read"]},"api":{"method":"GET","path":"/trailers/{jobId}/storyboard/sound-map","operationId":"getTrailerSoundMap","idempotent":false},"cli":{"command":"sleeperhit trailer sound-map <jobId> [--beat <n>]"},"mcp":{"tool":"get_trailer_sound_map","resource":null,"workflowId":"trailer-rendering"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"pitch-deck.soundMap.get","title":"Read the pitch-deck sound map","description":"Read what a sound pass is placed from, for every chapter or one (`?sceneIndex=`, its chapterIndex): its length in the master (the window a cue's offset is measured in), whether it cuts straight into the next, every shot's seconds with its framing, who is on camera and what happens, every spoken line's speaker and seconds, what the cut already carries under each call (`heard`: silence, cast_lines, room_tone or scene_sound) and the room tone it was made with, its own mix (`chapterMixLufs`: voice, kept scene sound and score, no sound effects, measured on the master at its last stitch; `chapterHeardLufs` with them) and the levels a new bed and spot take under it (`suggestedLevels`), the sound-effect cues already placed (cueId, kind, offset, length, level, fades, muted; how loud each really is: assetLufs, normGainDb, mixLufs; where it sits against its own mix: underChapterMixDb and targetLevel, against the map's targets of a bed 10–14 dB and a spot 3–8 dB under; a bed's continuity; insideLine for a spot inside a spoken line; loudnessFlag too_quiet, clipped, gappy or unmeasured) and the music over it, and the deck's bell lane. Read-only.","availability":"available","tags":["pitch-deck","audio","sfx"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:read"]},"api":{"method":"GET","path":"/pitch-decks/{jobId}/storyboard/sound-map","operationId":"getPitchDeckSoundMap","idempotent":false},"cli":{"command":"sleeperhit pitch-deck sound-map <jobId> [--chapter <chapterIndex>]"},"mcp":{"tool":"get_pitch_deck_sound_map","resource":null,"workflowId":"pitch-deck-rendering"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"pitchDeck.scoreToPicture.get","title":"Read the pitch deck's score to picture","description":"Read the score composed to the deck's cut and whether one can be composed now: `status` (none / waiting_for_master / queued / composing / laid / failed / reverted), `canScore` and `blocked` (why not — music the writer placed is never replaced), `runtimeMs`, `fitsCut` (false when the cut changed after the score was composed) and the `cueSheet` — its concept and palette, its sections by cut number with their windows, mood, players and intensity, its hit points and where speech sits — and `silentGap` with its `note` when the laid score fell silent as it was first composed and was composed again (a score with dead air is never laid). Before any master, `plannedCut` is true (`runtimeMs` and `cuts` are the planned cut) and `sketch` is the sketch composed to it for a score that waits for the master: `status` (composing / ready / failed) and a `url` to listen to — never laid, never charged. On a deck whose title sequence cuts on the bell's beat grid, the `cueSheet` carries `beatGrid` (the beat, the tempo, and the required bell strikes: every intro cut and the title, with hit points marked `required`), and `beatAlignment` (null otherwise) is the score check: each strike's cut, the nearest bell onset measured in the laid score, the offset in ms and in frames and whether it is within a frame (`aligned`), the constant `shiftMs` applied to put them on the cuts (a shift, never a retime), and the `note` — a `warning` (\"Intro bell strikes not on the cuts: …\") when they are not, which also ends `message`. Nothing is composed again for it: scoring again is the writer's priced choice. When `status` is failed, `error` is why (the Details). A score asked for with a `direction` that could not be composed is NEVER replaced by the table read's scene beds: they come off the cut, the bell lane and the sound effects stay, and `message` says so plainly — \"The score couldn't be composed (reason in Details). The bell plays alone. Score to picture to try again.\" (with no bell lane, no music plays under the cut; music the writer placed is named as still on it). Say that to the writer. Scoring to picture again without a new `direction` keeps the one it had; a score asked for without a direction that fails still leaves the scene beds.","availability":"available","tags":["pitch-deck","audio","music"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:read"]},"api":{"method":"GET","path":"/pitch-decks/{jobId}/score-to-picture","operationId":"getPitchDeckScoreToPicture","idempotent":false},"cli":{"command":"sleeperhit pitch-deck score-to-picture <jobId> show"},"mcp":{"tool":"get_pitch_deck_score_to_picture","resource":null,"workflowId":"pitch-deck-rendering"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"pitchDeck.scoreToPicture.start","title":"Score the pitch deck to picture","description":"Compose ONE score to the deck's cut and lay it under the whole master in place of the table read's scene beds, then re-stitch the master. TWO CALLS: sent without `confirmed` it PRICES the score and holds nothing (`quotedOnly: true`, `credits`, `balanceAfter`, `sufficient`, and a `note` to show the writer); sent again with `confirmed: true` it holds the quoted credits and starts composing. On a DRAFT plan (set the music direction before anything renders) or while the first render pass is still running, it is priced on the planned cut and waits for the master, and a SKETCH to the planned cut is composed right away — free, never laid — to listen to (`sketch.url` on the read); the table read's scene beds are not laid while a score is asked for. Priced like the app's other music: included today, quoted first. Refused before any price when the writer placed music of their own, or edited an earlier score. `direction` is an optional note on the music the writer wants (\"one score: a two-beat tolling bell throughout\").","availability":"available","tags":["pitch-deck","audio","music"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["artifact:publish"]},"api":{"method":"POST","path":"/pitch-decks/{jobId}/score-to-picture","operationId":"scorePitchDeckToPicture","idempotent":true},"cli":{"command":"sleeperhit pitch-deck score-to-picture <jobId> start [--direction <text>] [--confirm]"},"mcp":{"tool":"score_pitch_deck_to_picture","resource":null,"workflowId":"pitch-deck-rendering"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"pitchDeck.scoreToPicture.revert","title":"Revert the pitch deck to its scene beds","description":"Take the score to picture off the deck's timeline, put back the table read's scene beds it replaced, and re-stitch the master — or cancel a score still waiting for the master. Free. Nothing else on the timeline is touched.","availability":"available","tags":["pitch-deck","audio","music"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:write"]},"api":{"method":"POST","path":"/pitch-decks/{jobId}/score-to-picture/revert","operationId":"revertPitchDeckScoreToPicture","idempotent":true},"cli":{"command":"sleeperhit pitch-deck score-to-picture <jobId> revert"},"mcp":{"tool":"revert_pitch_deck_score_to_picture","resource":null,"workflowId":"pitch-deck-rendering"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"pitchDeck.bellLane.get","title":"Read the pitch deck's bell on the beat","description":"Read the deck's bell on the beat: `available` (the deck has a bell beat grid — its title sequence cuts on the bell's beat; `unavailable.message` says how to turn it on), the `grid` (the beat in seconds, where beat 0 is in the master, the intros' and the title's starts), the `lane` (its one sound, `every` 1 or 2, `fromSeconds`/`toSeconds`, `skipSceneIndexes`, `accent`, `level`, `duckUnderVoice`), every strike on the cut (`strikes`: beat, `atMs`, the part it falls in, `accent`; on the PLANNED cut before any master, `plannedCut: true`), the `parts` it can skip (the title sequence, each chapter, each black interlude, by their `sceneIndex` key, with the strikes each gets) and handy start/end `points`, and `check`: every strike found in the published master after assembly by matching the lane's own bell sound, and timed against its beat — `verdict` (`on`: every strike it could time is within a frame; `off`: some are off their beat, a real timing error; `unmeasured`: none could be timed), `label` (the verdict in words, the badge every surface shows), `strikes`, `aligned`, `offBeat`, `tooQuiet` (strikes too quiet in the mix to time — buried under a line or the score; neither on nor off), `worstOffsetMs`, the `off` ones (each with its `offsetMs`, `offsetFrames` and `match`), `ok` and a `note` (a `warning` when strikes are off their beat); `checkCurrent` is false when it was measured on an earlier master or lane. `audibility` is how loud the bell sits against the score (a median dB per strike over the 400 ms after it, `on` the master or the sketch), with a `note` when most strikes are more than 12 dB under it. `scoreMadeRoom` is false when the score on the timeline was composed before the lane and carries its own bell.","availability":"available","tags":["pitch-deck","audio","sfx"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:read"]},"api":{"method":"GET","path":"/pitch-decks/{jobId}/bell-lane","operationId":"getPitchDeckBellLane","idempotent":false},"cli":{"command":"sleeperhit pitch-deck bell <jobId> show"},"mcp":{"tool":"get_pitch_deck_bell_lane","resource":null,"workflowId":"pitch-deck-rendering"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"pitchDeck.bellLane.set","title":"Strike a bell on every beat of the pitch deck","description":"Strike ONE bell sound on every beat of the deck's bell beat grid, frame-exact, as one lane on its audio timeline — or change the lane. The sound is `assetId` (a My Library sound effect), `sound: { fromJobId }` (another deck's bell of the same project, exactly as it struck there: the same bell as v2), or `prompt` (words for one to be made with the sound-effect generator and banked in My Library; `label`, `durationSeconds`), or — on a change — the lane's own. `every` 1 (every beat, default) or 2 (every 2nd beat); `fromSeconds`/`toSeconds` in seconds of the master (null: its first/last frame, the default); `skipSceneIndexes` the parts it stays out of (black interludes, chapters, the title sequence); `accent` (the intros and the title louder, default true); `level` 0–1 (0.12: every bell is struck levelled to a -1 dBFS peak, and 0.12 sits a few dB under a laid score); `duckUnderVoice` (default true: it ducks under the spoken lines like the score). Fields left out keep the lane's; an unknown field is refused by name. Free: nothing is rendered again — a deck in review or finished re-stitches its master for its sound (`reassembling`), a sketch waiting for its master is mixed again with the bell (`sketchRemixing`), and a score to picture composed with a lane leaves room for the struck bell (no bell of its own, nothing on the downbeat). Refused with a 409 when the deck has no bell beat grid.","availability":"available","tags":["pitch-deck","audio","sfx"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:write"]},"api":{"method":"POST","path":"/pitch-decks/{jobId}/bell-lane","operationId":"strikePitchDeckBellOnTheBeat","idempotent":true},"cli":{"command":"sleeperhit pitch-deck bell <jobId> strike [--asset <id>|--from-deck <jobId>|--prompt <text>] [--every 1|2] [--from <s>|start] [--to <s>|end] [--skip <keys>|none] [--accent on|off] [--level <0-1>] [--duck on|off]"},"mcp":{"tool":"strike_pitch_deck_bell_on_the_beat","resource":null,"workflowId":"pitch-deck-rendering"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"pitchDeck.bellLane.remove","title":"Take the bell off the pitch deck","description":"Take the bell lane off the deck's timeline. Free; nothing else on the timeline is touched (the bell sound stays in My Library); a deck in review or finished re-stitches its master for its sound.","availability":"available","tags":["pitch-deck","audio","sfx"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:write"]},"api":{"method":"POST","path":"/pitch-decks/{jobId}/bell-lane/remove","operationId":"removePitchDeckBellLane","idempotent":true},"cli":{"command":"sleeperhit pitch-deck bell <jobId> remove"},"mcp":{"tool":"remove_pitch_deck_bell_lane","resource":null,"workflowId":"pitch-deck-rendering"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"projects.sounds.list","title":"List the sounds a project uses","description":"List every sound the project's decks and trailers use: each deck's bell on the beat, every music clip and sound effect on a deck's or trailer's timeline, named as it was used (\"Low church bell\") and by its video, numbered in the project by when it was made (\"Deck 2 · Karamazov v2\"). Each entry carries `listenUrl` and `bellSound`, how to strike it as a deck's bell (`{ sound: { fromJobId } }` for another deck's bell, `{ assetId }` for a banked sound effect), to pass to the bell lane. `kind` (bell, music, sfx) and `query` (words of the name, the deck's title or \"deck 2\") narrow it. Reads only.","availability":"available","tags":["projects","audio"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:read"]},"api":{"method":"GET","path":"/story-projects/{projectId}/sounds","operationId":"listProjectSounds","idempotent":false},"cli":{"command":"sleeperhit projects sounds <projectId> [--kind bell|music|sfx] [--query <text>]"},"mcp":{"tool":"list_project_sounds","resource":null,"workflowId":"pitch-deck-rendering"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"trailer.scoreToPicture.get","title":"Read the trailer's score to picture","description":"Read the score composed to the trailer's cut and whether one can be composed now: `status` (none / waiting_for_master / queued / composing / laid / failed / reverted), `canScore` and `blocked` (why not — music the writer placed is never replaced), `runtimeMs`, `fitsCut` (false when the cut changed after the score was composed) and the `cueSheet` — its concept and palette, its sections by cut number with their windows, mood, players and intensity, its hit points and where speech sits — and `silentGap` with its `note` when the laid score fell silent as it was first composed and was composed again (a score with dead air is never laid). Before any master, `plannedCut` is true (`runtimeMs` and `cuts` are the planned cut) and `sketch` is the sketch composed to it for a score that waits for the master: `status` (composing / ready / failed) and a `url` to listen to — never laid, never charged. When `status` is failed, `error` is why (the Details). A score asked for with a `direction` that could not be composed is NEVER replaced by the table read's scene beds: they come off the cut, the bell lane and the sound effects stay, and `message` says so plainly — \"The score couldn't be composed (reason in Details). The bell plays alone. Score to picture to try again.\" (with no bell lane, no music plays under the cut; music the writer placed is named as still on it). Say that to the writer. Scoring to picture again without a new `direction` keeps the one it had; a score asked for without a direction that fails still leaves the scene beds.","availability":"available","tags":["trailer","audio","music"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:read"]},"api":{"method":"GET","path":"/trailers/{jobId}/score-to-picture","operationId":"getTrailerScoreToPicture","idempotent":false},"cli":{"command":"sleeperhit trailer score-to-picture <jobId> show"},"mcp":{"tool":"get_trailer_score_to_picture","resource":null,"workflowId":"trailer-rendering"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"trailer.scoreToPicture.start","title":"Score the trailer to picture","description":"Compose ONE score to the trailer's cut and lay it under the whole master, then re-stitch the master. TWO CALLS: sent without `confirmed` it PRICES the score and holds nothing (`quotedOnly: true`, `credits`, `balanceAfter`, `sufficient`, and a `note` to show the writer); sent again with `confirmed: true` it holds the quoted credits and starts composing. On a DRAFT plan (set the music direction before anything renders) or while the first render pass is still running, it is priced on the planned cut and waits for the master, and a SKETCH to the planned cut is composed right away — free, never laid — to listen to (`sketch.url` on the read). Priced like the app's other music: included today, quoted first. Refused before any price when the writer placed music of their own, or edited an earlier score. `direction` is an optional note on the music the writer wants (\"one score: a two-beat tolling bell throughout\").","availability":"available","tags":["trailer","audio","music"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["artifact:publish"]},"api":{"method":"POST","path":"/trailers/{jobId}/score-to-picture","operationId":"scoreTrailerToPicture","idempotent":true},"cli":{"command":"sleeperhit trailer score-to-picture <jobId> start [--direction <text>] [--confirm]"},"mcp":{"tool":"score_trailer_to_picture","resource":null,"workflowId":"trailer-rendering"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"trailer.scoreToPicture.revert","title":"Revert the trailer to its scene beds","description":"Take the score to picture off the trailer's timeline, put back any beds it replaced, and re-stitch the master — or cancel a score still waiting for the master. Free. Nothing else on the timeline is touched.","availability":"available","tags":["trailer","audio","music"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:write"]},"api":{"method":"POST","path":"/trailers/{jobId}/score-to-picture/revert","operationId":"revertTrailerScoreToPicture","idempotent":true},"cli":{"command":"sleeperhit trailer score-to-picture <jobId> revert"},"mcp":{"tool":"revert_trailer_score_to_picture","resource":null,"workflowId":"trailer-rendering"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"trailer.storyboard.coverage.get","title":"Read trailer plan coverage","description":"Read the pre-render report for the exact trailer beat plan that would render right now — current/stale, overall score, the 8.0 gate, seven dimensions, machine-checked plan defects, per-beat notes, and priority fixes. A plan with no report yet reads back as `missing`, not as a 404; the latest draft edit's coverage, waiting to start, reads back as `queued` (a burst of edits is one run, started once the plan has been left alone for three minutes); a run that failed, or a draft edit whose coverage could not be queued at all (no Series Bible, no reachable coverage provider), reads back as `failed` with the reason in `failureMessage`. Near the bar the same revision is judged again and the gate decides on the median of each score: `judging` lists every judgment with its score, the medians, and whether another is pending. The report's `opening` is the judge's note on the deck's opening title sequence (`present`, `whatItSays`, `servesIntent`, `nextMove`).","availability":"available","tags":["trailer","storyboard","coverage"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:read"]},"api":{"method":"GET","path":"/trailers/{jobId}/storyboard/coverage","operationId":"getTrailerStoryboardCoverage","idempotent":false},"cli":{"command":"sleeperhit trailer coverage <jobId>"},"mcp":{"tool":"get_storyboard_coverage","resource":null,"workflowId":"pitch-deck-rendering"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"trailer.storyboard.coverage.generate","title":"Generate trailer plan coverage","description":"Queue a pre-render report for the current trailer beat plan. It grades the PLAN, never a rendered frame, so it spends no render credits. The gate is 8.0 — stricter than the 7.0 foundational Bible gate — because a plan that renders wrong spends real money.","availability":"available","tags":["trailer","storyboard","coverage"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:write"]},"api":{"method":"POST","path":"/trailers/{jobId}/storyboard/coverage","operationId":"generateTrailerStoryboardCoverage","idempotent":true},"cli":{"command":"sleeperhit trailer coverage <jobId> --generate"},"mcp":{"tool":"generate_storyboard_coverage","resource":null,"workflowId":"pitch-deck-rendering"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"trailer.intent.get","title":"Read a trailer's intent","description":"Read what the trailer is FOR beside what its plan says: its intent, each beat's arc stage and how it advances the central question, where the beats break the arc, and plan coverage's first-time-viewer takeaway — written before the judge saw the intent — with the story checks. Every deck and trailer is planned from an explicit intent — what the video is for, its logline, theme, central question, stakes, what a first-time viewer is promised, a four-stage arc (setup, escalation, turn, closing question) and how the ending lands the question. Every chapter or beat names the arc stage it serves (`arcStage`), how it advances the central question (`advancesQuestion`) and, after the first, why it follows the one before it (`whyItFollows`: the visible link — a cause, an answer, a contrast, a match cut, a look, an object, a sound — and what it moves forward; one line, never shown on screen). Plan coverage first writes what a first-time viewer would take away from the plan without seeing the intent (`viewerTakeaway`, with how much of the story the words recited rather than let them work out: `toldVersusShown`, and where they lost the thread: `lostTheThread`), then compares it with the intent: intent clarity, the central question, the buildup and whether the theme is carried each fail the plan on their own, and so do subtext — a plan that recites its plot instead of posing its question — and transitions — a part that follows the one before it for no reason a first-time viewer can feel (`weakTransitions` names the weakest, each with its fix); voices (do the characters speak, rather than the narrator carrying everything) is scored beside them. A read.","availability":"available","tags":["trailer","intent"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:read"]},"api":{"method":"GET","path":"/trailers/{jobId}/intent","operationId":"getTrailerIntent","idempotent":false},"cli":{"command":"sleeperhit trailer intent <jobId>"},"mcp":{"tool":"get_video_intent","resource":null,"workflowId":"pitch-deck-rendering"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"trailer.intent.update","title":"Edit a draft trailer's intent","description":"Edit a DRAFT trailer's intent — its purpose, audience, logline, theme, central question, stakes, viewer promise, ending, or its whole four-stage arc (each stage's purpose, temperature and a 1–10 intensity that rises to the turn). Editing the intent is free and only while the plan is a draft (approving the plan approves its intent): it saves the new intent and queues plan coverage again for the latest revision — a burst of edits is one coverage run, started once the plan has been left alone for three minutes. The chapters or beats are not re-planned; edit them (their `arcStage`, `advancesQuestion` and `whyItFollows` included) to follow the new intent. Answers the saved intent, `planCoverage`, and `arcProblems` — where the beats now break the new arc; fix them with the beat refine's `arcStage` and `advancesQuestion`.","availability":"available","tags":["trailer","intent"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:write"]},"api":{"method":"POST","path":"/trailers/{jobId}/intent","operationId":"updateTrailerIntent","idempotent":true},"cli":{"command":"sleeperhit trailer intent <jobId> [--purpose <text>] [--audience <text>] [--logline <text>] [--theme <text>] [--central-question <text>] [--stakes <text>] [--viewer-promise <text>] [--ending <text>] [--arc <json>]"},"mcp":{"tool":"update_video_intent","resource":null,"workflowId":"pitch-deck-rendering"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"trailer.beats.refine","title":"Refine one trailer beat","description":"Edit one trailer beat's plan: what it delivers (`storyBeat`), its framing (`shotType`), motion direction, its staging (`characterAction` and `stagingNotes`, which a beat held as one shot is filmed from; '' clears either), either side of a seam, on-screen caption, composition, duration, who is in the picture (`visibleCharacters` is the named characters on camera; unnamed people need no listing), where it is set (`location`, stored as a canonical location key), the stage of the trailer's intent it serves (`arcStage`), how it advances the central question (`advancesQuestion`) and why it follows the beat before it (`whyItFollows`: the link a viewer sees or hears, never on screen; \"\" clears it) — plan words that never make a take stale; on a draft the changed plan is queued for plan coverage (`planCoverage`) — and `shots` — its cut list of shots with hard cuts between them, each with whatever camera move it wants, performed inside its render calls (the cuts are free; cost is per rendered second). A beat names where it is set in its `location`: a canonical location key, the place its location image is made of. A beat may travel: a shot set somewhere else names that place in its own `location` (a key, or a place in plain words), and the render follows it there. Free: it saves the plan and marks what went stale — an edit to what the beat films marks its takes out of date (they stay playable), a caption edit marks only its text layer. Render the beat again with the priced render-clip op. Allowed in draft, review and complete. Returns a shareable `previewUrl` for the beat.","availability":"available","tags":["trailer","storyboard"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:write"]},"api":{"method":"POST","path":"/trailers/{jobId}/beats/refine","operationId":"refineTrailerBeat","idempotent":true},"cli":{"command":"sleeperhit trailer refine <jobId> --beat <n> [--story-beat <text>] [--shot-type <text>] [--motion-prompt <text>] [--transition-prompt <text>] [--transition-in <text>] [--caption <text>] [--composition image|text|both] [--visible-characters <a,b>] [--featured-character <name>] [--location <key>] [--duration <4..30>] [--shots <json>] [--character-action <text>] [--staging-notes <text>] [--arc-stage setup|escalation|turn|closing_question] [--advances-question <text>] [--montage | --no-montage]"},"mcp":{"tool":"refine_trailer_beat","resource":null,"workflowId":"trailer-rendering"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"trailer.beats.renderClip","title":"Render one trailer beat again","description":"Render one trailer beat again at 480p — the writer's priced retake: a new take of one call (`callId`) or of every call of the beat. A beat whose plan changed since it rendered is recompiled first (free) and its new calls are priced. Each new take is checked like every take and may earn the call's one automatic retake at our cost (a re-voiced line, or an opening off its planned framing); a moderation refusal is released and never retried. TWO CALLS: sent without `confirmed` it PRICES the render and reserves nothing (`quotedOnly: true`, `credits`, the `lines`, `balanceAfter` — what the writer would have left — `sufficient`, and a `note` to show the writer; when `sufficient` is false the note names the top-up link, and the caller must not confirm); sent again with `confirmed: true` it reserves exactly the quoted lines and queues the takes. Not a required `confirmed: true` literal — a field that must be true to validate cannot tell a confirmed call from an unconfirmed one. Refused before the price: a text-only beat, a beat that is not in the cut, a call id the beat does not have, and a cast member with no body figure (the refusal names the action that fixes it). Review or complete only. Returns a shareable per-beat `previewUrl`.","availability":"available","tags":["trailer","storyboard"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["artifact:publish"]},"api":{"method":"POST","path":"/trailers/{jobId}/beats/render-clip","operationId":"renderTrailerBeatClip","idempotent":true},"cli":{"command":"sleeperhit trailer render-clip <jobId> --beat <n> [--call <callId>] [--confirm]"},"mcp":{"tool":"render_trailer_beat_clip","resource":null,"workflowId":"trailer-rendering"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"trailer.beats.selectTake","title":"Select a take of one trailer call","description":"Choose which take of one of a beat's calls the cut plays and the finish delivers. Free and reversible — select another take to change it — so there is no price and nothing to confirm; the beat's preview cut is re-assembled from the new selection. A take that replaced an on-camera line with its own reading (re-voiced) is never selected, by default or here: the refusal names the lines — stage the line as a voice-over, or render a new take. The answer's `warning` names anything else the chosen take was flagged for, and the finish quote and the export carry it too. In a complete trailer a new selection sends the cut back to review, and the next finish quotes just that take. Review or complete only. Answers `{ jobId, beatIndex, callId, take, warning }`.","availability":"available","tags":["trailer","storyboard"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:write"]},"api":{"method":"POST","path":"/trailers/{jobId}/beats/{beatIndex}/select-take","operationId":"selectTrailerTake","idempotent":true},"cli":{"command":"sleeperhit trailer select-take <jobId> --beat <n> --call <callId> --take <n>"},"mcp":{"tool":"select_trailer_take","resource":null,"workflowId":"trailer-rendering"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"trailer.beats.repairTake","title":"Repair one take of a trailer call in place","description":"Every rendered take is watched with its sound after its checks. A cut nobody asked for at the start or end of an otherwise good take is trimmed off first, before any new take: free, frame for frame, only where the cut is measured in the file, outside every spoken line (each kept whole with a breath after it), and only when what is left keeps its chapter or beat within a quarter of its planned length. When the shot's automatic new take is spent and the take it plays still has such a cut outside its line, that end is trimmed as a last resort: past the quarter, as long as the line stays whole, at least 2 seconds are left and the chapter or beat keeps half its planned length. A cut inside a spoken line is never trimmed. A speaker whose lips keep moving past the take's last line, where nothing is heard, is trimmed half a second after the line, free and frame for frame. Lips moving where no line is heard are never retaken on their own: the same staging brings them back, so the shot is offered for restaging (one face, framed closer), a trim, or your call. Any other defect is remedied by rule during processing, at our cost: first a new take told what to avoid; a repair in place when the same problem comes back after a new take, or when the take passed every other check and only something removable (a period anachronism, garbled lettering, a stray or doubled person) or the light is wrong. Camera movement and its speed (a move that rushes, or dies into a hold at the end), timing, cuts and a crowd moving as one (extras in step, everyone turning or looking down at once, repeated faces) are only ever fixed by a new take, or by the free trim when they sit only at an end of the take; spoken shots are not repaired in place. A line the speaker's mouth did not speak on two takes is no longer retaken on camera: the next take stages it as a voice-over, the speaker seen from behind, the line heard over the picture. Every take plays its own sound under its own picture, so the lips follow what is heard: a line said in the take's own reading is kept, and only a line not heard, or said in a voice too like another character's, is a defect (a new take). Where a speaker's mouth cannot be measured (or the face is too small to trust a miss), the watcher's own judgment of the lips decides the line: a mouth it saw not speak is a miss, one it saw speak is uncertain. Each shot gets at most one automatic new take, one automatic repair in place and one automatic voice-over re-stage, so a new take whose removable defect came back is repaired in the same pass; a repaired or trimmed take is never remedied again on its own. A repair that fails on the repair service's own side (never one declined at its content check) and cost nothing is sent again once; if that fails too, a new take instead. A repaired take keeps the take's own sound, is judged again, and is kept as a new take linked to the one it repairs; it plays only when it passes. A trimmed take plays over the take it came from when it passes, or when it shows only part of what that take showed, with the same speech and faces: it is judged by time window, so anything seen inside the span it keeps counts as that take's own footage too, and it wins when the trim cut something off. This is the writer's own repair of one take. TWO CALLS: sent without `confirmed` it PRICES the repair and reserves nothing (`quotedOnly: true`, `credits` for the seconds it sends — the whole take, or only the shots its defect sits in, two seconds at least — `summary`, `balanceAfter`, `sufficient` and a `note` to show the writer; when `sufficient` is false the caller must not confirm); sent again with `confirmed: true` it reserves exactly that line and queues the repair as a new take linked to the one it repairs (`repairTake`). The repaired take keeps the take's own sound, is checked again and plays only if it passes; a repair that does not land is released (nothing charged). Refused before anything is reserved: the project's spend gate, a take that is not an accepted take of the call, a repair of a repair, a take whose repair was declined at the content check (never sent again unchanged), a spoken shot (not repaired in place yet), repair not set up, and a length the repair cannot take. To render a new take instead, use render-clip with `callId`: a new take is told what the watcher saw on the takes before it. Review or complete only.","availability":"available","tags":["trailer","storyboard"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["artifact:publish"]},"api":{"method":"POST","path":"/trailers/{jobId}/beats/{beatIndex}/repair-take","operationId":"repairTrailerTake","idempotent":true},"cli":{"command":"sleeperhit trailer repair-take <jobId> --beat <n> --call <callId> --take <n> [--confirm]"},"mcp":{"tool":"repair_trailer_take","resource":null,"workflowId":"trailer-rendering"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"trailer.beats.overrideTakeRepair","title":"Override the repair decision on one trailer take","description":"Override the repair engine on one take of a beat's call. Free, so there is no price and nothing to confirm. `keep` keeps the take as it is: what was found on it no longer ranks it down or warns, and the engine never acts on it. `restore` lets the engine's decision stand again. The call's default selection re-runs unless the writer chose its take explicitly, and the cut re-assembles when the take it plays changed. `rewatch` watches again, at our cost, a take whose watch could not finish (its decision `unwatched`: never clean, never remedied on its own): its checks are queued and it is decided when the watch lands; a take already watched is refused. Review or complete only. Answers `{ jobId, callId, take, decision, repair, selectedTake, message }`.","availability":"available","tags":["trailer","storyboard"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:write"]},"api":{"method":"POST","path":"/trailers/{jobId}/beats/{beatIndex}/take-repair-override","operationId":"overrideTrailerTakeRepair","idempotent":true},"cli":{"command":"sleeperhit trailer override-repair <jobId> --beat <n> --call <callId> --take <n> --keep|--restore|--rewatch"},"mcp":{"tool":"override_trailer_take_repair","resource":null,"workflowId":"trailer-rendering"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"trailer.beats.trimTake","title":"Trim one take of a trailer call","description":"Trim one take of a beat's call to a span: \"trim this take to <start>–<end>\". Free: one call, nothing priced, reserved or confirmed. The span `[keepStartSeconds, keepEndSeconds)` is snapped to the take's frames and kept as a NEW take linked to the one it trims (`trimTake`); the take itself stays. Never into a spoken line: the span must keep every line placed on the take's speech track whole (`trim_cuts_speech`), lie inside the take, keep at least the shortest a take is trimmed to, and not be the whole take (`trim_span_invalid`) — refused before anything is queued. The trimmed take is checked again and plays over the take it came from only if it passes; its cut then plays its real, shorter length. The repair engine trims on its own, first and for free, when a cut nobody asked for sits at the start or end of an otherwise good take (rule `trim_edge`), or a speaker's lips run on past the take's last line where nothing is heard (rule `trim_overrun`: cut half a second after the line as the take says it); each take's `trimBounds` says what it may keep. Review or complete only. Answers `{ jobId, callId, take, trimTake, keepStartSeconds, keepEndSeconds, queued, message }`.","availability":"available","tags":["trailer","storyboard"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:write"]},"api":{"method":"POST","path":"/trailers/{jobId}/beats/{beatIndex}/trim-take","operationId":"trimTrailerTake","idempotent":true},"cli":{"command":"sleeperhit trailer trim-take <jobId> --beat <n> --call <callId> --take <n> --keep <start>-<end>"},"mcp":{"tool":"trim_trailer_take","resource":null,"workflowId":"trailer-rendering"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"trailer.beats.stageVoiceOver","title":"Stage one trailer take's line as a voice-over","description":"Stage the line of one take of a beat's call as a VOICE-OVER in a new take of the call: the speaker seen from behind, the cast's own voice laid over the picture, so no mouth has to follow the line. The lines staged are the call's on-camera lines that a take of it replaced with its own reading (a re-voiced take is never played), else every line it says on camera (each take's `voiceOverRestage` shows them, with the price). The engine does this on its own, at our cost, once the same line is re-voiced on two takes of a call. Metered like a new take of the call, TWO CALLS: sent without `confirmed` it PRICES the new take and reserves nothing (`quotedOnly: true`, `credits`, `voiceOverTake`, `lineRefs`, `summary`, `balanceAfter`, `sufficient` and a `note` to show the writer; when `sufficient` is false the caller must not confirm); sent again with `confirmed: true` it reserves exactly that line, records the request on the take and queues the new take (`voiceOverTake`), which is checked like every take and plays only when it is the best take of the call. Refused before anything is reserved: the project's spend gate, a take that is not an accepted take of the call (`trailer_take_not_accepted`), and a call that says nothing on camera (`voice_over_nothing_to_stage`). Review or complete only. The path `{beatIndex}` is the beat's key from the beats read.","availability":"available","tags":["trailer","storyboard"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["artifact:publish"]},"api":{"method":"POST","path":"/trailers/{jobId}/beats/{beatIndex}/stage-voice-over","operationId":"stageVoiceOverTrailerTake","idempotent":true},"cli":{"command":"sleeperhit trailer stage-voice-over <jobId> --beat <n> --call <callId> --take <n> [--confirm]"},"mcp":{"tool":"stage_trailer_take_as_voice_over","resource":null,"workflowId":"trailer-rendering"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"trailer.finish","title":"Finish the trailer","description":"Finish the cut: every selected take is upscaled from its 480p render to the delivery class — 720p unless the writer asked for 1080p (`deliveryResolution`, else the trailer's own class) — the on-screen text layers are composited over the finished cut, and the finished master is stitched. Nothing is generated again, and a take already finished at the class is reused, not charged twice. TWO CALLS: sent without `confirmed` it PRICES the finish and reserves nothing (`quotedOnly: true`, `credits`, the `lines`, a `warnings` entry per flagged take the writer kept, `balanceAfter`, `sufficient`, and a `note` to show the writer); sent again with `confirmed: true` it reserves exactly those lines and starts the finish (`finishing`, then `complete`). Refused before the price while any call has no selected take (a call whose every take re-voiced a line: stage the line as a voice-over, or render a new take), and while the trailer's master FAILED its video coverage (`trailer_video_coverage_failed`, with the findings and their fixes) unless `acknowledgeVideoCoverage: true` — only once the writer has seen the findings and chosen to finish anyway. Coverage still running, one that could not run, or one of an earlier master never holds the finish; the quote's `warnings` say so. While the read's `autoFix.state` is `reviewing` or `fixing` the engine is retaking what the review flagged by itself — wait for it rather than retaking by hand; once it has stopped short (`verdict.state: your_call`), the writer either finishes anyway or lets it try more fixes (the more-fixes op). Review or complete (finishing again at a new class) only.","availability":"available","tags":["trailer","render"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["artifact:publish"]},"api":{"method":"POST","path":"/trailers/{jobId}/finish","operationId":"finishTrailer","idempotent":true},"cli":{"command":"sleeperhit trailer finish <jobId> [--resolution 720p|1080p] [--confirm] [--acknowledge-video-coverage]"},"mcp":{"tool":"finish_trailer","resource":null,"workflowId":"trailer-rendering"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"trailer.reassemble","title":"Re-assemble a trailer whose assembly failed, or rebuild its master","description":"Put a FAILED trailer back together from the takes it already has. A trailer whose assembly failed for good — `assemble`, the 480p preview, or `finish_assemble`, the finished master — lost nothing it paid for: every call's takes (and their finished upscales) are kept. This re-runs THAT stage: the trailer goes back to `rendering` (then `review`) or `finishing` (then `complete`). Free — nothing is rendered, upscaled or reserved — so there is no price and nothing to confirm. Refused (409, with the reason) for a trailer that is not failed, one that failed while its shots were being sent to render or to be finished (nothing to assemble), or one missing an accepted take; the beats read's `reassembly` says whether it applies (`available`) and why not (`refusal`) before you call. A trailer in `review` or `complete` has its master REBUILT, free and fresh, with the current sound rules: in review the preview assembly runs (`assemble`, older-recipe cuts re-cut) and the trailer stays in review; complete, the finished master is stitched again at its class (`restitch`) and the trailer STAYS complete. Never changes the selected takes. Refused while a master is already being assembled for the trailer (`trailer_reassemble_assembly_in_flight`) or a shot has a take in flight (`trailer_reassemble_take_in_flight`). Answers `{ jobId, queued, stage, status, credits: 0, message }`.","availability":"available","tags":["trailer","render"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:write"]},"api":{"method":"POST","path":"/trailers/{jobId}/reassemble","operationId":"reassembleTrailer","idempotent":true},"cli":{"command":"sleeperhit trailer reassemble <jobId>"},"mcp":{"tool":"reassemble_trailer","resource":null,"workflowId":"trailer-rendering"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"trailer.cancelRender","title":"Stop a trailer's render","description":"Stop the trailer's render in flight — its first pass, its finish, or a retake or repair still running. Nothing more is sent to a provider: its queued and running render jobs are cancelled, and a job already running stops at its next step. The writer's reservations for work that had not run are released (`released`, `releasedCredits`); every accepted take, selection, cut, finished take and master is kept (`keptTakes`). A shot already out at the provider is stopped and recorded on its beat (`abandoned`): not charged to the writer (the provider may still bill it, at our cost), and never resumed. It lands in `review` with what rendered, back at `draft` when nothing did (approving again quotes the same shots), back in `review` after a stopped finish, or as it was after a stopped retake. Free: no price and nothing to confirm. With nothing rendering it answers `stopped: false` and changes nothing. Answers `{ jobId, surface, stopped, previousStatus, status, cancelledJobs, abandoned, released, releasedCredits, keptTakes, note }`; read `trailer beats` after it.","availability":"available","tags":["trailer","render"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["artifact:publish"]},"api":{"method":"POST","path":"/trailers/{jobId}/cancel-render","operationId":"cancelTrailerRender","idempotent":true},"cli":{"command":"sleeperhit trailer cancel-render <jobId>"},"mcp":{"tool":"cancel_trailer_render","resource":null,"workflowId":"trailer-rendering"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"trailer.moreFixes","title":"Let the trailer's automatic fixes try more","description":"The render approval carries an automatic-fix allowance: the engine watches the 480p preview and retakes the shots its review flags, inside that ceiling, until the preview is clean or it stops short (the beats read's `autoFix`: `state: stopped`, `stopReason`, `stoppedBecause`). When it stopped for want of credits or rounds, or because a flagged shot reached its tries, `autoFix.moreFixes` offers ONE MORE GRANT of `credits` and `verdict.choices` carries `more_fixes`; this op takes it. Metered, TWO CALLS: sent without `confirmed` it PRICES the grant and reserves nothing (`quotedOnly: true`, `credits`, `costLabel`, `balanceAfter`, `sufficient`, and a `note` to show the writer; when `sufficient` is false the caller must not confirm); sent again with `confirmed: true` it reserves the grant, raises the loop's caps (a round of fixes and a try per shot more) and answers the same review again (`quotedOnly: false`, `queued: true`, `credits`, `message`, `autoFix`). Only what the fixes draw is charged; the rest comes back when the loop stops. Refused (409, `details.refusal.code`): `auto_fix_not_in_review`, `auto_fix_nothing_more` (still fixing, or nothing a new take or a text render would fix — finish anyway instead), `auto_fix_already_running`; 402 when the balance cannot hold it. Review only.","availability":"available","tags":["trailer","render"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["artifact:publish"]},"api":{"method":"POST","path":"/trailers/{jobId}/more-fixes","operationId":"allowMoreTrailerFixes","idempotent":true},"cli":{"command":"sleeperhit trailer more-fixes <jobId> [--confirm]"},"mcp":{"tool":"allow_more_trailer_fixes","resource":null,"workflowId":"trailer-rendering"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"trailer.videoCoverage.get","title":"Read trailer video coverage","description":"Read the trailer's VIDEO COVERAGE: its stitched master (the 480p preview, then the finished master) watched with its sound and scored on its quality and its adherence to the shot list — lip sync, prompt adherence, visual fidelity, motion naturalness, identity continuity, text placement, audio sync — never its story. Answers which master it watched and whether that is the current one, the score against the bar with the dimensions that fail it on their own, every finding with its timecode located on beats, calls and shots and its remedy (retake that call, or render the text again), and `blocksFinish` — while true the finish is refused (`trailer_video_coverage_failed`) unless the writer chooses to finish anyway. `report.judging` says how the verdict was reached: near the bar the master is watched again (a third time when two watches disagree) and every score is the median of its watches; a master whose picture is frame-identical to an earlier judged one carries that report's picture scores and judges only lip sync, audio sync and transitions again. `report.lipSync` is the MEASURED lip sync: every spoken line, what the mouth check measured on the take it plays from (missed, uncertain, in sync, not measured) and why; each miss is also a `measured` lip-sync finding that holds lip sync under the bar whatever the judge scored, fixed by a new take of its call. A trailer with no report reads back as `missing`, not as a 404.","availability":"available","tags":["trailer","render","video_coverage"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:read"]},"api":{"method":"GET","path":"/trailers/{jobId}/video-coverage","operationId":"getTrailerVideoCoverage","idempotent":false},"cli":{"command":"sleeperhit trailer video-coverage <jobId>"},"mcp":{"tool":"get_video_coverage","resource":null,"workflowId":"pitch-deck-rendering"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"trailer.videoCoverage.generate","title":"Cover the trailer video again","description":"Watch the trailer's CURRENT master again as a new video coverage report. Free — the watch costs the writer nothing — so there is no price and no `confirmed`. Coverage already runs by itself, once per master, when the preview is stitched and again when the finished master is; a report already running on this master is returned as it is. Refused for a trailer with no stitched master, one not in review or complete, or when no provider can watch a video right now (which never holds the finish).","availability":"available","tags":["trailer","render","video_coverage"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:write"]},"api":{"method":"POST","path":"/trailers/{jobId}/video-coverage","operationId":"generateTrailerVideoCoverage","idempotent":true},"cli":{"command":"sleeperhit trailer video-coverage <jobId> --generate"},"mcp":{"tool":"generate_video_coverage","resource":null,"workflowId":"pitch-deck-rendering"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"trailer.storyboard.moveBeat","title":"Move a trailer beat to another position","description":"Move one beat to another position in the cut; `toIndex` is where it ENDS UP. Costs no credits and generates nothing — it rewrites the order and carries each beat's rendered takes and cut with it. Returns the new `beatCount`, `movedTo`, and `staleBeats`: the beats whose following beat changed, so their seam direction is out of date. Their footage stays playable.","availability":"available","tags":["trailer","storyboard"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:write"]},"api":{"method":"POST","path":"/trailers/{jobId}/storyboard/move-beat","operationId":"moveTrailerBeat","idempotent":true},"cli":{"command":"sleeperhit trailer move-beat <jobId> --from <n> --to <n>"},"mcp":{"tool":"move_trailer_beat","resource":null,"workflowId":"trailer-rendering"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"trailer.storyboard.insertBeat","title":"Insert a blank trailer beat","description":"Insert a new blank beat at a seam — `atIndex` is the position it takes, `afterBeatIndex` puts it just after that beat, and omitting both appends it. Costs no credits and generates nothing: the new beat arrives with no footage — direct it with the refine op, then render it with the priced render-clip op. Returns `insertedBeatIndex`, the new `beatCount`, and `staleBeats`.","availability":"available","tags":["trailer","storyboard"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:write"]},"api":{"method":"POST","path":"/trailers/{jobId}/storyboard/insert-beat","operationId":"insertTrailerBeat","idempotent":true},"cli":{"command":"sleeperhit trailer insert-beat <jobId> [--at <n> | --after <n>]"},"mcp":{"tool":"insert_trailer_beat","resource":null,"workflowId":"trailer-rendering"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"trailer.storyboard.removeBeat","title":"Remove a trailer beat","description":"Remove one beat from the cut, with everything already rendered on it. Costs no credits — and refunds none: what that beat bought is gone, and the cut's last beat cannot be removed. Returns the new `beatCount` and `staleBeats`.","availability":"available","tags":["trailer","storyboard"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:write"]},"api":{"method":"POST","path":"/trailers/{jobId}/storyboard/remove-beat","operationId":"removeTrailerBeat","idempotent":true},"cli":{"command":"sleeperhit trailer remove-beat <jobId> --beat <n>"},"mcp":{"tool":"remove_trailer_beat","resource":null,"workflowId":"trailer-rendering"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"trailer.storyboard.beatTakes","title":"Read a trailer beat's earlier cuts","description":"Read the earlier cuts a beat has played — the cuts it was re-assembled away from, newest first, up to `takesKept`. A beat's cut is assembled from its calls' selected takes, so each earlier cut stands for an earlier selection. Costs no credits and renders nothing: it hands back urls that already exist. Give `beat` for one beat or omit it to see which beats in the whole cut have anything to compare. Call it before restoring, because a restore needs an exact url and this is where the urls come from. Returns each beat's current `clipUrl`, its earlier cuts (`takes`), and a `reviewUrl` to watch them. The per-call takes themselves are on the beats read.","availability":"available","tags":["trailer","storyboard"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:read"]},"api":{"method":"GET","path":"/trailers/{jobId}/storyboard/takes","operationId":"getTrailerBeatTakes","idempotent":false},"cli":{"command":"sleeperhit trailer takes <jobId> [--beat <n>]"},"mcp":{"tool":"get_trailer_beat_takes","resource":null,"workflowId":"trailer-rendering"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"trailer.storyboard.restoreTake","title":"Put an earlier cut of a beat back","description":"Put one of a beat's earlier cuts back, replacing the cut it plays now, and re-select the takes that cut was assembled from — so the finish delivers exactly what was restored (a flagged take included: the writer has seen it). Costs no credits and renders nothing. Fully reversible: the cut it displaces joins the beat's list, so the same call with the other url undoes it. That is why there is no price and nothing to confirm. `url` must be one this beat actually played; a url it never held is refused rather than trusted. A complete trailer goes back to review, and a burned-in text layer over the replaced cut is marked out of date. Answers `{ success, clipUrl, selection }`.","availability":"available","tags":["trailer","storyboard"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:write"]},"api":{"method":"POST","path":"/trailers/{jobId}/storyboard/restore-take","operationId":"restoreTrailerTake","idempotent":true},"cli":{"command":"sleeperhit trailer restore-take <jobId> --beat <n> --url <url>"},"mcp":{"tool":"restore_trailer_take","resource":null,"workflowId":"trailer-rendering"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"trailer.storyboard.directTextMotion","title":"Direct how a trailer beat's text moves","description":"Say in plain words how one beat's on-screen text should move — \"type it out letter by letter, then draw an underline\" — and it is compiled into the motion spec the text layer executes. Costs no credits and renders nothing: it writes the spec and keeps your own words beside it, so the next direction is not authored blind. Re-directing REPLACES the treatment rather than adding to it, which is why there is no price and nothing to confirm. Render the text layer afterwards to see it. Refused before anything is compiled when the beat has nothing to move: a beat that is footage only, or one with no caption written yet.","availability":"available","tags":["trailer","storyboard"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:write"]},"api":{"method":"POST","path":"/trailers/{jobId}/storyboard/direct-text-motion","operationId":"directTrailerTextMotion","idempotent":true},"cli":{"command":"sleeperhit trailer direct-text-motion <jobId> --beat <n> --direction <text>"},"mcp":{"tool":"direct_trailer_text_motion","resource":null,"workflowId":"trailer-rendering"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"trailer.storyboard.regenerateText","title":"Render one trailer text layer","description":"Render one trailer beat's on-screen text / motion-graphic layer with its current caption and treatment, composited over the beat's cut or its poster (metered — one per-text credit). TWO CALLS: sent without `confirmed` it PRICES the render and reserves nothing (`quotedOnly: true`, `credits`, `balanceAfter` — what the writer would have left — `sufficient`, and a `note` to show the writer; when `sufficient` is false the note says they are short and names the top-up link, and the caller must not confirm); sent again with `confirmed: true` it reserves the one credit line and queues the render. Not a required `confirmed: true` literal — a field that must be true to validate cannot tell a confirmed call from an unconfirmed one, and it would force the price to be announced after the money moved. Preconditions run above the price: a beat missing from the cut, a beat that is footage only, and a cut in a status where beats can no longer be edited are refused with no quote at all. The finish composites every text layer at the delivery class; this op is for seeing a caption before the finish. A confirmed call returns `reviewUrl` + a shareable per-beat `previewUrl`.","availability":"available","tags":["trailer","storyboard"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["artifact:publish"]},"api":{"method":"POST","path":"/trailers/{jobId}/storyboard/regenerate-text","operationId":"regenerateTrailerText","idempotent":true},"cli":{"command":"sleeperhit trailer regenerate-text <jobId> --beat <n> [--confirm]"},"mcp":{"tool":"regenerate_trailer_text","resource":null,"workflowId":"trailer-rendering"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"trailer.video.export","title":"Re-stitch the finished trailer master","description":"Rebuild the finished trailer MP4 from the finished cuts and the narration and music already on the job. Generates nothing and costs no render credits — it re-runs the composition over EXISTING finished cuts, so it is how a music bed or a narration track that landed after the finish is folded in. Only a complete trailer exports: a 480p preview master is for review, never the deliverable, so a trailer in review is refused (409 — finish it first). The answer carries `warnings`, one per flagged take the writer kept (a re-voiced line, an opening off its plan). A queued or rendering export short-circuits rather than stacking.","availability":"available","tags":["trailer","render"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:write"]},"api":{"method":"POST","path":"/trailers/{jobId}/video-export","operationId":"exportTrailerVideo","idempotent":true},"cli":{"command":"sleeperhit trailer export <jobId>"},"mcp":{"tool":"export_trailer_video","resource":null,"workflowId":"trailer-rendering"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"trailer.plan.approve","title":"Approve the trailer plan into the render","description":"Approve a draft trailer's beat plan into the render — the next step of EVERY trailer job, which stops at its plan (a story job's `progress.trailerJobId`, `progress.nextStep: approve_trailer_plan`): approving THIS job renders the cut that was scored, while creating a new plan re-runs the stochastic planner and renders an ungraded draw. TWO CALLS: sent without `confirmed` it runs the coverage gate, compiles and voices every footage beat (free to the writer) and PRICES the 480p render — a line per call at its voiced seconds and a line per location plate the renders make first, the `calls`, advisory `warnings`, `balanceAfter`, `sufficient`, and a `note` to show the writer — reserving nothing; sent again with `confirmed: true` it reserves exactly the quoted calls and starts the render (`rendering`, then `review`). The quote also carries the AUTOMATIC-FIX ALLOWANCE (`autoFixAllowance: { credits, note }`, and a `lines` entry of kind `allowance`): a ceiling, sized from the render, that the engine may draw on to retake the shots the review of the 480p preview flags (and render flagged on-screen text again), reserved with the render — only what the fixes draw is charged and the rest comes back when the loop stops (0 when the balance covers only the render: the preview is still reviewed). Follow it on the read's `autoFix`. The 720p finish stays a separate approval. Every call renders at 480p with the cast's own recorded lines; a take that re-voices a line, has lips out of step with its lines, or misses its opening framing is retaken once automatically at our cost. Refused before the price, with the action that fixes it (`error.details.refusal`): an unscored or failing plan, a narrated cut with no narrator, a beat whose cast has no body figure or cast voice. A plan the gate refuses on the judge's scores alone (`error.details.overridable: true`) may be rendered anyway on the writer's explicit choice with `acknowledgePlanCoverage: { reason }` — never over a blocking defect decided in code, or a missing, running, failed, stale or old-rubric report; the confirmed approval records it on the report (the coverage read's `writerOverride`). Draft only. A trailer is priced by the second: 1 credit a second to render at 480p, plus 1 credit a second to finish at 720p (2 credits a second in all; a 1080p finish is 4 credits a second instead). Planning is free. The exact price is quoted per shot once the plan is ready, before anything renders; location plates and on-screen text are itemized in the same quotes.","availability":"available","tags":["trailer","plan"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:write"]},"api":{"method":"POST","path":"/trailers/{jobId}/plan/approve","operationId":"approveTrailerPlan","idempotent":true},"cli":{"command":"sleeperhit trailer approve-plan <jobId> [--confirm] [--acknowledge-plan-coverage \"<reason>\"]"},"mcp":{"tool":"approve_trailer_plan","resource":null,"workflowId":"trailer-rendering"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"library.images.list","title":"List My-Library images","description":"List your reusable My-Library images (cached cast headshots, with the full-body figure when one exists) a page at a time, newest first: each image's `id`, the character it depicts and the script it came from, the library's true `total`, and a `nextCursor` for the next page. A read of what the library holds; nothing renders from it directly.","availability":"available","tags":["library"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:read"]},"api":{"method":"GET","path":"/library/images","operationId":"listMyLibraryImages","idempotent":false},"cli":{"command":"sleeperhit library images [--limit N] [--cursor C]"},"mcp":{"tool":"list_my_library_images","resource":null,"workflowId":"pitch-deck-rendering"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"library.audio.list","title":"List reusable My-Library audio","description":"List durable music, sound effects, and soundscapes a page at a time, newest first, optionally filtered by kind or searched by label/prompt, with the true `total` and a `nextCursor` for the next page.","availability":"available","tags":["library"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:read"]},"api":{"method":"GET","path":"/library/audio","operationId":"listMyLibraryAudio","idempotent":false},"cli":{"command":"sleeperhit library audio list [--kind music|sfx|soundscape] [--query <text>] [--limit N] [--cursor C]"},"mcp":{"tool":"list_my_library_audio","resource":null,"workflowId":"publishing-analytics"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"library.audio.import","title":"Import reusable audio","description":"Bank owned or licensed audio as a durable reusable music, SFX, or soundscape asset; public URLs and CLI-local files share the same validated import pipe.","availability":"available","tags":["library"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["story:write"]},"api":{"method":"POST","path":"/library/audio","operationId":"importMyLibraryAudio","idempotent":true},"cli":{"command":"sleeperhit library audio import (--file <path> | --source-url <url>) --kind <kind> --label <text>"},"mcp":{"tool":"import_my_library_audio","resource":null,"workflowId":"publishing-analytics"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"artifacts.sfx.manage","title":"Manage sound effects","description":"Add, update, mute, retime, regenerate, or remove line-level SFX cues for a table-read artifact.","availability":"available","tags":["artifacts","sfx"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["artifact:publish"]},"api":{"method":"POST","path":"/artifacts/{artifactId}/sfx","operationId":"manageArtifactSfx","idempotent":true},"cli":{"command":"sleeperhit sfx add|update|remove <artifactId>"},"mcp":{"tool":"add_sfx/update_sfx/remove_sfx","resource":null,"workflowId":null},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"artifacts.sfx.list","title":"List sound effects","description":"List timed SFX cues for a table-read artifact.","availability":"available","tags":["artifacts","sfx"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["artifact:read"]},"api":{"method":"GET","path":"/artifacts/{artifactId}/sfx","operationId":"listArtifactSfx","idempotent":false},"cli":{"command":"sleeperhit sfx list <artifactId>"},"mcp":{"tool":"list_sfx","resource":null,"workflowId":"table-reads-audio"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"artifacts.locationPlates.get","title":"Read the location plates","description":"Read the location plates of the script behind a table-read artifact — the empty rooms every video render places the cast into. Every room the script stores or walks through, each lighting variant of it (the same room by day and by night is ONE room with two variants, and a room stored under two spellings is reported in `duplicates`, never renamed), and per variant the master, medium and close plate in the landscape and portrait pools: `status` (`ready`, or `missing` — made when a video renders), `imageUrl`, `description` (the room as the plate shows it, written when the plate was accepted, which the render declares and stages against), the judge's advisory `note` (\"accepted after 2 retries: …\") and any remake in flight. Plates are never approved: a render makes each one within a fixed cap and accepts the least defective attempt. Costs no credits and never makes a plate.","availability":"available","tags":["artifacts","location_plates"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["artifact:read"]},"api":{"method":"GET","path":"/artifacts/{artifactId}/location-plates","operationId":"getArtifactLocationPlates","idempotent":false},"cli":{"command":"sleeperhit locations get <artifactId>"},"mcp":{"tool":"get_location_plates","resource":null,"workflowId":"video-rendering"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"artifacts.locationPlates.remake","title":"Remake one location plate","description":"Remake ONE location plate that looks wrong (a person baked into the room, a collage, the wrong framing). METERED: one still image per attempt, at most 3 attempts. TWO CALLS: sent without `confirmed` it PRICES the remake and makes nothing (`quotedOnly: true`, `credits`, `balanceAfter`, `sufficient`, and a `note` to show the writer — when `sufficient` is false the caller must not confirm); sent again with `confirmed: true` it holds one credit line per attempt and queues one capped round — the same cap and judge as every plate — which replaces the plate as soon as it ends. The writer pays only for the attempts made. There is NO approval step and nothing waits on the writer. Preconditions run above the price: an unknown key is 404 `location_plate_not_found`; a plate not made yet, one already being remade, one whose source plate is missing, or no image model bound is 409 `location_plate_precondition_failed`, with nothing priced. A confirmed call answers with a `chatToolJobId`; read the location plates until the plate's `remake` leaves `pending`.","availability":"available","tags":["artifacts","location_plates"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["artifact:publish"]},"api":{"method":"POST","path":"/artifacts/{artifactId}/location-plates/{plateKey}/remake","operationId":"remakeArtifactLocationPlate","idempotent":true},"cli":{"command":"sleeperhit locations remake <artifactId> <plateKey> [--confirm]"},"mcp":{"tool":"remake_location_plate","resource":null,"workflowId":"video-rendering"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"publishing.providerConfigs.list","title":"List publishing provider config","description":"List user-level publishing provider configuration for future OAuth/API-key-backed destinations.","availability":"available","tags":["publishing","destinations"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["publishing:connect"]},"api":{"method":"GET","path":"/publishing-provider-configs","operationId":"listPublishingProviderConfigs","idempotent":false},"cli":{"command":"sleeperhit publishing provider-configs list"},"mcp":{"tool":"list_publishing_provider_configs","resource":null,"workflowId":"publishing-analytics"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"publishing.providerConfigs.upsert","title":"Upsert publishing provider config","description":"Create or update user-level provider configuration metadata and encrypted credential references.","availability":"available","tags":["publishing","destinations"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["publishing:connect"]},"api":{"method":"POST","path":"/publishing-provider-configs","operationId":"upsertPublishingProviderConfig","idempotent":true},"cli":{"command":"sleeperhit publishing provider-configs upsert --provider <provider> --medium <medium>"},"mcp":{"tool":"upsert_publishing_provider_config","resource":null,"workflowId":"publishing-analytics"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"publishing.series.create","title":"Create a publishing series","description":"Create a project-owned publishing series with cadence, medium, format, prompt direction, and default RSS destination for audio.","availability":"available","tags":["publishing","series"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["publishing:write"]},"api":{"method":"POST","path":"/story-projects/{projectId}/publishing-series","operationId":"createPublishingSeries","idempotent":true},"cli":{"command":"sleeperhit publishing series create <projectId> [--title <title>]"},"mcp":{"tool":"create_publishing_series","resource":null,"workflowId":"publishing-analytics"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"publishing.series.list","title":"List publishing series","description":"List publishing series owned by a story project.","availability":"available","tags":["publishing","series"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["publishing:read"]},"api":{"method":"GET","path":"/story-projects/{projectId}/publishing-series","operationId":"listPublishingSeries","idempotent":false},"cli":{"command":"sleeperhit publishing series list <projectId>"},"mcp":{"tool":"list_publishing_series","resource":null,"workflowId":"publishing-analytics"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"publishing.series.get","title":"Read a publishing series","description":"Read one series, including configured destinations and RSS feed URL.","availability":"available","tags":["publishing","series"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["publishing:read"]},"api":{"method":"GET","path":"/publishing-series/{seriesId}","operationId":"getPublishingSeries","idempotent":false},"cli":{"command":"sleeperhit publishing series get <seriesId>"},"mcp":{"tool":"get_publishing_series","resource":null,"workflowId":"publishing-analytics"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"publishing.series.update","title":"Update a publishing series","description":"Update series setup, cadence, status, ownership metadata, and prompt direction; grant the show's standing approval to one API key (with the user's confirmation) or revoke it.","availability":"available","tags":["publishing","series"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["publishing:write"]},"api":{"method":"PATCH","path":"/publishing-series/{seriesId}","operationId":"updatePublishingSeries","idempotent":false},"cli":{"command":"sleeperhit publishing series update <seriesId> [--title <title>] [--status <status>] [--standing-approval-key <keyId|self|null>] [--episode-credit-cap <n>] [--monthly-credit-cap <n>] [--publish-policy auto|hold] [--confirm]"},"mcp":{"tool":"update_publishing_series","resource":null,"workflowId":"publishing-analytics"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"publishing.showSourceTemplates.list","title":"List interesting recurring sources","description":"A short catalog of interesting recurring sources to suggest when the writer has no feed in mind: NASA, arXiv, Wikipedia's daily features, the Library of Congress, public-domain archives, the Federal Register, USGS, and a topic searched in the news. Each comes ready to save as one of `showConfig.sources`, with the cadence it suits, how much text its items carry (a headlines feed makes a thin episode, so it suits a weekly digest), and a note on who owns the material. Free.","availability":"available","tags":["publishing","shows"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["publishing:read"]},"api":{"method":"GET","path":"/show-source-templates","operationId":"listShowSourceTemplates","idempotent":false},"cli":{"command":"sleeperhit publishing series templates"},"mcp":{"tool":"list_show_source_templates","resource":null,"workflowId":"recurring-shows"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"publishing.series.quote","title":"Quote a recurring show","description":"What a recurring show costs, before its caps are agreed. One episode's quote (the pricing library's price for each paid step), the caps suggested from it — an episode at its quote + 25%, a month at the episodes the cadence makes × that — the caps the show holds, and what this calendar month's episodes have spent. Free.","availability":"available","tags":["publishing","series","shows"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["publishing:read"]},"api":{"method":"GET","path":"/publishing-series/{seriesId}/quote","operationId":"getShowQuote","idempotent":false},"cli":{"command":"sleeperhit publishing series quote <seriesId>"},"mcp":{"tool":"get_show_quote","resource":null,"workflowId":"recurring-shows"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"publishing.series.previewSources","title":"Preview a show's sources","description":"Read the show's sources now, free, without making anything: what each would give an episode over the window (the item titles, authors and links, how much text), which items earlier episodes already covered, and which sources failed and why. Pass `sources` to try ones not saved yet.","availability":"available","tags":["publishing","series","shows"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["publishing:read"]},"api":{"method":"POST","path":"/publishing-series/{seriesId}/source-preview","operationId":"previewShowSources","idempotent":false},"cli":{"command":"sleeperhit publishing series preview-sources <seriesId> [--sources <json>] [--lookback-days <n>]"},"mcp":{"tool":"preview_show_sources","resource":null,"workflowId":"recurring-shows"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"publishing.series.produceEpisode","title":"Make a show episode now (a preview until live)","description":"Make ONE episode now. Before the show is live it is a PREVIEW: made from the show's sources like any episode, priced by the same library, held for the creator to hear and never published — and a show is armed only after one is made. On a live show, `preview: false` makes an extra episode that goes out like any other. Two calls: without `userConfirmed` it quotes (nothing made); with `userConfirmed: true` it charges and queues.","availability":"available","tags":["publishing","series","shows"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["publishing:write"]},"api":{"method":"POST","path":"/publishing-series/{seriesId}/episodes","operationId":"produceShowEpisode","idempotent":true},"cli":{"command":"sleeperhit publishing series produce <seriesId> [--prompt <text>] [--episode-type <key>] [--live] [--confirm]"},"mcp":{"tool":"produce_show_episode","resource":null,"workflowId":"recurring-shows"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"publishing.series.episodes","title":"List a show's episodes","description":"Every episode the show set out to make, newest first: queued, producing, published, ready (made, not published: a preview, held for review, or not authorized), skipped (why: no new material, not runnable, not ready, cap reached) or failed (the code and sentence that ended it), with what it cost and the items it covered.","availability":"available","tags":["publishing","series","shows"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["publishing:read"]},"api":{"method":"GET","path":"/publishing-series/{seriesId}/episodes","operationId":"listShowEpisodes","idempotent":false},"cli":{"command":"sleeperhit publishing series episodes <seriesId>"},"mcp":{"tool":"list_show_episodes","resource":null,"workflowId":"recurring-shows"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"publishing.series.generateCoverArt","title":"Generate podcast cover art","description":"Generate a 1536×1536 podcast cover image from the series context (title, description, genre). Returns a durable R2 URL; use update to persist it.","availability":"available","tags":["publishing","series"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["publishing:write"]},"api":{"method":"POST","path":"/publishing-series/{seriesId}/generate-cover-art","operationId":"generatePublishingSeriesCoverArt","idempotent":false},"cli":{"command":"sleeperhit publishing series generate-cover-art <seriesId> [--title <title>] [--description <text>] [--podcast-category <text>] [--podcast-subcategory <text>]"},"mcp":{"tool":"generate_publishing_cover_art","resource":null,"workflowId":"publishing-analytics"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"publishing.destinations.list","title":"List publishing destinations","description":"List series destinations, including RSS and later provider-specific targets.","availability":"available","tags":["publishing","destinations"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["publishing:read"]},"api":{"method":"GET","path":"/publishing-series/{seriesId}/destinations","operationId":"listPublishingDestinations","idempotent":false},"cli":{"command":"sleeperhit publishing destinations list <seriesId>"},"mcp":{"tool":"list_publishing_destinations","resource":null,"workflowId":"publishing-analytics"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"publishing.destinations.upsert","title":"Connect a publishing destination","description":"Create or update a series destination. RSS is first-party; provider-specific OAuth destinations can be configured for later publishers.","availability":"available","tags":["publishing","destinations"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["publishing:connect"]},"api":{"method":"POST","path":"/publishing-series/{seriesId}/destinations","operationId":"upsertPublishingDestination","idempotent":true},"cli":{"command":"sleeperhit publishing destinations upsert <seriesId> --provider rss"},"mcp":{"tool":"upsert_publishing_destination","resource":null,"workflowId":"publishing-analytics"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"publishing.releases.list","title":"List publishing releases","description":"List releases under a series with promoted assets and target status.","availability":"available","tags":["publishing","releases"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["publishing:read"]},"api":{"method":"GET","path":"/publishing-series/{seriesId}/releases","operationId":"listPublishingReleases","idempotent":false},"cli":{"command":"sleeperhit publishing releases list <seriesId>"},"mcp":{"tool":"list_publishing_releases","resource":null,"workflowId":"publishing-analytics"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"publishing.releases.create","title":"Promote an artifact into a publishing release","description":"Create a release under a series by promoting an already-finalized table-read artifact. Publishing does not create or refine MP3/MP4 assets.","availability":"available","tags":["publishing","releases"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["publishing:write"]},"api":{"method":"POST","path":"/publishing-series/{seriesId}/releases","operationId":"createPublishingRelease","idempotent":true},"cli":{"command":"sleeperhit publishing releases create <seriesId> --source-artifact-id <artifactId> --title <title>"},"mcp":{"tool":"create_publishing_release","resource":null,"workflowId":"publishing-analytics"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"publishing.releases.get","title":"Read a publishing release","description":"Read release metadata, linked StoryPlan/StoryJob/StoryArtifact ids, assets, and targets.","availability":"available","tags":["publishing","releases"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["publishing:read"]},"api":{"method":"GET","path":"/publishing-releases/{releaseId}","operationId":"getPublishingRelease","idempotent":false},"cli":{"command":"sleeperhit publishing releases get <releaseId>"},"mcp":{"tool":"get_publishing_release","resource":null,"workflowId":"publishing-analytics"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"publishing.releases.update","title":"Update publishing release metadata","description":"Update title, episode metadata, rights, prompt direction, and scheduled time without creating media.","availability":"available","tags":["publishing","releases"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["publishing:write"]},"api":{"method":"PATCH","path":"/publishing-releases/{releaseId}","operationId":"updatePublishingRelease","idempotent":false},"cli":{"command":"sleeperhit publishing releases update <releaseId> [--title <title>] [--description <text>]"},"mcp":{"tool":"update_publishing_release","resource":null,"workflowId":"publishing-analytics"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"publishing.releases.generate_description","title":"Generate a podcast episode description","description":"Write and persist short, specific podcast episode copy from the promoted table-read transcript. Accepts optional prompt direction to steer tone and emphasis.","availability":"available","tags":["publishing","releases"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["publishing:write"]},"api":{"method":"POST","path":"/publishing-releases/{releaseId}/description/generate","operationId":"generatePublishingReleaseDescription","idempotent":true},"cli":{"command":"sleeperhit publishing releases generate-description <releaseId> [--direction <text>]"},"mcp":{"tool":"generate_publishing_release_description","resource":null,"workflowId":"publishing-analytics"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"publishing.releases.schedule","title":"Schedule a publishing release","description":"Set the scheduled publish time for a promoted, ready release. Scheduling IS publishing, later and unattended, so it takes the user's confirmation now.","availability":"available","tags":["publishing","releases"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["publishing:publish"]},"api":{"method":"POST","path":"/publishing-releases/{releaseId}/schedule","operationId":"schedulePublishingRelease","idempotent":true},"cli":{"command":"sleeperhit publishing releases schedule <releaseId> --at <iso> --confirm"},"mcp":{"tool":"schedule_publishing_release","resource":null,"workflowId":"publishing-analytics"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"publishing.releases.publish","title":"Publish a release","description":"Queue provider target publishing. RSS v1 marks the item live in the first-party feed. Takes the user's confirmation, or the show's standing approval for the one API key it is bound to.","availability":"available","tags":["publishing","releases"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["publishing:publish"]},"api":{"method":"POST","path":"/publishing-releases/{releaseId}/publish","operationId":"publishPublishingRelease","idempotent":true},"cli":{"command":"sleeperhit publishing releases publish <releaseId> --confirm"},"mcp":{"tool":"publish_publishing_release","resource":null,"workflowId":"publishing-analytics"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"publishing.releases.refresh_media","title":"Refresh published release media","description":"Rebind a published audio episode's RSS enclosure to the latest finalized MP3 from its existing table-read source artifact without creating a duplicate episode; direct-provider targets are left unchanged.","availability":"available","tags":["publishing","releases","repair"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["publishing:publish"]},"api":{"method":"POST","path":"/publishing-releases/{releaseId}/refresh-media","operationId":"refreshPublishedReleaseMedia","idempotent":true},"cli":{"command":"sleeperhit publishing releases refresh-media <releaseId> --source-artifact-id <artifactId>"},"mcp":{"tool":"refresh_published_release_media","resource":null,"workflowId":"publishing-analytics"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"publishing.releases.cancel","title":"Cancel a publishing release","description":"Cancel a promoted release before it is published. Scheduled publish jobs become harmless because persisted release status is authoritative.","availability":"available","tags":["publishing","releases"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["publishing:publish"]},"api":{"method":"POST","path":"/publishing-releases/{releaseId}/cancel","operationId":"cancelPublishingRelease","idempotent":true},"cli":{"command":"sleeperhit publishing releases cancel <releaseId>"},"mcp":{"tool":"cancel_publishing_release","resource":null,"workflowId":"publishing-analytics"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"publishing.releases.unpublish","title":"Unpublish a published release","description":"Take a published episode back out of the podcast feed, reversibly: the release returns to ready and its RSS item leaves the feed on the next fetch (apps that read the feed drop it on their next refresh). Its audio, GUID and original publish date are kept, so publishing it again restores the same episode under its first date. Refused for a release that is not published, a season-run release, or one still live on YouTube or TikTok. Repeating it on an unpublished release changes nothing.","availability":"available","tags":["publishing","releases"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["publishing:publish"]},"api":{"method":"POST","path":"/publishing-releases/{releaseId}/unpublish","operationId":"unpublishPublishingRelease","idempotent":true},"cli":{"command":"sleeperhit publishing releases unpublish <releaseId> --confirm"},"mcp":{"tool":"unpublish_publishing_release","resource":null,"workflowId":"publishing-analytics"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"publishing.releases.targets","title":"List publishing release targets","description":"List provider target status for one promoted release.","availability":"available","tags":["publishing","releases","destinations"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["publishing:read"]},"api":{"method":"GET","path":"/publishing-releases/{releaseId}/targets","operationId":"listPublishingReleaseTargets","idempotent":false},"cli":{"command":"sleeperhit publishing releases targets <releaseId>"},"mcp":{"tool":"list_publishing_release_targets","resource":null,"workflowId":"publishing-analytics"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"publishing.analytics.list","title":"List publishing analytics","description":"List normalized analytics snapshots for a publishing series.","availability":"available","tags":["publishing","analytics"],"auth":{"accountRequired":true,"schemes":["oauth2.1","bearer_api_key"],"scopes":["publishing:analytics"]},"api":{"method":"GET","path":"/publishing-series/{seriesId}/analytics","operationId":"listPublishingAnalyticsSnapshots","idempotent":false},"cli":{"command":"sleeperhit publishing analytics list <seriesId>"},"mcp":{"tool":"list_publishing_analytics","resource":null,"workflowId":"publishing-analytics"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"},{"id":"publishing.feed","title":"Read RSS feed","description":"Public podcast RSS feed for one publishing series.","availability":"available","tags":["publishing","rss"],"auth":{"accountRequired":false,"schemes":[],"scopes":[]},"api":{"method":"GET","path":"/publishing-feeds/{seriesSlug}.xml","operationId":"getPublishingRssFeed","idempotent":false},"cli":{"command":"sleeperhit publishing feed <seriesSlug>"},"mcp":{"tool":"get_publishing_rss_feed","resource":null,"workflowId":"publishing-analytics"},"docsUrl":"https://docs.sleeperhit.studio/api-reference"}],"publicCapabilities":[{"id":"public.search","title":"Search public Sleeper Hit discovery documents","description":"Search opted-in public writer profiles, project summaries, and writer-approved public assets. Compatible with ChatGPT deep research and company knowledge.","auth":{"accountRequired":false,"schemes":[],"scopes":[]},"mcp":{"tool":"search"}},{"id":"public.fetch","title":"Fetch public Sleeper Hit discovery document","description":"Fetch the full public discovery document for a search result by ID. Compatible with ChatGPT deep research and company knowledge.","auth":{"accountRequired":false,"schemes":[],"scopes":[]},"mcp":{"tool":"fetch"}},{"id":"public.find_writers","title":"Find writers","description":"Search opt-in public Sleeper Hit Studio writer profiles.","auth":{"accountRequired":false,"schemes":[],"scopes":[]},"mcp":{"tool":"find_writers"}},{"id":"public.get_writer_profile","title":"Get writer profile","description":"Get a public writer profile by slug, including public projects and shared assets.","auth":{"accountRequired":false,"schemes":[],"scopes":[]},"mcp":{"tool":"get_writer_profile"}},{"id":"public.find_projects","title":"Find projects","description":"List public projects for a writer. Results include project hub URLs and public asset summaries.","auth":{"accountRequired":false,"schemes":[],"scopes":[]},"mcp":{"tool":"find_projects"}},{"id":"public.get_project_summary","title":"Get project summary","description":"Get one public project summary for a writer.","auth":{"accountRequired":false,"schemes":[],"scopes":[]},"mcp":{"tool":"get_project_summary"}},{"id":"public.list_writer_assets","title":"List writer assets","description":"List all writer-approved public share URLs for a writer.","auth":{"accountRequired":false,"schemes":[],"scopes":[]},"mcp":{"tool":"list_writer_assets"}},{"id":"public.list_project_assets","title":"List project assets","description":"List writer-approved public share URLs for a specific project.","auth":{"accountRequired":false,"schemes":[],"scopes":[]},"mcp":{"tool":"list_project_assets"}},{"id":"public.get_public_pitch_assets","title":"Get public pitch assets","description":"List writer-approved public pitch deck assets for a writer.","auth":{"accountRequired":false,"schemes":[],"scopes":[]},"mcp":{"tool":"get_public_pitch_assets"}},{"id":"public.get_access_info","title":"Read Sleeper Hit access and onboarding routing","description":"Read what Sleeper Hit Studio can do without an account, what requires one, and the signup URL for each intent. Call this before telling a user you cannot create something here — creation lives on the separate authenticated connector.","auth":{"accountRequired":false,"schemes":[],"scopes":[]},"mcp":{"tool":"get_access_info"}}],"discovery":{"capabilityManifest":"https://sleeperhit.studio/capabilities.json","openapi":"https://sleeperhit.studio/api/v1/openapi.json","capabilities":"https://sleeperhit.studio/api/v1/capabilities","agentGuidance":"https://sleeperhit.studio/api/v1/agent-guidance","examples":"https://sleeperhit.studio/api/v1/examples","llms":"https://sleeperhit.studio/llms.txt","llmsFull":"https://sleeperhit.studio/llms-full.txt","agentIndex":"https://sleeperhit.studio/agent-index.json","surfaceContract":"https://sleeperhit.studio/docs/surface-contract.json","cliCommands":"https://sleeperhit.studio/docs/cli-commands.json","mcpTools":"https://sleeperhit.studio/docs/mcp-tools.json","searchIndex":"https://sleeperhit.studio/docs/search-index.json","publicDiscoveryApi":"https://sleeperhit.studio/api/public/v1","docsSite":"https://sleeperhit.studio/docs","sitemap":"https://sleeperhit.studio/sitemap.xml","robots":"https://sleeperhit.studio/robots.txt"}}