Lovely RouterDocs
Get a key
API reference

Character endpoints

Every /v1/characters and /v1/scenes endpoint — save a character (a name, a description and a turnaround sheet) or a scene (a place and its picture), list, retrieve, update and delete them, download their pictures, and use them in music videos, character swaps and video shots.

A saved character is a person you want to use again: a name, a description (face, hair, build, the clothes they usually wear) and a turnaround sheet — the same person from the front, three-quarter, side and back, over close-ups of their face with six expressions, in one picture — plus, optionally, the photo it was made from and a voice. Pass its id as character_id to music videos and character swaps instead of sending the picture every time.

Saved characters are optional. Every video endpoint still takes the picture and the text inline, so a one-off call needs no saved character at all.

The endpoints live under https://lovelyrouter.com/v1/characters. Authenticate with your API key as Authorization: Bearer $LOVELY_API_KEY (Authentication). Characters are free to keep, private to your account, and kept until you delete them; an account can keep up to 100.

The character object#

Attributes

idstring

Unique id, chr_ followed by 24 characters.

objectstring

Always character.

namestring

What you call the character, up to 80 characters.

descriptionstring

Who the person is, as you wrote it: face, hair, body and default outfit. Up to 4,000 characters; may be empty.

sheet_urlstring

The turnaround sheet. See Download the pictures. The v query value changes when you replace the sheet.

photo_urlstring | null

The source photo, when you saved one.

voiceobject | null

The character's voice in video shots: id (a saved voice), description (how it was designed, or null) and audio_url (the sample). null when the character has no voice. See Give a character a voice.

created_atinteger

Unix seconds.

updated_atinteger

Unix seconds of the last change.

The character object
{
  "id": "chr_3b9e1f0c7a2d4e58b6c1a9f2",
  "object": "character",
  "name": "Mara",
  "description": "A woman in her thirties with a long black braid, brown eyes, freckles and an athletic build; a green bomber jacket over a grey hoodie, black cargo trousers and white sneakers.",
  "sheet_url": "https://lovelyrouter.com/v1/characters/chr_3b9e1f0c7a2d4e58b6c1a9f2/sheet?v=mh2x7k1c",
  "photo_url": null,
  "voice": {
    "id": "voice_7d2a9c4e1b6f3a8d0c5e2b1f",
    "description": "A low, calm alto, unhurried",
    "audio_url": "https://lovelyrouter.com/v1/audio/voices/voice_7d2a9c4e1b6f3a8d0c5e2b1f/audio"
  },
  "created_at": 1792915200,
  "updated_at": 1792915200
}

Create a character#

POST/v1/characters

Saves a character and returns 201 with the character object. Send multipart (sheet and photo as files) or JSON (the same as http(s) or data: URLs). To save a sheet you generated with the images API, pass the image job's id as sheet_image_job instead of the file.

Body parameters

namestringRequired

Up to 80 characters.

descriptionstring

Face, hair, body and default outfit, up to 4,000 characters. Music videos use it as the character brief when you don't send one.

sheetfile or stringRequired

The turnaround sheet: PNG, JPEG or WebP up to 10 MB, as a file or an http(s) / data: URL (also sheet_url). Use sheet_image_job instead to take it from an image job.

sheet_image_jobstring

An image job id (img_…) of your account that has succeeded: its first image becomes the sheet. Send either this or sheet.

photofile or string

The photo the sheet was made from, PNG, JPEG or WebP up to 10 MB (also photo_url, or photo_image_job). Kept for your records; videos use the sheet.

voice_idstring

One of your saved voices (voice_…) to give the character.

voicefile or string

A new voice sample instead: WAV, MP3, OGG/Opus, FLAC, M4A or WebM up to 10 MB, as a file or an http(s) / data: URL. It is saved as one of your voices, named after the character, and linked. Needs consent.

voice_transcriptstring

What the sample says (up to 1,000 characters) — voices clone better with it.

consentboolean

true confirms the sample is your voice or you have the speaker's permission to use it. Required with voice.

voice_descriptionstring

How the voice was designed, e.g. the description you gave qwen3-tts (up to 1,000 characters). Kept with the voice for your records.

curl https://lovelyrouter.com/v1/characters \
  -H "Authorization: Bearer $LOVELY_API_KEY" \
  -F name=Mara \
  -F description="A woman in her thirties with a long black braid, brown eyes and freckles; a green bomber jacket" \
  -F sheet=@mara-sheet.png

List characters#

GET/v1/characters

Your characters, newest first.

Query parameters

limitintegerDefault 20

1–100.

afterstring

A character id: list the ones saved before it (the next page).

cURL
curl "https://lovelyrouter.com/v1/characters?limit=50" \
  -H "Authorization: Bearer $LOVELY_API_KEY"
Response
{
  "object": "list",
  "data": [{ "id": "chr_3b9e1f0c7a2d4e58b6c1a9f2", "object": "character", "name": "Mara" }],
  "first_id": "chr_3b9e1f0c7a2d4e58b6c1a9f2",
  "last_id": "chr_3b9e1f0c7a2d4e58b6c1a9f2",
  "has_more": false
}

Retrieve a character#

GET/v1/characters/{id}

Returns the character object; 404 for an id that isn't one of yours.

cURL
curl https://lovelyrouter.com/v1/characters/CHARACTER_ID \
  -H "Authorization: Bearer $LOVELY_API_KEY"

Update a character#

PATCH/v1/characters/{id}

Changes the fields you send and returns the character object. Takes JSON or multipart, like Create. Videos already made keep the sheet they were made with.

Body parameters

namestring

A new name.

descriptionstring

A new description (an empty string clears it).

sheetfile or string

A new sheet, or sheet_image_job.

photofile

A new photo (or photo_image_job); null removes it.

voice_idstring or null

Link one of your saved voices; null unlinks the voice (the saved voice itself stays).

voicefile

A new sample (with voice_transcript and consent, as in Create); null unlinks.

voice_descriptionstring or null

How the voice was designed. A newly linked voice takes the description you send with it, or none.

cURL
curl -X PATCH https://lovelyrouter.com/v1/characters/CHARACTER_ID \
  -H "Authorization: Bearer $LOVELY_API_KEY" \
  -H "content-type: application/json" \
  -d '{"description": "A woman in her thirties with a long black braid, now in a red raincoat"}'

Download the pictures#

GET/v1/characters/{id}/sheet

The sheet image with its own content type; GET /v1/characters/{id}/photo is the photo (404 when there is none). Only your key can read them.

cURL
curl https://lovelyrouter.com/v1/characters/CHARACTER_ID/sheet \
  -H "Authorization: Bearer $LOVELY_API_KEY" -o sheet.png

Delete a character#

DELETE/v1/characters/{id}

Deletes the character and its pictures. Videos already made with it are not affected.

cURL
curl -X DELETE https://lovelyrouter.com/v1/characters/CHARACTER_ID \
  -H "Authorization: Bearer $LOVELY_API_KEY"
Response
{ "id": "chr_3b9e1f0c7a2d4e58b6c1a9f2", "object": "character.deleted", "deleted": true }

Give a character a voice#

A character can have a voice: one of your saved voices. In a video shot a character with a voice speaks their lines in it — its timbre, pitch and manner, not its words.

  • Upload one: send the sample as voice (with voice_transcript and consent: true) when you create or update the character. It is saved as a voice named after the character.
  • Design one: make a sample with qwen3-tts from a description and a line the character would say (instructions = the description, input = the line, no voice), save it with POST /v1/audio/voices, then link it as voice_id — with the description as voice_description.

voice_id: null (or voice: null) unlinks the voice. Deleting a character keeps its voice; deleting the voice unlinks it from every character.

cURL
# Link a saved voice to a character.
curl -X PATCH https://lovelyrouter.com/v1/characters/CHARACTER_ID \
  -H "Authorization: Bearer $LOVELY_API_KEY" \
  -H "content-type: application/json" \
  -d '{"voice_id": "voice_7d2a9c4e1b6f3a8d0c5e2b1f", "voice_description": "A low, calm alto, unhurried"}'

Saved scenes#

POST/v1/scenes

A saved scene is a place you want to use again in video shots: a name, a description of the place and its picture. Scenes work like characters, under https://lovelyrouter.com/v1/scenes, with the picture called image (a file, an http(s) / data: URL, or image_image_job) and no photo. Up to 100 per account, besides your characters; free.

The scene object: {id: "scn_…", object: "scene", name, description, image_url, created_at, updated_at}.

RequestWhat it does
POST /v1/scenesname (required, up to 80 characters), description, image (required). Returns 201.
GET /v1/scenesYour scenes, newest first (?limit, ?after).
GET /v1/scenes/{id}One scene.
PATCH /v1/scenes/{id}name, description, image.
GET /v1/scenes/{id}/imageThe picture (your key only).
DELETE /v1/scenes/{id}Deletes the scene and its picture.
cURL
curl https://lovelyrouter.com/v1/scenes \
  -H "Authorization: Bearer $LOVELY_API_KEY" \
  -F name="Night Café" \
  -F description="A small café at night, rain on the windows, warm lamps" \
  -F image=@cafe.jpg

Use a character#

Pass character_id where you would send the picture. The inline fields keep working, so pick per call:

EndpointOne-off call (inline)With a saved character
POST /v1/videos/musiccharacter (text) and/or character_image (file or URL)character_id: its sheet is the reference picture, its description the character text unless you send one. Not with character_image, and only with mode: "image".
POST /v1/videosinput_reference (file or URL)character_id: its sheet is the reference picture. Send exactly one of the two.
POST /v1/videos/shotscharacters / scenes: {name, image} objectscharacters / scenes: ids; the prompt tags them (@Mara), each tagged one is a reference picture.

The music video object and the video object show the character_id they were made with (null for inline calls).

cURL
# A one-off music video: the picture sent with the call.
curl https://lovelyrouter.com/v1/videos/music \
  -H "Authorization: Bearer $LOVELY_API_KEY" \
  -F model=ltx-music-video -F song=@song.mp3 -F consent=true \
  -F character="A woman with a long black braid" -F character_image=@mara.png

# The same with a saved character.
curl https://lovelyrouter.com/v1/videos/music \
  -H "Authorization: Bearer $LOVELY_API_KEY" \
  -F model=ltx-music-video -F song=@song.mp3 -F consent=true \
  -F character_id=chr_3b9e1f0c7a2d4e58b6c1a9f2

Errors#

Errors use the standard error body.

StatustypeWhy
400invalid_request_errorA missing name or sheet, a field too long, a picture that isn't PNG, JPEG or WebP or is larger than 10 MB, an image job that isn't yours or hasn't succeeded, or 100 characters already saved. A voice_id that isn't one of your voices, a voice that isn't audio or is larger than 10 MB, or one sent without consent, or 100 voices already saved.
401authentication_errorA missing or invalid API key.
404not_found_errorAn unknown or deleted character, or one of another account — also as character_id in a video request.