API v1 Documentation — View changelog
Vozia
GET /api/v1/podcasts/:podcastId/status

Get Status

Get the current generation status of a podcast. Poll this endpoint to track progress during audio generation.

Status States

draft

Podcast created but generation not started

generating

Script generation in progress (using AI)

processing

Audio synthesis in progress (using TTS)

ready

Generation complete — audio URL available

failed

Generation failed — check errorMessage

Path Parameters

podcastId required
string

The ID of the podcast

Query Parameters

jobId optional
string

Specific job ID to check. If not provided, returns the most recent job.

Response

200 OK
JSON (ready state)
{
  "podcastId": "pod_xyz789",
  "status": "ready",
  "audioUrl": "https://res.cloudinary.com/vozia/podcasts/pod_xyz789.mp3",
  "duration": 312.5,
  "errorMessage": null,
  "job": {
    "id": "job_abc123",
    "status": "completed",
    "progress": 100,
    "currentStep": "Complete",
    "totalSegments": 24,
    "completedSegments": 24,
    "startedAt": "2024-01-15T10: 30: 00Z",
    "completedAt": "2024-01-15T10: 32: 15Z",
    "errorMessage": null
  }
}
JSON (processing state)
{
  "podcastId": "pod_xyz789",
  "status": "processing",
  "audioUrl": null,
  "duration": null,
  "job": {
    "id": "job_abc123",
    "status": "processing",
    "progress": 45,
    "currentStep": "Generating audio segments",
    "totalSegments": 24,
    "completedSegments": 11,
    "startedAt": "2024-01-15T10: 30: 00Z",
    "completedAt": null
  }
}

Code Examples

JavaScript - Polling
async function waitForPodcast(podcastId) {
  const API_KEY = class="hl-string">'YOUR_API_KEY';
  const BASE_URL = class="hl-string">'https:class="hl-comment">//api.vozia.io/v1';

  while (true) {
    const response = await fetch(
      class="hl-string">`${BASE_URL}/podcasts/${podcastId}/status`,
      {
        headers: { class="hl-string">'Authorization': class="hl-string">`Bearer ${API_KEY}` }
      }
    );

    const status = await response.json();

    class="hl-comment">// Log progress
    if (status.job) {
      console.log(class="hl-string">`[${status.job.progress}%] ${status.job.currentStep}`);
    }

    class="hl-comment">// Check completion
    if (status.status === class="hl-string">'ready') {
      return {
        audioUrl: status.audioUrl,
        duration: status.duration
      };
    }

    if (status.status === class="hl-string">'failed') {
      throw new Error(status.errorMessage || class="hl-string">'Generation failed');
    }

    class="hl-comment">// Wait 2 seconds before next check
    await new Promise(resolve => setTimeout(resolve, 2000));
  }
}

class="hl-comment">// Usage
const result = await waitForPodcast(class="hl-string">'pod_xyz789');
console.log(class="hl-string">'Audio ready:', result.audioUrl);
cURL
# Check status
curl https://api.vozia.io/v1/podcasts/pod_xyz789/status \
  -H "Authorization: Bearer YOUR_API_KEY"

# Check specific job
curl "https://api.vozia.io/v1/podcasts/pod_xyz789/status?jobId=job_abc123" \
  -H "Authorization: Bearer YOUR_API_KEY"

Polling Best Practices

  • Poll every 2-3 seconds during active generation
  • Use exponential backoff if implementing retries
  • Consider using webhooks for production (coming soon)
  • Set a maximum timeout to avoid infinite loops