Uploads
How to provide files to the Cleanvoice API.
Try with your API key
Paste your key — all code examples on this page update instantly. Stays in your browser only, never sent anywhere.
Option 1: Public URL
POST https://api.cleanvoice.ai/v2/editsPass the file URL directly in the files array. The API fetches it — no upload step needed.
curl -X POST https://api.cleanvoice.ai/v2/edits \
-H "X-API-Key: $CLEANVOICE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"input": {
"files": ["https://example.com/episode.mp3"],
"config": { "fillers": true }
}
}'<?php
$ch = curl_init('https://api.cleanvoice.ai/v2/edits');
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'X-API-Key: ' . getenv('CLEANVOICE_API_KEY'),
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => json_encode([
'input' => [
'files' => ['https://example.com/episode.mp3'],
'config' => ['fillers' => true],
],
]),
]);
$response = json_decode(curl_exec($ch), true);
curl_close($ch);
echo $response['id'];import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
String body = """
{
"input": {
"files": ["https://example.com/episode.mp3"],
"config": {"fillers": true}
}
}""";
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://api.cleanvoice.ai/v2/edits"))
.header("X-API-Key", System.getenv("CLEANVOICE_API_KEY"))
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(body))
.build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());require 'net/http'
require 'json'
uri = URI('https://api.cleanvoice.ai/v2/edits')
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
request = Net::HTTP::Post.new(uri)
request['X-API-Key'] = ENV['CLEANVOICE_API_KEY']
request['Content-Type'] = 'application/json'
request.body = JSON.generate({
input: {
files: ['https://example.com/episode.mp3'],
config: { fillers: true },
},
})
response = JSON.parse(http.request(request).body)
puts response['id']{ "id": "edit_abc123" }Use the id to poll for the result.
Works with any direct download URL: S3, GCS, Dropbox (?dl=1), Google Drive, or your own CDN.
Option 2: Local file upload
POST https://api.cleanvoice.ai/v2/upload?filename=... → PUT (signed URL) → POST https://api.cleanvoice.ai/v2/editsFor local files, use a three-step process: request a signed URL, PUT your file, then submit the edit.
Step 1 — Request a signed upload URL:
curl -X POST "https://api.cleanvoice.ai/v2/upload?filename=episode.mp3" \
-H "X-API-Key: $CLEANVOICE_API_KEY"Response:
{
"signedUrl": "https://storage.example.com/episode.mp3?signature=..."
}Step 2 — PUT your file to the upload URL:
SIGNED_URL="https://storage.example.com/episode.mp3?signature=..."
curl -X PUT "$SIGNED_URL" \
-H "Content-Type: audio/mpeg" \
--data-binary @/path/to/episode.mp3Response: HTTP 200 OK (empty body)
Step 3 — Submit the edit using the signed URL without its query string:
FILE_URL="${SIGNED_URL%%\?*}"
curl -X POST https://api.cleanvoice.ai/v2/edits \
-H "X-API-Key: $CLEANVOICE_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "input": { "files": ["'"$FILE_URL"'"], "config": { "fillers": true } } }'Response:
{ "id": "edit_abc123" }<?php
$apiKey = getenv('CLEANVOICE_API_KEY');
$filePath = '/path/to/episode.mp3';
// Step 1 — Request a signed upload URL
$ch = curl_init('https://api.cleanvoice.ai/v2/upload?filename=episode.mp3');
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ["X-API-Key: $apiKey"],
]);
$upload = json_decode(curl_exec($ch), true);
curl_close($ch);
// $upload = ["signedUrl" => "..."]
$signedUrl = $upload['signedUrl'];
$fileUrl = strtok($signedUrl, '?');
// Step 2 — PUT the file
$fh = fopen($filePath, 'rb');
$ch = curl_init($signedUrl);
curl_setopt_array($ch, [
CURLOPT_PUT => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ['Content-Type: audio/mpeg'],
CURLOPT_INFILE => $fh,
CURLOPT_INFILESIZE => filesize($filePath),
]);
curl_exec($ch); // HTTP 200 OK
curl_close($ch);
fclose($fh);
// Step 3 — Submit the edit
$ch = curl_init('https://api.cleanvoice.ai/v2/edits');
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
"X-API-Key: $apiKey",
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => json_encode([
'input' => [
'files' => [$fileUrl],
'config' => ['fillers' => true],
],
]),
]);
$response = json_decode(curl_exec($ch), true);
curl_close($ch);
// $response = ["id" => "edit_abc123"]
echo $response['id'];import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.nio.file.Path;
String apiKey = System.getenv("CLEANVOICE_API_KEY");
String filePath = "/path/to/episode.mp3";
HttpClient client = HttpClient.newHttpClient();
// Step 1 — Request a signed upload URL
HttpRequest step1 = HttpRequest.newBuilder()
.uri(URI.create("https://api.cleanvoice.ai/v2/upload?filename=episode.mp3"))
.header("X-API-Key", apiKey)
.POST(HttpRequest.BodyPublishers.noBody())
.build();
String uploadBody = client.send(step1, HttpResponse.BodyHandlers.ofString()).body();
// Parse signedUrl from uploadBody with your JSON library
// uploadBody = {"signedUrl": "..."}
String signedUrl = /* parse signedUrl */;
String fileUrl = signedUrl.split("\\?", 2)[0];
// Step 2 — PUT the file (replace signedUrl with the parsed value)
HttpRequest step2 = HttpRequest.newBuilder()
.uri(URI.create(signedUrl))
.header("Content-Type", "audio/mpeg")
.PUT(HttpRequest.BodyPublishers.ofFile(Path.of(filePath)))
.build();
client.send(step2, HttpResponse.BodyHandlers.discarding()); // HTTP 200 OK
// Step 3 — Submit the edit (replace fileUrl with signedUrl stripped of its query string)
String editBody = String.format("""
{"input":{"files":["%s"],"config":{"fillers":true}}}""", fileUrl);
HttpRequest step3 = HttpRequest.newBuilder()
.uri(URI.create("https://api.cleanvoice.ai/v2/edits"))
.header("X-API-Key", apiKey)
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(editBody))
.build();
HttpResponse<String> response = client.send(step3, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body()); // {"id":"edit_abc123"}require 'net/http'
require 'json'
api_key = ENV['CLEANVOICE_API_KEY']
file_path = '/path/to/episode.mp3'
# Step 1 — Request a signed upload URL
uri = URI('https://api.cleanvoice.ai/v2/upload?filename=episode.mp3')
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
req = Net::HTTP::Post.new(uri)
req['X-API-Key'] = api_key
upload = JSON.parse(http.request(req).body)
# upload = {"signedUrl" => "..."}
signed_url = upload['signedUrl']
file_url = signed_url.split('?').first
# Step 2 — PUT the file
upload_uri = URI(signed_url)
Net::HTTP.start(upload_uri.host, upload_uri.port, use_ssl: true) do |h|
put_req = Net::HTTP::Put.new(upload_uri)
put_req['Content-Type'] = 'audio/mpeg'
put_req.body_stream = File.open(file_path, 'rb')
put_req.content_length = File.size(file_path)
h.request(put_req) # HTTP 200 OK
end
# Step 3 — Submit the edit
edit_req = Net::HTTP::Post.new(URI('https://api.cleanvoice.ai/v2/edits'))
edit_req['X-API-Key'] = api_key
edit_req['Content-Type'] = 'application/json'
edit_req.body = JSON.generate({
input: { files: [file_url], config: { fillers: true } },
})
response = JSON.parse(http.request(edit_req).body)
# response = {"id" => "edit_abc123"}
puts response['id']Uploaded files are automatically deleted 7 days after processing.
Multi-track
For interviews or multi-speaker recordings, pass multiple file URLs and set upload_type to "multitrack":
{
"input": {
"files": [
"https://example.com/host.mp3",
"https://example.com/guest.mp3"
],
"upload_type": "multitrack",
"config": { "fillers": true }
}
}This is multi-track, not batch processing. Multiple files are treated as separate tracks of the same recording (e.g. host mic + guest mic). To process multiple independent files, create a separate edit request for each one.
Supported formats
| Type | Formats |
|---|---|
| Audio | WAV, MP3, OGG, FLAC, M4A, AIFF, AAC |
| Video | MP4, MOV, WebM, AVI, MKV |
Getting public URLs for your files
If you don't have a direct download link yet, here's how to generate one from common storage providers:
- Dropbox — Share the file and change
?dl=0to?dl=1 - Google Drive — Share as "Anyone with the link", then use
https://drive.google.com/uc?export=download&id=YOUR_FILE_ID - S3 — Generate a pre-signed GET URL with your AWS SDK or CLI