BigCommerce sends only the order ID: fetch it, then render a Sume clip

BigCommerce order webhooks carry a scope and an ID, not the order. Ack, fetch the order yourself, then submit POST /v1/videos to Sume with a stable key.

4 min readSume
All posts

A BigCommerce webhook does not contain the order. It contains a scope, a data object with a type and an id, and a hash. So the pattern is three steps: answer 200 immediately, fetch the order from BigCommerce, then submit a video job to Sume and let Sume call you back when it is done.

Everything about the order itself (line items, product images, copy) has to come from your own call to BigCommerce, which this post does not cover. The Sume half is below.

What arrives from BigCommerce

Per the BigCommerce webhooks page, callbacks are deliberately small.

BigCommerce webhook payload fields, read 2026-10-05
FieldContent
store_id, producerWhich store and which BigCommerce producer sent it
scopeThe event name
dataAn object holding the event type and the id (the example shows only type and id)
hashUsed for duplicate detection

What Sume gives you back

POST /v1/videos is asynchronous. A submit returns 202 with an id, a polling_url, a status and the model. The video is downloaded later from GET /v1/videos/{id}/content.

Sume video submit, from Sume docs checked 2026-10-05
ItemValue
SubmitPOST https://api.sume.com/v1/videos
Response202 with id, polling_url, status (pending on submit), model
Completion noticecallback_url (HTTPS); the signed event is job.completed, job.failed or job.canceled
Required fieldsmodel and prompt
Example modelseedance-2: 4 to 15 second durations, 480p, 720p and 1080p

Submit with a key derived from the order

BigCommerce can deliver the same event more than once, so derive the Sume idempotency key from the order id. The Sume jobs docs say to send an Idempotency-Key on submit requests that a client may retry, and that the same key with the same payload returns the original job. The /v1/videos page itself does not list that header in its parameter table, so confirm it against the live OpenAPI before you rely on it; your own order-id lookup table is the fallback.

const KEY = process.env.SUME_API_KEY;

async function renderOrderClip(orderId, prompt) {
  const res = await fetch("https://api.sume.com/v1/videos", {
    method: "POST",
    headers: {
      Authorization: `Bearer ${KEY}`,
      "Content-Type": "application/json",
      "Idempotency-Key": `bc-order-${orderId}`,
    },
    body: JSON.stringify({
      model: "seedance-2",
      prompt,
      duration: 5,
      resolution: "720p",
      callback_url: "https://hooks.example.com/sume",
    }),
  });
  if (res.status !== 202) throw new Error(`submit failed: ${res.status}`);
  return (await res.json()).id;
}

async function main() {
  console.log(await renderOrderClip(1234, "Product shot, slow push-in"));
}
main();

Wire it up

  • BigCommerce handler: store the id, return 200 at once, enqueue the rest.
  • Worker: fetch the order from BigCommerce, build the prompt, call renderOrderClip, save the Sume job id against the order.
  • Sume callback handler: verify the HMAC signature, dedupe on job_id, fetch the result, attach the clip to the order.
  • Backup: poll GET /v1/jobs/{id}/status if no callback arrives. Sume says to keep polls available for deliveries that never come.

Sources

Related posts

More in Integrations

All Integrations posts

Written by Sume