---
title: "Keep one frame on the project mood board."
method: POST
path: "/story-projects/{projectId}/mood-board/frames"
tags: ["Projects"]
---

# Keep one frame on the project mood board.

`POST /story-projects/{projectId}/mood-board/frames`

## Request

- Base URL: `https://docs.sleeperhit.studio/api/v1`
- URL: `https://docs.sleeperhit.studio/api/v1/story-projects/{projectId}/mood-board/frames`
- Auth: HTTP bearer

Pin one frame as part of the 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 replaces that entry. Keeping a fifth distinct frame is REFUSED with 409 `mood_board_full` and nothing is trimmed — four is the most that can bind a render, so a fifth frame would silently have no effect. A project that has not passed premise coverage is refused with 409 `project_precondition_failed`.

## Headers

- `Idempotency-Key` string, required

## Request body

- MoodBoardFrameKeepRequest
  - `frame` MoodBoardFrame, required
    - `id` string, required: Stable id for this frame; keeping an id that is already on the board replaces that entry.
    - `url` string, required: Where the picture lives; https only. Frames are re-hosted, because a provider URL goes dead overnight.
    - `r2Key` string
    - `prompt` string: What was asked for. A resumed conversation reads these to know the look it is continuing.
    - `note` string: The writer's own words about why this frame is right. Never generated.
    - `modelId` string
    - `providerType` string
    - `seed` integer
    - `aspectRatio` string
    - `keptAt` string: Set by the server when the frame is kept.

## Response `200`

Mood board envelope after the keep.

- MoodBoardEnvelope
  - `moodBoard` object, required
    - `projectId` string, required
    - `content` MoodBoardContent, required
      - `frames` MoodBoardFrame[]
        - `id` string, required: Stable id for this frame; keeping an id that is already on the board replaces that entry.
        - `url` string, required: Where the picture lives; https only. Frames are re-hosted, because a provider URL goes dead overnight.
        - `r2Key` string
        - `prompt` string: What was asked for. A resumed conversation reads these to know the look it is continuing.
        - `note` string: The writer's own words about why this frame is right. Never generated.
        - `modelId` string
        - `providerType` string
        - `seed` integer
        - `aspectRatio` string
        - `keptAt` string: Set by the server when the frame is kept.
      - `updatedAt` string
    - `currentVersion` integer, required
    - `updatedAt` string, date-time, required
  - `candidates` MoodBoardCandidateFrame[]
    - `id` string, required
    - `url` string, required
    - `prompt` string
    - `modelId` string
    - `aspectRatio` string
  - `renders` MoodBoardRenderRecord[]
    - `chatToolJobId` string, required
    - `status` string, required: pending | completed | failed.
    - `count` integer, nullable, required: How many frames the batch asked for.
    - `error` string, nullable, 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.
- `409`: The frame was not kept, and nothing was trimmed: the board already holds the maximum number of frames that can bind a render (`mood_board_full` — drop a frame, then keep the new one), or the project has not passed premise coverage (`project_precondition_failed`, with `details.stage`).
- `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)
