> ## Documentation Index
> Fetch the complete documentation index at: https://cue.vibeset.ai/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Underscore a script

> Match licensed music to a script. No video needed.

Every other video workflow starts with a video. Underscore starts with the words. Paste a
short-form script: a TikTok hook, a Reels voiceover, a LinkedIn explainer. Cue reads it the way a
music supervisor would: it infers the mood, the pace and the payoff from the writing, then returns
a ranked shortlist of licensed tracks that fit.

There's no video to ingest and no per-minute analysis, so it's one synchronous call. The result
comes straight back.

## Match a script

```bash theme={null}
curl https://cue.vibeset.ai/v1/underscore \
  -H "x-api-key: vbsk_live_..." \
  -H "content-type: application/json" \
  -d '{
    "script": "You have been folding your shirts wrong your whole life. Here is the fold in three moves. Follow for the ones they do not teach you."
  }'
```

You get back a lane of tracks. Each carries a `track_id` you resolve in your catalog, its tempo,
and a why-it-fits map.

```json 200 theme={null}
{
  "lane": {
    "title": "Your shortlist",
    "reasoning": "A clean, modern rhythmic bed that lands the turn without crowding the read.",
    "matches": [
      {
        "track_id": "14792",
        "audio_id": "60184",
        "soundstripe_song_id": "14792",
        "soundstripe_audio_file_id": "60184",
        "title": "Skeptical",
        "artist_name": "Lincoln Davis",
        "score": 0.98, "bpm": 120, "instrumental": true, "duration_seconds": 164.01,
        "match_map": [
          { "video": "punchy hook", "audio": "driving 120 BPM" },
          { "video": "confident tone", "audio": "bright synths" }
        ]
      }
    ]
  }
}
```

`script` runs from 1 to 7000 characters. Anything longer is a `422` here rather than a truncated
body at the edge.

The shortlist is a fixed ten tracks, enough to give a creator a real choice without making them
wade. It isn't a request parameter, which is what keeps the call's latency and its bill
predictable.

## The why-it-fits map

Every track carries a `match_map`: a short list of links between a phrase **in the script** (the
`video` side) and a trait **in the track** (the `audio` side). It is the reasoning made legible,
which words pulled which sound, so you can show a creator *why* a track was picked and not just
that it was.

## Steering the result

<ParamField path="platform" type="string">
  A free-form hint, up to 40 characters, passed to the model as part of the brief. `tiktok`,
  `reels`, `shorts`, `linkedin` and `youtube` are the vocabulary it's written for. A LinkedIn
  explainer leans calmer and cleaner, a TikTok hook faster and more contemporary. Nothing rejects
  another value, and an unrecognised one is simply a weaker steer.
</ParamField>

<ParamField path="creative_direction" type="string">
  A plain-language steer, e.g. "warm, upbeat, no vocals". Up to 500 characters.
</ParamField>

<ParamField path="mood" type="string">
  A single mood, e.g. "uplifting" or "tense".
</ParamField>

<ParamField path="era" type="string">
  A period steer, e.g. "80s".
</ParamField>

<ParamField path="vocals" type="string">
  Whether you want vocals, and what kind.
</ParamField>

## Getting the audio

The response identifies tracks, it doesn't carry them. `soundstripe_song_id` is the work and
`soundstripe_audio_file_id` is the specific render. Resolve them through your own catalog access.
This is the same posture as every other Cue endpoint, and the reasoning is in
[Render under your own license](/docs/own-license#preview-audio).

If you're still evaluating and don't license a catalog yet, ask us to enable `preview` on your
account. Each track then also carries a short-lived watermarked link for judging a track before
you license it. Without that grant no audio is attached at all, on this endpoint or any other.

`?expand=full` swaps the lean track object for the full one, adding tags, energy, musical key and
description, and puts a `candidate_pool` array on the lane. You don't need it to draw a result
card: title, artist, tempo and the why-it-fits map are all on the default response.

## What it costs

Underscore is **\$0.05 per call**, flat, however many tracks come back. There's no analysis charge,
because there's no video to ingest. A call that errors, or that comes back with no tracks at all,
isn't billed. See [Metering & pricing](/docs/metering-and-pricing).

Over MCP the same thing is the [`underscore`](/docs/mcp-tools#underscore) tool.
