---
title: "Import the deliverable's own test-case script."
method: POST
path: "/story-projects/{projectId}/deliverables/{deliverableId}/script"
tags: ["Projects"]
---

# Import the deliverable's own test-case script.

`POST /story-projects/{projectId}/deliverables/{deliverableId}/script`

## Request

- Base URL: `https://docs.sleeperhit.studio/api/v1`
- URL: `https://docs.sleeperhit.studio/api/v1/story-projects/{projectId}/deliverables/{deliverableId}/script`
- Auth: HTTP bearer

Import the deliverable's own test-case script: `markdown` is the submission checklist — its §6 cases, and its starter prompts and release notes when it carries them — parsed deterministically, so malformed markdown is a named 400 and nothing is stored. `starterPrompts`, `releaseNotes` and `platforms` override what it says. The script is this deliverable's alone; the import bumps `scriptVersion` and clears every variant's last check.

## Request body

- VideoDeliverableScriptImportRequest: The deliverable's own test-case script to import. Parsed deterministically; malformed markdown is a named 400 and nothing is stored. The import bumps `scriptVersion` and clears every variant's `lastCheck`.
  - `markdown` string, required: The submission checklist: its §6 test-case tables (an optional `Platform` column sets each case's platform), and its "Default prompts" list and `**Release notes:**` line when it carries them.
  - `starterPrompts` string[]: Replaces the starter prompts the markdown lists.
  - `releaseNotes` string: Replaces the release notes the markdown carries.
  - `platforms` object: A case's platform by id, e.g. `{ "P2": "mobile_app" }`. An id the script does not have is a 400.

## Response `200`

The deliverable with its new script, the script version, and how many cases the parse carried.

- VideoDeliverableScriptImportResult
  - `deliverable` VideoDeliverable, required: One destination video deliverable: the title, the destination its PRIMARY variant is made for, its OWN surface scout, its OWN imported test-case script, the per-step state, and every variant.
    - `id` string, required
    - `projectId` string, required
    - `userId` string, required
    - `title` string, required
    - `primaryDestinationKey` string, required: The VideoDestination.key the PRIMARY variant is made for.
    - `cutTrailerJobId` string, nullable: The one editable cut's trailer job, or null.
    - `scout` object, nullable: Ranked surface moments, in rank order: `{ id, tool, kind, why, evidence[], legibilityEstimate, setupNeeded, risk }` per moment. Validated against the shared `surfaceScoutSchema`; an unknown moment kind or any other malformed field is a named 400 and nothing is stored.
      - `moments` object[], required
        - `id` string, required: Snake-case moment id (`^[a-z][a-z0-9_]{0,63}$`, at most 64 chars), unique within the document — a duplicate id is refused with the same named 400.
        - `tool` string, required: The tool this moment films. Trimmed by the validator: it must contain a non-whitespace character.
        - `kind` 'widget_render' | 'approval_prompt' | 'quote' | 'list' | 'refusal', required: What filming this moment shows: `widget_render`, `approval_prompt`, `quote`, `list` or `refusal`.
        - `why` string, required: Why the moment earns its rank. Trimmed by the validator: it must contain a non-whitespace character.
        - `evidence` object[], required
          - `kind` 'tool_annotation' | 'output_template_present' | 'route' | 'checkpoint', required
          - `detail` string, required: The receipt a reviewer (or the cut) can check the moment against. Trimmed by the validator: it must contain a non-whitespace character.
        - `legibilityEstimate` string, required: The human estimate of on-screen legibility. Trimmed by the validator: it must contain a non-whitespace character.
        - `setupNeeded` boolean, required
        - `risk` object, required
          - `spend` boolean, required
          - `destructive` boolean, required
    - `script` DestinationScript, required: A deliverable's own test-case script: the cases, and the starter prompts and release notes the packet is built around.
      - `cases` DestinationScriptCase[], required
        - `id` string, required: `P1`…`P5` for a positive case, `N1`…`N3` for a negative one.
        - `polarity` 'positive' | 'negative', required
        - `scenario` string, required: The first sentence of what the case shows.
        - `user_prompt` string, required
        - `tools_triggered` string[], required
        - `expected_output` string, required: The whole expected result (positive) or expected behaviour (negative).
        - `platform` 'web' | 'mobile_app' | 'mobile_web', required
        - `setup` string, required
        - `mustShowMoment` string, required
      - `starterPrompts` string[], required
      - `releaseNotes` string, required
    - `scriptVersion` integer, required: How many imports the script has had (0 = none). A variant's `lastCheck.scriptVersion` names the one it checked.
    - `steps` object, required: Per step: `{ state, jobId, inputHash, revision, error, updatedAt }`.
    - `revision` integer, required
    - `createdAt` string, date-time, required
    - `updatedAt` string, date-time, required
    - `variants` VideoDeliverableVariant[], required
      - `id` string, required
      - `deliverableId` string, required
      - `destinationKey` string, required: The video destination key this variant is cut and checked for.
      - `trailerJobId` string, nullable: The trailer job holding this variant's cut, or null before one is cut.
      - `exportTarget` string, nullable: The export target key (`site` | `youtube` | `x`), or null.
      - `lastCheck` object, nullable: The kept check report `{ masterSha256, cutRevision, scriptVersion, specVersion, results[], checkedAt }`, or null when the variant has not been checked since the last script import (every import clears it).
      - `shareUrl` string, nullable
      - `status` 'draft' | 'cutting' | 'checking' | 'ready' | 'failed', required
      - `createdAt` string, date-time, required
      - `updatedAt` string, date-time, required
  - `scriptVersion` integer, required: The script version this import made.
  - `counts` object, required: How many test cases the parse carried, by polarity.
    - `positive` integer, required
    - `negative` integer, required

## Other responses

- `400`: Request payload failed validation. The error message names the offending field.
- `401`: Missing, malformed, revoked, or expired API key.
- `403`: API key is valid but lacks the scope, is blocked by IP allowlist, or the account is disabled.
- `404`: The named project or source does not exist or is owned by another account.
- `429`: Rate limit for this API key + IP + route family was exceeded.
- `500`: The API failed unexpectedly. Safe to retry with the same Idempotency-Key.

---

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