API Documentation
Integrate TrendingCaptions into your applications with our REST API. Process videos and add AI-powered captions programmatically.
🔐 Authentication
All API requests require authentication using a Bearer token. Get your API key from the Telegram Bot.
Authorization: Bearer YOUR_API_KEY⚡ Rate Limiting
API requests are limited to 20 requests per minute per API key. Exceeding this limit returns a 429 status with a Retry-After header.
🌐 Base URL
https://api.trendingcaptions.app📋 Endpoints
Returns all available caption templates grouped by script type (latin, cyrillic, greek).
curl -X GET "https://api.trendingcaptions.app/api/templates" \
-H "Authorization: Bearer YOUR_API_KEY"const response = await fetch('https://api.trendingcaptions.app/api/templates', {
headers: { 'Authorization': 'Bearer YOUR_API_KEY' }
});
const templates = await response.json();Response Example
{
"latin": [
{ "name": "popin", "description": "Energetic 'Expert' style using Montserrat ExtraBold..." },
{ "name": "karaoke", "description": "Interactive style with word-by-word highlighting..." },
{ "name": "minimal", "description": "Clean and modern style with semantic highlighting..." }
],
"cyrillic": [...],
"greek": [...]
}Returns all possible video processing statuses and their descriptions.
curl -X GET "https://api.trendingcaptions.app/api/statuses" \
-H "Authorization: Bearer YOUR_API_KEY"const response = await fetch('https://api.trendingcaptions.app/api/statuses', {
headers: { 'Authorization': 'Bearer YOUR_API_KEY' }
});
const statuses = await response.json();Response Example
{
"new": {
"description": "Video has been uploaded and queued for processing. Initial state."
},
"processing": {
"description": "Video passed validation and is currently being processed (transcription, rendering)."
},
"done": {
"description": "Video processing completed successfully. The video is ready for download."
},
"error": {
"description": "Video processing failed. This could be due to validation errors (format, size) or system errors. Credits are refunded."
}
}Upload a video for captioning. Supports two upload methods: JSON (base64) and multipart/form-data. Returns a render ID to track progress.
📤 Upload Methods
Content-Type: application/json — send video as a base64-encoded string in the JSON body.
Content-Type: multipart/form-data — send the video file directly. Recommended for large files to avoid base64 overhead.
JSON Body Parameters
| Parameter | Type | Description |
|---|---|---|
| video_base64 required | string | Base64-encoded video content |
| template_id optional | string | Template name (default: karaoke) |
Form-Data Fields
| Field | Type | Description |
|---|---|---|
| video required | file | Video file (mp4, mov, webm) |
| template_id optional | string | Template name (default: karaoke) |
⚠️ Size Limits
Maximum input video size is 100 MB. Videos must be in 9:16 aspect ratio. Output is optimized for Telegram (≤50MB).
# Upload video file directly via form-data (recommended)
curl -X POST "https://api.trendingcaptions.app/api/videos" \
-H "Authorization: Bearer YOUR_API_KEY" \
-F "video=@your_video.mp4" \
-F "template_id=popin"# Encode video to base64 and send as JSON
VIDEO_B64=$(base64 -i your_video.mp4)
curl -X POST "https://api.trendingcaptions.app/api/videos" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d "{\"video_base64\": \"$VIDEO_B64\", \"template_id\": \"popin\"}"// Upload file directly via FormData (recommended)
const file = document.getElementById('videoInput').files[0];
const formData = new FormData();
formData.append('video', file);
formData.append('template_id', 'popin');
const response = await fetch('https://api.trendingcaptions.app/api/videos', {
method: 'POST',
headers: { 'Authorization': 'Bearer YOUR_API_KEY' },
body: formData
});
const { renderId } = await response.json();
console.log('Render ID:', renderId);// Convert file to base64 and send as JSON
const file = document.getElementById('videoInput').files[0];
const reader = new FileReader();
reader.onload = async () => {
const base64 = reader.result.split(',')[1];
const response = await fetch('https://api.trendingcaptions.app/api/videos', {
method: 'POST',
headers: {
'Authorization': 'Bearer YOUR_API_KEY',
'Content-Type': 'application/json'
},
body: JSON.stringify({
video_base64: base64,
template_id: 'popin'
})
});
const { renderId } = await response.json();
console.log('Render ID:', renderId);
};
reader.readAsDataURL(file);Response Example (202 Accepted)
{
"status": "new",
"renderId": "550e8400-e29b-41d4-a716-446655440000",
"message": "Video uploaded and processing started."
}Check the processing status of a video. Returns a download URL when complete.
curl -X GET "https://api.trendingcaptions.app/api/videos/550e8400-e29b-41d4-a716-446655440000" \
-H "Authorization: Bearer YOUR_API_KEY"// Poll for status until done
async function pollStatus(renderId) {
const response = await fetch(
`https://api.trendingcaptions.app/api/videos/${renderId}`,
{ headers: { 'Authorization': 'Bearer YOUR_API_KEY' } }
);
const result = await response.json();
if (result.status === 'done') {
console.log('Download URL:', result.downloadUrl);
} else if (result.status === 'error') {
console.error('Processing failed');
} else {
setTimeout(() => pollStatus(renderId), 5000);
}
}Response Example (status: done)
{
"renderId": "550e8400-e29b-41d4-a716-446655440000",
"status": "done",
"description": "Video processing completed successfully. The video is ready for download.",
"downloadUrl": "https://...presigned-url...?X-Amz-Expires=3600"
}❌ Error Responses
| Status | Description |
|---|---|
400 | Invalid request body or missing required fields |
401 | Missing or invalid API key |
403 | User not found, no credits, or inactive subscription |
404 | Render not found |
413 | Video exceeds 100 MB size limit |
429 | Rate limit exceeded (20 req/min) |