Jobs API
Monitor your processing jobs and download results through the Developer Portal, webhooks, or the download-result API.
Monitoring Jobs
There are two ways to monitor your jobs:
1. Webhooks (Recommended)
Configure a webhook URL in your Settings to receive real-time notifications when job status changes. See the Webhooks Guide for details.
2. Developer Portal
View all your jobs and their status in the Jobs page of the Developer Portal.
Job Statuses
Jobs progress through different statuses depending on the API product:
Transcribe Workflow
- created: Job queued for processing
- transcribing: Transcription in progress
- transcribed: Transcription complete ✓
Translate Workflow
- created: Job queued for processing
- transcribing: Transcription in progress (if media file provided)
- transcribed: Transcription complete
- translating: Translation in progress
- translated: Translation complete ✓
Voiceover Workflow
- created: Job queued for processing
- dubbing: Voice-over generation in progress
- dubbed: Voice-over complete
- merging: Merging audio with video
- merged: Merge complete ✓
Dub Workflow
- created: Job queued for processing
- transcribing: Transcription in progress
- transcribed: Transcription complete
- translating: Translation in progress
- translated: Translation complete
- dubbing: Voice-over generation in progress
- dubbed: Voice-over complete
- merging: Merging audio with video
- merged: Merge complete ✓
Failed States (All Workflows)
- failed: Job failed due to processing error
- rejected: Job rejected (insufficient balance, invalid input, file too large, etc.)
Webhook Events
When you configure a webhook, you'll receive notifications for these events:
- job.created: Job has been created (status:
created) - job.processing: Job is being processed (intermediate statuses like
transcribing,translating,dubbing,merging) - job.completed: Job finished successfully (status:
transcribedfor transcribe,translatedfor translate,mergedfor voiceover/dub) - job.failed: Job failed or was rejected (status:
failedorrejected)
Downloading Results
Once a job completes successfully, you can download the output files using the download-result endpoint.
Endpoint
POST /v1/jobs/{jobId}/download-result
Authentication
API Key (Bearer token)
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| jobId | string | Yes | The job identifier |
Request Body
{
"expirationSeconds": 3600
}| Parameter | Type | Required | Description |
|---|---|---|---|
| expirationSeconds | number | No | URL expiration time in seconds. Default: 3600 (1 hour). Min: 60, Max: 604800 (7 days) |
Response - Success (200 OK)
For Transcribe workflow (single file):
{
"jobId": "job_xyz789",
"apiProduct": "transcribe",
"expiresAt": "2025-12-07T14:30:00Z",
"outputs": [
{
"url": "https://s3.amazonaws.com/bucket/path.srt?X-Amz-Algorithm=...",
"expiresAt": "2025-12-07T14:30:00Z",
"sizeBytes": 12458
}
]
}For Translate workflow (multiple context files):
{
"jobId": "job_xyz789",
"apiProduct": "translate",
"expiresAt": "2025-12-07T14:30:00Z",
"outputs": [
{
"outputIndex": 0,
"url": "https://s3.amazonaws.com/bucket/path_0.srt?X-Amz-Algorithm=...",
"expiresAt": "2025-12-07T14:30:00Z",
"sizeBytes": 8234
},
{
"outputIndex": 1,
"url": "https://s3.amazonaws.com/bucket/path_1.srt?X-Amz-Algorithm=...",
"expiresAt": "2025-12-07T14:30:00Z",
"sizeBytes": 7891
}
]
}For Voiceover and Dubbing workflows (single video):
{
"jobId": "job_xyz789",
"apiProduct": "voiceover",
"expiresAt": "2025-12-07T14:30:00Z",
"outputs": [
{
"url": "https://s3.amazonaws.com/bucket/path.mp4?X-Amz-Algorithm=...",
"expiresAt": "2025-12-07T14:30:00Z",
"sizeBytes": 45678901
}
]
}Response - Error Cases
Job Not Found (404):
{
"error": {
"code": "RESOURCE_NOT_FOUND",
"message": "Job not found"
}
}Job Not Completed (400):
{
"error": {
"code": "INVALID_REQUEST",
"message": "Job is not completed yet. Current status: processing"
}
}Job Failed (400):
{
"error": {
"code": "INVALID_REQUEST",
"message": "Job failed. No output files available."
}
}Invalid Expiration (400):
{
"error": {
"code": "INVALID_REQUEST",
"message": "Expiration time must be between 60 and 604800 seconds"
}
}Code Examples
cURL
curl -X POST https://api.rednerapp.com/v1/jobs/job_abc123/download-result \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"expirationSeconds": 3600
}'Python
import requests
url = "https://api.rednerapp.com/v1/jobs/job_abc123/download-result"
headers = {
"Authorization": "Bearer YOUR_API_KEY",
"Content-Type": "application/json"
}
payload = {
"expirationSeconds": 3600
}
response = requests.post(url, json=payload, headers=headers)
result = response.json()
# Download the first output file
if result.get("outputs"):
download_url = result["outputs"][0]["url"]
file_response = requests.get(download_url)
with open("output.srt", "wb") as f:
f.write(file_response.content)
print(f"Downloaded {result['outputs'][0]['sizeBytes']} bytes")JavaScript
const response = await fetch(
'https://api.rednerapp.com/v1/jobs/job_abc123/download-result',
{
method: 'POST',
headers: {
'Authorization': 'Bearer YOUR_API_KEY',
'Content-Type': 'application/json'
},
body: JSON.stringify({
expirationSeconds: 3600
})
}
);
const result = await response.json();
// Download the first output file
if (result.outputs && result.outputs.length > 0) {
const downloadUrl = result.outputs[0].url;
const fileResponse = await fetch(downloadUrl);
const blob = await fileResponse.blob();
// Save file in browser
const link = document.createElement('a');
link.href = URL.createObjectURL(blob);
link.download = 'output.srt';
link.click();
console.log(`Downloaded ${result.outputs[0].sizeBytes} bytes`);
}Java
HttpClient client = HttpClient.newHttpClient();
String json = "{\"expirationSeconds\":3600}";
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://api.rednerapp.com/v1/jobs/job_abc123/download-result"))
.header("Authorization", "Bearer YOUR_API_KEY")
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(json))
.build();
HttpResponse<String> response = client.send(
request,
HttpResponse.BodyHandlers.ofString()
);
// Parse JSON response
JsonObject result = JsonParser.parseString(response.body()).getAsJsonObject();
JsonArray outputs = result.getAsJsonArray("outputs");
if (outputs.size() > 0) {
String downloadUrl = outputs.get(0).getAsJsonObject().get("url").getAsString();
// Download file
HttpRequest downloadRequest = HttpRequest.newBuilder()
.uri(URI.create(downloadUrl))
.GET()
.build();
HttpResponse<Path> fileResponse = client.send(
downloadRequest,
HttpResponse.BodyHandlers.ofFile(Paths.get("output.srt"))
);
System.out.println("Downloaded to: " + fileResponse.body());
}Output Files by Workflow
| Workflow | API Product | Output Files | Description |
|---|---|---|---|
| Transcribe | transcribe | 1 SRT file | Single consolidated transcription |
| Translate | translate | N SRT files | Multiple context files (N varies by input length) |
| Voiceover | voiceover | 1 video file | Final merged video with voice-over |
| Full Dubbing | dub | 1 video file | Final merged video with dubbing |
Webhook Integration
When a job completes successfully, the webhook notification automatically includes presigned URLs for downloading results. These URLs expire after 1 hour.
Webhook Payload Example:
{
"event": "job.completed",
"timestamp": "2025-12-07T12:34:56Z",
"data": {
"jobId": "job_abc123",
"status": "transcribed",
"apiProduct": "transcribe",
"duration": 125.5,
"cost": 2.51,
"outputs": [
{
"url": "https://s3.amazonaws.com/bucket/path.srt?X-Amz-Algorithm=...",
"expiresAt": "2025-12-07T13:34:56Z",
"sizeBytes": 12458
}
]
}
}Note: The status field shows the actual processing status (transcribed for transcribe jobs, translated for translate jobs, merged for voiceover/dub jobs), while the event field shows the logical event type (job.completed).
If webhook URLs expire, you can always request new ones using the download-result endpoint.
Best Practices
URL Expiration
- Presigned URLs are temporary and expire after the specified time
- Default expiration is 1 hour (3600 seconds)
- Maximum expiration is 7 days (604800 seconds)
- Download files before URLs expire
- Request new URLs if needed using the download-result endpoint
Multiple Output Files
For translation jobs that produce multiple context files:
- Each output has an
outputIndex(0, 1, 2, etc.) - Download all files to get the complete translation
- Files are ordered sequentially
Error Handling
Always check the job status before requesting download URLs:
- Only completed jobs have downloadable outputs
- Failed or rejected jobs return an error
- Jobs still processing return an error with current status
Security
- Presigned URLs are publicly accessible but time-limited
- Anyone with the URL can download the file before expiration
- Store URLs securely if you need to share them