Appearance
Audio tools
- Clean audio removes background noise, splits a song into vocals and music, splits stems, or isolates a described sound.
- Voice changer keeps a recording's words, timing and delivery in another voice.
Both run in the background on an uploaded audio or video file.
Endpoints:
GET /v1/clean-audio/optionsPOST /v1/clean-audioGET /v1/clean-audio/{id}GET /v1/clean-audio/{id}/files/{name}GET /v1/voice-changer/optionsPOST /v1/voice-changerGET /v1/voice-changer/{id}GET /v1/voice-changer/{id}/files/{name}
Clean audio
Get clean audio options
GET /v1/clean-audio/options
Response
200 OK
json
{
"modes": [
{ "id": "voice", "label": "Remove background noise", "description": "Keep only the voice: noise, music and room sound removed. Works on video too.", "creditsPerMinute": 1000 },
{ "id": "vocals", "label": "Vocals and music", "description": "Split a song into the singing and the instrumental.", "creditsPerMinute": 600 },
{ "id": "stems", "label": "Split into stems", "description": "Vocals, drums, bass and other instruments, or 6 stems with guitar and piano.", "creditsPerMinute": 400 },
{ "id": "sound", "label": "Isolate a sound", "description": "Describe any sound, like a dog barking or applause, and pull it out.", "creditsPerMinute": 600 }
],
"stemSets": [
{ "id": "4", "stems": ["Vocals", "Drums", "Bass", "Other instruments"] },
{ "id": "6", "stems": ["Vocals", "Drums", "Bass", "Guitar", "Piano", "Other instruments"] }
],
"soundExamples": ["a person speaking", "dog barking", "applause", "birds singing", "car horn", "acoustic guitar"],
"maxPromptChars": 200,
"maxSeconds": 3600,
"maxUploadBytes": 2147483648
}Credits
Free.
Example
bash
curl https://api.cinara.ai/v1/clean-audio/options \
-H "Authorization: Bearer $CINARA_API_KEY"Clean audio
POST /v1/clean-audio
Starts a clean audio job on an uploaded file.
Needs a verified phone.
Request body
| Field | Type | Required | Description |
|---|---|---|---|
key | string | yes | The storage key of a finished audio or video upload. |
mode | string | yes | voice, vocals, stems or sound. |
prompt | string | sound mode | The sound to isolate, 1–200 characters. Ignored in other modes. |
stems | string | no | stems mode: "4" (default) or "6". Any other value is "4". |
keepVideo | boolean | no | voice mode on a video: also return the video with the clean audio. Default true. |
durationSeconds | number | no | A hint: the file's length in seconds, up to 3,600. Cinara reads the real length from the file and uses this only when it can't. |
fileName | string | no | Up to 200 characters. Defaults to the upload's file name. |
Steps by mode:
| Mode | Audio file | Video file |
|---|---|---|
voice | Remove background noise | Remove background noise, then put the clean audio back on the video (with keepVideo) |
vocals, sound | Separate the sound | Take the audio out of the video, then separate |
stems | Split into stems | Take the audio out of the video, then split |
Response
201 Created
json
{
"generation": {
"id": "5c8a2e6f-9d1b-4f3a-b7e4-6a0d3c9f2b18",
"module": "clean_audio",
"status": "running",
"input": {
"key": "workspaces/3f6b2a1c-8d4e-4b7a-9c2d-5e1f0a9b8c7d/uploads/1e7c4a9b-5d2f-4b6e-8a3c-7f0b9d2e5a64/demo-track.wav",
"fileName": "demo-track.wav",
"contentType": "audio/wav",
"size": 37044000,
"durationSeconds": 210,
"durationMeasured": true,
"mode": "stems",
"prompt": null,
"stems": "4",
"keepVideo": false,
"totalSteps": 1
},
"output": { "stage": "queued", "step": 1, "stageLabel": "Splitting into stems" },
"credits": 1400,
"error": null,
"created_at": "2026-09-15T18:02:15.550913+00:00",
"completed_at": null
},
"credits": 43831
}Errors
| Status | error | Message |
|---|---|---|
| 400 | invalid_request | Upload a file first |
| 400 | invalid_request | Choose what to do with the audio |
| 400 | invalid_request | Describe the sound in 1 to 200 characters |
| 400 | invalid_request | Files can be up to 1 hour long |
| 404 | not_found | That upload isn't finished. Upload the file again. |
| 400 | invalid_request | Upload an audio or video file |
| 402 | insufficient_credits | This needs 1,400 credits |
| 403 | phone_unverified | Verify your phone number to start creating. |
| 502 | generation_failed | Clean audio couldn't start. Your credits were refunded. |
The length is read from the file (MP3, WAV, MP4, M4A or MOV) before anything is charged, and a file over 1 hour is refused. When it can't be read (for example WebM, OGG or FLAC), a durationSeconds over 1 hour is refused instead.
Credits
max(1, ceil(minutes × rate)), where the rate per minute is:
| Mode | Credits per minute |
|---|---|
voice | 1,000 |
vocals | 600 |
stems | 400 |
sound | 600 |
- Length read from the file: charged on the file's real length.
input.durationMeasuredistrue. - Length can't be read: a reserve is held on the longer of
durationSecondsand an estimate from the file size, up to 1 hour. When the job finishes, the charge is settled to the length of the result.input.durationMeasuredisfalse.
Refunded if it fails.
Example
bash
curl -X POST https://api.cinara.ai/v1/clean-audio \
-H "Authorization: Bearer $CINARA_API_KEY" \
-H "Content-Type: application/json" \
-d '{"key": "workspaces/3f6b2a1c-8d4e-4b7a-9c2d-5e1f0a9b8c7d/uploads/1e7c4a9b-5d2f-4b6e-8a3c-7f0b9d2e5a64/demo-track.wav", "mode": "stems", "stems": "4", "durationSeconds": 210}'Get a clean audio job
GET /v1/clean-audio/{id}
Checks a clean audio job, moves it forward, and returns it with its files once finished.
Response
200 OK
json
{
"generation": {
"id": "5c8a2e6f-9d1b-4f3a-b7e4-6a0d3c9f2b18",
"module": "clean_audio",
"status": "succeeded",
"input": {
"key": "workspaces/3f6b2a1c-8d4e-4b7a-9c2d-5e1f0a9b8c7d/uploads/1e7c4a9b-5d2f-4b6e-8a3c-7f0b9d2e5a64/demo-track.wav",
"fileName": "demo-track.wav",
"contentType": "audio/wav",
"size": 37044000,
"durationSeconds": 210,
"durationMeasured": true,
"mode": "stems",
"prompt": null,
"stems": "4",
"keepVideo": false,
"totalSteps": 1
},
"output": { "step": 1 },
"credits": 1400,
"error": null,
"created_at": "2026-09-15T18:02:15.550913+00:00",
"completed_at": "2026-09-15T18:03:40.118822+00:00"
},
"files": [
{ "name": "vocals", "label": "Vocals", "contentType": "audio/mpeg", "size": 3371264, "url": "https://api.cinara.ai/media/1789539820/Ee4tA…/workspaces/…/vocals.mp3" },
{ "name": "drums", "label": "Drums", "contentType": "audio/mpeg", "size": 3371264, "url": "https://api.cinara.ai/media/1789539820/Uu0kM…/workspaces/…/drums.mp3" },
{ "name": "bass", "label": "Bass", "contentType": "audio/mpeg", "size": 3371264, "url": "https://api.cinara.ai/media/1789539820/Rw9bN…/workspaces/…/bass.mp3" },
{ "name": "other", "label": "Other instruments", "contentType": "audio/mpeg", "size": 3371264, "url": "https://api.cinara.ai/media/1789539820/Lc2hS…/workspaces/…/other.mp3" }
],
"mediaUrl": "https://api.cinara.ai/media/1789539820/Mf6jQ…/workspaces/…/uploads/…/demo-track.wav",
"credits": 43831
}Files by mode (empty until the job succeeds):
| Mode | Files (name: label) |
|---|---|
voice | voice: Clean voice. On a video with keepVideo, also video: Clean video. |
vocals | vocals: Vocals; music: Music. |
sound | sound: the prompt, capitalised; rest: Everything else. |
stems "4" | vocals, drums, bass, other |
stems "6" | vocals, drums, bass, guitar, piano, other |
mediaUrl is a signed link (6 hours) to the uploaded file.
Failures: Clean audio took too long and was stopped., This file couldn't be read. Try MP3, WAV, M4A, MP4 or WebM., Clean audio failed.
Errors
| Status | error | Message |
|---|---|---|
| 404 | not_found | Not found |
Credits
Free to read.
Polling example
bash
while :; do
RES=$(curl -s "https://api.cinara.ai/v1/clean-audio/$ID" -H "Authorization: Bearer $CINARA_API_KEY")
STATUS=$(echo "$RES" | jq -r .generation.status)
[ "$STATUS" != "running" ] && break
echo "Step $(echo "$RES" | jq -r .generation.output.step) of $(echo "$RES" | jq -r .generation.input.totalSteps): $(echo "$RES" | jq -r .generation.output.stageLabel)"
sleep 5
done
echo "$RES" | jq -r '.files[] | "\(.name) \(.url)"'Download a clean audio file
GET /v1/clean-audio/{id}/files/{name}
Downloads one finished file as an attachment.
Response
200 OK with the file and Content-Disposition: attachment; filename="demo-track-vocals.mp3".
Errors
| Status | error | Message |
|---|---|---|
| 404 | not_found | File not found |
Credits
Free.
Example
bash
curl -L "https://api.cinara.ai/v1/clean-audio/5c8a2e6f-9d1b-4f3a-b7e4-6a0d3c9f2b18/files/vocals" \
-H "Authorization: Bearer $CINARA_API_KEY" -o vocals.mp3Voice changer
Get voice changer options
GET /v1/voice-changer/options
Response
200 OK
json
{
"creditsPerMinute": 300,
"noiseCreditsPerMinute": 1000,
"maxSeconds": 600,
"maxUploadBytes": 2147483648
}Credits
Free.
Example
bash
curl https://api.cinara.ai/v1/voice-changer/options \
-H "Authorization: Bearer $CINARA_API_KEY"Change a voice
POST /v1/voice-changer
Starts changing the voice in an uploaded recording.
Needs a verified phone.
A library voice converts toward its preview clip. A workspace voice converts toward its saved sample.
Request body
| Field | Type | Required | Description |
|---|---|---|---|
key | string | yes | The storage key of a finished audio or video upload. |
voiceId | string | yes | A library voice id, or a workspace voice's providerVoiceId. |
removeNoise | boolean | no | Remove background noise first. Default false. |
keepVideo | boolean | no | For videos: also return the video with the new voice. Default true. |
durationSeconds | number | no | A hint: the recording's length, up to 600 seconds. Cinara reads the real length from the file and uses this only when it can't. |
fileName | string | no | Up to 200 characters. Defaults to the upload's file name. |
Steps: remove noise (with removeNoise) or take the audio out of a video, then change the voice, then put the new voice on the video (videos with keepVideo).
Response
201 Created
json
{
"generation": {
"id": "e3b7d1a9-4c6f-4e2b-9a8d-5f1c0e7b3a26",
"module": "voice_changer",
"status": "running",
"input": {
"key": "workspaces/3f6b2a1c-8d4e-4b7a-9c2d-5e1f0a9b8c7d/uploads/8a3d6f1c-2e9b-4d7a-b5c8-1f4e7a0d9c32/promo-read.mp3",
"fileName": "promo-read.mp3",
"contentType": "audio/mpeg",
"size": 720000,
"durationSeconds": 45,
"durationMeasured": true,
"voiceId": "captain",
"voiceName": "Captain · Ryan",
"targetContentType": null,
"removeNoise": true,
"keepVideo": false,
"totalSteps": 2
},
"output": { "stage": "queued", "step": 1, "stageLabel": "Removing background noise" },
"credits": 975,
"error": null,
"created_at": "2026-09-15T18:30:05.887452+00:00",
"completed_at": null
},
"credits": 43006
}Errors
| Status | error | Message |
|---|---|---|
| 400 | invalid_request | Upload a recording first |
| 400 | invalid_request | Choose a voice |
| 400 | invalid_request | Recordings can be up to 10 minutes |
| 404 | not_found | That upload isn't finished. Upload the file again. |
| 400 | invalid_request | Upload an audio or video file |
| 402 | insufficient_credits | This needs 975 credits |
| 403 | phone_unverified | Verify your phone number to start creating. |
| 502 | generation_failed | Voice change couldn't start. Your credits were refunded. |
The length is read from the file (MP3, WAV, MP4, M4A or MOV) before anything is charged, and a recording over 10 minutes is refused. When it can't be read (for example WebM, OGG or FLAC), a durationSeconds over 10 minutes is refused instead.
Credits
max(1, ceil(minutes × rate)). The rate is 300 credits per minute, or 1,300 (300 + 1,000) with removeNoise.
- Length read from the file: charged on the recording's real length.
- Length can't be read: a reserve is held on the longer of
durationSecondsand an estimate from the file size, up to 10 minutes. When the job finishes, the charge is settled to the length of the result.
Refunded if it fails.
Example
bash
curl -X POST https://api.cinara.ai/v1/voice-changer \
-H "Authorization: Bearer $CINARA_API_KEY" \
-H "Content-Type: application/json" \
-d '{"key": "workspaces/3f6b2a1c-8d4e-4b7a-9c2d-5e1f0a9b8c7d/uploads/8a3d6f1c-2e9b-4d7a-b5c8-1f4e7a0d9c32/promo-read.mp3", "voiceId": "captain", "removeNoise": true, "durationSeconds": 45}'Get a voice changer job
GET /v1/voice-changer/{id}
Checks a voice changer job, moves it forward, and returns it with its files once finished.
Response
200 OK
json
{
"generation": {
"id": "e3b7d1a9-4c6f-4e2b-9a8d-5f1c0e7b3a26",
"module": "voice_changer",
"status": "succeeded",
"input": { "key": "workspaces/…/uploads/…/promo-read.mp3", "voiceId": "captain", "voiceName": "Captain · Ryan", "totalSteps": 2, "…": "…" },
"output": { "step": 2 },
"credits": 975,
"error": null,
"created_at": "2026-09-15T18:30:05.887452+00:00",
"completed_at": "2026-09-15T18:30:51.340126+00:00"
},
"files": [
{ "name": "voice", "label": "Captain · Ryan's voice", "contentType": "audio/wav", "size": 3969080, "url": "https://api.cinara.ai/media/1789541451/Yx3pF…/workspaces/…/voice.wav" }
],
"mediaUrl": "https://api.cinara.ai/media/1789541451/Gd8sK…/workspaces/…/uploads/…/promo-read.mp3",
"credits": 43006
}Files: voice (labelled with the voice's name), and for videos with keepVideo, video ("Video with the new voice"). Empty until the job succeeds.
Failures: Voice change took too long and was stopped., This file couldn't be read. Try MP3, WAV, M4A, MP4 or WebM., Voice change failed.
Errors
| Status | error | Message |
|---|---|---|
| 404 | not_found | Not found |
Credits
Free to read.
Polling example
bash
while :; do
RES=$(curl -s "https://api.cinara.ai/v1/voice-changer/$ID" -H "Authorization: Bearer $CINARA_API_KEY")
[ "$(echo "$RES" | jq -r .generation.status)" != "running" ] && break
sleep 5
done
curl -L "https://api.cinara.ai/v1/voice-changer/$ID/files/voice" -H "Authorization: Bearer $CINARA_API_KEY" -o new-voice.wavDownload a voice changer file
GET /v1/voice-changer/{id}/files/{name}
Downloads one finished file (voice or video) as an attachment.
Response
200 OK with the file and Content-Disposition: attachment; filename="promo-read-voice.wav".
Errors
| Status | error | Message |
|---|---|---|
| 404 | not_found | File not found |
Credits
Free.
Example
bash
curl -L "https://api.cinara.ai/v1/voice-changer/e3b7d1a9-4c6f-4e2b-9a8d-5f1c0e7b3a26/files/voice" \
-H "Authorization: Bearer $CINARA_API_KEY" -o new-voice.wav