manipulation.cc
api documentation
How it works
single request • fast path + fallbackPOST /v1/create uploads an audio file and applies a type.
- 200 → returns the processed file directly (recommended path).
- 202 → returns JSON with jobId if processing didn’t finish within the sync window.
Auth can be provided via authHeader form field, or Authorization: Bearer ….
Supported type: bait, language, tempo, pitch, distort
Quick spec
multipart/form-dataPOST /v1/create
apply methodRequest: multipart/form-data
file: (binary audio)
type: bait | language | tempo | pitch | distort
authHeader: <api key> (optional if using Authorization header)
Response:
200 application/octet-stream
Content-Disposition: attachment; filename="..." (server provided)
202 application/json
{
"jobId": 123,
"status": "queued_or_processing",
"statusUrl": "/v1/status?jobId=123",
"downloadUrl": "/v1/download?jobId=123"
}
If you get 202, call /v1/status then /v1/download.
GET /v1/status
job stateQuery: jobId
GET /v1/status?jobId=123
Response (example):
{
"id": 123,
"status": "queued | processing | done | failed",
"type": "bait",
"error_text": null,
"created_at": "2026-01-08 20:13:20",
"updated_at": "2026-01-08 20:13:25"
}
GET /v1/download
download outputQuery: jobId
GET /v1/download?jobId=123
Response:
200 application/octet-stream (binary)
409 application/json {"error":"Not ready"}
404 application/json {"error":"Not found"}
Errors
common codes400 Bad Request {"error":"..."}
401 Unauthorized {"error":"Unauthorized"}
409 Not ready {"error":"Not ready"}
429 Too Many {"error":"Rate limit"}
500 Server error {"error":"server_error","details":"..."}
cURL • single request
200 file or 202 jsoncurl -sS -X POST "https://manipulation.cc/v1/create" \
-F "file=@input.mp3" \
-F "type=bait" \
-F "authHeader=YOUR_KEY" \
-o out.bin -D headers.txt
# if status != 200, inspect body:
# cat out.bin
Node.js • minimal
axios + form-dataconst fs = require("fs");
const axios = require("axios");
const FormData = require("form-data");
(async () => {
const fd = new FormData();
fd.append("file", fs.createReadStream("./input.mp3"));
fd.append("type", "bait");
fd.append("authHeader", "YOUR_KEY");
const r = await axios.post("https://manipulation.cc/v1/create", fd, {
headers: fd.getHeaders(),
responseType: "arraybuffer",
validateStatus: () => true
});
if (r.status === 200) return fs.writeFileSync("out.bin", r.data);
console.log(Buffer.from(r.data).toString()); // 202 json or error json
})();
Fallback flow (202)
status + download# status
curl "https://manipulation.cc/v1/status?jobId=123"
# download once done
curl -L "https://manipulation.cc/v1/download?jobId=123" -o out.bin
Auth header option
Bearercurl -X POST "https://manipulation.cc/v1/create" \
-H "Authorization: Bearer YOUR_KEY" \
-F "file=@input.mp3" \
-F "type=distort" \
-o out.bin
Try it (browser)
downloads resultThe browser will download the response if the server returns a file. If the server returns 202, this page will auto-poll and download when ready.
Response
raw output// …