Aller au contenu principal

Guide d’implémentation

Terminer la tâche une fois la requête disparue.

Une tâche média survit à l’appel HTTP qui l’a créée, à la page qui l’a déclenchée et souvent au déploiement en cours à ce moment-là. Tout ce qui suit sert à y survivre.

L’enjeu

La connexion n’est pas la transaction

Entre l’envoi et le fichier en main, il y a quatre endroits où perdre du travail : une création réexpédiée à l’aveugle après un délai dépassé, un rappel invérifiable, une boucle d’interrogation qui matraque ou abandonne, et une URL de résultat expirée pendant votre réflexion.

01

Une reprise sans clé, c’est une deuxième facture

Idempotency-Key fait qu’une répétition du même modèle, de la même entrée et du même rappel sous 24 heures renvoie la tâche d’origine sans réserver deux fois. La portée est une clé d’API ; une clé voisine rejouant la même valeur reçoit 409 sans identifiant de tâche.

02

Un rappel non vérifié est un point d’entrée ouvert

Les livraisons portent X-Webhook-Timestamp et une HMAC-SHA256 en Base64 dans X-Webhook-Signature, calculée sur taskId.timestamp.sha256(raw_body). Vérifiez sur les octets bruts en temps constant et rejetez les horodatages anciens avant de toucher à l’état de la tâche ou de la facturation.

03

Interroger sans plafond mène au rate limit

recordInfo est un secours, pas un transport. Commencez vers deux secondes, augmentez de moitié, plafonnez à quinze et arrêtez-vous à une échéance que vous avez choisie.

La méthode

Un enregistrement durable par tâche, écrit avant de répondre

Persistez la clé d’idempotence, le taskId et votre propre identifiant de corrélation dans la transaction qui répond à l’appelant. Chaque événement ultérieur — rappel, interrogation, reprise, question de support — se résout sur cette ligne, et une livraison en double devient une mise à jour et non une seconde commande.

Vérifier d’abord, lire ensuite. La signature couvre les octets bruts : on analyse après la comparaison.

Verify the callback before you trust it

import { createHash, createHmac, timingSafeEqual } from "node:crypto";

// rawBody is the exact bytes that arrived. Parse only to read the task ID:
// the digest is always computed over those raw bytes, never over a re-encode.
export function verifyDelivery(rawBody, headers, webhookKey) {
  const timestamp = headers["x-webhook-timestamp"];
  if (Math.abs(Date.now() / 1000 - Number(timestamp)) > 300) return false;

  const taskId = JSON.parse(rawBody).data.taskId;          // payload version 2
  const digest = createHash("sha256").update(rawBody).digest("hex");
  const expected = createHmac("sha256", webhookKey)
    .update(`${taskId}.${timestamp}.${digest}`)
    .digest("base64");

  const sent = Buffer.from(headers["x-webhook-signature"] ?? "", "utf8");
  const mine = Buffer.from(expected, "utf8");
  return sent.length === mine.length && timingSafeEqual(sent, mine);
}

Delivery headers

X-Webhook-Timestamp: 1788652800
X-Webhook-Signature: <base64>
X-Webhook-Payload-Version: 2

{
  "code": 200,
  "msg": "success",
  "request_id": "whd_01k3m8x9q2z4v7n5p6r8s0t1w3",
  "data": { "taskId": "job_01k3…", "state": "succeeded", "settled": true, … }
}

Contrat

Les points à figer d’emblée

API média asynchrone : tâches, webhooks, reprises — Les points à figer d’emblée
Champ ou en-têteValeur ou limite
Idempotency-Key24 h · scoped to one API key
X-Webhook-Signaturebase64(HMAC-SHA256)
signed stringtaskId.timestamp.sha256(raw_body)
X-Webhook-Payload-Version2 for new integrations

Balayez horizontalement pour voir toutes les colonnes.

Intégration

Du premier appel à la production

  1. 01Générez et stockez une clé d’idempotence, puis appelez createTask avec elle et un callBackUrl HTTPS sur le port 80 ou 443.
  2. 02Écrivez data.taskId en base avant de répondre à l’appelant ; le 202 est le seul endroit où il apparaît en premier.
  3. 03Acceptez le rappel, vérifiez la signature sur le corps brut, dédupliquez sur request_id et mettez à jour votre enregistrement.
  4. 04Gardez recordInfo avec backoff exponentiel en secours et copiez output.assets avant l’expiration de l’URL signée.

Pertinence

Quand cette voie convient

À choisir si

  • Tout ce qui produit des médias. Les points d’accès image, vidéo et audio sont asynchrones par construction.
  • Vous avez besoin d’une trace durable de ce qui a été envoyé, de ce que cela devait coûter et de la façon dont cela s’est terminé.

À éviter si

  • Vous appelez un modèle de texte : celui-ci diffuse dans la requête et se règle sur l’usage mesuré.
  • Vous voulez que le navigateur possède la tâche. Les clés appartiennent à votre serveur, et l’enregistrement aussi.

Vérifications

Ce que vous pouvez contrôler vous-même

Chaque réponse porte un request_id

L’enveloppe est {code, msg, data, request_id} sur toutes les opérations /api/v1. En version 2 de charge utile, le request_id d’une livraison reste stable entre les renvois : c’est la clé de déduplication naturelle.

Les réservations sont visibles dans l’enregistrement

cost avec settled: false est l’estimation réservée ; settled: true est la facturation finale. Un succès ne dépasse jamais la réservation, un échec ou une expiration la libère intégralement.

Les échecs utilisent un vocabulaire fermé

errorCode vaut l’une de neuf valeurs stables : invalid_request, unsupported_combination, content_rejected, rate_limited, upstream_unavailable, generation_failed, timeout, invalid_asset, upstream_failed. Traitez toute autre valeur comme upstream_failed.

Avant la mise en production

Comportements de la plateforme à confirmer

  • Stockez la clé d’idempotence avec la tâche, pas dans la mémoire du processus.
  • Rendez le traitement du rappel idempotent ; les livraisons sont retentées par conception.
  • Fixez une échéance d’interrogation et alertez sur les tâches qui la dépassent.
  • Copiez les fichiers avant expiresAt et redemandez une URL plutôt que d’en mettre une en cache.

Questions fréquentes

Ce qu’on nous demande sur cette page

Renvoyez la même requête avec la même Idempotency-Key. Sous 24 heures et avec la même clé d’API, vous récupérez la tâche d’origine sans seconde réservation. N’envoyez jamais un nouveau corps après un délai dépassé : ce serait une nouvelle tâche facturée séparément.

Et après

Construire un flux de tâches qui survit à un déploiement

Envoyer de longues tâches média depuis votre serveur et les terminer sûrement : clés d’idempotence, rappels signés, interrogation bornée, cinq états.

Guides associés