Passer au contenu
Guide de l’API

Webhooks

Afficher en Markdown Mis à jour

Au lieu d'effectuer des interrogations répétées, fournissez une webhook_url à une exécution. Lorsque la requête atteint un état final (succeeded, failed ou canceled), nous envoyons un POST signé à cette URL.

terminal
curl -X POST "https://api.doitong.com/v1/run/{model_id}?webhook_url=https://example.com/hooks/doitong" \
  -H "Authorization: Bearer $DOITONG_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"prompt": "..."}'

L'événement

En-têtes de la requête
POST /hooks/doitong HTTP/1.1
Content-Type: application/json
User-Agent: Doitong-Webhooks/1
Doitong-Request-Id: req_8k2m4q7x1z9c3v5b6n0p2r4t
Doitong-Signature: t=1760961609,v1=5f1c0d6e2b…
Corps de la requête
{
  "id": "evt_8k2m4q7x1z9c3v5b6n0p2r4t_succeeded",
  "object": "event",
  "type": "request.succeeded",
  "created_at": "2026-10-20T12:00:09Z",
  "data": {
    "id": "req_8k2m4q7x1z9c3v5b6n0p2r4t",
    "object": "request",
    "status": "succeeded",
    "outputs": [ { "type": "video", "url": "https://content.doitong.com/dev-api/…/0-output.mp4" } ]
  }
}
  • type vaut request.succeeded, request.failed ou request.canceled.
  • data est l'objet de requête complet, exactement celui renvoyé par GET /requests/{id}.
  • id est stable pour une requête et son état final. Utilisez-le pour ignorer une livraison que vous avez déjà traitée.

Livraisons et nouvelles tentatives

Répondez avec n'importe quel statut 2xx dans les 10 secondes. Toute autre réponse (ou un délai d'attente dépassé) entraîne une nouvelle tentative : jusqu'à 6 tentatives au total, après 30 secondes, 2 minutes, 10 minutes, 1 heure et 6 heures. Effectuez les opérations lentes après avoir répondu, pas avant.

Vérifier la signature

Chaque clé possède son propre secret de signature. Lisez-le une seule fois depuis GET https://api.doitong.com/v1/account (webhook_signing_secret, il commence par whsec_) et stockez-le avec la clé.

L'en-tête Doitong-Signature est t=<unix time>,v1=<signature>, où la signature est le HMAC-SHA256 hexadécimal de "<t>.<raw request body>", avec votre secret comme clé. Pour vérifier :

  1. Prenez les octets bruts du corps exactement tels qu'ils ont été reçus (avant toute analyse JSON).
  2. Calculez le HMAC-SHA256 de t + "." + body avec votre secret, en hexadécimal minuscules.
  3. Comparez-le avec v1 en temps constant.
  4. Rejetez l'événement lorsque t est distant de plus de 5 minutes de votre horloge (protection contre les rejeux).

Un récepteur complet en Node.js (Express) et Python (Flask) :

import crypto from "node:crypto";
import express from "express";

const SECRET = process.env.DOITONG_WEBHOOK_SECRET; // whsec_...
const app = express();

app.post("/hooks/doitong", express.raw({ type: "application/json" }), (req, res) => {
  const header = req.get("Doitong-Signature") || "";
  const parts = Object.fromEntries(header.split(",").map((p) => p.split("=", 2)));
  const t = Number(parts.t);
  const expected = crypto.createHmac("sha256", SECRET).update(t + "." + req.body).digest("hex");
  const given = Buffer.from(parts.v1 || "", "utf8");
  const valid =
    given.length === expected.length &&
    crypto.timingSafeEqual(given, Buffer.from(expected, "utf8")) &&
    Math.abs(Date.now() / 1000 - t) < 300;
  if (!valid) return res.status(400).send("bad signature");

  const event = JSON.parse(req.body);
  if (event.type === "request.succeeded") {
    console.log(event.data.id, event.data.outputs.map((o) => o.url));
  }
  res.sendStatus(204);
});

Conseils

  • Répondez rapidement et mettez votre propre traitement en file d'attente.
  • Le secret appartient à la clé API qui a démarré l'exécution. Les clés utilisées dans différents services ont des secrets différents.