▶Table of Contents
Votxt OpenAPI Documentation (Beta)
⚠️ Beta Version Notice This API is currently in beta. Features and endpoints may change without notice. We recommend testing thoroughly in development environments before production use. Please report any issues or feedback to our support team.
Overview
The Votxt OpenAPI provides programmatic access to our transcription services, enabling you to integrate audio and video transcription into your workflows, applications, and automation tools like n8n, Zapier, and Make.
Base URL
https://api.votxt.coAuthentication
API Key Authentication
Include your API key in the request header:
X-API-Key: your_api_key_hereGetting Your API Key
- Log in to your Votxt account.
- Navigate to Settings → API Keys.
- Click "Create New Key".
- Copy and securely store your API key.
Important:
- API access requires an active subscription or LTD plan.
- Free users and one-time purchase users cannot access the API.
- Keep your API key secure and never share it publicly.
File Upload Workflow
The OpenAPI supports two ways to provide files for transcription:
Option 1: Upload Files Directly
- Get Upload URLs: Call
/api/v1/files/upload-urlto get pre-signed URLs - Upload File: Use the upload URL to upload your file directly to our storage
- Create Transcription: Use the returned
file_keyto create a transcription
Option 2: External File URLs
Provide a publicly accessible file URL for transcription.
Requirements for both options:
- File must be in a supported format
- File size must not exceed 5GB
- File duration must not exceed 10 hours
Additional requirements for external URLs:
- File must be publicly accessible via HTTP/HTTPS and downloadable.
- YouTube URLs are not supported (use the dedicated YouTube endpoint instead)
Endpoints
1. Get File Upload URLs
Endpoint: POST /api/v1/files/upload-url
Description: Generate pre-signed URLs for uploading files directly to our storage
Request:
POST /api/v1/files/upload-url
Content-Type: application/json
X-API-Key: your_api_key
{
"filename": "my-audio.mp3",
"file_size": 1048576,
"upload_expires_in": 3600,
"download_expires_in": 1800
}Parameters:
filename(string, required): Name of the file to uploadfile_size(integer, required): Size of the file in bytesupload_expires_in(integer, optional): Upload URL expiration time in seconds (default: 3600, max: 86400)download_expires_in(integer, optional): Download URL expiration time in seconds (default: 1800, max: 7200)
Response:
{
"success": true,
"data": {
"upload_url": "https://r2.cloudflare.com/bucket/12345-abc123.mp3?X-Amz-Signature=...",
"download_url": "https://r2.cloudflare.com/bucket/12345-abc123.mp3?X-Amz-Signature=...",
"file_key": "12345-abc123def456.mp3",
"upload_expires_at": "2024-01-16T11:30:00Z",
"download_expires_at": "2024-01-16T10:30:00Z"
},
"message": "Success",
"timestamp": "2024-01-15T10:30:00Z"
}Usage:
- Call this endpoint to get upload URLs
- Use the
upload_urlto upload your file (PUT request with file content) - Use the
file_keyto create a transcription task
2. Create Transcription
Endpoint: POST /api/v1/transcriptions
Description: Create a new transcription task from an uploaded file or external URL
Request Options:
Option 1: Using uploaded file
POST /api/v1/transcriptions
Content-Type: application/json
X-API-Key: your_api_key
{
"file_key": "12345-abc123def456.mp3",
"filename": "my_audio_file.mp3",
"language_code": "en",
"transcription_type": "transcript",
"enable_speaker_diarization": false,
"webhook_url": "https://your-webhook-url.com"
}Option 2: Using external file URL
POST /api/v1/transcriptions
Content-Type: application/json
X-API-Key: your_api_key
{
"file_url": "https://your-storage.com/audio.mp3",
"filename": "my-audio-file.mp3",
"language_code": "en",
"transcription_type": "transcript",
"enable_speaker_diarization": false,
"webhook_url": "https://your-webhook-url.com"
}Parameters:
file_key(string, required iffile_urlnot provided): File key from upload APIfile_url(string, required iffile_keynot provided): Public URL to audio/video file (Note: YouTube URLs are not supported here, use/api/v1/transcriptions/youtubeinstead)filename(string, optional, but recommended): Custom filename for the transcription. If not provided:- For uploaded files: filename will be extracted from the
file_key - For URL downloads: filename will be extracted from the URL path
- For uploaded files: filename will be extracted from the
language_code(string, required): Language code (e.g., "en", "zh", "es"), see Language Supporttranscription_type(string, optional): "transcript" or "subtitle"enable_speaker_diarization(boolean, optional): Enable speaker identificationwebhook_url(string, optional): URL to receive completion notifications
Note: You must provide either file_key OR file_url, but not both.
Supported File Types:
- Audio: mp3, mpeg, mpga, m4a, wav, aac, ogg, opus, flac
- Video: mp4, webm, mov (audio will be extracted)
Response:
{
"success": true,
"data": {
"id": "1234567890",
"status": "queued",
"created_at": "2024-01-15T10:30:00Z"
}
}Status Values:
queued: Task is queued for processingpreprocessing: Media file is being preprocessed (for large files or youtube videos)processing: Transcription is in progresscompleted: Transcription is completefailed: Transcription failed
3. List Transcriptions
Retrieve a paginated list of your transcriptions.
Endpoint: GET /api/v1/transcriptions
Parameters:
cursor(integer, optional): Pagination cursorlimit(integer, optional): Number of items per page (1-20, default: 10)
Example:
GET /api/v1/transcriptions?limit=10&cursor=1234567890
X-API-Key: your_api_keyResponse:
{
"success": true,
"data": {
"items": [
{
"id": "1234567890",
"filename": "audio.mp3",
"status": "completed",
"duration": 120.5,
"language_code": "en",
"transcription_type": "transcript",
"created_at": "2024-01-15T10:30:00Z",
"completed_at": "2024-01-15T10:35:00Z",
"file_size": 1048576,
"source_type": "upload"
}
],
"has_more": true,
"next_cursor": "1234567889"
},
"message": "Success",
"timestamp": "2024-01-15T10:30:00Z"
}4. Get Transcription Details
Retrieve detailed information and results for a specific transcription.
Endpoint: GET /api/v1/transcriptions/{id}
Example:
GET /api/v1/transcriptions/1234567890
X-API-Key: your_api_keyResponse:
{
"success": true,
"data": {
"id": "1234567890",
"filename": "audio.mp3",
"status": "completed",
"duration": 120.5,
"language_code": "en",
"transcription_type": "transcript",
"created_at": "2024-01-15T10:30:00Z",
"completed_at": "2024-01-15T10:35:00Z",
"file_size": 1048576,
"source_type": "upload",
"source_url": "https://your-storage.com/audio.mp3",
"result": {
"text": "Full transcript text...",
"summary": "This audio discusses...",
"outline": "# 1. Introduction\n2. Main Points\n3. Conclusion",
"language": "English",
"segments": [
{
"start": 0.0,
"end": 5.2,
"text": "Hello, this is a sample",
"speaker": "A",
"words": [
{
"start": 0.0,
"end": 0.8,
"text": "Hello"
}
]
}
]
}
},
"message": "Success",
"timestamp": "2024-01-15T10:30:00Z"
}5. Get Transcription Status
Check the current status of a transcription.
Endpoint: GET /api/v1/transcriptions/{id}/status
Example:
GET /api/v1/transcriptions/1234567890/status
X-API-Key: your_api_keyResponse:
{
"success": true,
"data": {
"id": "1234567890",
"status": "processing",
"created_at": "2024-01-15T10:30:00Z",
"updated_at": "2024-01-15T10:33:00Z",
"error_message": null
},
"message": "Success",
"timestamp": "2024-01-15T10:30:00Z"
}Failed Status Response:
{
"success": true,
"data": {
"id": "1234567890",
"status": "failed",
"created_at": "2024-01-15T10:30:00Z",
"updated_at": "2024-01-15T10:32:00Z",
"error_message": "Failed to download file from URL: Connection timeout"
},
"message": "Success",
"timestamp": "2024-01-15T10:30:00Z"
}6. Create YouTube Transcription
Create a transcription from a YouTube video URL.
Endpoint: POST /api/v1/transcriptions/youtube
Request:
POST /api/v1/transcriptions/youtube
Content-Type: application/json
X-API-Key: your_api_key
{
"url": "https://www.youtube.com/watch?v=VIDEO_ID",
"language_code": "en",
"transcription_type": "transcript",
"enable_speaker_diarization": false,
"webhook_url": "https://your-webhook-url.com"
}Parameters:
url(string, required): YouTube video URLlanguage_code(string, required): Language code (e.g., "en", "zh", "es"), see Language Supporttranscription_type(string, optional): Type of transcriptionenable_speaker_diarization(boolean, optional): Enable speaker identificationwebhook_url(string, optional): Webhook URL for notifications
Note: Video title and duration are automatically extracted from the YouTube URL.
Response: Same format as regular transcription creation - returns task status for async processing.
Status Values
Transcriptions progress through the following statuses:
queued: Task is queued for processingpreprocessing: Media file is being preprocessed (for large files or youtube videos)processing: Transcription is in progresscompleted: Transcription is completefailed: Transcription failed
Webhook Notifications
When you provide a webhook_url, Votxt will send HTTP POST notifications to your endpoint when transcription completes or fails.
Webhook Events
Transcription Completed
{
"event": "transcription.completed",
"data": {
"id": "1234567890",
"filename": "audio.mp3",
"status": "completed",
"duration": 120.5,
"language_code": "en",
"transcription_type": "transcript",
"created_at": "2024-01-15T10:30:00Z",
"completed_at": "2024-01-15T10:35:00Z",
"file_size": 1048576,
"source_type": "upload"
},
"timestamp": "2024-01-15T10:35:00Z"
}Transcription Failed
{
"event": "transcription.failed",
"data": {
"id": "1234567890",
"filename": "audio.mp3",
"status": "failed",
"created_at": "2024-01-15T10:30:00Z",
"completed_at": "2024-01-15T10:32:00Z",
"error_message": "Failed to download file from URL: Connection timeout"
},
"timestamp": "2024-01-15T10:32:00Z"
}Webhook Requirements
- Your webhook endpoint must respond with HTTP 2xx status code
- Timeout: 30 seconds
- Include User-Agent: Votxt-Webhook/1.0 header
Error Handling
Understanding Different Types of Errors
Votxt API distinguishes between two types of errors that require different handling approaches:
1. API Call Errors
These occur when the API request itself fails (authentication, validation, system errors, etc.). The response will have success: false:
{
"success": false,
"error": {
"message": "Invalid API Key",
"code": 41001,
"details": "The provided API key is not valid"
},
"timestamp": "2024-01-15T10:30:00Z"
}2. Async Task Failures
These occur when the API call succeeds but the transcription/preprocessing task fails during execution. The response will have success: true but data.status: "failed":
{
"success": true,
"data": {
"id": "1234567890",
"status": "failed",
"created_at": "2024-01-15T10:30:00Z",
"updated_at": "2024-01-15T10:32:00Z",
"error_message": "Failed to download file from URL: Connection timeout"
},
"message": "Success",
"timestamp": "2024-01-15T10:30:00Z"
}Client-Side Error Handling
Here's the recommended approach for handling both types of errors:
JavaScript Example
async function handleTranscriptionResponse(response) {
const data = await response.json();
// First, check if the API call itself succeeded
if (!data.success) {
// Handle API-level errors
console.error("API Error:", data.error.message);
throw new Error(`API Error (${data.error.code}): ${data.error.message}`);
}
// API call succeeded, now check the task status
if (data.data.status === "failed") {
// Handle async task failures
console.error("Transcription Failed:", data.data.error_message);
throw new Error(`Transcription Failed: ${data.data.error_message}`);
}
// Success case
return data.data;
}Python Example
def handle_transcription_response(response):
data = response.json()
# Check API call success
if not data.get("success", False):
error_info = data.get("error", {})
raise APIError(f"API Error ({error_info.get('code')}): {error_info.get('message')}")
# Check task status
task_data = data.get("data", {})
if task_data.get("status") == "failed":
error_msg = task_data.get("error_message", "Unknown error")
raise TranscriptionError(f"Transcription Failed: {error_msg}")
return task_dataError Response Format
API call errors follow this consistent format:
{
"success": false,
"error": {
"message": "Error description",
"code": 41000,
"details": "Additional error details (optional)"
},
"timestamp": "2024-01-15T10:30:00Z"
}Common Error Codes
| HTTP Status | Error Code | Description |
|---|---|---|
| 400 | 10001 | Invalid request parameters |
| 403 | 20003 | Account has been deactivated |
| 403 | 30006 | Insufficient transcription quota |
| 400 | 40001 | Invalid YouTube URL |
| 403 | 40005 | YouTube video extraction error |
| 500 | 40006 | YouTube video download error |
| 403 | 41000 | API Access Denied (requires active subscription or LTD plan) |
| 401 | 41001 | Invalid API Key |
| 401 | 41002 | API Key Required |
| 413 | 41003 | File size exceeded (5GB limit) |
| 400 | 41004 | Invalid file format |
| 500 | 41005 | Webhook delivery error |
| 400 | 41006 | File upload URL generation failed |
| 400 | 41007 | File not found (invalid file_key) |
| 400 | 41008 | File upload expired or not completed |
| 404 | 41009 | API key not found |
| 409 | 41010 | API key limit exceeded (max 5 keys per user) |
| 409 | 41011 | API key name already exists |
| 404 | 45001 | Transcription not found |
| 403 | 45002 | Transcription permission denied |
| 429 | - | Rate limit exceeded (60 requests/minute, 1000 requests/day) |
Rate Limits
- Default: 60 requests per minute, 1000 requests per day
- Rate limits are per API key
- Higher limits can be discussed and adjusted based on your usage requirements. Contact hi@votxt.co if you need a higher limit
- Exceeded limits return HTTP 429 with retry information
Supported File Formats
- Audio: mp3, mpeg, mpga, m4a, wav, aac, ogg, opus, flac
- Video: mp4, webm, mov (audio will be extracted)
Language Support
Votxt supports 63 languages. Complete list of supported language codes:
| Language | Code | Language | Code | Language | Code |
|---|---|---|---|---|---|
| Afrikaans | af | Gujarati (ગુજરાતી) | gu | Polish (Polski) | pl |
| Arabic (العربية) | ar | Hebrew (עברית) | he | Portuguese (Português) | pt |
| Azerbaijani (Azərbaycan) | az | Hindi (हिन्दी) | hi | Romanian (Română) | ro |
| Belarusian (Беларуская) | be | Croatian (Hrvatski) | hr | Russian (Русский) | ru |
| Bulgarian (Български) | bg | Haitian Creole (Kreyòl ayisyen) | ht | Slovak (Slovenčina) | sk |
| Bengali (বাংলা) | bn | Hungarian (Magyar) | hu | Slovenian (Slovenščina) | sl |
| Bosnian (Bosanski) | bs | Indonesian (Bahasa Indonesia) | id | Albanian (Shqip) | sq |
| Catalan (Català) | ca | Italian (Italiano) | it | Serbian (Српски) | sr |
| Czech (Čeština) | cs | Japanese (日本語) | ja | Swedish (Svenska) | sv |
| Welsh (Cymraeg) | cy | Kazakh (Қазақ) | kk | Swahili (Kiswahili) | sw |
| Danish (Dansk) | da | Kannada (ಕನ್ನಡ) | kn | Tamil (தமிழ்) | ta |
| German (Deutsch) | de | Korean (한국어) | ko | Telugu (తెలుగు) | te |
| Greek (Ελληνικά) | el | Lithuanian (Lietuvių) | lt | Thai (ไทย) | th |
| English | en | Latvian (Latviešu) | lv | Tagalog (Tagalog/Filipino) | tl |
| Spanish (Español) | es | Macedonian (Македонски) | mk | Turkish (Türkçe) | tr |
| Estonian (Eesti) | et | Malayalam (മലയാളം) | ml | Ukrainian (Українська) | uk |
| Basque (Euskara) | eu | Marathi (मराठी) | mr | Urdu (اردو) | ur |
| Persian (فارسی) | fa | Malay (Bahasa Melayu) | ms | Vietnamese (Tiếng Việt) | vi |
| Finnish (Suomi) | fi | Dutch (Nederlands) | nl | Chinese (Cantonese) (粵語) | yue |
| French (Français) | fr | Norwegian (Norsk) | no | Chinese (Simplified) (中文 简体) | zh |
| Galician (Galego) | gl | Punjabi (ਪੰਜਾਬੀ) | pa | Chinese (Taiwanese Mandarin) (國語) | zh_tw |
Integration Examples
n8n Workflow
- HTTP Request Node:
- Method: POST
- URL: https://api.votxt.co/api/v1/transcriptions
- Headers: X-API-Key: your_api_key
- Body: JSON with file_url, optional filename, and webhook_url
- Webhook Node:
- Listen for completion notifications
- Process transcription results
Python Example
import requests
# Create transcription
response = requests.post(
'https://api.votxt.co/api/v1/transcriptions',
headers={'X-API-Key': 'your_api_key'},
json={
'file_url': 'https://example.com/audio.mp3',
'filename': 'my-recording.mp3',
'language_code': 'en',
'webhook_url': 'https://your-app.com/webhook'
}
)
transcription = response.json()
transcription_id = transcription['data']['id']
# Check status
status_response = requests.get(
f'https://api.votxt.co/api/v1/transcriptions/{transcription_id}/status',
headers={'X-API-Key': 'your_api_key'}
)
print(status_response.json())cURL Examples
# 1. Get upload URLs
curl -X POST https://api.votxt.co/api/v1/files/upload-url \
-H "X-API-Key: your_api_key" \
-H "Content-Type: application/json" \
-d '{
"filename": "audio.mp3",
"file_size": 1048576,
"upload_expires_in": 3600,
"download_expires_in": 1800
}'
# 2. Upload file using the returned upload_url
curl -X PUT "https://r2.cloudflare.com/bucket/12345-abc123.mp3?X-Amz-Signature=..." \
-H "Content-Type: audio/mpeg" \
--data-binary @audio.mp3
# 3. Create transcription using file_key
curl -X POST https://api.votxt.co/api/v1/transcriptions \
-H "X-API-Key: your_api_key" \
-H "Content-Type: application/json" \
-d '{
"file_key": "12345-abc123def456.mp3",
"language_code": "en",
"webhook_url": "https://your-webhook.com"
}'
# Alternative: Create transcription from external URL
curl -X POST https://api.votxt.co/api/v1/transcriptions \
-H "X-API-Key: your_api_key" \
-H "Content-Type: application/json" \
-d '{
"file_url": "https://example.com/audio.mp3",
"filename": "my-audio.mp3",
"language_code": "en",
"webhook_url": "https://your-webhook.com"
}'
# Get transcription results
curl -X GET https://api.votxt.co/api/v1/transcriptions/1234567890 \
-H "X-API-Key: your_api_key"Best Practices
- File Upload Strategy:
- Use direct file upload (/api/v1/files/upload-url) for better performance and reliability
- External URLs are suitable for files already hosted elsewhere
- Set appropriate expiration times for upload URLs (shorter is more secure)
- Webhook Reliability: Always implement webhook endpoints with proper error handling and idempotency
- File Size: Ensure files do not exceed 5GB limit
- Language Detection: Specify
language_codewhen known for better accuracy - Status Polling: If not using webhooks, poll status endpoint every 30-60 seconds
- Error Handling:
- Distinguish between API call errors (success: false) and task failures (success: true, status: "failed")
- Implement retry logic for network errors and rate limits
- For task failures, check error_message for specific failure reasons
- Some task failures may be retryable (network issues), others may not (invalid file format)
- File Management:
- Use file_key immediately after upload to avoid expiration issues
- Temporary uploaded files are automatically cleaned up after 48 hours if not used
- Files used for transcription become permanent and follow normal lifecycle
- Security: Never expose API keys in client-side code or public repositories
Support
- Support Email: hi@votxt.co
- Discord: https://discord.gg/RJTaS28UWU
For technical questions or integration assistance, please contact our support team.