Does a failed Sume video job send a webhook to callback_url?

Yes. A job that ends in failure sends job.failed with a public error to the HTTPS callback_url you set on POST /v1/videos, signed like every Sume webhook.

4 min readSume
All posts

Yes. Pass an HTTPS callback_url on POST /v1/videos and Sume POSTs to it when the job reaches a terminal state. If the job fails, the event is job.failed, sent with a public error; success is job.completed and cancel is job.canceled.

Details are from the Webhooks guide and video docs, read 2026-09-30. Whether a failed job is billed is a separate question, answered in do failed AI video jobs cost money.

Which events can the callback receive?

Sume sends terminal events only. There are no progress or partial deliveries.

Job webhook events, read 2026-09-30: https://docs.sume.com/workflows/webhooks
EventWhen it is sentStatus in payload
job.completedA public result is availableOK
job.failedThe job failed with a public errorERROR plus an error object
job.canceledThe job reached canceled stateERROR plus an error object

How do I verify and branch on the event?

Sume signs the raw JSON body. Headers are x-sume-webhook-timestamp and x-sume-webhook-signature (sume-v1=<hex>), computed with HMAC SHA 256 over <timestamp>.<raw_body>. Read the raw body before parsing, refuse an empty secret, and reject old timestamps.

import crypto from "node:crypto";

export function handle(raw: string, ts: string, sig: string, secret: string) {
  if (!secret) throw new Error("missing webhook secret");
  const age = Math.abs(Date.now() / 1000 - Number(ts));
  if (!Number.isFinite(age) || age > 300) return "stale";
  const hex = crypto
    .createHmac("sha256", secret)
    .update(ts + "." + raw)
    .digest("hex");
  const want = "sume-v1=" + hex;
  const ok = sig.split(",").some((s) => {
    const a = Buffer.from(s.trim());
    const b = Buffer.from(want);
    return a.length === b.length && crypto.timingSafeEqual(a, b);
  });
  if (!ok) return "bad signature";
  const body = JSON.parse(raw);
  return body.event === "job.failed" ? "failed" : body.event;
}

What should the handler do on job.failed?

Record job_id and the error object, mark the item failed in your system, and decide whether to resubmit. Keep polling as a fallback: the docs recommend a polling path alongside webhooks, since a delivery can be missed.

Does the URL have to be public?

It must be HTTPS. For the model endpoints, webhook URLs must be public; localhost, private-network, and non-HTTPS URLs are rejected. See webhook URL rejected.

Sources

Related posts

More in Developers

All Developers posts

Written by Sume