Security policy
Anyone who knows your endpoint URL could send it requests. To be sure an event genuinely comes from Tomorro, verify the signature on every request before acting on it.Signing secret
Each webhook has its own secret, generated when you create it and shared only between Tomorro and you. Tomorro uses it to sign every event; you use it to verify them. Treat it like a password — never expose it client-side or commit it to source control.Signature header
Every event is sent with a signature header. Tomorro signs the event by computing an HMAC-SHA256 over the timestamp and the raw request body, using your webhook secret:Leeway-Signature header, in the form t=<timestamp>,sha256=<hash>:
t— the timestamp the event was signed at, in milliseconds since the Unix epoch.sha256— the computed HMAC-SHA256 hash, hex-encoded.
For backward compatibility the same value is also sent in a
Leeway_Signature header (with an
underscore). Prefer the canonical Leeway-Signature; some proxies strip headers that contain
underscores.Verifying the signature
To verify, recompute the HMAC overtimestamp + "." + rawBody with your secret and compare it
to the sha256 value from the header.
Node.js
Always use a constant-time comparison (e.g.
timingSafeEqual) rather than === to avoid
timing attacks.Replay protection
The signed timestamp also lets you reject replayed events: comparet to the current time
and discard anything outside a tolerance window you control (5 minutes is a reasonable default,
as shown above). This prevents an attacker from re-sending a previously valid, intercepted
request.
Delivery & retries
What counts as a successful delivery
When Tomorro sends an event, your endpoint must:- respond with a
2xxHTTP status code, and - do so within the 3-second timeout.
Retry policy
If a delivery fails, Tomorro automatically retries it:- Failed events are re-queued with a 5-minute delay between attempts.
- Tomorro retries up to 10 times for a given event.
- If every attempt fails, Tomorro stops retrying and disables the webhook. A disabled webhook receives no further events until you re-enable it from the Webhooks settings.
Because retries are spaced 5 minutes apart, your endpoint may receive the same event more than
once. Make your handler idempotent — deduplicate using the
eventId field so reprocessing
a delivery has no side effects.Exact timeout and retry values may change over time as we tune delivery.