Edit a song

June 3, 2026 (August 12, 2026)

Table of contents

  1. Request Headers
  2. Request Body
    1. operation: effect
    2. operation: extend
    3. operation: replace
    4. operation: cover
    5. operation: remix
    6. operation: stems
  3. Responses
  4. Model
  5. Examples
  6. Try It

Edit an existing clip — the operation field selects one of six edit kinds, each taking a clip (an encoded clip asset ID from a previous generation or GET /music).

operation is required — one of:

operation What it does Required params Optional params
effect Apply one audio effect effect + that effect’s scalar param(s)
extend Add new music to the end, or from a point instruction extend_s, extend_from_s
replace Regenerate a time section instruction, mask_start_s, mask_end_s
cover Restyle the whole song (a Lyria cover) instruction, strength, model
remix Re-sing with edited lyrics lyrics prompt
stems Separate into 4 stem clips (drums/bass/vocals/other)

https://api.useapi.net/v1/flowmusic/music/edit

Request Headers

Authorization: Bearer {API token}
Content-Type: application/json
# Alternatively you can use multipart/form-data
# Content-Type: multipart/form-data

Request Body

Every operation accepts these common fields (there is no email — the clip already identifies its account, and the edit runs there):

  • clip is required, the encoded clip asset ID to edit.
  • seed is optional, an integer ≥ 0 — pins the result for reproducibility.
  • title is optional, a title for the result clip.
  • model is optional, the music model used to re-render. Supported values: lyria-3.5 and lyria-3-pro (default). It is sent with the operations that re-synthesise audio — cover, extend, replace, and remix. effect and stems accept it but their output is unaffected, because those are signal processing and stem separation with no music model in the loop. Omitting it keeps the behaviour that existed before the parameter was added.
  • mode is optional, sync (default — blocks until ready) or async (returns 201 with a jobid; poll GET /jobs/jobid). In sync your connection must stay open until ready — if it drops the result is lost, so prefer async on mobile, flaky networks, or short-timeout platforms. Ignored by stems, which is always sync.
  • replyUrl is optional, a webhook URL — the job record is POSTed to it when the edit completes or fails. Ignored by stems.
  • replyRef is optional, a custom reference string echoed back in the webhook.

Plus the chosen operation’s own fields, below.

operation: effect

effect is one of Trim, Fade, Gain, Reverb, Pan, Equalizer. Each effect reads only its own flat scalar params (sending a param for a different effect is ignored):

  • Gaingain_db (−30 … 30).
  • Reverbmix, room_size (0 … 1 each).
  • Panpan (−1 left … 1 right).
  • Equalizerbass_db, mid_db, treble_db (−12 … 12 each).
  • Fadefade_in_s, fade_out_s (≥ 0, at least one > 0).
  • Trimstart_s, end_s (end_s > start_s, ≤ duration).
{
  "operation": "effect",
  "clip": "user:[email protected]:...",
  "effect": "Reverb",
  "mix": 0.4,
  "room_size": 0.7
}

operation: extend

{
  "operation": "extend",
  "clip": "user:1234-...-clip:...",
  "instruction": "add an instrumental outro",
  "extend_s": 30
}
  • instruction is required, what to add.
  • extend_s is optional, seconds to add, 1–300 (default 150).
  • extend_from_s is optional, the point to extend from (default = end of clip).

operation: replace

{
  "operation": "replace",
  "clip": "user:1234-...-clip:...",
  "instruction": "softer piano in this section",
  "mask_start_s": 0,
  "mask_end_s": 8
}
  • instruction is required, how to regenerate the section.
  • mask_start_s is required, the section start (seconds).
  • mask_end_s is required, the section end (seconds), > mask_start_s, ≤ duration.

operation: cover

Restyle the entire song. instruction is optional (a free-text style direction); strength is the cover-strength slider.

{
  "operation": "cover",
  "clip": "user:1234-...-clip:...",
  "instruction": "lo-fi chillhop reinterpretation",
  "strength": 0.7
}
  • instruction is optional, a free-text style direction.
  • strength is optional, 0 … 1 (default 1).

operation: remix

Re-sing the song with edited lyrics. By default it reuses the source song’s sound prompt; override with prompt. The edited lyrics round-trip into the result clip’s lyrics.

{
  "operation": "remix",
  "clip": "user:1234-...-clip:...",
  "lyrics": "[Verse 1]\nNeon rain on the avenue\n[Chorus]\nWe rise again",
  "prompt": "dreamy synthwave, 100 bpm"
}
  • lyrics is required, the edited lyrics, [Verse]/[Chorus]-tagged.
  • prompt is optional, a sound-prompt override (defaults to the source clip’s).

operation: stems

Separate the song into its individual tracks. Flow Music runs the split server-side and creates 4 new clipsdrums, bass, vocals, other — each a normal clip with its own id and a public audio_url/wav_url. Only clip is needed.

{
  "operation": "stems",
  "clip": "user:1234-...-clip:..."
}
  • stems is synchronous — the request blocks ~15–60 s while the split runs, then returns all four stems in one reply (it ignores mode/replyUrl/replyRef). Re-running on an already-split clip returns its stems immediately.
  • Download any stem with GET /music/download (mp3) or its audio_url/wav_url.

Its response differs from the other edits — it’s a flat manifest of the stem clips, not a job record:

{
  "email": "[email protected]",
  "operation": "stems",
  "source_clip": "user:1234-...-clip:...",
  "status": "completed",
  "clips": [
    {
      "stem_type": "drums",
      "clip": "user:1234-...-clip:...",
      "title": "Song - drums",
      "duration_s": 173.0,
      "audio_url": "https://storage.googleapis.com/...1a2b3c4d.m4a",
      "wav_url": "https://storage.googleapis.com/...1a2b3c4d.wav",
      "image_url": null
    }
  ]
}

(four entries — drums, bass, vocals, other).

Responses

Same job-record shape as POST /musicoperation echoes the requested edit kind. (operation: stems is the exception — it returns the flat stem manifest shown above, not a job record.)

  • 200 OK

    Sync mode (default) — the edit is rendered and the full record is returned inline.

    {
      "jobid": "job:aaaabbbb-cccc-4ddd-8eee-ffff99990000-user:[email protected]:flowmusic",
      "email": "[email protected]",
      "operation": "cover",
      "status": "completed",
      "created_at": "2026-06-01T18:40:42.412Z",
      "completed_at": "2026-06-01T18:41:37.432Z",
      "duration_ms": 55020,
      "clips": [
        {
          "clip": "user:[email protected]:c3d4e5f6-a7b8-4c9d-0e1f-2a3b4c5d6e7f",
          "title": "Morning Sun (Cover)",
          "duration_s": 171.02,
          "lyrics": "[Verse 1]\nCity lights blur in the rain\n[Chorus]\nAnd I will wait for the morning sun",
          "seed": 123456,
          "lyrics_timing": [ [0.0, 2.4], [2.4, 5.1] ],
          "created_at": "2026-06-01T18:41:30.118Z",
          "audio_url": "https://storage.googleapis.com/...c3d4e5f6.m4a",
          "wav_url": "https://storage.googleapis.com/...c3d4e5f6.wav",
          "image_url": "https://storage.googleapis.com/...d4e5f6a7.jpg"
        }
      ],
      "request": {
        "operation": "cover",
        "clip": "user:[email protected]:...",
        "strength": 0.7
      }
    }
    
  • 201 Created

    Async mode ("mode": "async") — the edit is queued and returned immediately as pending. Poll GET /jobs/jobid until status is completed or failed.

    {
      "jobid": "job:aaaabbbb-cccc-4ddd-8eee-ffff99990000-user:[email protected]:flowmusic",
      "email": "[email protected]",
      "operation": "remix",
      "status": "pending",
      "created_at": "2026-06-01T18:40:42.412Z",
      "request": {
        "operation": "remix",
        "clip": "user:1234-...-clip:...",
        "lyrics": "[Verse 1]\n...",
        "mode": "async"
      }
    }
    
  • 400 Bad Request

    Validation error — an unknown operation, a missing required field for the chosen operation (e.g. replace without mask_start_s/mask_end_s, or effect without effect), or a clip that isn’t a clip-type asset ID.

    {
      "error": "instruction required for operation=extend",
      "code": 400
    }
    
  • 401 Unauthorized

    Invalid API token.

    {
      "error": "Unauthorized",
      "code": 401
    }
    
  • 402 Payment Required

    The targeted Flow Music account has insufficient credits to complete the edit. Top up its credit balance (or target a funded account with email), then retry.

    {
      "error": "recipes/create failed (402): {\"detail\":\"User has insufficient credits\"}",
      "code": 402
    }
    
  • 404

    The clip’s account isn’t configured under your useapi.net account, or the source clip no longer exists on Flow Music.

    {
      "error": "source clip not found on FlowMusic",
      "code": 404
    }
    
  • 422

    The edit produced no audio (e.g. a content-moderation refusal — a terminal status: "failed" record), or the source clip can’t be edited (an uploaded clip has no conversation_id).

    {
      "jobid": "job:aaaabbbb-cccc-4ddd-8eee-ffff99990000-user:[email protected]:flowmusic",
      "email": "[email protected]",
      "operation": "cover",
      "status": "failed",
      "created_at": "2026-06-01T18:40:42.412Z",
      "completed_at": "2026-06-01T18:41:10.512Z",
      "error": { "code": "moderation_reject", "message": "the model declined to generate audio for this edit" },
      "request": {
        "operation": "cover",
        "clip": "user:1234-...-clip:..."
      }
    }
    
  • 429 Too Many Requests

    Passed through from Flow Music when the clip’s account is already running too many concurrent jobs — retry once one finishes.

    {
      "error": "producer/tool-call failed (429): {\"detail\":\"Too Many Requests\"}",
      "code": 429
    }
    
  • 596 Account Error

    The clip’s account is in an error state and can’t be used — re-add it via POST /accounts.

    {
      "error": "Account [email protected] in error state: refresh token rejected",
      "code": 596
    }
    

Model

Same job-record shape as POST /music, plus a top-level operation. The request echoes the edit body you submitted. (operation: stems returns a flat manifest of the 4 stem clips instead — see operation: stems.)

  • {
      jobid: string                  // job:<uuid>-user:<id>-<email>-bot:flowmusic
      email: string
      operation: 'effect' | 'extend' | 'replace' | 'cover' | 'remix' | 'stems'
      status: 'completed' | 'pending' | 'failed'
      created_at: string             // ISO 8601 timestamp
      completed_at?: string          // present when terminal
      duration_ms?: number           // wall-clock render time
      clips: Array<{
        clip: string                 // encoded clip asset id — use with /music/download and /music/edit
        title: string | null
        duration_s: number | null
        lyrics: string | null        // [Verse]/[Chorus]-tagged; "[Instrumental]" for instrumentals
        seed: number | null
        lyrics_timing: Array<[number, number]> | null  // timing markers, [start, end] seconds (vocal clips)
        created_at: string           // ISO 8601 timestamp
        audio_url: string            // m4a download URL
        wav_url: string              // wav download URL
        image_url: string | null     // auto-generated artwork URL
      }>
      request: {                     // the edit body you submitted, echoed back verbatim
        operation: 'effect' | 'extend' | 'replace' | 'cover' | 'remix' | 'stems'
        clip: string
        model?: 'lyria-3.5' | 'lyria-3-pro'   // cover/extend/replace/remix — inert on effect/stems
        seed?: number                // common — pins the result
        title?: string               // common
        mode?: 'sync' | 'async'      // common
        replyUrl?: string            // common — webhook
        replyRef?: string            // common — webhook reference
        effect?: 'Trim' | 'Fade' | 'Gain' | 'Reverb' | 'Pan' | 'Equalizer'   // effect
        gain_db?: number             // effect=Gain (-30..30)
        mix?: number                 // effect=Reverb (0..1)
        room_size?: number           // effect=Reverb (0..1)
        pan?: number                 // effect=Pan (-1..1)
        bass_db?: number             // effect=Equalizer (-12..12)
        mid_db?: number              // effect=Equalizer (-12..12)
        treble_db?: number           // effect=Equalizer (-12..12)
        fade_in_s?: number           // effect=Fade
        fade_out_s?: number          // effect=Fade
        start_s?: number             // effect=Trim
        end_s?: number               // effect=Trim
        instruction?: string         // extend / replace / cover
        extend_s?: number            // extend (1..300)
        extend_from_s?: number       // extend
        mask_start_s?: number        // replace
        mask_end_s?: number          // replace
        strength?: number            // cover (0..1)
        lyrics?: string              // remix
        prompt?: string              // remix
      }
    }
    
  • {
      jobid: string                  // job:<uuid>-user:<id>-<email>-bot:flowmusic
      email: string
      operation: 'effect' | 'extend' | 'replace' | 'cover' | 'remix' | 'stems'
      status: 'pending'
      created_at: string             // ISO 8601 timestamp
      request: { }                   // the edit body you submitted — same shape as the 200 (Completed) model above
    }
    

Examples

  • # Cover (restyle) — instruction optional
    curl -H "Content-Type: application/json" \
         -H "Authorization: Bearer YOUR_API_TOKEN" \
         -X POST "https://api.useapi.net/v1/flowmusic/music/edit" \
         -d '{ "operation": "cover", "clip": "user:[email protected]:...", "strength": 0.7 }'
    
  • const response = await fetch('https://api.useapi.net/v1/flowmusic/music/edit', {
      method: 'POST',
      headers: { 'Authorization': 'Bearer YOUR_API_TOKEN', 'Content-Type': 'application/json' },
      body: JSON.stringify({
        operation: 'remix',
        clip: 'user:[email protected]:...',
        lyrics: '[Verse 1]\nNeon rain on the avenue\n[Chorus]\nWe rise again'
      })
    });
    console.log(await response.json());
    
  • import requests
    
    response = requests.post(
        'https://api.useapi.net/v1/flowmusic/music/edit',
        headers={'Authorization': 'Bearer YOUR_API_TOKEN'},
        json={'operation': 'effect', 'clip': 'user:[email protected]:...',
              'effect': 'Gain', 'gain_db': 6}
    )
    print(response.status_code, response.json())
    

Try It