Retrieve an Edit
Poll for the status and result of an edit job.
Endpoint
GET /v2/edits/{edit_id}Try with your API key
Paste your key — all code examples on this page update instantly. Stays in your browser only, never sent anywhere.
Single request
curl https://api.cleanvoice.ai/v2/edits/edit_abc123 \
-H "X-API-Key: $CLEANVOICE_API_KEY"<?php
$editId = 'edit_abc123';
$ch = curl_init("https://api.cleanvoice.ai/v2/edits/$editId");
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ['X-API-Key: ' . getenv('CLEANVOICE_API_KEY')],
]);
$response = json_decode(curl_exec($ch), true);
curl_close($ch);
print_r($response);import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
String editId = "edit_abc123";
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://api.cleanvoice.ai/v2/edits/" + editId))
.header("X-API-Key", System.getenv("CLEANVOICE_API_KEY"))
.GET()
.build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());require 'net/http'
require 'json'
edit_id = 'edit_abc123'
uri = URI("https://api.cleanvoice.ai/v2/edits/#{edit_id}")
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
request = Net::HTTP::Get.new(uri)
request['X-API-Key'] = ENV['CLEANVOICE_API_KEY']
response = JSON.parse(http.request(request).body)
puts responseWhile processing (PENDING, STARTED, or one of the worker phase statuses):
{
"task_id": "edit_abc123",
"status": "PENDING"
}On success:
{
"task_id": "edit_abc123",
"status": "SUCCESS",
"result": {
"download_url": "https://cdn.cleanvoice.ai/cleaned/edit_abc123.mp3",
"transcription": null,
"summarization": null,
"social_content": []
}
}On failure:
{
"task_id": "edit_abc123",
"status": "FAILURE"
}Anonymized live examples
These examples were captured from real GET /v2/edits/{id} responses and then shortened and anonymized for documentation. URLs, transcript text, summaries, and social copy are intentionally trimmed.
Success with summarization
{
"task_id": "edit_abc123",
"status": "SUCCESS",
"result": {
"video": false,
"filename": "anonymized_clean.wav",
"download_url": "https://storage.example.com/uploads/.../anonymized_clean.wav?...",
"summarization": {
"title": "[Anonymized title]",
"summary": "[Anonymized summary text about avoiding sticky foods and protecting braces.]",
"chapters": [
{
"start": 0.11,
"title": "[Anonymized chapter 1]"
},
{
"start": 17.68,
"title": "[Anonymized chapter 2]"
}
],
"summaries": [
"[Anonymized long-form summary text.]"
],
"key_learnings": "- [Anonymized takeaway 1]\n- [Anonymized takeaway 2]",
"summary_of_summary": "[Anonymized short summary.]",
"episode_description": "# [Anonymized episode description]\n\n[Anonymized markdown body.]"
},
"transcription": {
"paragraphs": [
{
"id": 0,
"start": 0.11,
"end": 25.83,
"text": "[Anonymized transcript paragraph 1.]"
},
{
"id": 1,
"start": 26.63,
"end": 29.89,
"text": "[Anonymized transcript paragraph 2.]"
}
],
"transcription": {
"words": [
{
"id": 0,
"start": 0.11,
"end": 0.69,
"text": "[word]"
}
],
"paragraphs": [
{
"id": 0,
"start": 0.11,
"end": 30.14,
"speaker": "SPEAKER_00"
}
]
}
},
"social_content": [],
"merged_audio_url": [],
"timestamps_markers_urls": [],
"waveform_result": []
}
}Success with social content
{
"task_id": "edit_def456",
"status": "SUCCESS",
"result": {
"video": false,
"filename": "anonymized_clean.wav",
"download_url": "https://storage.example.com/uploads/.../anonymized_clean.wav?...",
"summarization": {
"title": "Protecting Your Braces: Why Hard and Sticky Foods Can Break Your Brackets",
"summary": "The speaker advises orthodontic patients to avoid hard and sticky foods like caramel and taffy, because they can damage brackets and extend treatment time."
},
"transcription": {
"paragraphs": [
{
"id": 0,
"start": 0.11,
"end": 25.83,
"text": "Stuff like caramel, taffy, you're also avoiding... it's not a super emergency... just call us so we know something is broken."
}
]
},
"social_content": {
"newsletter": "# Don't Let Your Braces Break-Here's What You Need to Know\n\nHello [Subscriber's Name],\n\nIn this episode we break down one of orthodontics' most common problems: broken brackets.\n\nHard candies, caramel, and taffy can damage brackets and delay treatment.\n\n...",
"twitter_thread": "<tweet>\n1/ Your braces can survive more than you think, but one mistake keeps adding months to your treatment.\n</tweet>\n\n<tweet>\n2/ Hard and sticky foods like caramel and taffy are bracket killers. A broken bracket isn't usually an emergency, but your orthodontist still needs to know.\n</tweet>\n\n...",
"linkedin": "Here's what most people miss about orthodontic care: a broken bracket isn't just about the inconvenience-it's about the ripple effects on your treatment timeline.\n\nOne broken bracket is manageable. Repeated breakage adds months to treatment.\n\n..."
},
"merged_audio_url": [],
"timestamps_markers_urls": [],
"waveform_result": []
}
}Status values
| Status | Meaning |
|---|---|
PENDING | Job is queued and not yet started |
STARTED | Job is actively being processed |
PREPROCESSING | Input analysis and setup is in progress |
CLASSIFICATION | Cleanvoice is classifying events in the media |
EDITING | The main edit pass is running |
POSTPROCESSING | Final cleanup and result assembly is running |
EXPORT | Output files are being written |
SUCCESS | Job completed — result.download_url contains the cleaned audio |
FAILURE | Job failed — inspect the returned payload for error details |
RETRY | Job encountered a transient error and is being retried |
A recent live social_content=true run stayed in POSTPROCESSING across multiple polls before finally returning SUCCESS. Do not treat POSTPROCESSING as a completed state.
Polling loop
#!/bin/bash
EDIT_ID="edit_abc123"
sleep 30 # wait before first poll
while true; do
RESPONSE=$(curl -s "https://api.cleanvoice.ai/v2/edits/$EDIT_ID" \
-H "X-API-Key: $CLEANVOICE_API_KEY")
STATUS=$(echo "$RESPONSE" | python3 -c "import sys,json; print(json.load(sys.stdin)['status'])")
echo "Status: $STATUS"
if [ "$STATUS" = "SUCCESS" ]; then
URL=$(echo "$RESPONSE" | python3 -c "import sys,json; print(json.load(sys.stdin)['result']['download_url'])")
echo "Download URL: $URL"
break
elif [ "$STATUS" = "FAILURE" ]; then
echo "Edit failed"
echo "$RESPONSE"
break
fi
sleep 10
done<?php
$editId = 'edit_abc123';
$apiKey = getenv('CLEANVOICE_API_KEY');
sleep(30); // wait before first poll
while (true) {
$ch = curl_init("https://api.cleanvoice.ai/v2/edits/$editId");
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ["X-API-Key: $apiKey"],
]);
$data = json_decode(curl_exec($ch), true);
curl_close($ch);
echo 'Status: ' . $data['status'] . PHP_EOL;
if ($data['status'] === 'SUCCESS') {
echo 'Download URL: ' . $data['result']['download_url'] . PHP_EOL;
break;
} elseif ($data['status'] === 'FAILURE') {
echo 'Edit failed' . PHP_EOL;
break;
}
sleep(10);
}import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
String apiKey = System.getenv("CLEANVOICE_API_KEY");
String editId = "edit_abc123";
HttpClient client = HttpClient.newHttpClient();
Thread.sleep(30_000); // wait before first poll
while (true) {
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://api.cleanvoice.ai/v2/edits/" + editId))
.header("X-API-Key", apiKey)
.GET()
.build();
String body = client.send(request, HttpResponse.BodyHandlers.ofString()).body();
System.out.println(body);
if (body.contains("\"SUCCESS\"")) {
// extract download_url with your preferred JSON library
break;
} else if (body.contains("\"FAILURE\"")) {
break;
}
Thread.sleep(10_000);
}require 'net/http'
require 'json'
edit_id = 'edit_abc123'
api_key = ENV['CLEANVOICE_API_KEY']
uri = URI("https://api.cleanvoice.ai/v2/edits/#{edit_id}")
sleep 30 # wait before first poll
loop do
request = Net::HTTP::Get.new(uri)
request['X-API-Key'] = api_key
data = Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|
JSON.parse(http.request(request).body)
end
puts "Status: #{data['status']}"
if data['status'] == 'SUCCESS'
puts "Download URL: #{data.dig('result', 'download_url')}"
break
elsif data['status'] == 'FAILURE'
puts 'Edit failed'
break
end
sleep 10
endFinal response when the loop exits successfully:
{
"task_id": "edit_abc123",
"status": "SUCCESS",
"result": {
"download_url": "https://cdn.cleanvoice.ai/cleaned/edit_abc123.mp3",
"transcription": null,
"summarization": null,
"social_content": []
}
}result.download_url is a time-limited link to your cleaned audio file. Download it promptly — the link expires after a short period.
If you enabled transcription, summarize, or social_content, the raw response uses result.transcription, result.summarization, and result.social_content.
Wait at least 30 seconds after submitting before your first poll. After that, poll every 10 seconds. Polling more frequently than every 5 seconds is not recommended.