About webhooks
Understand callbacks, subscriptions, signatures, delivery behavior, and retry rules in OmniLab webhooks.
This article explains how OmniLab turns product events into outbound HTTPS requests. If you are preparing a receiver or reviewing a webhook design with OmniLab, start here.
The two objects that matter
| Object | What it does | Typical fields |
|---|---|---|
| Callback | Defines where OmniLab sends requests and how the outbound request is shaped | HTTPS URL, authentication mode, signing secret, optional method/body/URL/header transformation |
| Subscription | Defines which events reach a callback | Event types, optional filters, status |
A single callback can receive several subscriptions. Subscriptions can narrow delivery to one tenant, one group, or one interaction, depending on what your downstream system needs.
Delivery flow
What OmniLab sends by default
- HTTPS requests only
POSTby defaultapplication/jsonby default- The raw source event as the request body unless a transformation is configured
- Delivery headers on every request
- A maximum raw payload size of
256 KBper delivery request
OmniLab can also transform the method, URL, content type, request body, and custom headers when a downstream system expects a different shape.
Headers to expect
| Header | What it means | How to use it |
|---|---|---|
webhook-id | Unique delivery identifier, prefixed with msg_ | Treat it as an idempotency key in your receiver |
webhook-timestamp | Unix timestamp used for signing | Check freshness before you accept the request |
webhook-signature | One or more v1,<base64-hmac> signatures over the raw body | Verify the request before processing it |
User-Agent | OmniLab-Webhook/1.0 | Helpful for diagnostics and allow-listing |
Authentication modes for outbound callbacks
OmniLab can send callbacks with one of these authentication strategies:
- No additional auth header
- Basic auth
- Bearer auth, using
Authorizationor another agreed header name - OAuth 2.0 client credentials, where OmniLab first exchanges the callback client ID and secret for an access token
If an OAuth 2.0 protected receiver returns 401, OmniLab can retry once after refreshing the access token.
Retry behavior and failure handling
2xxresponses are treated as success.5xx, transient network failures, timeouts, and429responses are retryable.- If your receiver returns
429, OmniLab can respect theRetry-Afterheader when it is present. 4xxresponses other than429are treated as permanent failures.410 Gonedeactivates the callback so later events stop generating outbound requests until the callback is corrected.- The same event and callback combination is deduplicated on OmniLab's side, but your receiver should still be idempotent because retries can reuse the same delivery identifier.
Signing and key rotation
OmniLab computes the signature from this exact string:
webhook-id + "." + webhook-timestamp + "." + raw_request_bodyThe signature uses HMAC-SHA256 and is returned with a v1, prefix.
import crypto from "node:crypto";
function isValidOmniLabSignature({
header,
webhookId,
webhookTimestamp,
rawBody,
signingSecret,
}) {
const signedPayload = `${webhookId}.${webhookTimestamp}.${rawBody}`;
const expected =
"v1," +
crypto
.createHmac("sha256", Buffer.from(signingSecret, "base64"))
.update(signedPayload)
.digest("base64");
return header.split(" ").includes(expected);
}During signing-secret rotation, OmniLab can send both the current and previous v1,... signatures in the same webhook-signature header. Accept either value during the rollout window, then retire the old secret on your side.