Lumavo expose une API REST pour intégrer la génération directement dans vos applications, vos automatisations ou vos outils internes — sans passer par l'interface.
L'API suit la mise à disposition progressive des capacités de Lumavo :
/v1/tts) — disponible dès maintenant./v1/transcribe) — disponible dès maintenant : audio/vidéo → texte./v1/jobs/:id) et gestion des clés — disponibles./v1/render), avatar parlant (/v1/lipsync) et génération de
script (/v1/script) — bientôt, activés au fur et à mesure.https://api.getlumavo.com/v1
Toutes les requêtes sont en HTTPS et échangent du JSON
(Content-Type: application/json).
Chaque requête doit porter votre clé d'API dans l'en-tête X-LUMAVO-API-KEY :
X-LUMAVO-API-KEY: votre_clé
Créez et gérez vos clés depuis votre compte, section Clés API. Une clé porte des permissions (voix, vidéo, avatar, script) : elle n'a accès qu'aux capacités que vous lui accordez. Gardez vos clés secrètes ; en cas de fuite, révoquez-les et recréez-en une.
L'ancien en-tête
X-LUMA-API-KEYreste accepté (rétro-compatibilité).
Clients sans dépendance, prêts à copier. Ils créent une voix et attendent le résultat.
Node.js (18+)
const KEY = process.env.LUMAVO_API_KEY, BASE = 'https://api.getlumavo.com';
const call = (p, o = {}) => fetch(BASE + p, { ...o,
headers: { 'X-LUMAVO-API-KEY': KEY, 'Content-Type': 'application/json', ...(o.headers || {}) },
}).then((r) => r.ok ? r.json() : Promise.reject(r.status));
const job = await call('/v1/tts', { method: 'POST', body: JSON.stringify({ text: 'Bonjour !', voice: 'narrator' }) });
let res;
do { await new Promise((r) => setTimeout(r, 1500)); res = await call(`/v1/jobs/${job.id}`); }
while (res.status !== 'done' && res.status !== 'failed');
console.log(res.resultUrl); // → WAV téléchargeable
Python (3.8+)
import os, time, json, urllib.request
KEY, BASE = os.environ["LUMAVO_API_KEY"], "https://api.getlumavo.com"
def call(path, method="GET", body=None):
req = urllib.request.Request(BASE + path, data=json.dumps(body).encode() if body else None,
method=method, headers={"X-LUMAVO-API-KEY": KEY, "Content-Type": "application/json"})
return json.load(urllib.request.urlopen(req))
job = call("/v1/tts", "POST", {"text": "Bonjour !", "voice": "narrator"})
res = job
while res["status"] not in ("done", "failed"):
time.sleep(1.5); res = call(f"/v1/jobs/{job['id']}")
print(res["resultUrl"]) # → WAV téléchargeable
curl -X POST https://api.getlumavo.com/v1/tts \
-H "X-LUMAVO-API-KEY: votre_clé" \
-H "Content-Type: application/json" \
-d '{
"text": "Bonjour, ceci est ma voix générée par Lumavo.",
"voice": "calm",
"speed": 1.0
}'
La réponse (202 Accepted) contient l'identifiant de la tâche :
{ "id": "b1f2…", "status": "pending" }
| Champ | Type | Obligatoire | Détail |
|---|---|---|---|
text |
string | oui | Le texte à lire (jusqu'à 8000 car.) |
voice |
string | non | Voix/style — voir GET /v1/voices |
emotion |
string | non | Ton (ex. calme, dynamique) |
speed |
number | non | Vitesse, entre 0.5 et 2 (défaut 1) |
curl https://api.getlumavo.com/v1/voices -H "X-LUMAVO-API-KEY: votre_clé"
Renvoie la liste des voix pour le champ voice : calm (calme), narrator
(narrateur), cinematic (cinématique), ad (publicité), tiktok (réseaux sociaux).
Convertit un fichier audio ou vidéo (accessible par URL) en texte, avec le découpage horodaté par segment — parfait pour générer des sous-titres, indexer ou analyser du contenu. Réponse directe (synchrone), pas de tâche à sonder.
curl -X POST https://api.getlumavo.com/v1/transcribe \
-H "X-LUMAVO-API-KEY: votre_clé" \
-H "Content-Type: application/json" \
-d '{
"mediaUrl": "https://exemple.com/audio.mp3",
"language": "fr"
}'
Réponse (200 OK) :
{
"text": "Bonjour et bienvenue sur Lumavo.",
"language": "fr",
"languageSource": "detected",
"duration": 2.4,
"segments": [
{ "start": 0.0, "end": 2.4, "text": "Bonjour et bienvenue sur Lumavo." }
]
}
| Champ | Type | Obligatoire | Détail |
|---|---|---|---|
mediaUrl |
string | oui | URL http(s) du fichier audio/vidéo à transcrire |
language |
string | non | Code langue ISO (ex. fr, en) — auto-détectée si omise |
Langues : passe un code ISO 639-1 (fr, en, es, de, ar, zh…) pour forcer la langue, ou omets language pour la détection automatique (une centaine de langues supportées).
Le champ languageSource te dit d'où vient language, pour que tu saches si tu peux t'y fier comme détection :
"detected" — tu as omis language → la valeur est la langue réellement détectée dans l'audio ;"requested" — tu as forcé une langue → la valeur est celle que tu as demandée (simple écho, pas une détection ; le moteur transcrit dans cette langue même si l'audio est dans une autre).La réponse inclut aussi duration (durée de l'audio en secondes).
Scope requis : transcribe.
L'API ne reçoit pas le fichier directement : tu téléverses d'abord vers une URL
signée, puis tu passes l'URL obtenue à /v1/transcribe. Trois étapes :
1. Demande une URL d'upload (POST /v1/uploads) :
curl -X POST https://api.getlumavo.com/v1/uploads \
-H "X-LUMAVO-API-KEY: votre_clé" -H "Content-Type: application/json" \
-d '{ "filename": "reunion.mp3", "contentType": "audio/mpeg" }'
{
"method": "PUT",
"uploadUrl": "https://cdn.getlumavo.com/luma-uploads/…?X-Amz-…",
"mediaUrl": "https://cdn.getlumavo.com/luma-uploads/…?X-Amz-…",
"objectKey": "…",
"uploadExpiresIn": 3600,
"mediaExpiresIn": 86400
}
2. Envoie ton fichier en PUT sur uploadUrl (aucune clé API ici — l'URL est déjà signée) :
curl -X PUT "<uploadUrl>" --data-binary @reunion.mp3 -H "Content-Type: audio/mpeg"
3. Transcris en passant mediaUrl :
curl -X POST https://api.getlumavo.com/v1/transcribe \
-H "X-LUMAVO-API-KEY: votre_clé" -H "Content-Type: application/json" \
-d '{ "mediaUrl": "<mediaUrl>", "language": "fr" }'
POST /v1/uploads est gratuit (il ne fait que générer des URLs signées) ; seule la transcription est débitée. Le fichier n'a jamais besoin d'être public : mediaUrl est une URL signée temporaire.
Rétention : les fichiers téléversés sont automatiquement supprimés après ~24 h (au-delà, l'URL signée a de toute façon expiré). Transcris juste après l'upload ; ne t'appuie pas sur un stockage durable côté Lumavo.
Ajoutez un en-tête Idempotency-Key (un identifiant unique que vous générez) à
POST /v1/tts · /render · /lipsync. Si vous rejouez la même requête (timeout réseau,
retry), Lumavo renvoie la tâche déjà créée au lieu d'en créer — et ne débite pas deux fois.
curl -X POST https://api.getlumavo.com/v1/tts \
-H "X-LUMAVO-API-KEY: votre_clé" \
-H "Idempotency-Key: 3f8c1e2a-…" \
-H "Content-Type: application/json" \
-d '{ "text": "Bonjour", "voice": "calm" }'
La génération est asynchrone : interrogez le statut de la tâche jusqu'à ce qu'elle soit terminée, puis récupérez l'URL du fichier.
curl https://api.getlumavo.com/v1/jobs/b1f2… \
-H "X-LUMAVO-API-KEY: votre_clé"
{ "id": "b1f2…", "type": "tts_only", "status": "done", "progress": 100, "resultUrl": "https://…/audio.wav" }
Chaque tâche a une forme stable : { id, type, status, progress, resultUrl, error, duration, createdAt }.
Interrogez ce point de terminaison toutes les 1–2 secondes jusqu'à
status: "done" (ou "failed"). L'URL renvoyée est directement téléchargeable.
curl "https://api.getlumavo.com/v1/jobs?limit=20" \
-H "X-LUMAVO-API-KEY: votre_clé"
Renvoie vos tâches les plus récentes, de la plus récente à la plus ancienne
(paramètre limit optionnel, max 100).
| Méthode & route | Rôle |
|---|---|
POST /v1/keys |
Créer une clé |
GET /v1/keys |
Lister ses clés |
POST /v1/keys/:id/revoke |
Révoquer une clé |
Au lieu de sonder /v1/jobs/:id, enregistrez une URL de callback : Lumavo vous
notifie dès qu'une tâche se termine (job.completed) ou échoue (job.failed).
curl -X POST https://api.getlumavo.com/v1/webhooks \
-H "X-LUMAVO-API-KEY: votre_clé" -H "Content-Type: application/json" \
-d '{"url":"https://votre-app.com/lumavo/callback"}'
{ "id": "…", "url": "https://votre-app.com/lumavo/callback", "secret": "whsec_…", "active": true }
Conservez le secret (affiché une seule fois). Chaque livraison est signée :
l'en-tête X-LUMAVO-Signature contient HMAC-SHA256(corps, secret) — recalculez-le
côté serveur pour vérifier l'authenticité. Corps reçu :
{ "event": "job.completed", "data": { "jobId": "…", "status": "done", "resultUrl": "https://…" }, "timestamp": 1720000000000 }
Vérifier la signature (indispensable) — recalculez le HMAC sur le corps brut (pas le JSON re-sérialisé) et comparez à temps constant :
// Express
import { createHmac, timingSafeEqual } from 'node:crypto';
app.post('/callback', express.raw({ type: 'application/json' }), (req, res) => {
const sig = req.header('X-LUMAVO-Signature') || '';
const expected = createHmac('sha256', SECRET).update(req.body).digest('hex');
const ok = sig.length === expected.length && timingSafeEqual(Buffer.from(expected), Buffer.from(sig));
if (!ok) return res.sendStatus(401);
const { event, data } = JSON.parse(req.body); // data = { jobId, status, resultUrl }
res.sendStatus(200);
});
# Flask
import hmac, hashlib
@app.post("/callback")
def callback():
sig = request.headers.get("X-LUMAVO-Signature", "")
expected = hmac.new(SECRET.encode(), request.data, hashlib.sha256).hexdigest()
if not hmac.compare_digest(expected, sig):
abort(401)
event = request.get_json() # { event, data: { jobId, status, resultUrl }, timestamp }
return "", 200
| Méthode & route | Rôle |
|---|---|
POST /v1/webhooks |
Enregistrer une URL |
GET /v1/webhooks |
Lister ses webhooks |
POST /v1/webhooks/:id/test |
Envoyer un événement de test |
DELETE /v1/webhooks/:id |
Supprimer |
Ces points de terminaison existent et seront activés progressivement :
POST /v1/script — génère un script à partir d'un sujet.POST /v1/render — produit une vidéo complète.POST /v1/lipsync — crée un avatar parlant.Ils suivent le même principe : la requête renvoie une tâche, dont vous suivez le
statut via /v1/jobs/:id.
| Code | Signification |
|---|---|
202 |
Tâche acceptée et mise en file |
200 |
Requête réussie (statut, listes) |
401 |
Clé d'API absente ou invalide |
403 |
La clé n'a pas la permission requise |
402 |
Crédits insuffisants |
429 |
Trop de requêtes — ralentissez (limite de débit par clé) |
429.X-RateLimit-Limit et X-RateLimit-Remaining
(requêtes restantes dans la fenêtre courante). Un 429 renvoie Retry-After (secondes).GET /v1/usage :curl https://api.getlumavo.com/v1/usage -H "X-LUMAVO-API-KEY: votre_clé"
{ "rateLimit": { "limit": 60, "remaining": 58, "windowSeconds": 60, "resetSeconds": 42 },
"dailyQuota": { "limit": 2000, "used": 12, "remaining": 1988 } }