A correct receiver does four things in a fixed order. Getting the order wrong is the usual bug.
In the dashboard, for the environment you are working in, set an HTTPS URL and copy the signing secret.
The whsec_… secret is shown once, at creation and at explicit rotation. Sakawave stores a verifier, not the secret — a lost secret cannot be recovered, only rotated. Put it in a secrets manager before you close the dialog.
Sakawave will refuse a URL that is not HTTPS, carries credentials or a fragment, is longer than 2048 characters, or resolves to anything other than a public internet address. Localhost and private ranges are rejected, at configuration time and again at delivery.
2. Write the receiver
The order matters: raw body, verify, deduplicate, acknowledge, then work.
Five things that receiver gets right, each of which is a common failure:
- Raw bytes. Parsing and re-serialising changes whitespace and key order, and the signature is over the exact bytes sent.
- Timestamp before HMAC. A cheap check first.
- Constant-time comparison, on equal-length buffers.
- Deduplication on the header id. The body has no id at all.
- Acknowledge fast, work later. You have ten seconds, and the work is not what you are being timed on.
3. Handle the event
An unrecognised event type is not an error. You receive every event for your business, including ones added after you wrote this, so the default branch must be a no-op rather than a throw.
4. Test it
Send a test event from the dashboard. It uses the same signing and delivery path as every real event, so a receiver that accepts endpoint.test will accept the rest.
Then check the four failure modes deliberately:
- A tampered body → your handler returns
401.
- A stale timestamp →
400.
- The same event twice →
2xx, and the work happens once.
- An unknown event type →
2xx, and nothing happens.
5. Add the sweeper
Delivery is one attempt with no automatic retry. Before you ship anything that moves money, add a reconciliation job.
Next