Quickstart
Denoise one audio file with zilapi/nr-4.1 in five steps. With a test key this costs nothing; with a live key, a 3-minute file costs about $0.10.
ZILAPI_KEY. Create a key (a test key is fine). The curl examples use jq and bash; Python uses requests; JavaScript runs on Node 20 or later as an ES module.Start an upload
Tell us the file name, size in bytes and audio type. You get a file id and a signed upload URL, valid for a limited time. Files up to 5 GB and 6 h are accepted; this example covers a single PUT, which is what you get for files up to 100 MB. Test keys accept files up to 25 MB.
curl -s https://api.zilapi.com/v1/files \
-H "Authorization: Bearer $ZILAPI_KEY" \
-H "Content-Type: application/json" \
-d '{"filename": "talk.wav", "size_bytes": '"$(wc -c < talk.wav)"', "content_type": "audio/wav"}' \
> upload.json
FILE_ID=$(jq -r .id upload.json) # file_3Lm8QpZ2rT6wUpload the bytes
PUT the file to upload.url and send every header in upload.headers with it. The bytes go straight to storage, not through the API.
mapfile -t HEADERS < <(jq -r '.upload.headers | to_entries[] | "-H", "\(.key): \(.value)"' upload.json)
curl -X PUT "$(jq -r .upload.url upload.json)" "${HEADERS[@]}" --data-binary @talk.wavFinish the upload and wait until it is ready
Finishing starts validation: we check the size and measure the audio. The file is validating for a few seconds, then ready (with duration_seconds) or rejected (not audio, or longer than 6 h).
curl -s -X POST https://api.zilapi.com/v1/files/$FILE_ID/complete \
-H "Authorization: Bearer $ZILAPI_KEY"
while :; do
FILE_STATUS=$(curl -s https://api.zilapi.com/v1/files/$FILE_ID -H "Authorization: Bearer $ZILAPI_KEY" | jq -r .status)
[ "$FILE_STATUS" != "validating" ] && break
sleep 2
done
echo "$FILE_STATUS" # readyCreate a denoise job
Name the file and the model. The job is queued and runs on our GPUs. With a live key we hold the exact cost from your credit; if your available credit is too low you get 402 insufficient_credit and nothing starts.
curl -s https://api.zilapi.com/v1/audio/denoise \
-H "Authorization: Bearer $ZILAPI_KEY" \
-H "Content-Type: application/json" \
-d '{"file": "'"$FILE_ID"'", "model": "zilapi/nr-4.1"}' \
> job.json
JOB_ID=$(jq -r .id job.json) # job_7Hq2xV9mKp4RWait for the job, then download the MP3
Poll every few seconds while the job is queued or processing. When it has succeeded, ask for a fresh download URL (valid for 1 hour). Results are kept for 7 days after the job succeeds.
while :; do
STATUS=$(curl -s https://api.zilapi.com/v1/jobs/$JOB_ID -H "Authorization: Bearer $ZILAPI_KEY" | jq -r .status)
case "$STATUS" in queued|processing) sleep 5 ;; *) break ;; esac
done
echo "$STATUS" # succeeded
curl -s https://api.zilapi.com/v1/jobs/$JOB_ID/output -H "Authorization: Bearer $ZILAPI_KEY" > output.json
curl -o "$(jq -r .filename output.json)" "$(jq -r .url output.json)"The same with the SDK
The official SDKs, zilapi for Python and @zilapi/sdk for JavaScript, wrap the same five calls: uploads (single or multipart), polling with backoff, retries and idempotency keys. They are in beta: the raw HTTP above is the reference.
curl -s https://api.zilapi.com/v1/files \
-H "Authorization: Bearer $ZILAPI_KEY" \
-H "Content-Type: application/json" \
-d '{"filename": "talk.wav", "size_bytes": '"$(wc -c < talk.wav)"', "content_type": "audio/wav"}' \
> upload.json
FILE_ID=$(jq -r .id upload.json) # file_3Lm8QpZ2rT6w
mapfile -t HEADERS < <(jq -r '.upload.headers | to_entries[] | "-H", "\(.key): \(.value)"' upload.json)
curl -X PUT "$(jq -r .upload.url upload.json)" "${HEADERS[@]}" --data-binary @talk.wav
curl -s -X POST https://api.zilapi.com/v1/files/$FILE_ID/complete \
-H "Authorization: Bearer $ZILAPI_KEY"
while :; do
FILE_STATUS=$(curl -s https://api.zilapi.com/v1/files/$FILE_ID -H "Authorization: Bearer $ZILAPI_KEY" | jq -r .status)
[ "$FILE_STATUS" != "validating" ] && break
sleep 2
done
echo "$FILE_STATUS" # ready
curl -s https://api.zilapi.com/v1/audio/denoise \
-H "Authorization: Bearer $ZILAPI_KEY" \
-H "Content-Type: application/json" \
-d '{"file": "'"$FILE_ID"'", "model": "zilapi/nr-4.1"}' \
> job.json
JOB_ID=$(jq -r .id job.json) # job_7Hq2xV9mKp4R
while :; do
STATUS=$(curl -s https://api.zilapi.com/v1/jobs/$JOB_ID -H "Authorization: Bearer $ZILAPI_KEY" | jq -r .status)
case "$STATUS" in queued|processing) sleep 5 ;; *) break ;; esac
done
echo "$STATUS" # succeeded
curl -s https://api.zilapi.com/v1/jobs/$JOB_ID/output -H "Authorization: Bearer $ZILAPI_KEY" > output.json
curl -o "$(jq -r .filename output.json)" "$(jq -r .url output.json)"Next steps
- Files: uploads over 100 MB in parts, limits and retention.
- Jobs: the lifecycle, polling guidance and canceling.
- Errors: every error code, what it means and what to do.
- Pricing & billing: per-second billing, the 1-minute minimum and receipts.
- API reference: every endpoint and field, from the OpenAPI spec.