ᡤᡝᠯᡳ ᡩᡝ ᠵᡠᠸᡝᠨ
API ᠵᠠᠯᡤᠠᠯᠠᠨ

Webhook

Markdown ᠰᡳ ᡤᡝᠯᡳ ᡝᠮᡠ ᠣᠮᠣᠯᠣᠨ

ᡳᠨᡝᠩᡤᡳ ᠪᠠᠶᠠᠨ ᠰᡳᠯᡤᠠᠯᠠᠮᡝ ᠪᠠᡳᡨᠠᠯᠠᡵᠠ ᡠᠨᡩᡝᡵᡝᠩᡤᡝ᠂ ᡝᡵᡝ ᠪᠠᠶᠠᠨ ᡳ webhook_url ᡳ ᠪᡝᠶᡝ ᠪᡝ ᡝᠨᡩᡝᡵᡝᠮᡝ ᡠᠯᡥᡳᠮᡝ ᠪᠠᠨᠵᡳᠨᠠᠮᡝ᠂ ᠪᠠᠶᠠᠨ ᡳ ᡩᠠᠯᡵᠠᠮᡝ ᠪᠠᡳᡨᠠᠯᠠᡵᠠ ᠪᠠᠶᠠᠨ ᡳ ᠮᡠᠩᡤᠠᠨ ᠪᠠᠶᠠᠨ ᡳ ᠮᡠᠶᠠᠨ ᡳ ᠪᠠᡳᡨᠠᠯᠠᠩᡤᡝ (succeeded, failed ᠵᡠᠯᡝ ᠪᠠᠨᡳ canceled) ᠪᠣᠯᠣᠮᡝ᠂ ᠮᡳᠨᡳ ᡝᠨᡩᡝᡵᡝᠮᡝ ᡤᠠᠰᡥᠠᠨ ᠵᠠᠯᠠᠨ ᡳ POST ᡝᠨᡩᡝᡵᡝᠮᡝ ᠪᡝᠶᡝ ᠵᠠᠯᠠᠨ ᡩᡝ ᡝᠨᡩᡝᡵᡝᠮᡝ.

ᠵᠠᠯᠠᠨ ᡳ ᠪᠠᡳ᠌ᠯᠠᠩᡤᠠ
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": "..."}'

ᡝᡵᡝ ᡤᡠᠯᡤᠠᠨ

ᡝᠨᡩᡝᡵᡝᠮᡝ ᠵᠠᠯᠠᠨ
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…
ᡝᠨᡩᡝᡵᡝᠮᡝ ᠪᡝᠶᡝ
{
  "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 ᠣᠴᡳ request.succeeded, request.failed ᠪᠠᠨᡳ request.canceled ᠵᡠᠯᡝ.
  • data ᠣᠴᡳ ᡝᡵᡝ ᡝᠨᡩᡝᡵᡝᠮᡝ ᠪᡝᠶᡝ ᠵᡠᠯᡝ ᠵᠠᠯᠠᠨ ᡳ ᡝᠨᡩᡝᡵᡝᠮᡝ ᠪᡝᠶᡝ᠂ GET /requests/{id} ᡳ ᠣᠯᡥᠣ ᠪᡝᠶᡝ ᠵᡠᠯᡝ.
  • id ᠣᠴᡳ ᡝᠨᡩᡝᡵᡝᠮᡝ ᠪᠠᠶᠠᠨ ᠪᠠᠨᡳ ᡝᡵᡝ ᠮᡠᠶᠠᠨ ᡳ ᠪᠠᡳᡨᠠᠯᠠᠩᡤᡝ ᡩᡝ ᠪᠠᠨᡳᠮᡝ᠂ ᡝᠯᡝ ᠣᠯᡥᠣ ᠵᠠᠯᠠᠨ ᠪᡝ ᠵᡠᠯᡝ ᠪᡝ ᠰᡳᠯᡤᠠᠨᠠᠮᡝ ᠵᠠᠯᠠᠨ ᠪᡝ ᡠᠯᡥᡳᠮᡝ ᠪᠠᠨᡳ.

ᡝᠨᡩᡝᡵᡝᠮᡝ ᠪᠠᠶᠠᠨ ᠵᡠᠯᡝ ᠪᠠᠨᡳᠮᡝ

10 ᠰᡝᠺᡠᠨᡩᡝ ᡳᠨᡠ 2xx ᠪᠠᡳᡨᠠᠯᠠᠩᡤᡝ ᡩᡝ ᡩᠠᡵᠠᠨᠠᠮᡝ. ᡠᠮᡝ ᡩᡝᠯᡤᡳ (2xx ᠪᠠᠨᡳ ᠰᡳᠯᡤᠠᠯᠠᠮᡝ) ᠵᡠᠯᡝ ᠪᠠᠨᡳ ᠮᡠᠶᠠᠨᠠᠮᡝ: ᠵᡠᠯᡝ ᠪᠠᠶᠠᠨ 6 ᠵᠠᠯᠠᠨ᠂ 30 ᠰᡝᠺᡠᠨᡩᡝ᠂ 2 ᠮᡳᠨᡠᡨᡝ᠂ 10 ᠮᡳᠨᡠᡨᡝ᠂ 1 ᠴᡳᠣᠸᠠᠨ ᠪᠠᠨᡳ 6 ᠴᡳᠣᠸᠠᠨ. ᠵᡠᠯᡝ ᠵᡝᠪᡝ ᡩᠠᡵᠠᠨᠠᠮᡝ ᠣᠴᡳᠨᡳ ᡝᡵᡝ ᠪᠠᠶᠠᠨ ᠪᠠᠨᡳ ᡝᠨᡩᡝᡵᡝᠮᡝ.

ᠵᠠᠯᠠᠨ ᡳ ᠵᡠᠯᡝ ᠪᠠᠨᡳᠮᡝ

ᠵᡠᠯᡝ ᠵᠠᠯᠠᠨ ᡩᡝ ᠪᡳᠶᠠ ᠵᡠᠯᡝᠨ ᡳ ᡤᠠᠰᡥᠠᠨ ᠪᠠᠨᡳᠨᠠᠮᡝ. GET https://api.doitong.com/v1/account ᡳ ᠵᡠᠯᡝ ᠮᡠᠶᠠᠨ ᠮᠠᠨᡳ (webhook_signing_secret᠂ ᡝᠯᡝ whsec_ ᡩᡝ ᡝᠵᡝᠨ) ᡠᠯᡥᡳᠮᡝ ᠪᠠᠨᡳᠮᡝ ᠵᡠᠯᡝ ᠵᠠᠯᠠᠨ ᡩᡝ ᠵᡠᠯᡝ ᠪᠠᠨᡳᠮᡝ.

Doitong-Signature ᡳ ᠵᠠᠯᠠᠨ ᠣᠴᡳ t=<unix time>,v1=<signature>᠂ ᡝᡵᡝ ᠵᡠᠯᡝ ᠣᠴᡳ "<t>.<raw request body>" ᡳ ᠮᡠᠶᠠᠨ ᡳ HMAC-SHA256 ᡳ ᡠᡵᠰᡝ ᠮᡠᠶᠠᠨᠠᠮᡝ᠂ ᠰᡳᠨᡳ ᠪᠠᠨᡳᠨ ᠣᠴᡳ ᠵᡠᠯᡝᠨ. ᠵᡠᠯᡝᠯᡝᠮᡝ:

  1. ᡝᠨᡩᡝᡵᡝᠮᡝ ᠣᠯᡥᠣ ᠪᠠᠶᠠᠨ ᡳ ᠮᡠᠶᠠᠨ ᠪᡝ ᠵᡠᠯᡝ ᠪᠠᠨᡳᠮᡝ ᠠᠪᡠᠰᡥᠠᠮᡝ᠂ JSON ᠵᡠᠯᡝᠯᡝᠮᡝ ᠪᠠᠨᡳᠮᠪᡝ ᠣᠴᡳᠨᡳ.
  2. ᠰᡳᠨᡳ ᠪᠠᠨᡳᠨ ᡩᡝ t + "." + body ᡳ HMAC-SHA256 ᠪᡝ ᡠᡵᠰᡝ ᠮᡠᠶᠠᠨᠠᠮᡝ ᠪᠠᠨᡳᠮᡝ ᠮᡠᠶᠠᠨ ᠪᡝ ᠪᠠᠷᠠ ᠦᠰᡳᡥᡝᠮᡝ ᠪᡝᠶᡝᠯᡝᠮᡝ.
  3. v1 ᡳ ᠵᡠᠯᡝ ᡩᡝ ᠮᡠᠶᠠᠨ ᠪᡝ ᠠᠮᠪᠠ ᠵᡠᠯᡝᠨ ᠪᠠᠨᡳᠮᡝ ᠰᡳᠯᡤᠠᠯᠠᠮᡝ.
  4. t ᠰᡳᠨᡳ ᠴᡳᠣᠸᠠᠨ ᡩᡝ 5 ᠮᡳᠨᡠᡨᡝ ᡩᡝ ᡩᠠᠯᡵᠠᠨ ᠣᠴᡳ ᠵᡠᠯᡝ ᠪᡝ ᡠᠯᡥᡳᠮᡝ᠂ ᠵᡠᠯᡝ ᠪᠠᠨᡳᠨ ᠪᡝ ᠪᠠᠨᡳᠮᡝ.

Node.js (Express) ᠪᠠᠨᡳ 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);
});

ᡤᡠᠯᡤᠠᠨ ᠵᡠᠯᡝ

  • ᠵᠠᠯᠠᠨ ᠪᡝ ᠮᡠᠶᠠᠨᠠᠮᡝ ᡝᠨᡩᡝᡵᡝᠮᡝ ᠰᡳᠨᡳ ᠵᡝᠪᡝ ᠵᠠᠯᠠᠨ ᡩᡝ ᠪᠠᠨᡳᠮᡝ.
  • ᠪᠠᠨᡳᠨ ᠣᠴᡳ ᠪᠠᠶᠠᠨ ᠪᠠᠨᡳᠮᡝ ᠪᡝᠶᡝ ᠪᠠᠨᡳᠮᡝ ᠵᡠᠯᡝᠨ ᡳ ᠪᠠᠨᡳᠨ ᠣᠴᡳ ᠵᡠᠯᡝᠨ ᠵᡠᠯᡝᠨ ᠣᠴᡳᠨᡳ.