Skip to content

Webhooks

What a webhook is

Benchmark sends one webhook event as a JSON POST to your HTTPS URL when a collection finishes.

The event type is collection.completed or collection.failed.

Set it up

Only a workspace admin can manage webhooks.

  1. Open Webhooks in the dashboard settings.
  2. Enter your HTTPS URL in Webhook URL. The URL must use the default HTTPS port and a public host name.
  3. Select Save and generate secret.
  4. Copy the Signing secret. It is shown one time.

After setup, the button says Rotate secret. Rotating saves the URL and a new secret at once. New events use the new values. Events that are already waiting, and their retries, keep the old URL and secret.

What Benchmark sends

Every event has these fields:

  • eventId: the event ID.
  • collectionId: the collection ID.
  • type: the event type.
  • entityType: profile, post, or link.
  • dataLevel: basic or enriched.
  • changed_fields: an optional list of fields that changed.
  • data: the result for a completed event, null when the data is not available, or an empty object for a failed event.
  • coverage: present when data is null. It says why no public result was available. private means the source indicates that the content is not public. Benchmark does not retrieve it. not_found means the content was not found.

This failed event uses values from the API description:

{
"collectionId": "20000000-0000-4000-8000-000000000003",
"dataLevel": "enriched",
"data": {},
"entityType": "post",
"eventId": "70000000-0000-4000-8000-000000000008",
"type": "collection.failed"
}

Webhook events contain only the structured fields shown in the schema. They do not include source media or transcript content.

Headers

Each request has these headers:

  • Benchmark-Idempotency-Key: the event ID.
  • Benchmark-Timestamp: the number of seconds since January 1, 1970.
  • Benchmark-Signature: the request signature.

Check the signature

The signature starts with v1=. The rest is the hex HMAC-SHA256 of TIMESTAMP.BODY. Benchmark uses your signing secret as the key. BODY is the exact raw request body.

Check each request in this order:

  1. Read the raw body before you parse the JSON.
  2. Join the timestamp, a period, and the raw body as TIMESTAMP.BODY.
  3. Compute the HMAC-SHA256 with your signing secret.
  4. Compare the two values in constant time.
  5. Reject old timestamps. You can choose five minutes as your own limit. Benchmark does not set a time limit for you.
  6. Use Benchmark-Idempotency-Key to ignore repeats.

This Node.js example checks a raw Buffer body:

import { createHmac, timingSafeEqual } from "node:crypto";
function hasValidSignature({ rawBody, secret, signature, timestamp }) {
const match = /^v1=([0-9a-f]{64})$/.exec(signature);
if (!match) return false;
const expected = createHmac("sha256", secret)
.update(timestamp)
.update(".")
.update(rawBody)
.digest();
const received = Buffer.from(match[1], "hex");
return timingSafeEqual(expected, received);
}
const rawBody = Buffer.from('{"type":"collection.failed"}');
const secret = "YOUR_WEBHOOK_SECRET";
const timestamp = "1787563200";
const signature = "YOUR_BENCHMARK_SIGNATURE";
console.log(hasValidSignature({ rawBody, secret, signature, timestamp }));

Retries

Benchmark retries when the request times out, the network fails, or your server returns 408, 429, or any 5xx status. It makes up to eight tries in total. The wait gets longer after each failed try.

Benchmark follows up to three redirects. These stop the retries: any other 3xx or 4xx response, too many redirects, or a URL that Benchmark cannot send to.

Return any 2xx response as soon as you can.

A webhook can arrive more than once. Use the idempotency key to ignore repeats.

A late or failed webhook does not change the collection. You can always check it with GET /v1/collections/COLLECTION_ID.