---
title: "Find reference films for a business video (free)."
method: POST
path: "/story-projects/{projectId}/references"
tags: ["Trailer"]
---

# Find reference films for a business video (free).

`POST /story-projects/{projectId}/references`

## Request

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

References are short films from refs.video that match a business video's category, shape and length, shown 4 at a time, each credited "References by refs" and playable in place from its original post through that platform's own player (`embed`; never rehosted), or shown by its stills when its post cannot be embedded. Choosing one makes its pacing — average and longest shot, cut rate, first cut, voice — the planner's target, as numbers only: a reference is an idea, never content to copy. Finding, choosing and clearing a reference are free; product projects only. A POST although it only reads: what the writer is making rides the JSON body, never a URL an access log could keep. refs receives the abstracted brief — one category, one shape and a duration band — and at most four plain keywords drawn from the feature names and `notes` (single lowercase words: never the notes themselves, the product's or the release's name, a person's name, a number or a link), so what the writer types changes which films come up; `keywords` answers the words sent (empty when none were, or the day's keyword headroom is used). The films are then put in order of fit to the whole intent on our side: `order: 'fit'`, else the search's own order (`order: 'refs'`: no intent given, or the order could not be read now). A story project is 409 `project_not_product`; switched off or not open to this account is 403 `references_unavailable`; the day's free finds used up is 429 `reference_allowance_reached`. Scope: `story:read`.

## Request body

- object
  - `scope` 'feature' | 'release': The video's scope: `feature` searches demo films by default, `release` launch films.
  - `category` string: A refs category the policy allows (default by scope).
  - `aspectRatio` '16:9' | '9:16' | '1:1'
  - `targetSeconds` number
  - `featureIds` string[]: The feature-map ids the video shows: the films are put in order of fit to them, and their names lend up to two keywords.
  - `releaseName` string: A release's name, for the order of fit. Never sent to refs (its words are kept out of the keywords).
  - `notes` string: What the writer is making — who it is for, the moment that matters, what to lead with — for the order of fit and a few plain keywords. The notes themselves are never sent to refs.

## Response `200`

The reference films, each credited and playable in place.

- FindReferencesResponse: Up to four reference films for a business video, each credited and playable in place.
  - `projectId` string, required
  - `category` string, required
  - `aspectRatio` '16:9' | '9:16' | '1:1', required
  - `targetSeconds` number, required
  - `cards` ReferenceCard[], required
    - `refsId` string, required: The REF id it is chosen by, e.g. `REF-3007`.
    - `url` string, required: The film's refs page, `https://refs.video/v/<id>`.
    - `credit` 'References by refs', required
    - `title` string, required
    - `by` string, required
    - `category` string, required
    - `durationSeconds` number, nullable, required
    - `aspect` '16:9' | '9:16' | '1:1' | 'null', nullable, required
    - `pacing` ReferencePacing, required: A reference film's pacing NUMBERS — the whole of what a reference lends a plan. `maxShotSeconds` is our bound (twice the average shot); the rest are the film's measured metrics. Loudness is shown for information: delivery loudness follows the export target.
      - `avgShotSeconds` number, nullable, required
      - `maxShotSeconds` number, nullable, required
      - `cutsPerMinute` number, nullable, required
      - `firstCutSeconds` number, nullable, required
      - `shots` integer, nullable, required
      - `hasVoice` boolean, nullable, required
      - `referenceLufs` number, nullable, required
    - `thumbnailUrl` string, nullable, required: The film's poster still (webp), served from Sleeper Hit's own storage: fetched once per film from refs and reused for every card (only for a film whose post cannot be played in place). Always shown with `credit`. Null until it is stored, or when stills are switched off: show an icon.
    - `stillUrls` string[], required: All of the film's stored stills (webp), the poster first; empty when none are stored. Never video.
    - `embed` ReferenceEmbed, required: How to play a reference film in place: its original post, through that platform's own player. Frame `embedUrl` (muted where the platform allows it, never autoplaying); never download, proxy or rehost the film.
      - `provider` 'youtube' | 'x' | 'vimeo', required
      - `videoId` string, required: The platform's id of the video or post.
      - `embedUrl` string, uri, required: The player to frame: `https://www.youtube-nocookie.com/embed/<id>`, `https://platform.twitter.com/embed/Tweet.html?id=<id>` or `https://player.vimeo.com/video/<id>`, with its muting and privacy parameters.
      - `sourceUrl` string, uri, required: The original post.
  - `order` 'fit' | 'refs', required: `fit`: the cards are in order of fit to the intent asked with (features, release, notes), closest first. `refs`: refs' own order (no intent, or the order could not be read now).
  - `keywords` string[], required: The plain keywords the films were also searched by, drawn from the feature names and notes (sorted). Empty when none were sent.
  - `credit` 'References by refs', required
  - `note` string, 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 project has not reached the development stage this call needs (`project_precondition_failed`), and nothing was created, queued or charged. `details` is ProjectPreconditionDetails: `stage` names the stage to finish, `missingFields` what it still lacks, `canPlan` / `canStartEpisode` what the project can do now. Finish the named stage — do not retry; the identical call refuses the same way until it is done.
- `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/64c1102ccb2f?raw)
