webhook, sqs, rabbitmq, eventbridge) send each matched event to a destination you own. A pull sink holds events on a server-side cursor that your consumer reads on its own schedule. This page covers what your consumer must do in each case.
Verifying a webhook signature
Every webhook delivery is signed with an HMAC over the request timestamp and the exact request body, so you can prove the request came from Streaming Hub and was not tampered with or replayed. Two headers carry the signature:
The signature is computed as:
- Read the raw body and the timestamp — verify before parsing the body, over the exact bytes received. Any re-serialization changes the bytes and breaks the signature.
- Check freshness — reject the request if
X-Webhook-Timestampis more than 5 minutes from now. This is the replay-protection window. - Recompute the signature — build
signature_inputas above with your signing secret and hex-encode the HMAC-SHA256. - Compare in constant time — compare your
v1,sha256=<hex>against the receivedX-Webhook-Signaturewith a constant-time (timing-safe) comparison. Reject on mismatch. - Respond — return
2xxonly after the signature and freshness both pass.
Handling two signatures during rotation
When you rotate a signing secret, the hub runs a 24-hour dual-sign overlap. During the overlap each delivery carries two
X-Webhook-Signature headers — one signed with the new secret and one with the previous secret — sent as repeated headers, so you can migrate to the new secret without dropping any delivery.
Verify against both: recompute the expected signature with each secret you currently hold, and accept the request if either received signature matches. Once you have deployed and confirmed the new secret, retire the old one.
Correlation headers
Every webhook delivery also carries a set of
X-Lerian-* context headers:
Deduplicating deliveries
Delivery is at-least-once: the hub may deliver the same event more than once, through retries or a redelivery after a worker restart. Deduplicate on
X-Lerian-Event-Id — it is stable across every redelivery of the same event, while X-Lerian-Delivery-Id differs per attempt. Treat a X-Lerian-Event-Id you have already processed as a duplicate: acknowledge it with a 2xx and do not reprocess. Keep your handler idempotent.
Responding quickly
Return a
2xx as soon as you have verified and durably accepted the event — then do the real work asynchronously. A slow or failing response is treated as a failed delivery, which triggers the retry curve and, if the destination stays broken long enough, eventually auto-disables the subscription. Acknowledge fast, process out of band.
Pulling events
A
pull subscription receives no push. Instead, your consumer reads a page of its events with:
seq, its ceId (for dedup), its type, and its payload. The response includes a next_cursor.
The read is the acknowledgment (cursor-as-ack). Fetching a page advances the subscription’s durable cursor to the highest seq returned. There is no separate ack call — reading a page acknowledges it. This is monotonic, so it never moves backward.
To page through normally, resume from the server’s next_cursor and stop when a short page (fewer than your limit) returns null. Two behaviors to keep in mind:
- A forward
?after=seek forfeits the gap. Passing?after=Ngreater than your current cursor advances the cursor past everything up toN— the skipped events are never redelivered. Asking for events afterNdeclares everything up toNconsumed. This can only happen with a hand-crafted forward seek, never through normalnext_cursorpagination. - A backward
?after=seek never rewinds. A stale or lower?after=that reads an older page does not move the cursor back, because the cursor only ever advances.
429 rate_limited — back off and retry. Deduplicate pulled events on ceId, just as a webhook consumer deduplicates on X-Lerian-Event-Id.
Next steps
Managing subscriptions
Create subscriptions, rotate secrets, and recover disabled destinations.
Operating Streaming Hub
Deploy, configure, and observe the hub.

