manipulation.cc

api documentation

Base: https://manipulation.cc

How it works

single request • fast path + fallback

POST /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 ….

POST /v1/create
GET /v1/status?jobId=123
GET /v1/download?jobId=123

Supported type: bait, language, tempo, pitch, distort

Quick spec

multipart/form-data
File field
file
Type field
type
Auth field
authHeader
Auth header
Authorization: Bearer <key>
Success
200 + binary response
Fallback
202 + JSON job info
Errors
4xx/5xx + JSON error
Tip: if you want “always 200”, keep files small so they complete before the sync timeout.

POST /v1/create

apply method

Request: 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 state

Query: 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 output

Query: 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 codes
400 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":"..."}
If your client expects a file, always treat non-200 as JSON/text first.

cURL • single request

200 file or 202 json
curl -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-data
const 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

Bearer
curl -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 result
Allowed: bait, language, tempo, pitch, distort
Choose audio file

The 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.

Idle

Response

raw output
If the API returns JSON (202 / error), it will show here.
// …