The SDK’s webhook surface is intentionally narrow today: a signature verifier you call inside your webhook handler. Endpoint management (create / list / revoke) is dashboard-only — see the Webhooks concept.Documentation Index
Fetch the complete documentation index at: https://docs.tallyforagents.com/llms.txt
Use this file to discover all available pages before exploring further.
Types
WebhookVerifyInput
WebhookVerifyResult
DEFAULT_TOLERANCE_SECONDS
toleranceSeconds field on WebhookVerifyInput to override.
Methods
tally.webhooks.verifySignature(input)
Verifies a tally-signature header against the raw request body.
WebhookVerifyResult. Synchronous; no HTTP, no allocation beyond the HMAC buffer.
verifySignature(input) (standalone)
The same function, exported directly for consumers who don’t want to instantiate a Tally client just to verify a webhook.
Full receiver example
Next.js App Router handler:Why pass the raw body
The HMAC is computed over the exact bytes Tally signed —<unix_ts>.<body>. Any transformation (parsing, re-stringifying, whitespace normalization) breaks the match.
In most frameworks, getting the raw body is await req.text() or equivalent. Don’t call req.json() and then JSON.stringify the result back — round-tripping through your runtime’s JSON parser changes key ordering, whitespace, or both, depending on the runtime.
If you’re behind a middleware or framework that consumes the body automatically (Express’s body-parser, for example), you’ll need to opt out for the webhook route. Most frameworks support a “give me the raw bytes” mode for this exact case.
Rejection reasons
WhenverifySignature returns { ok: false, reason }, the reason tells you exactly what failed:
| Reason | Meaning | Likely cause |
|---|---|---|
missing_header | No tally-signature header on the request. | Wrong endpoint, or the proxy stripped headers. |
malformed_header | The header doesn’t parse — couldn’t extract t=. | Manual testing with the wrong format. |
no_v1_signature | The v1= segment is absent. | Same — manual tests, or a future signature version Tally adds. |
timestamp_out_of_tolerance | The t= timestamp is more than toleranceSeconds away from now. | Clock skew on either side, or a replayed payload. |
signature_mismatch | The header parsed and the timestamp is in window, but the HMAC doesn’t match. | Wrong secret, or the body was modified in transit. |
Tolerance window
The default 5-minute tolerance is calibrated for the realities of clock drift across servers and Tally’s retry schedule (the first retry is 1 minute after the initial attempt). Don’t widen it casually:timestamp_out_of_tolerance, fix the clock skew on your receiving server first.
Not yet in the SDK
tally.webhooks.list()/create()/revoke()— endpoint management.tally.webhooks.deliveries.list()/replay()— delivery log access.