Reelora API

REST API for programmatic integration of subtitles, voiceover, transcription, dubbing, and pause removal. The same capabilities as the Telegram bot — via HTTP. Available on all plans, including Free.

Endpoints

MethodPathDescription
GET/healthService health check
GET/v1/meProfile, limits, usage
POST/v1/uploadsUpload file
POST/v1/tasksCreate task
GET/v1/tasksList of tasks
GET/v1/tasks/{id}Task status + result

Quick Start

1

Get API Key

In the bot @reelora_ai_bot send /apikey or open Settings → 🔑 API Access. The key is shown only once.

2

Upload File

POST /v1/uploads → get upload_id

3

Create Task

POST /v1/tasks with type and parameters

4

Get Result

Poll GET /v1/tasks/{id} or specify webhook_url

Authentication

All requests (except /health) require the header:

X-API-Key: reel_xxxxxxxx_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
⚠️The key is shown only once. If lost — run /revokekey in the bot and generate a new one via /apikey.
API is available on all plans. Limits are the same as in the bot — Free, Standard, Pro, Pro+.

Base URL

https://api.reelora.cc

Interactive Swagger documentation: https://api.reelora.cc/docs

Status Check

GET/healthno auth required
curl https://api.reelora.cc/health
# {"status":"ok","service":"reelora-api"}

Profile and Limits

GET/v1/me
curl https://api.reelora.cc/v1/me -H "X-API-Key: reel_..."
{
  "user_id": 618899534, "tariff": "pro_plus",
  "tariff_expires_at": "2026-07-17T07:20:20",
  "limits": {
    "seconds_per_month": 36000, "tts_chars_limit": 1000000,
    "elevenlabs_chars_limit": 25000, "transcription_seconds": 72000,
    "max_photos": 30, "max_video_duration": 600, "max_file_size_mb": 500,
    "can_translate": true, "can_dub": true, "premium_voices": true
  },
  "usage": {
    "used_seconds_this_month": 705, "used_chars_this_month": 12674,
    "used_eleven_chars_this_month": 0, "used_transcription_seconds": 0,
    "limit_reset_date": "2026-07-17T07:18:07"
  },
  "api_key_prefix": "xxxxxxxx", "api_key_created_at": "2026-06-19T22:43:23"
}

File Upload

POST/v1/uploads

Uploads a file and returns upload_id. Files live for 2 hours. Limit: 20 uploads/min.

curl -X POST https://api.reelora.cc/v1/uploads \
  -H "X-API-Key: reel_..." -F "[email protected]"
# {"upload_id":"550e8400-...","filename":"photo.jpg","size_bytes":245891}
TypeFormatsMax.
ImagesJPEG, PNG, WebP500 MB
VideoMP4, MOV, AVI500 MB
AudioMP3, WAV, M4A500 MB
SubtitlesSRT

Use upload_id in the photos, file, srt_file, bgm_file fields. Alternatively, you can pass direct https:// URLs instead of uploading.

Task Creation

POST/v1/tasks202 Accepted

Task type is defined in the "type" field. Executed asynchronously. All types support webhook_url and send_to_telegram.

{ "task_id": 744, "status": "pending" }

Type: video — video creation

Photos or video clips + voiceover + karaoke subtitles + music → MP4.

{
  "type": "video",
  "photos": ["upload_id_1", "https://example.com/img.jpg"],
  "text": "Text for voiceover",
  "scene_durations": null, "scene_transitions": null, "target_duration": 30,
  "format": "9_16", "animation": "ken_burns", "transition": "random", "transition_duration": 0.5,
  "tts_provider": "google", "tts_voice": "Chirp3-HD-Aoede",
  "tts_scene": "Speak like a news anchor.",
  "subtitles": true, "sub_style": "yellow_basic", "sub_position": "bottom",
  "bgm_track": "chill_background-lofi-vibes-113884.mp3", "bgm_volume": 0.2
}
FieldDefaultDescription
photosrequiredupload_id or https:// (images or video clips, max. 30)
textoptionalnullTexte de la voix off. Sans texte — vidéo sans son. Insère des marqueurs de scène entre les paragraphes pour changer le plan (et choisir la transition) : {scene} · {scene:slide} · {scene:zoom:0.8} · {scene:0.8}
scene_durationsoptionalnullDurées explicites par média en secondes, ex. [10, 15, 5]. Longueur = nombre de médias. Remplace l’auto-timing {scene}, fonctionne même sans voix
scene_transitionsoptionalnullTransition explicite par coupe (longueur = photos − 1), ex. ["slide","zoom"]. Alternative aux marqueurs {scene:type}
target_durationoptionalnullDurée cible du clip en secondes. Si le résultat est plus long, il est accéléré (vidéo+audio+sous-titres synchronisés) pour tenir. Plus court — laissé tel quel. Accélération limitée à ×2. Doit être ≤ la limite de votre forfait
formatoptional"9_16""9_16" · "16_9" · "1_1" · "original"
animationoptional"none""none" · "ken_burns"
transitionoptional"crossfade"Transition globale pour les coupes non marquées : none · random · fade · dissolve · slide · cover · reveal · zoom · squeeze · wind · pixel · circle (crossfade = alias de dissolve). Actif seulement quand animation ≠ none
transition_durationoptional0.5Durée de transition en secondes. Durée par coupe via {scene:type:sec}
tts_provideroptional"google"TTS provider (see Providers section)
tts_voiceoptionalfrom profileVoice name (see Voices section)
tts_speedoptional1.00.8 · 1.0 · 1.2 · 1.5
languageoptionalLangue de la voix off — n’importe quel code de la section Langues ("ar", "fa"…) ou un locale complet "ru-RU". Pour les langues rares — tts_provider:"edge"
tts_sceneoptionalnullSpeech style instruction (for Gemini TTS)
tts_styleoptionalnullVoice style preset: standard · calm · expressive · energetic · dramatic · cheerful (Gemini and ElevenLabs)
subtitlesoptionaltrueKaraoke subtitles
sub_styleoptional"yellow_basic"Subtitle style
sub_positionoptional"bottom""top" · "center" · "bottom"
sub_sizeoptional"medium""small" · "medium" · "large"
sub_coloroptionalnullASS color: "&H0000E6FF" (yellow)
text_overlaysoptionalnullLégendes statiques par-dessus l'image, indépendantes de la voix off (voir « Texte sur la vidéo » ci-dessous)
text_overlays_rawoptionalnullLa même chose sous forme de chaîne « codes » compacte, analysée côté serveur (voir ci-dessous). Utilisé seulement si text_overlays est absent
auto_textoptionalfalse⚡ Auto-texte. Un LLM choisit les mots-clés les plus forts de la voix off et les ajoute en légendes animées, synchronisées sur les timestamps de mots du TTS (voir « Auto-texte » ci-dessous). Nécessite text. Décompté de votre quota mensuel d'auto-texte
bgm_trackoptionalnullFile name from the music library (see BGM section)
bgm_fileoptionalnullupload_id of your own MP3 file (mutually exclusive with bgm_track)
bgm_volumeoptional0.2Music volume 0.0–1.0
audio_mix_typeoptional"replace"Mixing for video clips: "replace" · "add" · "overlay"

audio_mix_type — for clips with original sound

ValueBehavior
replaceTTS/BGM only — clip sound is removed
addTTS on top of original (both at full volume)
overlayTTS at full volume + original audio is ducked

🎬 Scènes dynamiques — quand le plan change

  • Avec voix : insère des marqueurs {scene} dans text entre les paragraphes. Chaque segment est cadencé par la narration et associé aux médias dans l’ordre. Les marqueurs sont retirés avant le TTS — la voix ne les lit jamais.
  • Sans voix / explicite : passe scene_durations (ex. [10, 15, 5]) — une valeur par média. Les clips sont coupés/bouclés, les photos affichées pour la durée de la scène.
  • Scènes ↔ médias : égal → 1:1 ; moins de scènes → la dernière se répartit sur le reste ; plus → le dernier média garde le reste.

✨ Transitions par coupe — comment le plan change

  • Dans le texte : étends un marqueur avec un type et/ou une durée : {scene:slide}, {scene:zoom:0.8}, {scene:0.8} (durée seule). La transition s’applique à la coupe vers cette scène.
  • Tableau explicite : scene_transitions (longueur = photos − 1), ex. ["slide","zoom","fade"] — une transition par coupe. Pratique pour les vidéos muettes à durées explicites.
  • Types : fade · dissolve · slide · cover · reveal · zoom · squeeze · wind · pixel · circle · random. Les directionnelles (slide/cover/reveal/wind) choisissent une direction aléatoire par coupe.
ℹ️Les transitions ne sont rendues que si animationnone. Un none par coupe n’est pas supporté — il revient à la transition globale.

🅰️ Texte sur la vidéo — légendes statiques

Ajoutez des légendes/titres arbitraires par-dessus la vidéo, indépendamment des sous-titres. Fonctionne avec ou sans narration. Chaque légende a son style, sa position, son timing et son fondu. Deux façons de les passer :

Structuré — text_overlays (tableau, max 10) :

"text_overlays": [
  { "text": "BIG TITLE", "style": "bold_yellow", "size": "large",
    "position": "top_center", "start": 0.0, "end": 3.0, "fade": true, "anim": "pop" },
  { "text": "the end", "style": "soft_pink", "position": "bottom_center", "start": 3.0 }
]
Champ
textrequiredobligatoire, max 200 caractères
startoptionals. null → à partir de 0
endoptionals. null → jusqu'à la fin de la vidéo
styleoptionalstyle de titre (ci-dessous)
sizeoptionalsmall · medium · large
positionoptionalgrille 9 : top_left · top_center · top_right · middle_left · center · middle_right · bottom_left · bottom_center · bottom_right
bold / italicoptionalremplace la graisse/l'italique du style
coloroptionalASS hex &HAABBGGRR, ex. "&H00B469FF" (rose)
fadeoptionalfondu d'entrée/sortie doux (300 ms)
animoptionalAnimation d'apparition : pop · slide_left · slide_right · type (machine à écrire). Prioritaire sur fade

Styles de titre (style) : clean_white · bold_yellow · outline_black · soft_pink · elegant_script · news_bar · impact_red.

Codes — text_overlays_raw (chaîne). Syntaxe universelle en anglais (identique dans toutes les langues d'interface), analysée côté serveur. Une légende par ligne (ou séparées par /) ; champs internes séparés par |:

TEXT | attributes | start-end
"text_overlays_raw": "Hello | large italic center | 0-3 / Subscribe | bottom pink pop | 3-end"
  • taille — small · medium · large
  • graisse/italique — bold · thin · italic
  • vertical — top · middle · bottom ; horizontal — left · center · right
  • couleur — white · yellow · red · green · blue · pink · orange · purple · black · cyan
  • temps — 0-3, 2.5-8, 5-end (s, point/virgule). Sans temps → la légende s'affiche tout le clip
  • animation — pop · slide · type (machine à écrire) · fade · none
📋Exemple : première légende — « Bonjour » en grand italique centré 0–3 s ; seconde — « Abonne-toi » en bas rose de la 3ᵉ seconde à la fin. Les attributs et le temps sont optionnels et indépendants de l'ordre. Les tokens inconnus sont ignorés (la requête n'échoue jamais).

⚡ Auto-texte — légendes automatiques de mots-clés

auto_text: true active ⚡ Auto-texte. Au lieu de placer les légendes vous-même, un LLM lit les mots reconnus de la voix off, choisit les plus forts (noms, chiffres, affirmations percutantes) et les rend en légendes animées, exactement sur les timestamps de mots du TTS. Il choisit par mot un style moderne, une couleur et une animation d'apparition (pop / slide / typewriter), empile les mots dits ensemble et évite la zone des sous-titres.

  • Nécessite une voix off (text non vide). Sans narration, il n'y a pas de timestamps de mots, donc auto_text est ignoré.
  • Additif : les légendes générées s'ajoutent à vos text_overlays / text_overlays_raw, elles ne les remplacent pas.
  • Entièrement automatique : aucun paramètre par mot. Si le LLM ne trouve rien, le rendu se poursuit simplement sans légendes supplémentaires (la requête n'échoue jamais).
  • Quota : chaque rendu auto-texte réussi consomme une unité de votre quota mensuel (auto_text_limit ; gratuit limité, offres payantes illimitées). Au-delà de la limite → 429.
  • L'auto-texte fonctionne dans tous les types de tâche de l'API : video, dubbing et subtitles. La traduction via l'API se fait par subtitles avec translate_to (pas de type translation séparé), donc auto_text couvre aussi les sous-titres traduits.

Type: transcription — transcription

Audio or video → text + .SRT with timecodes.

{
  "type": "transcription", "file": "upload_id_or_https_url",
  "language": "uk", "ai_prompt": "Medical podcast. Correct terminology.",
  "output_format": "both"
}
FieldDescription
filerequiredupload_id or https:// URL
languageoptional"uk" · "en" · "de" · "fr" etc. null = auto
ai_promptoptionalContext for Whisper (improves accuracy)
output_formatoptional"txt" · "srt" · "both" (default)
// result_urls for transcription
{ "txt_url": "https://cdn.reelora.cc/.../transcript.txt",
  "srt_url": "https://cdn.reelora.cc/.../transcript.srt" }

Type: audio — voiceover (TTS)

Text → MP3 file without video.

{
  "type": "audio", "text": "Hello! This is a Reelora API test.",
  "tts_provider": "gemini", "tts_voice": "Puck",
  "tts_speed": 1.0, "tts_scene": "Warm and friendly tone",
  "tts_style": "expressive"
}
FieldDefaultDescription
textrequiredText to synthesize
tts_provideroptional"google"TTS provider (see Providers section)
tts_voiceoptionalfrom profileVoice name (see Voices section)
tts_speedoptional1.00.8 · 1.0 · 1.2 · 1.5
tts_sceneoptionalnullSpeech style instruction (for Gemini TTS)
tts_styleoptionalnullVoice style preset: standard · calm · expressive · energetic · dramatic · cheerful (Gemini and ElevenLabs)

Type: subtitles — subtitles on video

Burns karaoke subtitles into a finished video via Whisper + FFmpeg. Standard+ plan.

{
  "type": "subtitles", "file": "upload_id_or_https_url",
  "language": "uk", "sub_style": "yellow_basic",
  "sub_position": "bottom", "sub_size": "medium"
}

Result: MP4 with subtitles in result_url. Seconds are deducted from the monthly limit.

Champ
translate_tooptionalCode ISO d'une langue cible. Défini → les sous-titres y sont traduits (le timing est conservé, l'audio reste d'origine). Omis → dans la langue d'origine
auto_textoptional⚡ Auto-texte — légendes de mots-clés à partir des temps des sous-titres (traduits). Décompté de votre quota d'auto-texte

Type: pause_removal — pause removal

Automatically cuts out silence and pauses from video. Standard+ plan. Silence threshold is detected automatically.

{ "type": "pause_removal", "file": "upload_id_or_https_url" }

Result: processed MP4 in result_url.

Type: dubbing — AI dubbing

Transcribes video, translates, synthesizes a new voice, mixes audio. Three modes. Available on all plans within the monthly limit.

Mode A: auto — fully automatic

{
  "type": "dubbing", "mode": "auto",
  "file": "upload_id_or_https_url",
  "source_lang": "auto", "target_lang": "en",
  "tts_provider": "edge", "tts_voice": "en-US-GuyNeural",
  "mix_mode": "overlay", "overlay_volume": 20,
  "sub_lang": "dubbed", "sub_style": "yellow_basic"
}
FieldDefaultDescription
filerequiredupload_id or URL of the video to dub
source_langoptional"auto""auto" ou n’importe quel code de la section Langues ("ar", "fa", "tr"…). Whisper détecte automatiquement avec "auto"
target_langrequiredLangue de doublage — n’importe quel code de la section Langues. Si le fournisseur ne la parle pas — repli auto sur Edge
tts_provideroptional"edge"TTS provider for the new voice
tts_voiceoptionalautoVoice for the target language
mix_modeoptional"overlay""overlay" (original is ducked) · "replace" (full replacement)
overlay_volumeoptional20Original volume % when mix_mode=overlay (0–100)
sub_langoptional"dubbed""dubbed" · "original" · "none" · or ISO language code
sub_styleoptional"yellow_basic"Subtitle style
sub_positionoptional"bottom""top" · "center" · "bottom"
tts_styleoptionalnullVoice style preset: standard · calm · expressive · energetic · dramatic · cheerful (Gemini and ElevenLabs)
auto_textoptionalfalse⚡ Auto-texte par-dessus la voix doublée — légendes animées de mots-clés choisies par le LLM. Décompté de votre quota d'auto-texte

Mode B: semi_auto — with verification (2 steps)

// Step 1: transcription
{ "type": "dubbing", "mode": "semi_auto", "step": "transcribe",
  "file": "upload_id_video", "source_lang": "uk", "target_lang": "en" }
// → srt_url: download, edit, upload via /v1/uploads

// Step 2: render with edited SRT
{ "type": "dubbing", "mode": "semi_auto", "step": "render",
  "file": "upload_id_video", "srt_file": "upload_id_of_your_srt",
  "target_lang": "en", "tts_provider": "edge",
  "tts_voice": "en-US-GuyNeural", "mix_mode": "overlay", "overlay_volume": 20 }

Mode C: manual — own SRT file

Skips transcription. You provide your own SRT file containing text in the target language.

{ "type": "dubbing", "mode": "manual",
  "file": "upload_id_video", "srt_file": "upload_id_of_srt_file",
  "target_lang": "uk", "tts_voice": "uk-UA-Wavenet-A", "mix_mode": "replace" }
📋SRT format: 1\n00:00:00,000 --> 00:00:03,500\nLine text\n\n2\n... Timecodes must not exceed video duration.
On the Free plan, dubbing is available only with "edge" and "google" providers. Monthly limit: Free 120s · Standard 1800s · Pro 3600s · Pro+ 18000s.

List of Tasks

GET/v1/tasks
curl "https://api.reelora.cc/v1/tasks?limit=10&offset=0" -H "X-API-Key: reel_..."

Parameters: limit (default 20, max 100), offset (default 0).

Task Status

GET/v1/tasks/{task_id}
{
  "task_id": 744, "type": "voiceover", "status": "completed", "progress": 100,
  "result_url": "https://cdn.reelora.cc/audio/.../744_a3f.mp3",
  "result_url_expires_at": "2026-06-21T23:03:19",
  "result_urls": null, "error_message": null,
  "created_at": "2026-06-19T23:03:17", "updated_at": "2026-06-19T23:03:19"
}
⏱️result_url is valid for 48 hours. For transcription, result_urls contains both: txt_url and srt_url.

Async Flow

POST /v1/tasks │ ▼ {"task_id": 744, "status": "pending"} │ ▼ Poll every 3–5 sec: GET /v1/tasks/744 │ ├── status: "pending" → wait ├── status: "processing" → wait (progress 0–100) ├── status: "completed" → download result_url ✅ └── status: "failed" → read error_message ❌

Task Statuses

pending
In queue, not started yet
processing
In progress. progress: 0–99
completed
Ready. File is in result_url
failed
Error in error_message

Webhooks

Specify a webhook_url — you will receive a POST request when the task is finished.

// POST to your webhook_url
{ "task_id": 744, "status": "completed", "result_url": "https://cdn.reelora.cc/..." }
Webhook retries up to 3 times (15s, 30s) if the server returns 5xx. We recommend backing it up with polling.

Langues

Les champs language (voix off/TTS), source_lang et target_lang (doublage) acceptent un code ISO court ("fa") ou un locale complet ("fa-IR"). Pour la transcription/traduction, Whisper + le LLM comprennent ~99 langues — voici celles avec une voix TTS dédiée.

31 langues avec voix TTS :

codelanguelocalemoteurs TTS
ukUkrainianuk-UAEdge, Gemini, 11Labs, Google
enEnglishen-USEdge, Gemini, 11Labs, Google
ruRussianru-RUEdge, Gemini, 11Labs, Google
esSpanishes-ESEdge, Gemini, 11Labs, Google
deGermande-DEEdge, Gemini, 11Labs, Google
frFrenchfr-FREdge, Gemini, 11Labs, Google
plPolishpl-PLEdge, Gemini, 11Labs, Google
itItalianit-ITEdge, Gemini, 11Labs, Google
ptPortuguesept-BREdge, Gemini, 11Labs, Google
zhChinesezh-CNEdge, Gemini, 11Labs, Google
jaJapaneseja-JPEdge, Gemini, 11Labs, Google
arArabic (RTL)ar-SAEdge, Gemini, 11Labs, Google
faPersian (RTL)fa-IREdge uniquement
heHebrew (RTL)he-ILEdge, Google
urUrdu (RTL)ur-PKEdge uniquement
trTurkishtr-TREdge, Gemini, 11Labs, Google
hiHindihi-INEdge, Gemini, 11Labs, Google
bnBengalibn-BDEdge, Gemini, Google
idIndonesianid-IDEdge, Gemini, 11Labs, Google
msMalayms-MYEdge, 11Labs, Google
viVietnamesevi-VNEdge, Gemini, Google
thThaith-THEdge, Gemini, Google
koKoreanko-KREdge, Gemini, 11Labs, Google
nlDutchnl-NLEdge, Gemini, 11Labs, Google
roRomanianro-ROEdge, Gemini, 11Labs, Google
elGreekel-GREdge, 11Labs, Google
csCzechcs-CZEdge, 11Labs, Google
svSwedishsv-SEEdge, 11Labs, Google
azAzerbaijaniaz-AZEdge uniquement
kkKazakhkk-KZEdge uniquement
uzUzbekuz-UZEdge uniquement
💡tts_provider: "edge" fonctionne pour les 31 langues et est gratuit — le choix par défaut sûr pour les langues rares (fa, ur, az, kk, uz — Edge uniquement). Si tu omets tts_voice, la bonne voix est choisie depuis language.
🌐Langues RTL (ar, fa, he, ur) : les sous-titres se rendent de droite à gauche avec une police arabe. Les styles karaoké animés reviennent au texte simple pour le RTL.

TTS Providers

ProviderValueQualityLimit
Google (Standard/Wavenet/Chirp)"google"Good1M chars/month
Gemini 2.5 / 3.1 TTS"gemini"Excellentplan limit
Azure Neural"azure"Goodplan limit
Edge TTS (Microsoft)"edge"Goodunlimited
HuggingFace"hf"Basicplan limit
ElevenLabs"elevenlabs"PremiumPro and Pro+

Voices

Google ("google")

Locale is taken from account settings. Change it via: Settings → 🌍 Language.

tts_voiceDescription
Standard-AFemale, basic quality
Standard-BMale, basic quality
Wavenet-AFemale, neural quality
Wavenet-BMale, neural quality
Journey-FFemale, EN only, natural
Chirp3-HD-AoedeFemale, multilingual, HD
Chirp3-HD-PuckMale, multilingual, HD

Gemini 2.5 / 3.1 TTS ("gemini")

Supports tts_scene and tts_style for speech styling. Add -3.1 for the 3.1 version variant (e.g. Puck-3.1).

tts_voiceCharacter
ZephyrBright 🌤
PuckUpbeat 🎉
CharonInformative 📚
KoreFirm 💪
FenrirExcitable ⚡
LedaYouthful 🌱
AoedeBreezy 🍃
CallirrhoeEasy-going 😌
SadachbiaLively 🎵
SulafatWarm 🔥
AchirdFriendly 🤝
EnceladusBreathy 🌬
GacruxMature 🍷

Edge TTS ("edge") — unlimited

tts_voiceLanguage
uk-UA-OstapNeuralUkrainian, male
uk-UA-PolinaNeuralUkrainian, female
en-US-GuyNeuralEnglish US, male
en-US-JennyNeuralEnglish US, female
en-GB-RyanNeuralEnglish GB, male
de-DE-ConradNeuralGerman, male
fr-FR-HenriNeuralFrench, male
es-ES-AlvaroNeuralSpanish, male
pl-PL-MarekNeuralPolish, male
it-IT-DiegoNeuralItalian, male
tr-TR-AhmetNeuralTurkish, male
cs-CZ-AntoninNeuralCzech, male
ru-RU-DmitryNeuralRussian, male

ElevenLabs ("elevenlabs") — Pro and Pro+

tts_voice (ID)Name
pNInz6obpgDQGcFmaJgBAdam (male, multilingual)
21m00Tcm4TlvDq8ikWAMRachel (female, multilingual)
AZnzlk1XvdvUeBnXmlldDomi (female, multilingual)

Background Music

Pass the exact file name in the bgm_track field. Alternatively, upload your own MP3 via /v1/uploads and pass bgm_file.

bgm_track (file name)Style
chill_background-lofi-vibes-113884.mp3Lofi chill
chill_background-the-weekend-117427.mp3Lofi weekend
bodleasons-lofi-chill-smooth-chill-lofi-for-vlogs-and-background-music-159456.mp3Lofi smooth
alexgrohl-phonk-505963.mp3Phonk
white_records-neon-drift-phonk-house-background-music-for-video-27-second-496492.mp3Phonk house (27s)
white_records-toxic-drift-slap-house-background-music-for-video-stories-37-second-503887.mp3Slap house (37s)
diamond_tunes-majestic-tides-60sec-286729.mp3Cinematic majestic (60s)
raspberrymusic-relic-of-honor-cinematic-video-game-epic-478243.mp3Cinematic epic
raspberrymusic-be-the-change-epic-documentary-corporate-394293.mp3Documentary
raspberrymusic-triumph-adventure-news-cinematic-394333.mp3News cinematic
Under_the_Clock.mp3Dramatic
The_Approaching_Hour.mp3Dramatic ambient

bgm_volume: 0.1 (quiet background) → 1.0 (full volume). Default is 0.2.

Subtitle Styles

sub_styleDescription
yellow_basicMrBeast style — bold yellow words
purple_greenNeon — purple + green highlight
minimal_whiteMinimal white, clean
news_styleNews rolling ticker line style
fire_orangeFiery orange highlight
pop_greenBright green
word_box_orangeOrange bounding box around word
karaoke_cyanKaraoke cyan
cursor_selectionCursor selection style
single_green_boxGreen bounding box on a single word
business_newsBusiness news style
dynamic_colorsDynamic colors

Video Formats

formatAspect RatioPlatforms
9_169:16 (vertical)TikTok, Instagram Reels, YouTube Shorts
16_916:9 (horizontal)YouTube, Desktop
1_11:1 (square)Instagram Feed, Facebook
originaloriginalKeep source dimensions

Plan Requirements

FeatureFreeStandardProPro+
video
transcription
audio (TTS)
subtitles
pause_removal
dubbing
ElevenLabs voices
API access

Error Codes

HTTPReason
401Missing or invalid X-API-Key
403Feature unavailable on the current plan
404Task or file not found (upload_id might have expired after 2h)
413File exceeds 500 MB
415Unsupported file type
429Monthly limit exceeded or 30 requests/min rate limit hit
500Internal server error
{ "detail": "Monthly video render limit exceeded" }

Example: Python — full video pipeline

import httpx, time

API_KEY = "reel_xxxxxxxx_..."
BASE    = "https://api.reelora.cc"
H       = {"X-API-Key": API_KEY}

def poll(task_id):
    while True:
        r = httpx.get(f"{BASE}/v1/tasks/{task_id}", headers=H).json()
        print(f"  status={r['status']} progress={r.get('progress')}%")
        if r["status"] == "completed": return r["result_url"]
        if r["status"] == "failed":    raise RuntimeError(r["error_message"])
        time.sleep(3)

with open("photo.jpg", "rb") as f:
    upload = httpx.post(f"{BASE}/v1/uploads", headers=H, files={"file": f}).json()

task = httpx.post(f"{BASE}/v1/tasks", headers=H, json={
    "type":         "video",
    "photos":       [upload["upload_id"]],
    "text":         "Breaking news from our channel.",
    "format":       "9_16",
    "tts_provider": "google",
    "tts_voice":    "Chirp3-HD-Aoede",
    "subtitles":    True,
    "sub_style":    "news_style",
    "bgm_track":    "raspberrymusic-triumph-adventure-news-cinematic-394333.mp3",
    "bgm_volume":   0.15,
}).json()

print("Download:", poll(task["task_id"]))

Example: Python — semi_auto dubbing

# Step 1: transcription
with open("video.mp4", "rb") as f:
    vid = httpx.post(f"{BASE}/v1/uploads", headers=H, files={"file": f}).json()

t1 = httpx.post(f"{BASE}/v1/tasks", headers=H, json={
    "type": "dubbing", "mode": "semi_auto", "step": "transcribe",
    "file": vid["upload_id"], "source_lang": "uk", "target_lang": "en",
}).json()
srt_url = poll(t1["task_id"])
# download srt_url → edit → save as edited.srt

# Step 2: render with edited SRT
with open("edited.srt", "rb") as f:
    srt = httpx.post(f"{BASE}/v1/uploads", headers=H, files={"file": f}).json()

t2 = httpx.post(f"{BASE}/v1/tasks", headers=H, json={
    "type": "dubbing", "mode": "semi_auto", "step": "render",
    "file": vid["upload_id"], "srt_file": srt["upload_id"],
    "target_lang": "en", "tts_provider": "edge",
    "tts_voice": "en-US-GuyNeural",
    "mix_mode": "overlay", "overlay_volume": 20,
}).json()
print("Dubbed video:", poll(t2["task_id"]))

Example: JavaScript / Node.js

const API_KEY = "reel_xxxxxxxx_...";
const BASE    = "https://api.reelora.cc";
const H       = { "X-API-Key": API_KEY, "Content-Type": "application/json" };

async function poll(taskId) {
  while (true) {
    await new Promise(r => setTimeout(r, 3000));
    const d = await fetch(`${BASE}/v1/tasks/${taskId}`, { headers: H }).then(r => r.json());
    if (d.status === "completed") return d.result_url;
    if (d.status === "failed")    throw new Error(d.error_message);
  }
}

const { task_id } = await fetch(`${BASE}/v1/tasks`, {
  method: "POST", headers: H,
  body:   JSON.stringify({ type: "audio", text: "Hello from JS!", tts_provider: "google", tts_voice: "Chirp3-HD-Puck" }),
}).then(r => r.json());

console.log("MP3:", await poll(task_id));

Example: curl — transcription

# Upload file
UPLOAD=$(curl -s -X POST https://api.reelora.cc/v1/uploads \
  -H "X-API-Key: reel_..." -F "[email protected]" \
  | python3 -c "import sys,json; print(json.load(sys.stdin)['upload_id'])")

# Transcription task
TASK=$(curl -s -X POST https://api.reelora.cc/v1/tasks \
  -H "X-API-Key: reel_..." -H "Content-Type: application/json" \
  -d "{\"type\":\"transcription\",\"file\":\"$UPLOAD\",\"language\":\"uk\",\"output_format\":\"both\"}" \
  | python3 -c "import sys,json; print(json.load(sys.stdin)['task_id'])")

# Polling
while true; do
  RESP=$(curl -s https://api.reelora.cc/v1/tasks/$TASK -H "X-API-Key: reel_...")
  STATUS=$(echo $RESP | python3 -c "import sys,json; print(json.load(sys.stdin)['status'])")
  echo "Status: $STATUS"
  [ "$STATUS" = "completed" ] && echo $RESP | python3 -m json.tool && break
  [ "$STATUS" = "failed"    ] && echo "Failed!" && break
  sleep 3
done