API Reference

Base URL: https://api.voiceclips.app/api/v1

AI agent? Append .md to this page's URL for a raw Markdown version.

Authentication

All requests require an Authorization header with a Bearer token.

HTTP
Authorization: Bearer vc_live_abc123...

API keys can be created from the Voice Clips dashboard (Business plan required). Keys use the format vc_live_{random} (production) or vc_test_{random} (test).

Each key has assigned scopes that control access:

Rate Limits

Note: API access (via API keys) requires a Business plan. Free and Pro users can only access the API through the web dashboard.

Rate limit headers are included in every response:

  • X-RateLimit-Limit — Max requests per window
  • X-RateLimit-Remaining — Remaining requests
  • X-RateLimit-Reset — Unix timestamp when window resets
  • Retry-After — Seconds to wait (only on 429 responses)

Error Format

All errors follow a consistent shape:

JSON
{
  "error": {
    "type": "validation_error",
    "message": "Human-readable description",
    "status": 400
  }
}

Response Conventions

  • All responses wrap data in a data key
  • Field names use snake_case
  • Timestamps are ISO 8601 with timezone
  • Null fields are included, not omitted
  • Paginated endpoints include a pagination object

Create a Job

POST/jobswrite

Submit a Twitter/X Space or tweet URL for processing. The system will download the audio, transcribe it, and extract notable quotes.

bash
curl -X POST https://api.voiceclips.app/api/v1/jobs \
  -H "Authorization: Bearer vc_live_abc123..." \
  -H "Content-Type: application/json" \
  -d '{
    "space_url": "https://x.com/i/spaces/1BRJjZaOZzXGw",
    "callback_url": "https://example.com/webhook",
    "callback_secret": "my_webhook_secret_123"
  }'

Response (201):

JSON
{
  "data": {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "space_url": "https://x.com/i/spaces/1BRJjZaOZzXGw",
    "space_title": null,
    "status": "pending",
    "progress": 0,
    "error": null,
    "retry_count": 0,
    "space_duration": null,
    "project_id": null,
    "is_archived": false,
    "created_at": "2025-01-15T10:30:00.000Z",
    "updated_at": "2025-01-15T10:30:00.000Z"
  }
}

Job limits per plan:

List Jobs

GET/jobsread

Response (200):

JSON
{
  "data": [
    {
      "id": "uuid",
      "space_url": "string",
      "space_title": "string or null",
      "status": "ready",
      "progress": 100,
      "error": null,
      "retry_count": 0,
      "space_duration": 3600.5,
      "project_id": "uuid or null",
      "is_archived": false,
      "quote_count": 8,
      "created_at": "ISO 8601",
      "updated_at": "ISO 8601"
    }
  ],
  "pagination": {
    "total": 42,
    "limit": 20,
    "offset": 0,
    "has_more": true
  }
}

Get Job Details

GET/jobs/:idread

Returns the full job with all quotes and metadata.

JSON
{
  "data": {
    "id": "uuid",
    "space_url": "string",
    "space_title": "string or null",
    "status": "ready",
    "progress": 100,
    "error": null,
    "retry_count": 0,
    "space_duration": 3600.5,
    "project_id": "uuid or null",
    "is_archived": false,
    "created_at": "ISO 8601",
    "updated_at": "ISO 8601",
    "speaker_suggestions": [
      { "username": "elonmusk", "display_name": "Elon Musk" }
    ],
    "space_metadata": {
      "host": { "username": "host_user", "display_name": "Host Name" },
      "total_live_listeners": 1500,
      "total_replay_watched": 3200,
      "started_at": "ISO 8601"
    },
    "quotes": [
      {
        "id": "uuid",
        "text": "The actual quote text...",
        "original_text": "string or null",
        "image_text": "string or null",
        "original_image_text": "string or null",
        "speaker_label": "Speaker 1",
        "username": "twitter_handle",
        "display_name": "Full Name",
        "start_time": 120.5,
        "end_time": 135.2,
        "audio_clip_url": "string or null",
        "image_card_url": "string or null",
        "video_card_url": "string or null",
        "is_favorite": false,
        "render_status": "completed",
        "render_progress": 100
      }
    ]
  }
}

Retry a Failed Job

POST/jobs/:id/retrywrite

Resets a failed job back to pending for reprocessing. Maximum 3 retries.

Response (200): Returns the job object with status: "pending" and incremented retry_count.

Delete a Job

DELETE/jobs/:idwrite
JSON
{
  "data": { "status": "deleted" }
}

Archive / Unarchive a Job

PATCH/jobs/:id/archivewrite

Toggles the archive status.

JSON
{
  "data": {
    "id": "uuid",
    "is_archived": true
  }
}

Download Job Files

GET/jobs/:id/files/:filenameread

Download audio clips, images, videos, or metadata files associated with a job. Returns binary content with the appropriate Content-Type.

Get a Quote

GET/quotes/:idread
JSON
{
  "data": {
    "id": "uuid",
    "text": "The quote text...",
    "original_text": "string or null",
    "image_text": "string or null",
    "original_image_text": "string or null",
    "speaker_label": "Speaker 1",
    "username": "twitter_handle",
    "display_name": "Full Name",
    "start_time": 120.5,
    "end_time": 135.2,
    "audio_clip_url": "string or null",
    "image_card_url": "string or null",
    "video_card_url": "string or null",
    "is_favorite": false,
    "render_status": "completed",
    "render_progress": 100
  }
}

Update a Quote

PATCH/quotes/:idwrite

Edit the quote text or reset it to the original.

One of text or reset is required. Response (200): Returns the updated quote object.

Update Quote Speaker

PATCH/quotes/:id/speakerwrite

Assign or update the speaker on a single quote. Clears any cached video so the next render uses the new name.

Response (200): Returns the updated quote object.

Render Video

POST/quotes/:id/render-videowrite

Triggers a video render for the quote.

JSON
{
  "data": { "status": "rendering" }
}

Render Image

POST/quotes/:id/render-imagewrite

Triggers a server-side image render for the quote.

JSON
{
  "data": {
    "id": "uuid",
    "status": "processing",
    "image_url": null
  }
}

Toggle Favorite

PATCH/quotes/:id/favoritewrite
JSON
{
  "data": {
    "id": "uuid",
    "is_favorite": true
  }
}

Create a Bulk Render Batch

POST/render/bulkwrite

Queue multiple image and/or video renders at once. Max 50 per batch. Video renders require Pro or Business plan.

bash
curl -X POST https://api.voiceclips.app/api/v1/render/bulk \
  -H "Authorization: Bearer vc_live_abc123..." \
  -H "Content-Type: application/json" \
  -d '{
    "renders": [
      { "quote_id": "uuid1", "type": "image" },
      { "quote_id": "uuid2", "type": "video" }
    ],
    "callback_url": "https://example.com/webhook",
    "callback_secret": "my_webhook_secret_123"
  }'

Response (202):

JSON
{
  "data": {
    "id": "uuid",
    "status": "processing",
    "total": 2,
    "completed": 0,
    "failed": 0,
    "created_at": "ISO 8601",
    "updated_at": "ISO 8601",
    "items": [
      {
        "id": "uuid",
        "quote_id": "uuid1",
        "type": "image",
        "status": "pending",
        "error": null,
        "result_url": null,
        "created_at": "ISO 8601"
      }
    ]
  }
}

Get Batch Status

GET/render/:idread

Returns the current status of a render batch, including per-item progress.

Get Theme

GET/themeread

Returns the current theme settings, or null if no custom theme is set.

JSON
{
  "data": {
    "id": "uuid",
    "user_id": "uuid",
    "preset": "brutalist",
    "background_color": "#0A0A0A",
    "pattern_color": "#111111",
    "accent_color": "#FF3366",
    "text_color": "#FFFFFF",
    "background_pattern": "stripes",
    "font_family": "inter",
    "show_corner_brackets": true,
    "show_accent_line": true,
    "logo_url": null,
    "custom_watermark_text": null,
    "created_at": "ISO 8601",
    "updated_at": "ISO 8601"
  }
}

Update Theme

PUT/themewrite

Create or update the theme. All color fields are required as 6-digit hex strings.

Response (200): Returns the updated theme object.

Delete Theme

DELETE/themewrite

Resets the theme to defaults (removes custom settings).

JSON
{
  "data": { "status": "deleted" }
}

Webhooks

When you provide callback_url and callback_secret on job creation or bulk render, Voice Clips will send POST requests to your URL on completion or failure.

Signature Verification

Every callback includes an X-VoiceClips-Signature header:

HTTP
X-VoiceClips-Signature: sha256=abc123def456...

Verify it by computing HMAC-SHA256(request_body, callback_secret) and comparing the hex digest.

Retry Behavior

  • Up to 3 retries with exponential backoff (1s, 2s, 4s)
  • 4xx responses are not retried
  • 10-second timeout per attempt
  • Success = any 2xx response status