Process private audio from your own systems.
Upload directly to private object storage, process individual files or manifests of up to 50,000 items, and use the same prepaid balance as your CleanWave web account.
curl https://api.cleanwaveaudio.com/v1/projects \
-H "Authorization: Bearer $CLEANWAVE_API_KEY"Authentication
Server integrations use a generated API key. Keys inherit the web account’s projects and credit balance. Never expose a key in browser or mobile code.
Authorization: Bearer cw_live_...
Content-Type: application/jsonRequest a private upload URL
The API creates the project record and returns a short-lived R2 upload URL. Audio bytes do not pass through the CleanWave API service.
curl -X POST https://api.cleanwaveaudio.com/v1/uploads \
-H "Authorization: Bearer $CLEANWAVE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"original_filename": "interview.wav",
"content_type": "audio/wav",
"claimed_size_bytes": 8451021
}'Upload and finalize
Use the returned URL without your CleanWave key. Send every header from the response’s headers object exactly as returned. A successful finalize validates size, container, stream, duration, channels and sample rate.
curl -X PUT "$UPLOAD_URL" \
-H "Content-Type: $UPLOAD_CONTENT_TYPE" \
--upload-file interview.wav
curl -X POST https://api.cleanwaveaudio.com/v1/uploads/$PROJECT_ID/finalize \
-H "Authorization: Bearer $CLEANWAVE_API_KEY"Start asynchronous analysis
A successful request returns 202 Accepted. Credits are reserved from the same balance used by the web application. Poll the project until it reachesready_for_review or failed.
curl -X POST https://api.cleanwaveaudio.com/v1/projects/$PROJECT_ID/analyze \
-H "Authorization: Bearer $CLEANWAVE_API_KEY"
curl https://api.cleanwaveaudio.com/v1/projects/$PROJECT_ID \
-H "Authorization: Bearer $CLEANWAVE_API_KEY"Review suggestions and export
Analysis returns a transcript, PII detections and suggested redactions. Update the redactions if necessary, then start the asynchronous WAV export. Poll until the project reaches completed and download_ready is true.
curl -X PUT https://api.cleanwaveaudio.com/v1/projects/$PROJECT_ID/redactions \
-H "Authorization: Bearer $CLEANWAVE_API_KEY" \
-H "Content-Type: application/json" \
-d '{"redactions":[{
"entity_type":"phone_number",
"text":"060123456",
"start_time":12.4,
"end_time":14.1,
"mode":"silence",
"review_status":"accepted",
"detection_ids":[]
}]}'
curl -X POST https://api.cleanwaveaudio.com/v1/projects/$PROJECT_ID/export \
-H "Authorization: Bearer $CLEANWAVE_API_KEY" \
-H "Content-Type: application/json" \
-d '{"mode":"silence"}'Download, verify and delete
Save and verify the result before deletion. API downloads do not delete a project automatically. After verification, delete the project to remove its original, output, temporary R2 objects and retained metadata immediately.
curl -L https://api.cleanwaveaudio.com/v1/projects/$PROJECT_ID/download \
-H "Authorization: Bearer $CLEANWAVE_API_KEY" \
--output interview-anonymized.wav
curl -X DELETE https://api.cleanwaveaudio.com/v1/projects/$PROJECT_ID \
-H "Authorization: Bearer $CLEANWAVE_API_KEY"Stream a manifest of up to 50,000 files
Open an empty batch, append descriptors in fragments of 500–1,000, close the manifest, request bounded upload windows, upload directly to R2, then callprocess once. Every manifest request needs a stable idempotency key.
curl -X POST https://api.cleanwaveaudio.com/v1/batches \
-H "Authorization: Bearer $CLEANWAVE_API_KEY" \
-H "Idempotency-Key: import-2026-09-manifest" \
-H "Content-Type: application/json" \
-d '{"name":"September import","expected_file_count":50000}'
curl -X POST https://api.cleanwaveaudio.com/v1/batches/$BATCH_ID/items \
-H "Authorization: Bearer $CLEANWAVE_API_KEY" \
-H "Idempotency-Key: import-2026-09-chunk-0001" \
-H "Content-Type: application/json" \
-d '{"files":[{
"client_reference":"call-000001",
"original_filename":"call-000001.wav",
"content_type":"audio/wav",
"claimed_size_bytes":8451021
}]}'
curl -X POST https://api.cleanwaveaudio.com/v1/batches/$BATCH_ID/finalize \
-H "Authorization: Bearer $CLEANWAVE_API_KEY"
curl "https://api.cleanwaveaudio.com/v1/batches/$BATCH_ID/uploads?limit=100&offset=0" \
-H "Authorization: Bearer $CLEANWAVE_API_KEY"
# Upload every item with its returned method, URL and headers.
curl -X PUT "$UPLOAD_URL" \
-H "Content-Type: $UPLOAD_CONTENT_TYPE" \
--upload-file call-000001.wav
curl -X POST https://api.cleanwaveaudio.com/v1/batches/$BATCH_ID/process \
-H "Authorization: Bearer $CLEANWAVE_API_KEY"Batch workers validate uploaded objects before analysis, so individual/uploads/{project_id}/finalize calls are optional for normal batch processing. Use /retry only after a terminal failed state and/cancel to stop work that has not begun.
Complete endpoint reference
The reference below covers the endpoints available to customer integrations. Administrator routes, signed provider callbacks and OIDC-protected scheduler routes are intentionally excluded.
Base URL: https://api.cleanwaveaudio.com. Unless an endpoint is explicitly marked public or browser-only, authenticate it withAuthorization: Bearer $CLEANWAVE_API_KEY.
Service status and configuration
/healthProcess liveness. Public; returns {"status":"ok"}.
/readyChecks PostgreSQL, R2, billing, FFmpeg and FFprobe. Public; returns 503 when a dependency is unavailable.
/v1/auth/configPublic browser helper that reports whether Google sign-in is enabled.
/v1/auth/google/start?next=/appBrowser-only Google OAuth entry point. Sets a short-lived state cookie and redirects to Google.
/v1/auth/google/callbackBrowser-only OAuth callback used by Google. Validates state, creates the secure session cookie and redirects back to the application.
/v1/configAuthenticated account-facing limits and feature flags, including file, batch, retention, billing and zero-access settings.
/v1/auth/meReturns the current identity and authentication method for a browser session or API key.
/v1/auth/logoutBrowser-only. Clears the web session. Add ?redirect=true to return to the public site.
API key management
Key management requires an authenticated Google web session; a machine key cannot create another key. expires_in_days accepts 1–365 ornull for no expiration.
/v1/api-keysLists active keys using only their ID, name, prefix, creation, expiration and last-use timestamps.
/v1/api-keysCreates a key from {"name":"Production import","expires_in_days":90}. The full cw_live_… secret appears only in this response.
/v1/api-keys/{key_id}Immediately invalidates the key and removes it from the active-key interface.
Balance and checkout
One credit represents one minute of analyzed audio. Web and API processing draw from the same account balance.
/v1/billing/balanceReturns available, reserved and debt values in seconds and credits.
/v1/billing/checkoutCreates a Lemon Squeezy checkout. Requires credits, accepted legal terms, the current legal version and immediate-service consent.
{
"credits": 60,
"terms_accepted": true,
"legal_terms_version": "2026-08-13-v2",
"immediate_service_requested": true
}Direct upload lifecycle
/v1/uploadsCreates one project and returns a presigned R2 PUT request. JSON fields are described below.
/v1/uploads/{project_id}/finalizeValidates an uploaded object and starts its retention clock. Zero-access uploads additionally submit their encryption envelope here.
/v1/projectsLegacy multipart upload through the API service. Use only for small or compatibility flows; direct R2 upload is preferred.
original_filenameRequired filename ending in .wav, .mp3 or .m4a.
content_typeRequired audio MIME type. Use the returned signed header unchanged.
claimed_size_bytesRequired positive byte count, checked again after upload.
redaction_policyOptional enabled categories and a custom instruction of at most 1,000 characters.
folder_id / folder_name / relative_pathOptional folder metadata; if one is supplied, all three are required.
zero_accessOptional encrypted-browser workflow. Ordinary server integrations should leave it false.
Batch manifests and processing
/v1/batchesOpens an idempotent manifest. Accepts name, optional expected_file_count and optionally up to 1,000 initial file descriptors.
/v1/batches/{batch_id}/itemsAtomically appends 1–1,000 descriptors. Each fragment requires its own stable Idempotency-Key.
/v1/batches/{batch_id}/finalizeCloses intake. The item total must match expected_file_count when it was declared.
/v1/batches/{batch_id}Returns aggregate counts and a page of items. Query: offset ≥ 0, limit 1–500.
/v1/batches/{batch_id}/uploadsReturns bounded, short-lived upload requests for a page of items still uploading.
/v1/batches/{batch_id}/processQueues the complete manifest and returns 202. Calling it again while queued or processing does not duplicate the run.
/v1/batches/{batch_id}/retryQueues only failed items from a failed or partially_failed batch.
/v1/batches/{batch_id}/cancelCancels work that has not started and marks the batch cancelled.
There is currently no customer endpoint to list all batches or delete an entire batch. Delete retained files individually with the project DELETE endpoint.
Projects, review, export and delivery
/v1/projectsLists retained projects owned by the authenticated account.
/v1/projects/{project_id}Returns metadata, progress, transcript, detections, redactions, error and download readiness.
/v1/projects/{project_id}/analyzeQueues asynchronous analysis and reserves credits. Returns 202.
/v1/projects/{project_id}/policyReplaces the redaction policy. A changed policy invalidates prior analysis and export, requiring re-analysis.
/v1/projects/{project_id}/redactionsReplaces the complete reviewed redaction list after analysis. A changed list invalidates an existing export.
/v1/projects/{project_id}/exportQueues WAV generation. Optional body: {"mode":"silence"} or {"mode":"beep"}.
/v1/projects/{project_id}/downloadDownloads the completed anonymized WAV. It does not delete the project automatically.
/v1/projects/{project_id}/audioStreams the retained original for authenticated preview.
/v1/downloads/archive?project_ids=…Builds a temporary ZIP from up to 20 completed projects. Repeat project_ids for multiple files.
/v1/projects/{project_id}Immediately removes the project’s entire R2 prefix and retained metadata. Call after a verified download.
Zero-access confidential processing
These endpoints support CleanWave’s encrypted browser workflow. They are not required for ordinary server-to-server batch integrations and require the documented cryptographic envelopes and an attested confidential worker.
/v1/projects/{project_id}/confidential-bindBinds encrypted upload metadata to an attested worker session.
/v1/projects/{project_id}/confidential-ticketIssues a signed, short-lived worker job ticket.
/v1/projects/{project_id}/confidential-reviewReturns a short-lived encrypted review download and its envelope.
/v1/projects/{project_id}/confidential-originalReturns a short-lived encrypted-original download and its envelope.
/v1/confidential/sessionStarts an attested confidential session for a project.
/v1/confidential/status?project_id=…Returns worker startup state and queue position.
/v1/confidential/processRelays an encrypted processing request to the confidential worker.
States and response fields
Project states: uploading, uploaded, analyzing, ready_for_review, exporting, completed, failed, cancelled.
Batch states: creating, ready, queued, processing, completed, partially_failed, failed, cancelled.
Review states: suggested, accepted, rejected. Redaction modes: silence and beep.
{
"id": "project UUID",
"original_filename": "interview.wav",
"file_size_bytes": 8451021,
"duration_seconds": 584.2,
"status": "ready_for_review",
"progress_percent": 100,
"zero_access": false,
"redaction_policy": {"enabled_categories": [], "custom_instruction": ""},
"transcript": {"language": "ro", "text": "…", "words": []},
"detections": [],
"redactions": [],
"download_ready": false,
"error": null,
"created_at": "ISO-8601",
"updated_at": "ISO-8601"
}Errors, idempotency and retries
400 / 422Malformed request or invalid field. Correct the request; do not retry unchanged.
401 / 403Missing, invalid, expired or unauthorized credential.
402Insufficient credits. Purchase credits before retrying analysis.
404Resource absent or owned by another account.
409State conflict, reused idempotency key with different content, or operation already active.
413 / 415File too large or unsupported/invalid audio.
425 / 429Capacity is starting or rate-limited. Respect Retry-After and use exponential backoff with jitter.
500 / 503Temporary server or dependency failure. Retry idempotent requests with bounded backoff.
Error bodies contain a safe detail and usually arequest_id. Preserve that ID when contacting support. Replaying an identical batch or fragment idempotency key is safe; changing the payload for an existing key returns 409.
Limits, polling and retention
- Files: WAV, MP3 and M4A; maximum 100 MB and 60 minutes per file.
- Audio: one audio stream, at most two channels, sample rate between 8 kHz and 96 kHz.
- Batches: maximum 50,000 files; fragments up to 1,000; upload/status pages up to 500.
- Archives: maximum 20 completed projects per ZIP.
- Polling: use bounded exponential backoff; do not poll every file continuously.
- Retention: validated uploads are removed automatically within 24 hours; production targets 23 hours plus scheduled cleanup.
- Immediate deletion: call
DELETE /v1/projects/{id}after verifying the download. - Detection: automated PII suggestions can miss content; human review remains recommended for sensitive use cases.
Presigned R2 URLs are short-lived and must be regenerated through the upload window endpoint after expiry. URL expiry does not delete an object already uploaded. All R2 URLs are secrets for their short lifetime and must not be logged or shared.
Operational rules
- Keep API keys and presigned URLs out of client-side code and logs.
- Retry a manifest fragment only with its unchanged idempotency key and payload.
- Verify downloads, then delete projects to minimize retained data.
- Respect Retry-After and bound upload, polling and processing concurrency.
- Human review remains recommended for sensitive or high-risk recordings.