Signature verification
Verify the provider's signature on the way in, and verify ours on the way out.
These pages describe ShellOrbit as it runs today. Breaking changes to the HTTP API are announced before they ship, and existing request and response shapes stay supported.
Why sign anything?
Your ingest URL is unguessable but not secret forever. Signing lets your handler prove that a delivery came from ShellOrbit and was not replayed by someone who captured it.
How do I verify a ShellOrbit delivery?
Every delivery carries a signature header:
ShellOrbit-Signature: t=1788445441,v1=5f2b1c9a0d...The signed payload is the timestamp, a dot, and the raw body. Compute HMAC SHA256 with your endpoint signing secret and compare in constant time.
import crypto from 'node:crypto';
export function verify(rawBody, header, secret, toleranceSeconds = 300) {
const pairs = header.split(',').map(value => value.split('='));
const timestamps = pairs.filter(([name]) => name === 't').map(([, value]) => value);
if (timestamps.length !== 1 || !/^\d+$/.test(timestamps[0])) return false;
const timestamp = Number(timestamps[0]);
if (!Number.isSafeInteger(timestamp) || Math.abs(Date.now() / 1000 - timestamp) > toleranceSeconds) return false;
const expected = crypto.createHmac('sha256', secret)
.update(`${timestamp}.`).update(rawBody).digest();
return pairs.filter(([name]) => name === 'v1').some(([, value]) => {
if (!/^[a-f0-9]{64}$/i.test(value || '')) return false;
return crypto.timingSafeEqual(expected, Buffer.from(value, 'hex'));
});
}Verify against the raw body. Parsing to JSON and re-serialising changes bytes and breaks the comparison.
Can you verify the provider’s signature for me?
On every plan, choose Stripe, Paddle, GitHub, Shopify, Standard Webhooks, or ShellOrbit and save the provider webhook secret. Verification uses the original incoming bytes. Quarantine stores an invalid request without forwarding it; observe mode records the failure and continues delivery. Deduplication applies only to verified provider identities.
Which senders does Standard Webhooks cover?
Standard Webhooks is a shared signing scheme used by Svix and by the many products that send through it, including Clerk, Resend, and Dodo Payments. Choose Standard Webhooks as the provider and paste the signing secret the sender gives you, which usually starts with whsec_.
ShellOrbit checks the webhook-id, webhook-timestamp, and webhook-signature headers, and the svix- versions of the same headers that Svix senders use. The signed content is the message id, the timestamp, and the raw body, joined by dots, signed with HMAC SHA256. A timestamp more than five minutes from now is refused, and during a secret rotation any one matching signature is enough. The webhook-id also serves as the provider event id for deduplication.
How do I rotate a signing secret?
An organization administrator can rotate the outbound key in endpoint settings. The new secret is shown once. For a fixed 24-hour overlap, deliveries include a v1 signature for each key; verify any matching signature, as the example does. The old key stops signing after that window. Another rotation is blocked until the overlap expires.
What is IP allowlisting?
On Business plans you can restrict which source addresses may post to an endpoint. Use it where a provider publishes stable egress ranges. Requests from outside the list are rejected by ingest with 403 and are not stored or counted.