---
title: "Start a tour draft for every shipped feature (or every moment of one story film) that has no tour yet."
method: POST
path: "/story-projects/{projectId}/tours/draft-missing"
tags: ["Sources"]
---

# Start a tour draft for every shipped feature (or every moment of one story film) that has no tour yet.

`POST /story-projects/{projectId}/tours/draft-missing`

## Request

- Base URL: `https://docs.sleeperhit.studio/api/v1`
- URL: `https://docs.sleeperhit.studio/api/v1/story-projects/{projectId}/tours/draft-missing`
- Auth: HTTP bearer

A tour draft is written from the feature’s Bible entry, its pages and the app’s address, is checked by the recorder’s own rules and saved as a drafted tour for you to edit, never opens the app, is for product projects only, and is free — up to 50 a day. No `featureId` on the wire: the project's Series Bible decides which features those are (a `planned` feature is skipped; one already drafting is answered as `alreadyRunning` with that run). The body may be omitted or empty; `connectionId` optionally names the app connection whose addresses the drafts read, and no other key exists — an unknown one is 400 `validation_failed` naming it. Answers `started` (the runs that began, in Bible order), `alreadyRunning`, `notStarted` (the features the daily cap left without a run, each with the cap's own sentence) and `alreadyToured`. With `storyId` (BL-2360) the same call drafts every product moment of that written story film that has neither a recording nor a saved tour, in the film's own order, and answers `TourDraftsForMissingStoryFilmMoments`: `started` and `alreadyRunning` as moment ids with their runs, `notStarted` per moment with its reason, `alreadyToured`. 202 when at least one run started, 200 when none did (a repeat starts nothing new, so no Idempotency-Key). A refusal common to every feature (no app connection, 409 `project_not_product`, the budget) is thrown with nothing started; the day's cap never throws — it ends the loop, the remaining features answering in `notStarted`.

## Request body

- StartMissingTourDraftsBody: The body may be omitted or empty (`{}`) — every shipped feature without a tour. `storyId` narrows the start to one written story film's moments that have neither a recording nor a saved tour (BL-2360). Optionally `connectionId` names the app connection whose addresses the drafts read. No other key exists: an unknown one is 400 `validation_failed` naming it.
  - `connectionId` string: The app connection to draft through, when the project has more than one.
  - `storyId` string: A written story film: draft a tour for every one of its product moments that still needs one, instead of the project's features.

## Response `200`

Nothing was started (every shipped feature — or every moment of the named story film — already has a tour or a drafting run, or the cap took the first one): `started` is empty.

- union
  - TourDraftsForMissingFeatures: What starting the tour drafts for every shipped feature without one answers: the runs that began, the runs already drafting, the features the daily cap left without a run, and how many shipped features already had a tour.
    - `projectId` string, required
    - `started` TourDraftRun[], required: The runs that began, in Bible order.
      - `id` string, required
      - `projectId` string, required
      - `featureId` string, required: The product feature (a Series Bible episode) the draft walks through.
      - `source` union, required: What the run was drafted from: the feature itself, or one product moment of a story film that needed a recording.
        - object
          - `kind` 'feature', required
          - `featureId` string, required
        - StoryBeatTourDraftSource: A story film’s product moment that still needs a recording can be drafted as its own tour: it types the story’s own names into the app and hesitates where the scene says to, and when its recording is finished it becomes that moment’s recording.
          - `kind` 'story_beat', required
          - `storyId` string, required: The scripted story film.
          - `captureRequestId` string, required: The product moment (its `[[capture:<id>]]` note in the script) that still needs a recording.
      - `feature` object, nullable, required: The feature as the Bible lists it, or null when the Bible lists it no more.
        - `id` string, required
        - `name` string, required
      - `connectionId` string, nullable, required: The app connection the pages and address were read through, or null when none was named.
      - `origin` string, required: The app connection's origin (the app's https address), snapshotted when the run started.
      - `status` 'drafting' | 'ready' | 'failed', required
      - `interrupted` boolean, required: True when a finished run was cut short.
      - `error` string, nullable, required: The one line that says why the run failed. Null unless `failed`.
      - `errors` string[], required: Everything the check refused in the drafts, readable: the run fails when these cannot be repaired.
      - `tourId` string, nullable, required: The staged tour the draft saved, or null until one (or ever, when `failed`).
      - `repairRounds` integer, required: How many times the drafted document was repaired before it passed the check.
      - `modelId` string, nullable, required
      - `notes` object, nullable, required: What the drafting held back and passed along. Null until `ready` or `failed`.
        - `assumptions` string[], required
        - `questions` string[], required
        - `steps` string[], required
        - `repairNote` string, nullable: BL-615: the line a run re-drafted because the app moved carries, so every read of the run says why. Absent on a run that was not repaired.
      - `startedAt` string, date-time, required
      - `finishedAt` string, date-time, nullable, required
    - `alreadyRunning` TourDraftRun[], required: The runs already drafting for their feature — a second run never starts beside one.
      - `id` string, required
      - `projectId` string, required
      - `featureId` string, required: The product feature (a Series Bible episode) the draft walks through.
      - `source` union, required: What the run was drafted from: the feature itself, or one product moment of a story film that needed a recording.
        - object
          - `kind` 'feature', required
          - `featureId` string, required
        - StoryBeatTourDraftSource: A story film’s product moment that still needs a recording can be drafted as its own tour: it types the story’s own names into the app and hesitates where the scene says to, and when its recording is finished it becomes that moment’s recording.
          - `kind` 'story_beat', required
          - `storyId` string, required: The scripted story film.
          - `captureRequestId` string, required: The product moment (its `[[capture:<id>]]` note in the script) that still needs a recording.
      - `feature` object, nullable, required: The feature as the Bible lists it, or null when the Bible lists it no more.
        - `id` string, required
        - `name` string, required
      - `connectionId` string, nullable, required: The app connection the pages and address were read through, or null when none was named.
      - `origin` string, required: The app connection's origin (the app's https address), snapshotted when the run started.
      - `status` 'drafting' | 'ready' | 'failed', required
      - `interrupted` boolean, required: True when a finished run was cut short.
      - `error` string, nullable, required: The one line that says why the run failed. Null unless `failed`.
      - `errors` string[], required: Everything the check refused in the drafts, readable: the run fails when these cannot be repaired.
      - `tourId` string, nullable, required: The staged tour the draft saved, or null until one (or ever, when `failed`).
      - `repairRounds` integer, required: How many times the drafted document was repaired before it passed the check.
      - `modelId` string, nullable, required
      - `notes` object, nullable, required: What the drafting held back and passed along. Null until `ready` or `failed`.
        - `assumptions` string[], required
        - `questions` string[], required
        - `steps` string[], required
        - `repairNote` string, nullable: BL-615: the line a run re-drafted because the app moved carries, so every read of the run says why. Absent on a run that was not repaired.
      - `startedAt` string, date-time, required
      - `finishedAt` string, date-time, nullable, required
    - `notStarted` object[], required: The features left without a run when the daily cap ended the loop — each reason is the cap's own sentence. Nothing was queued for them.
      - `featureId` string, required
      - `name` string, required: The feature as the Bible lists it.
      - `reason` string, required
    - `alreadyToured` integer, required: How many shipped features a tour already covers (before this call).
  - TourDraftsForMissingStoryFilmMoments: What starting the tour drafts for every moment of one story film that has neither a recording nor a saved tour answers: the runs that began, the moments already drafting with their run, the moments left without a run with the reason, and how many moments already had a recording or a tour.
    - `projectId` string, required
    - `storyId` string, required
    - `started` StoryFilmMomentTourDraftRun[], required: The runs that began, in the film's own moment order. Poll each with GET /tours/drafts/{runId}.
      - `momentId` string, required: The film's product moment.
      - `runId` string, required: Its draft run.
    - `alreadyRunning` StoryFilmMomentTourDraftRun[], required: The moments whose run was already drafting — a second run never starts beside one.
      - `momentId` string, required: The film's product moment.
      - `runId` string, required: Its draft run.
    - `notStarted` object[], required: The moments left without a run: the daily cap's own sentence when it ended the walk, or a refusal about that one moment.
      - `momentId` string, required
      - `reason` string, required
    - `alreadyToured` integer, required: How many of the film's moments already had a recording or a saved tour (before this call).

## Other responses

- `202`: The runs that began, and what the answer held besides.
- `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.
- `409`: `project_not_product` — the project is a story project. PATCH its `kind` to `product` first; nothing was started. `script_state_invalid` — the named story film has no script yet, so it has no moments to draft.
- `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)
