APIGuides

Webhooks

Get told when a format or video you started through the API is ready or failed, and check that each message came from 10xvid.

Add a webhook

Open the API keys page in the app, go to Webhooks, and give the address of your server. It must start with https://. You get a signing secret beside it. Send test sends a ping at once and shows what your server answered.

Only what you started through the API tells your webhook. What you make in the app does not.

Events

EventWhen it is sent
format.readyThe Format DNA is written and passed: videos can be made from it.
format.failedThe site could not be read, or the Format DNA could not be written. What it cost was given back.
video.doneA video finished. Its files are in the message.
video.failedA video could not be finished. Its price was given back.
image.done, image.failedThe same for image ads.
pingThe Send test button.

The message

A POST with a JSON body. data.object is the format or the video, the same as the API answers for it.

{
  "id": "evtmgn5c1a2b3c",
  "object": "event",
  "type": "video.done",
  "created": "2026-10-13T10:02:18.120Z",
  "data": { "object": { "id": "MV40XXRN514AA9", "object": "video", "status": "done", "files": [] } }
}

Three headers come with it:

HeaderWhat it holds
X-10xvid-Signaturet=<seconds>,v1=<signature>
X-10xvid-EventThe event, such as video.done
X-10xvid-DeliveryThe message's id, the same on every try

Check the signature

The signature is the HMAC SHA-256 of the seconds, a full stop and the raw body, under your webhook's secret, as Stripe signs its own. Check it, and turn away a message more than five minutes old.

import crypto from 'node:crypto';

export function isFrom10xvid(body, header, secret) {
  const [, t, v1] = /t=(\d+),v1=([a-f0-9]{64})/.exec(header ?? '') ?? [];
  if (!v1 || Math.abs(Date.now() / 1000 - Number(t)) > 300) return false;
  const want = crypto.createHmac('sha256', secret).update(`${t}.${body}`).digest('hex');
  return crypto.timingSafeEqual(Buffer.from(v1), Buffer.from(want));
}

Answer, and tries again

Answer with any 2xx. Anything else, or no answer within 10 seconds, and the message is sent again after 1 minute, 5 minutes, 30 minutes, 2 hours and 6 hours, then given up. The last messages and what your server answered are listed under the webhook. Use X-10xvid-Delivery to notice a message you already handled.

A new secret

New secret signs every message from then on with a new one. Put it on your server before the next message arrives.