Documentation

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: transcribed for transcribe, translated for translate, merged for voiceover/dub)
  • job.failed: Job failed or was rejected (status: failed or rejected)

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

ParameterTypeRequiredDescription
jobIdstringYesThe job identifier

Request Body

json
{
  "expirationSeconds": 3600
}
ParameterTypeRequiredDescription
expirationSecondsnumberNoURL expiration time in seconds. Default: 3600 (1 hour). Min: 60, Max: 604800 (7 days)

Response - Success (200 OK)

For Transcribe workflow (single file):

json
{
  "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):

json
{
  "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):

json
{
  "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):

json
{
  "error": {
    "code": "RESOURCE_NOT_FOUND",
    "message": "Job not found"
  }
}

Job Not Completed (400):

json
{
  "error": {
    "code": "INVALID_REQUEST",
    "message": "Job is not completed yet. Current status: processing"
  }
}

Job Failed (400):

json
{
  "error": {
    "code": "INVALID_REQUEST",
    "message": "Job failed. No output files available."
  }
}

Invalid Expiration (400):

json
{
  "error": {
    "code": "INVALID_REQUEST",
    "message": "Expiration time must be between 60 and 604800 seconds"
  }
}

Code Examples

cURL

bash
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

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

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

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

WorkflowAPI ProductOutput FilesDescription
Transcribetranscribe1 SRT fileSingle consolidated transcription
TranslatetranslateN SRT filesMultiple context files (N varies by input length)
Voiceovervoiceover1 video fileFinal merged video with voice-over
Full Dubbingdub1 video fileFinal 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:

json
{
  "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