← Back to Home
🌐 RU

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

GET /api/templates

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": [...]
}
GET /api/statuses

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();
new Video uploaded and queued for processing
processing Video is being transcribed and rendered
done Processing complete, ready for download
error Processing failed (credits refunded)
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."
  }
}
POST /api/videos

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

ParameterTypeDescription
video_base64 requiredstringBase64-encoded video content
template_id optionalstringTemplate name (default: karaoke)

Form-Data Fields

FieldTypeDescription
video requiredfileVideo file (mp4, mov, webm)
template_id optionalstringTemplate 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."
}
GET /api/videos/:id

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

StatusDescription
400Invalid request body or missing required fields
401Missing or invalid API key
403User not found, no credits, or inactive subscription
404Render not found
413Video exceeds 100 MB size limit
429Rate limit exceeded (20 req/min)