Appearance
Headers & Signature Passthrough
SignalBin doesn't sign anything. There's no HMAC secret and no X-SignalBin-Signature header, and nothing in the capture or forward path computes a signature of its own. What it does instead is simpler: it passes the original request through, headers and all.
INFO
If you came here looking for "how do I verify SignalBin's signature", that feature doesn't exist. This page covers what actually happens to headers on the way through, plus what people usually mean when they ask about "securing" a SignalBin endpoint.
Signature headers pass through on fan-out
When a provider sends a webhook, whether that's Stripe, GitHub, or anything else that signs its payloads, the signature lands in a header like Stripe-Signature or X-Hub-Signature-256, computed over the raw body using a secret only you and the provider share. SignalBin has no part in that computation and doesn't need one.
The automatic fan-out that runs the moment a webhook is captured relays the request as the provider sent it, with the original body and the original headers, including that signature header. A destination is your own system receiving the original webhook, so it verifies the signature exactly the way it always would, against the same secret you configured with the provider directly. Testing against a signing provider through SignalBin therefore works the same as testing against it directly: point the provider at your SignalBin endpoint URL, and your destination sees the same bytes it would have seen from the provider.
A few things shape that relayed request along the way:
- Header stripping is configured per destination, in the Strip headers field of the Add destination dialog (see Endpoints & Destinations). Strip
Stripe-Signature,X-Hub-Signature-256, or whatever your provider uses, and verification fails downstream, not because SignalBin altered the signature but because it never arrived. - Connection-scoped headers are always dropped.
Connection,Content-Length,Host,Transfer-Encoding, and the rest of the hop-by-hop set describe the link the request arrived on rather than the message itself, so they go regardless of configuration. None of them are part of a signature computation. - An endpoint's
X-SignalBin-Secretheader is relayed like any other. It's meant for SignalBin rather than for your destination, so add it to that destination's Strip headers if you'd rather it stopped here. - The destination URL is used as-is. The captured request's path and query string aren't appended to it, so a provider that signs over the URL rather than the body has nothing to check against downstream.
Replay sends the stored copy, not the original
SignalBin redacts sensitive values on the way into storage, and manual replay resends what's in storage rather than the original bytes.
A header counts as sensitive when its name contains signature, secret, token, password, credential, or an API-key spelling such as api-key or apikey. Authorization, Cookie, and Set-Cookie count too. Those values are stored as the literal string [redacted], and JSON or form-encoded body fields named the same way get the same treatment. So a replayed request arrives at your destination carrying Stripe-Signature: [redacted] in place of the provider's real signature, and any verification your endpoint performs on it fails.
The redaction is deliberate: the stored capture is what the workspace UI and the API show to anyone with access, and a provider signature is a credential in its own right. Open any capture's Headers panel and you can see for yourself which values were masked on the way in. Replay is good for exercising your handler's logic, but it won't reproduce a signature check. For that you need a fresh webhook from the provider, which travels the fan-out path.
The shared secret is a different thing
An endpoint's optional shared secret is not a signature scheme, and the two are easy to confuse. It's a static string you and the sender agree on, sent either as an X-SignalBin-Secret header or a secret query parameter, and checked against a stored hash before SignalBin decides whether to store the request at all:
- A request without the right secret is turned away and never stored. The sender gets an authentication error (
401 invalid_endpoint_secret). - A matching secret, or no secret configured on the endpoint, means the request is captured as normal.
It protects your endpoint from unwanted traffic, an access gate on the way in, but it doesn't sign the payload, and it has no bearing on what a provider's own signature header looks like once the request is relayed onward. See Endpoints & Destinations for how to set one up with Rotate and reveal secret.
Loop protection
Separately from signing, SignalBin guards against a destination that points back at one of its own ingest URLs. Every relayed request carries a hop counter in X-Signalbin-Relay-Count, and a captured request that already carries a count of 1 or more is not relayed again. The guard has no slack on purpose: with up to 10 destinations fanning out per hop, each extra hop it tolerated would multiply the possible amplification tenfold.
This isn't a security feature aimed at your provider's signature. It's protection for SignalBin's own forwarding pipeline, so a misconfigured destination can't turn one webhook into an unbounded loop of deliveries. It applies to the automatic fan-out only, so a manual replay of a chained capture still goes through.
Summary
| Concept | What it is | What it isn't |
|---|---|---|
Provider signature headers (Stripe-Signature, etc.) | Passed through verbatim on fan-out; [redacted] on manual replay | Never generated or verified by SignalBin |
X-SignalBin-Secret | Access control on whether a request gets stored | Not a payload signature |
X-Signalbin-Relay-Count | Loop prevention for the forwarding pipeline | Not related to signing or verification |