Passer au contenu
Guide de l’API

Webhooks

Afficher en Markdown Mis à jour

Au lieu d’effectuer des sondages, 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.ru/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 est request.succeeded, request.failed ou request.canceled.
  • data est l’objet de requête complet, exactement comme celui que renvoie 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 état 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 tâches lentes après avoir répondu, et non avant.

Vérifier la signature

Chaque clé possède son propre secret de signature. Lisez-le une seule fois à partir de GET https://api.doitong.ru/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 effectuer la vérification :

  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 minuscule.
  3. Comparez-le avec v1 en temps constant.
  4. Refusez l’événement lorsque t est à plus de 5 minutes de l’heure 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 placez votre propre traitement en file d’attente.
  • Le secret appartient à la clé API qui a démarré l’exécution. Les clés de différents services possèdent des secrets différents.