---
title: "Read the project mood board (the agreed look, as kept frames)."
method: GET
path: "/story-projects/{projectId}/mood-board"
tags: ["Projects"]
---

# Read the project mood board (the agreed look, as kept frames).

`GET /story-projects/{projectId}/mood-board`

## Request

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

The kept frames every new character render is made in. Costs no credits. A project that has agreed no look yet returns an empty board rather than a 404, because "no look agreed yet" is a normal state. 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 renderProjectMoodBoardFrames terminates instead of waiting forever on a batch that failed.

## Response `200`

Mood board envelope.

- 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

- `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)
