Enregistrez un mediaWebhookUrl, recevez un POST lorsqu’une tâche est terminée, interrogez GET /api/media/jobs/{id}, gérez les codes d’erreur et comprenez les limites de facturation et d’idempotence.
Guide opérationnel des tâches multimédias asynchrones : enregistrement des webhooks, statuts, interrogation périodique, codes d’erreur, frais et limites d’idempotence, strictement selon l’implémentation actuelle du code.
Cycle de vie d’une tâche
POST /api/media/generate — en cas de succès, 202 et { ok: true, jobId, status: "processing" }. L’API ne comporte pas de statuts distincts queued / running : jusqu’à la fin du job, le client voit processing.
L’amont peut passer par des étapes internes (waiting, generating) qui ne sont pas reflétées dans l’API publique ; pendant l’interrogation, la tâche reste processing.
États du terminal : success (contient resultUrls, facturé en cas de succès) ou fail (aucun frais).
La complétion est enregistrée une seule fois : via le callback en amont ou lors d’une interrogation différée dans GET /api/media/jobs/{id}.
Interrogation : GET /api/media/jobs/{id}
GEThttps://getvibeapi.com/api/media/jobs/{id}
Paramètre
Type
Description
status
string
submitting | processing | success | fail. submitting + media_submission_uncertain is non-terminal; within about 10–15 minutes such a submission is closed as fail (media_submission_not_started) without a charge — create a new task.
Montant des frais en USD (0 en cas d’échec ou avant la fin).
failMsg
string | null
Message de sécurité en cas d'échec ou de media_submission_uncertain non terminal.
errorCode
string | null
Code d’erreur (media_generation_failed) ou non-terminal media_submission_uncertain.
retryGuidance
string | null
Sur media_submission_uncertain : une instruction sûre pour interroger ultérieurement le même jobId et ne pas créer automatiquement de doublon.
# 2. poll the job until it is ready
curl https://getvibeapi.com/api/media/jobs/JOB_ID \
-H "Authorization: Bearer $GETVIBE_API_KEY"
# → {"status":"success","resultUrls":["https://..."],"priceRub":...}
Intervalle d’interrogation recommandé : 3–5 s, avec une temporisation exponentielle pouvant atteindre 30 s. Le délai d’expiration côté client dépend du SLA de votre application (la génération vidéo peut prendre plusieurs minutes).
Enregistrement du webhook
GEThttps://getvibeapi.com/api/webhooks
PATCHhttps://getvibeapi.com/api/webhooks
Une URL par compte : mediaWebhookUrl. Configurée dans dashboard → Webhooks ou via l’API avec une account session (un cookie après la connexion). L’endpoint n’accepte passk-pv-… : uniquement une session authentifiée.
# Example (a dashboard session is required, not an API key)
curl -X PATCH https://getvibeapi.com/api/webhooks \
-H "Content-Type: application/json" \
-b "session=YOUR_SESSION" \
-d '{"mediaWebhookUrl":"https://example.com/webhooks/media"}'
# Clear the URL
curl -X PATCH https://getvibeapi.com/api/webhooks \
-H "Content-Type: application/json" \
-b "session=YOUR_SESSION" \
-d '{"mediaWebhookUrl":null}'
Exigences relatives aux URL
Paramètre
Type
Description
mediaWebhookUrl
URL HTTPS
Une adresse HTTPS publique ; les adresses privées ou de bouclage et nos propres domaines sont refusés (protection contre les SSRF), et l’adresse est vérifiée à nouveau avant chaque livraison. Une chaîne vide ou null réinitialise ce paramètre.
balanceWebhookUrl
URL HTTPS
Un webhook distinct pour les soldes faibles (pas pour les médias), signé avec le même secret de compte, x-pv-event: balance.low. Le seuil est balanceWebhookThresholdRub.
Livraison du webhook à la fin du traitement
Lorsqu’une tâche atteint un statut final, GetVibe crée un événement logique unique et le distribue via POST au mediaWebhookUrl enregistré. La livraison est limitée : le service effectue au total jusqu’à 5 tentatives. Le même payload peut être reçu plusieurs fois.
// POST to your mediaWebhookUrl when a job finishes
{
"jobId": "...",
"status": "success", // or "fail"
"model": "veo-3.1",
"kind": "video", // image | video | audio | music | 3d
"resultUrls": ["https://getvibeapi.com/api/media/file/..."],
"failMsg": null,
"createdAt": "2026-06-17T10:00:00.000Z"
}
Comportement de livraison (comme dans le code)
Paramètre
Type
Description
Signature / auth
—
Chaque livraison est signée selon la norme Standard Webhooks : les en-têtes webhook-id, webhook-timestamp et webhook-signature (v1, HMAC-SHA256 en base64 de « id.timestamp.body »). Le secret de compte est affiché dans le tableau de bord → Webhooks et renvoyé à une clé API sous le nom accountSecret par GET /api/media/webhook-secret ; les livraisons vers un webhook_url fourni par requête sont signées avec le secret de cette clé (le champ secret). Rejetez toute requête dont la signature est incorrecte ou dont l’horodatage date de plus de 5 minutes.
Retries
outbox
Jusqu’à 5 tentatives au total ; intervalle après un échec : 1, 2, 4, 8 minutes. Après épuisement des tentatives, l’événement passe à FAILED et n’est plus livré automatiquement. La requête GET /api/media/jobs/{id} reste la source de l’état.
Receiver dedup
required
Dédupliquez selon la paire jobId + status et rendez votre gestionnaire idempotent. N’utilisez pas le webhook comme unique source d’état.
Content-Type
application/json
Le corps est un JSON contenant les champs jobId, status, model, kind, resultUrls, failMsg, createdAt.
Erreurs de POST /api/media/generate
HTTP
Quand
Frais
Réessayer
202
Tâche acceptée (ok: true, jobId)
Non (uniquement après réussite)
—
400
JSON / corps de requête invalide
Non
Corriger la requête
401
Clé API manquante ou non valide
Non
Vérifier l’autorisation
402
Solde insuffisant (admission)
Non
Recharger le solde
422
Modèle inconnu, options non valides, ok: false renvoyé par la façade
Non
Fix model/opts
502
media_submit_failed — service en amont indisponible
Non
Réessayer avec temporisation progressive
503
priceUnavailable, garde de routage, VIDEO_DISABLED, veo sans prix
Non
Autre modèle / ultérieurement
Erreurs d’interrogation et échecs terminaux
HTTP / statut
Signification
Frais
404
tâche introuvable ou jobId appartenant à un autre compte
Non
processing
La tâche est toujours en cours d’exécution
Non
success
Terminé, resultUrls renseigné
Oui — priceRub dans la réponse
fail
Échec de la génération
No (priceRub = 0)
Facturation et idempotence
Facturé une seule fois en cas de succès. Dans finalizeJob, la transition processing → success|fail est atomique : un callback ou un sondage répété ne déclenche pas de seconde facturation.
fail — gratuit. Aucun débit n’est effectué pour un statut fail.
Cotation d’admission. Si une cotation a été enregistrée lors de la création, c’est exactement ce montant qui est facturé en cas de succès (jamais davantage que le décompte réel du fournisseur amont).
Créez l’idempotence — via un en-tête. Un POST répété vers /api/media/generate sans l’en-tête crée un nouveau job et une nouvelle facturation en cas de succès. Envoyez Idempotency-Key (jusqu’à 255 caractères ASCII) : une nouvelle tentative avec la même clé et le même corps dans les 24 heures renvoie le même jobId sans créer de nouveau job ; la même clé avec un corps différent renvoie 422, et 409 tant que la première requête est encore en cours de traitement. Le jobId d’une génération payante apparaît également dans GET /v1/generations (le champ job_id).
Le webhook est limité à cinq tentatives. Un événement logique est créé pour chaque transition finale, mais les tentatives de livraison peuvent se répéter. Après cinq échecs, l’événement reçoit le statut FAILED . Le gestionnaire client doit dédupliquer la paire jobId + status.