Skip to content

Jobs और webhooks

Media generation asynchronous है: job ID लेकर poll करें या callback_url दें। Webhook signature source की पुष्टि करता है।

  • Status queued और processing से completed या failed होता है।
  • Polling सरल है; webhook के लिए public HTTPS receiver चाहिए।
  • Duplicate delivery स्वीकारें, signature जाँचें और job ID से idempotent processing करें।

पूरे उदाहरण

मूल गाइड के सभी चलने योग्य उदाहरण नीचे सुरक्षित रखे गए हैं। केवल अपने टूल और ऑपरेटिंग सिस्टम से संबंधित ब्लॉक चलाएँ।

POST /media/generate  →  status: processing  ──►  done   (result_url ready)
        │                                     └─►  failed (error, funds refunded)
        └── (optional) callback_url → push webhook on done/failed
json
{ "id": "beefb531-…", "model": "image/nano-banana-2", "status": "processing",
  "poll": "https://nordrouter.com/media/job/beefb531-…" }
json
{ "id": "beefb531-…", "status": "done",
  "result_url": "https://nordrouter.com/media/file/beefb531-…",
  "cost_usd": 0.052, "error": null }
bash
curl https://nordrouter.com/media/job/beefb531-…
bash
curl https://nordrouter.com/media/generate \
  -H "Authorization: Bearer sk-nr-YOUR-KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "image/nano-banana-2",
    "input": { "prompt": "…" },
    "callback_url": "https://your-server.com/webhooks/nordrouter",
    "callback_secret": "any-string-of-yours"
  }'
json
{ "event": "media.completed", "id": "beefb531-…", "status": "done",
  "result_url": "https://nordrouter.com/media/file/beefb531-…",
  "cost_usd": 0.052, "error": null }
python
import hmac, hashlib

def verify(raw_body: bytes, header: str, secret: str) -> bool:
    expected = "sha256=" + hmac.new(secret.encode(), raw_body, hashlib.sha256).hexdigest()
    return hmac.compare_digest(expected, header)  # constant-time compare
javascript
import crypto from "node:crypto";
function verify(rawBody, header, secret) {
  const expected = "sha256=" + crypto.createHmac("sha256", secret).update(rawBody).digest("hex");
  return crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(header));
}
javascript
import express from "express";
import crypto from "node:crypto";

const SECRET = "any-string-of-yours";          // = your callback_secret
const app = express();

app.post("/webhooks/nordrouter",
  express.raw({ type: "application/json" }),    // raw body — required for the signature
  (req, res) => {
    const expected = "sha256=" + crypto.createHmac("sha256", SECRET).update(req.body).digest("hex");
    const got = req.headers["x-nr-signature"] || "";
    if (expected.length !== got.length || !crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(got)))
      return res.sendStatus(401);              // signature mismatch — not from us
    const job = JSON.parse(req.body);
    if (job.event === "media.completed") console.log("done:", job.result_url, "$" + job.cost_usd);
    res.sendStatus(200);                        // reply 2xx or we retry
  });

app.listen(3000);
python
import hmac, hashlib
from fastapi import FastAPI, Request, Response

SECRET = b"any-string-of-yours"                # = your callback_secret
app = FastAPI()

@app.post("/webhooks/nordrouter")
async def hook(request: Request):
    raw = await request.body()                 # raw bytes — required for the signature
    expected = "sha256=" + hmac.new(SECRET, raw, hashlib.sha256).hexdigest()
    if not hmac.compare_digest(expected, request.headers.get("X-NR-Signature", "")):
        return Response(status_code=401)       # signature mismatch — not from us
    job = await request.json()
    if job["event"] == "media.completed":
        print("done:", job["result_url"], "$", job["cost_usd"])
    return Response(status_code=200)           # reply 2xx or we retry

आधिकारिक दस्तावेज़ और लिंक

PollingWebhook
Public https addressnot neededrequired
Latencyup to poll intervalnear-instant
Guaranteeyou control itbest-effort + polling backup
Best forscripts, CI, laptopservers, production backends

पहले न्यूनतम text request से कनेक्शन जाँचें, फिर streaming, tool calls, images और दूसरी advanced सुविधाएँ जोड़ें। API key को public code या browser frontend में कभी न रखें।

समस्या निवारण