Overview#
Files sent through the API are processed on Kleervox servers. The web “Clean a file” tool is different: it still cleans files inside your browser and never uploads them.
Creator includes 2 hours of API cleanup a month. Past that, optional per-minute overage — current price on the pricing page.
Inputs and outputs are deleted 24 hours after the job finishes, unless you save the result to your File Library.
Create a job, then poll with a 45-second long-poll. Retries with an Idempotency-Key never create a second job.
Authentication#
Every request carries an API key as a bearer token: Authorization: Bearer kvk_live_…. Create keys in Dashboard → AI agents & API (up to 10 active keys). A key is shown once; we store only a hash, so keep it in a secret store and revoke it from the dashboard if it leaks — revocation applies on the next request. Keys carry scopes: cleanup (create, read, cancel jobs; also reads usage) and usage:read.
Creating jobs needs an active Creator plan: its included API time is used first, and past it jobs need overage turned on (same dashboard section). Otherwise the API answers 402 BILLING_REQUIRED with the link.
Quickstart#
Requests and responses are JSON. Files never pass through the API itself — they go straight to storage over short-lived presigned URLs.
export KLEERVOX_API_KEY=kvk_live_… # Dashboard → AI agents & API → API keys# 1. Ask for an upload URL (exact size in bytes + the Content-Type you will send)curl -sS -X POST https://api.kleervox.com/api/v1/cleanups/uploads \ -H "Authorization: Bearer $KLEERVOX_API_KEY" \ -H "Content-Type: application/json" \ -d '{"filename":"interview.mp3","sizeBytes":'"$(stat -c%s interview.mp3)"',"contentType":"audio/mpeg"}'# → data.uploadId, data.putUrl, data.headers, data.curlCommand, data.expiresAt (1 h)# 2. PUT the file straight to storage (the file never passes through the API)curl -fsS -X PUT -H "Content-Type: audio/mpeg" -T interview.mp3 "<putUrl>"# 3. Start the cleanup (a retry with the same Idempotency-Key returns the same job)curl -sS -X POST https://api.kleervox.com/api/v1/cleanups \ -H "Authorization: Bearer $KLEERVOX_API_KEY" \ -H "Content-Type: application/json" \ -H "Idempotency-Key: interview-2026-10-20" \ -d '{"uploadId":"<uploadId>","options":{"output":"mp3","strength":1}}'# → data.job.id, data.job.status = "queued"# 4. Wait for it: long-poll up to 45 s per call, repeat until the status is finalcurl -sS "https://api.kleervox.com/api/v1/cleanups/<jobId>?wait=45" -H "Authorization: Bearer $KLEERVOX_API_KEY"# → data.job.status = "done", data.job.downloadUrl (valid 1 h, re-issued on every GET)# 5. Download the cleaned filecurl -fsS -o interview-clean.mp3 "<downloadUrl>"From a public URL instead
If the file is already online (a public link, a presigned cloud-storage URL), skip the upload and pass sourceUrl. It must be a public https:// URL without credentials in it; we download it on our side.
curl -sS -X POST https://api.kleervox.com/api/v1/cleanups \ -H "Authorization: Bearer $KLEERVOX_API_KEY" \ -H "Content-Type: application/json" \ -H "Idempotency-Key: podcast-ep-42" \ -d '{"sourceUrl":"https://example.com/podcast-ep-42.mp4","options":{"keepVideo":true}}'Response envelope
// success{ "success": true, "message": "ok", "data": { "job": { "id": "…", "status": "queued", … } } }// refused request{ "success": false, "message": "API & MCP cleanup is part of the Creator plan (2 h a month included, then per-minute overage). Upgrade to Creator to use Kleervox from an AI agent: …", "data": null, "error_code": "BILLING_REQUIRED" }Endpoints#
All paths are relative to /api/v1/cleanups.
/api/v1/cleanups/uploadsCreate a presigned upload URL (1 h). Body: filename, sizeBytes, contentType.
/api/v1/cleanupsStart a cleanup from exactly one of uploadId, sourceUrl or libraryItemId. Header Idempotency-Key (recommended).
/api/v1/cleanups/:id?wait=0–45Job status, progress, billing and — when done — the download URL. wait long-polls until the job is final.
/api/v1/cleanups/?limit=1–50&status=Your recent jobs, newest first (default 20).
/api/v1/cleanups/:id/cancelCancel a job that has not finished. Cancelled jobs are never billed.
/api/v1/cleanups/usageBilling status, price, minutes and amount this month, spend limit and what remains, file limits.
Request & options#
| Field | Values | Notes |
|---|---|---|
uploadId | id from POST /uploads | After the PUT has finished. Exactly one source per job. |
sourceUrl | public https:// URL | We fetch it (public hosts only, no credentials in the URL, redirects re-checked). |
libraryItemId | File Library item id | Only for accounts that also have a File Library (Pro and Creator plans). |
idempotencyKey | printable ASCII, ≤ 255 | Same as the Idempotency-Key header (the body wins). |
displayName | text, ≤ 200 | Optional label for URL / library jobs. Shown only to you. |
options.output | same · wav · mp3 · m4a | Default same: keep the input’s format (video stays video). |
options.strength | 0–1 | Default 1 (full noise removal). 0 leaves the audio untouched. |
options.keepVideo | true · false | Default true: remux the cleaned audio into the original video. false returns audio only. |
options.saveToLibrary | true · false | Default false. Also copy the result into your File Library (its quota applies; skipped with a reason if it cannot). |
Accepted inputs: .wav .mp3 .m4a .aac .ogg .opus .flac .webm .mp4 .mov .mkv — checked by inspecting the file on our server, not by its extension. Video keeps its picture track untouched; only the audio is cleaned.
Job statuses#
| Status | Meaning |
|---|---|
awaiting_upload | Upload URL issued; waiting for the PUT and the create call. Expires after 1 hour. |
queued | Accepted and waiting for a worker. |
processing | Being fetched, measured, cleaned and encoded. progress.phase / progress.fraction show where. |
done | Finished. downloadUrl is set; the files are deleted 24 hours later. The only billed status. |
failed | Processing failed (see error.code). Not billed. |
cancelled | You cancelled it. Not billed. |
rejected | Refused after inspection — invalid media, too large or long, or over your spend limit. Not billed. |
expired | The upload never arrived within the hour. Not billed. |
done, failed, cancelled, rejected and expired are final. A finished job’s error is { code, message } with a code from the table below.
Error codes#
Refused requests return the envelope with error_code; failed or rejected jobs carry the same codes in job.error.code (“job” below). Codes are stable — branch on them, never on the message. Malformed input returns 400 VALIDATION_ERROR; exceeding a rate limit returns 429.
| Code | HTTP | Meaning |
|---|---|---|
BILLING_REQUIRED | 402 | The job needs API time the account doesn’t have: not on Creator (Free and Pro include none), or Creator’s included time is used and overage is off. The message carries the link. |
PAYMENT_PAST_DUE | 402 | The last invoice failed. Update the card (link in the message); running jobs still finish. |
SPEND_LIMIT_REACHED | job | The file would cross your monthly spend limit, so the job is rejected before any work. |
TOO_MANY_ACTIVE_JOBS | 429 | More than 3 jobs queued or processing. Wait for one to finish. |
TOO_MANY_PENDING_UPLOADS | 429 | 10 uploads already waiting. Finish them or let them expire. |
AGENT_CLEANUP_DISABLED | 503 | The API is temporarily not accepting new jobs. Retry later. |
AGENT_ACCESS_DISABLED | 403 | API access is disabled for this account. Contact support. |
INSUFFICIENT_SCOPE | 403 | The key lacks the scope (cleanup, or usage:read for /usage). |
INVALID_CREDENTIALS | 401 | Missing, unknown, revoked or expired key. |
API_KEY_LIMIT | 409 | Dashboard only: at most 10 active keys. Revoke one first. |
IDEMPOTENCY_KEY_REUSED | 409 | This idempotency key was already used for a different request (other source or options). Use a new key; the same key only replays the identical request. |
RATE_LIMITED | 429 | Too many requests for this key: 30/min to create, upload or cancel, 120/min to read. Retry after Retry-After (MCP: retry_after_seconds). |
VALIDATION_ERROR | 400 | A field is missing or invalid. The message names the field(s) (MCP: _meta fields). |
INVALID_SOURCE_URL | 400 | sourceUrl is not a public https:// URL, or contains credentials. |
SOURCE_FETCH_FAILED | job | We could not download the sourceUrl (or library file). |
UPLOAD_NOT_FOUND | 409 | The create call came before the PUT finished. PUT the file, then retry. |
UPLOAD_EXPIRED | 410 | The 1-hour upload window passed. Create a new upload. |
UPLOAD_SIZE_MISMATCH | 400 | The uploaded object is not the declared sizeBytes. Upload again. |
LIBRARY_ITEM_NOT_FOUND | 404 | libraryItemId is not one of your ready File Library files. |
INVALID_MEDIA | job | Corrupt file, no audio stream, or an unsupported container. |
FILE_TOO_LARGE | 413 / job | Larger than 2 GiB. |
TOO_LONG | 400 / job | Longer than 3 hours (measured on our server). |
WORKER_CRASH | job | Processing was interrupted 3 times. Not billed — retry the job. |
TIMEOUT | job | Processing exceeded the per-job time limit. Not billed. |
VERIFY_FAILED | job | The encoded output failed our quality check. Not billed. |
CANCELLED | job | You cancelled the job. |
EXPIRED | job | The upload never arrived. |
STORAGE_UNAVAILABLE | 503 | File storage is unavailable. Retry later. |
NOT_FOUND | 404 | Unknown job id (or not yours). |
INTERNAL_ERROR | 500 / job | Something unexpected failed on our side. Not billed — retry. |
Limits#
| Limit | Value |
|---|---|
| File size | 2 GiB |
| Duration | 3 hours |
| Jobs queued or processing at once | 3 |
| Uploads waiting at once | 10 |
| Upload URL / pending upload lifetime | 60 minutes |
| Download URL lifetime | 60 minutes (a fresh one on every GET) |
| Long-poll (wait) | up to 45 seconds per request |
| Rate limits per key | 30/min for uploads, creates and cancels; 120/min for reads |
| Active API keys | 10 |
Billing#
- Creator’s included 2 hours a month are used first. Past them, overage is billed on the input audio duration measured by our server, per second, priced per minute. Video is billed on its audio duration.
- Minimum 30 seconds per job.
- Only
donejobs are billed. Failed, rejected, cancelled and expired jobs cost nothing; idempotent retries never bill twice. - A monthly spend limit (default $25, adjustable in the dashboard) caps the total: a job that would cross it is rejected with
SPEND_LIMIT_REACHEDbefore any work. New accounts are capped at $25 until the first invoice is paid. - Invoiced monthly in arrears by Stripe.
GET /usageshows this month’s minutes, amount and remaining limit.
API time is part of the Creator plan: it includes 2 hours of API cleanup a month, used first. Once it runs out, further jobs need Creator overage turned on — the same overage that covers web File Cleanup beyond Creator’s hours. Free and Pro include no API time, and there is no separate pay-as-you-go plan.
Retention & privacy#
Inputs and outputs are deleted 24 hours after a job finishes (with a storage-level rule as a backstop); job records without the file are kept 90 days. Files are processed automatically, never used for training, and filenames and URLs are not written to our logs. Only the host of a sourceUrl is stored, never the full URL.
MCP server for AI agents#
Connect Kleervox to Claude, ChatGPT, Cursor or any MCP client. It exposes the same jobs as the REST API.
Endpoint: https://mcp.kleervox.com/mcp (Streamable HTTP; API key or OAuth).
https://mcp.kleervox.com/mcpclaude mcp add --transport http kleervox \ https://mcp.kleervox.com/mcp \ --header "Authorization: Bearer <YOUR_API_KEY>"{ "mcpServers": { "kleervox": { "url": "https://mcp.kleervox.com/mcp", "headers": { "Authorization": "Bearer <YOUR_API_KEY>" } } }}| Tool | What it does |
|---|---|
clean_audio | Start a cleanup from source_url, upload_id or library_item_id, with output_format, strength, keep_video, save_to_library and idempotency_key. |
create_upload | Get a presigned upload URL and a ready-to-run curl command for a local file. |
get_cleanup | Status and progress (with wait_seconds long-poll); the download link when done. |
list_cleanups | Your recent jobs. |
cancel_cleanup | Cancel a running job (never billed). |
get_usage | Billing status, price, this month’s minutes and spend, limits. |
FAQ#
01Does the Kleervox API upload my file?
Yes — unlike the Kleervox web tool, which cleans files inside your browser, the API cleans files on Kleervox servers. The file goes straight to private storage through a presigned URL, is processed automatically, and the input and output are deleted 24 hours after the job finishes.
02How is the API billed?
The API is part of the Creator plan, which includes 2 hours of API cleanup a month. Past that, a Creator subscriber can turn on overage: per minute of input audio, measured by our server and billed per second. Only jobs that finish successfully are billed; failed, rejected, cancelled and expired jobs cost nothing. A monthly spend limit you control caps the total, and overage is invoiced monthly in arrears. The same overage also covers web File Cleanup beyond Creator’s hours. Free and Pro include no API time.
03Can I use it from Claude, Cursor or other AI agents?
Yes. Connect the Kleervox MCP server, or give a coding agent an API key and the REST endpoints on this page.
Ready to build?
Create a key in your dashboard and run the quickstart.
