Verify a delivery
A delivery arrives over the public internet at a URL anyone could discover. Verify first, then read the body. An unverified body must not reach your store, or your reporting numbers are whatever a stranger decided to POST.
The scheme, code samples in three languages, and secret rotation are documented in Security. This page is the reporting-receiver checklist and the two details that specifically matter for a pipeline.
The four steps
- Capture the raw body bytes before any JSON parsing.
- Recompute the HMAC-SHA256 of those bytes with your endpoint's signing secret, hex-encode it, and compare against the hex after
v0=inX-Revenexx-Signature. Compare in constant time. During a secret rotation the header carries several comma-separated signatures — accept the delivery if any of them matches. - Dedupe on the event
id(also sent asX-Revenexx-Id). - Return
2xxfast, then do the work out of band.
Reject an unverifiable request with 401. Do not process it, and do not return 2xx — an unverifiable request is not a real delivery.
The timestamp header
Every delivery carries X-Revenexx-Timestamp, the unix time the request was formatted. Use it to reject a delivery whose timestamp is implausibly far from your own clock — a few minutes' tolerance in either direction is a reasonable default — as a cheap defence against a replayed request.
Be clear about what that does and does not buy you:
- The signature covers only the raw body bytes. Nothing else is mixed in, so the timestamp header is not itself protected by the signature.
- Therefore a tolerance window is a hygiene control, not proof of freshness. Your real protection against a replay is idempotency: the same event
idmust never be counted twice, however often it arrives. - Your clock is part of the check. A receiver with a drifting clock and a tight window rejects genuine deliveries. If you enforce a window, run NTP and keep the window generous.
For a reporting receiver, dedupe on id is the control that matters. Treat the timestamp check as a bonus.
What to return, and when it retries
| Your response | The platform |
|---|---|
Any 2xx | Stops. You have taken responsibility for the event. |
Any non-2xx | Treats it as failed and retries with exponential backoff. |
| A connection error or a timeout | Same — failed, retried. |
Acknowledge first, work later. Verify, record the raw event, return 2xx — then transform, aggregate and load. A receiver that does its ETL before responding is a receiver that trips the timeout on the exact day the batch is largest, and then gets the same event again while it is still busy with the first copy.
An endpoint that keeps failing is auto-disabled, which for a reporting pipeline is indistinguishable from "the metrics went flat". See Delivery.
The other headers
| Header | Use it for |
|---|---|
X-Revenexx-Signature | The HMAC to verify. |
X-Revenexx-Id | Deduplication — the same value as the envelope's id. |
X-Revenexx-Topic | Routing, before you parse the body. |
X-Revenexx-Timestamp | The tolerance check above. |
Routing on the header lets a receiver hand a body to the right consumer without parsing it first, which keeps the acknowledge path short.
Where to go next
- Security — the scheme, working code, and secret rotation.
- Delivery guarantees — what at-least-once means for your figures.
- Incremental sync — reconciling what the stream told you against a re-read.