Accéder au contenu
Guide de l’API

Webhooks

Afficher en Markdown Mis à jour

Au lieu d'effectuer des interrogations périodiques, 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 tel que renvoyé par GET /requests/{id}.
  • id est stable pour une requête et son état final. Utilisez-le pour ignorer une livraison déjà traitée.

Livraisons et nouvelles tentatives

Répondez avec n'importe quel statut 2xx dans les 10 secondes. Dans le cas contraire (ou en cas d'expiration du délai), une nouvelle tentative est effectuée : jusqu'à 6 tentatives au total, après 30 secondes, 2 minutes, 10 minutes, 1 heure et 6 heures. Effectuez les traitements longs après avoir répondu, et non avant.

Vérifier la signature

Chaque clé possède son propre secret de signature. Lisez-le une fois avec 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>", calculé avec votre secret comme clé. Pour vérifier :

  1. Récupérez 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 minuscule.
  3. Comparez-le avec v1 en temps constant.
  4. Rejetez l'événement lorsque t diffère de votre horloge de plus de 5 minutes (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 vos propres traitements en fichier d'attente.
  • Le secret appartient à la clé API qui a démarré l'exécution. Les clés de services différents ont des secrets différents.