Finetuning.aiFinetuning.ai

POST /v1/generations

Create a new music generation

Start generating an AI music track with the specified parameters. Deducts one credit and submits to the generation queue.

Want vocal-free instrumentals without specifying BPM, key, or scale? See POST /v1/instrumental.

Request

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

Headers

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

Body parameters

ParameterTypeRequiredDefaultDescription
tagsstringYesMusic description (max 700 chars)
lyricsstringNoLyrics text (max 2000 chars)
durationnumberNo60Track duration in seconds (5–210; free tier capped at 120)
bpmnumberNo120Beats per minute (60–200)
languagestringNoLanguage code (en, ja, de, fr, es, zh, ko, pt, it, ru)
keystringNoautoMusical key (C, C#, D, ... B)
scalestringNoautoScale type (major, minor)
timesignaturestringNo"4"Time signature (2–7)
vocalGenderstringNo"auto"Steers the singing voice: auto, female, or male. Only meaningful when lyrics are supplied. See Vocal gender below.
seednumberNoSeed for reproducibility
webhookstringNoHTTPS URL we'll POST the completed (or failed) track to. Skips polling. Max 2048 chars. Identified by User-Agent: finetuning-webhook/1.0. See the Webhooks guide for payload shape and how to secure your endpoint.
certificatebooleanNofalsetrue issues a generation certificate for this track the moment it completes, and returns a download URL on your webhook. See Certificates below.

Example request

curl -X POST https://pub.finetuning.ai/v1/generations \
  -H "X-API-Key: ft_live_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "tags": "lofi chill piano night",
    "duration": 120,
    "bpm": 85,
    "key": "C",
    "scale": "minor",
    "language": "en",
    "timesignature": "4",
    "seed": 1234567,
    "webhook": "https://your-app.com/finetuning-callback?token=YOUR_SECRET"
  }'

Response

202 Accepted
{
  "data": {
    "id": "gen_xyz789",
    "status": "processing",
    "prompt": "lofi chill piano night",
    "parameters": {
      "bpm": 85,
      "duration": 120,
      "timesignature": "4",
      "language": "en",
      "keyscale": "C minor",
      "seed": 1234567
    },
    "webhook": "https://your-app.com/finetuning-callback?token=YOUR_SECRET",
    "certificate": false,
    "creditsRemaining": 1952,
    "createdAt": "2025-01-15T10:30:00Z"
  }
}

If webhook was not provided, the field is returned as null.

Response fields

FieldTypeDescription
data.idstringUnique generation ID
data.statusstringprocessing, pending, completed, failed
data.promptstringThe tags/prompt actually used — includes the vocal-gender phrasing when vocalGender was set
data.parameters.bpmnumberBPM of the track
data.parameters.durationnumberRequested duration in seconds
data.parameters.timesignaturestringTime signature
data.parameters.languagestringLanguage code
data.parameters.keyscalestringCombined key and scale (e.g., "C minor")
data.parameters.seednumberSeed used for generation
data.webhookstring | nullEcho of the webhook URL we accepted, or null if not provided
data.certificatebooleanEcho of the certificate flag we accepted
data.creditsRemainingnumberCredits remaining after this generation
data.createdAtstringISO 8601 timestamp

Certificates

Set certificate: true to have a generation certificate issued the moment the track completes. The completion webhook then carries the certificate's number, its public verification URL and a download URL for the PDF.

{
  "tags": "lofi chill piano night",
  "certificate": true,
  "webhook": "https://your-app.com/finetuning-callback?token=YOUR_SECRET"
}

You only need this if you delete tracks after archiving them: a certificate is rendered from the generation, so it can't be produced once the generation is gone. If you keep your tracks, leave the flag off and call GET /v1/generations/:id/certificate whenever you need the PDF.

Two things worth knowing:

  • It must be a real JSON boolean. We accept true and nothing else — the string "true" is read as "no certificate". The response's data.certificate is how you confirm what we accepted.
  • Certificates are free. Requesting one never costs a credit, and a certificate that fails to issue never stops the track being delivered.

See Certificates for the webhook payload and the archiving pattern.

Vocal gender

Set vocalGender to female or male to steer the singing voice. It only affects tracks that have lyrics — an instrumental has no voice to steer.

{
  "tags": "modern pop, clean production, catchy melody",
  "lyrics": "[verse]\nCity lights are fading out tonight",
  "vocalGender": "female"
}

Three things are worth knowing before you rely on it:

  • It is a strong steer, not a guarantee. In our own blind testing the requested gender was never inverted, but a small share of takes come out with the vocal too indistinct to call. If a take is wrong, generate again — a different seed usually resolves it.
  • data.prompt comes back rewritten. We prepend the vocal phrasing to your tags, and the response echoes what was actually used. Store data.prompt if you want to reproduce a track exactly.
  • Re-sending a returned prompt is safe. If you feed data.prompt back in as tags with a different vocalGender, the previous phrasing is replaced rather than stacked, so the two never conflict.

Omitting the field, or sending auto, leaves generation exactly as it was before this option existed.

Errors

CodeStatusDescription
VALIDATION_ERROR400Invalid parameters (check message field for details)
MISSING_API_KEY401X-API-Key header was not provided
INVALID_API_KEY401API key is malformed, revoked, or does not exist
MONTHLY_LIMIT_REACHED402No generations remaining this month
PRO_PLAN_REQUIRED403Your subscription does not include API access
RATE_LIMITED429Too many requests on a read endpoint — wait and retry (60/min/user)
GENERATION_RATE_LIMITED429Too many POST /v1/generations calls — wait and retry (10/min/user)
QUEUE_FULL429Too many generations in progress
GENERATION_FAILED500Generation queue submission failed

On this page