Finetuning.aiFinetuning.ai

POST /v1/reimagine

A new song from your song's lyrics, in a style you choose — 2 credits in total

Write and perform a brand-new track from an upload's lyrics and length, in a new style. Only the words and the length carry over: the melody, instruments and voice are new. Returns immediately with processing; the track arrives on your webhook or by polling GET /v1/generations/:id.

The first Reimagine from an upload costs 1 credit, on top of the 1 credit its transcription cost — 2 in total. Every later Reimagine from the same upload costs 2. (So does one from an upload whose transcription was refunded, if you send your own lyrics.) Credits are refunded automatically if the job fails; a failed first Reimagine hands the transcription credit back, so the next try costs 1 again. creditsCharged in the response and the upload's pricing.nextReimagineCredits tell you exactly.

The track is private to your account — it can't be made public, shared or certified.

Request

POST https://pub.finetuning.ai/v1/reimagine

Headers

HeaderTypeRequiredDescription
X-API-KeystringYesYour API key
Content-TypestringYesapplication/json

Body parameters

ParameterTypeRequiredDefaultDescription
uploadIdstringYes—From POST /v1/songs/uploads
lyricsstringNothe transcriptWhat the new song sings, one line per sung line, with optional section tags ([verse], [chorus], [bridge]…). Max: the upload's lyricsCap (18 characters per second of song, 600–3,500; 3,240 for 3:00). Omit to use the lyrics we heard
templateIdstringOne of templateId / prompt—A curated style with vocals (isInstrumental: false) from GET /v1/templates
promptstringOne of templateId / prompt—Your own style description, like tags on POST /v1/generations. Max 700 characters. Ignored when templateId is set
extraPromptstringNo—With templateId: extra words added to the style (max 300 characters)
vocalGenderstringNo"auto""auto", "female" or "male"
webhookstringNo—HTTPS URL we POST the finished (or failed) track to. Max 2,048 characters. See Webhooks

The new track is as long as the upload's window (durationSeconds, at most 3:00).

Example request

curl -X POST https://pub.finetuning.ai/v1/reimagine \
  -H "X-API-Key: ft_live_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "uploadId": "22970e5b-c403-494c-b10d-846df6dde7c5",
    "templateId": "template-open-roads",
    "vocalGender": "female",
    "webhook": "https://your-app.com/finetuning-callback?token=YOUR_SECRET"
  }'
const res = await fetch('https://pub.finetuning.ai/v1/reimagine', {
  method: 'POST',
  headers: { 'X-API-Key': process.env.FINETUNING_API_KEY!, 'Content-Type': 'application/json' },
  body: JSON.stringify({
    uploadId: upload.id,
    prompt: 'acoustic folk, fingerpicked guitar, warm',
    // Fix a misheard line before rendering, or leave `lyrics` out to sing the transcript as heard:
    lyrics: upload.lyrics.replace('Neon humming', 'Neon hums along'),
  }),
})
if (res.status === 409) {
  // TRANSCRIPT_NOT_READY: still listening. Poll GET /v1/songs/uploads/:id, or send your own lyrics.
}
const { data } = await res.json()

Response

202 Accepted
{
  "data": {
    "id": "959ef62f-45c1-4cb6-a4db-fa1da227f5fe",
    "status": "processing",
    "type": "reimagine",
    "title": "my-song (Open Roads)",
    "uploadId": "22970e5b-c403-494c-b10d-846df6dde7c5",
    "duration": 180,
    "isPublic": false,
    "webhook": "https://your-app.com/finetuning-callback?token=YOUR_SECRET",
    "creditsCharged": 1,
    "creditsRemaining": 2044,
    "createdAt": "2026-09-30T13:53:47.108Z"
  }
}

The track usually takes about a minute. Poll GET /v1/generations/{id} until status is completed (it then has an audioUrl) or failed (its credits are already back). With a curated style, the generation's prompt is empty: template prompts stay private, as they do everywhere else.

Errors

CodeStatusDescription
VALIDATION_ERROR400uploadId missing; no templateId or prompt; unknown or instrumental templateId; prompt over 700; bad webhook
LYRICS_REQUIRED400No lyrics sent and none heard (e.g. status: "no_vocals")
LYRICS_TOO_LONG400Over the cap; details.maxLength is the cap for this upload
INSUFFICIENT_CREDITS402Fewer credits left than this render costs (1 or 2). details.cost says which
PAID_PLAN_REQUIRED403Not on a paid plan
NOT_FOUND404No upload with that id on your account
TRANSCRIPT_NOT_READY409lyrics omitted while we're still listening
TRANSCRIPT_REQUIRED409A Remove vocals upload that hasn't been transcribed yet
CATALOGUE_MATCH409The upload was blocked
CREDITS_CHANGED409Your balance changed mid-request; retry
UPLOAD_EXPIRED410The upload's 24 hours are up
QUEUE_FULL429Too many generations in progress
GENERATION_RATE_LIMITED429More than 10 Reimagine / Remove vocals requests in a minute
GENERATION_FAILED502We couldn't start it; your credits are back

On this page