securityToken — a shared secret between Raise and the partner endpoint. Raise uses this token to sign outgoing webhook deliveries; the partner endpoint verifies the signature on every incoming request to confirm the request actually came from Raise rather than from a forger.
Signature verification is not optional. Without it, any party that learns the partner’s webhook URL can deliver forged events to the integration — and the partner endpoint has no way to know the difference. This page covers the verification pattern, the practical defenses, and what’s known about the exact algorithm.
The signing model
The mechanism follows the standard webhook signature pattern used by Stripe, GitHub, and most other major API platforms: The two sides hold the same shared secret. Raise computes a signature over the request body using the secret; the partner computes the same signature using its copy of the secret. If both signatures match, the partner knows the request came from Raise. If the partner’s recomputed signature doesn’t match what Raise sent, the request didn’t come from Raise — or the request body was tampered with in transit. Either way, reject it.What the spec confirms
The Raise OpenAPI spec is explicit about one thing: theWebhookRequest carries a securityToken field that the partner sets when creating or updating a subscription. This is the shared secret.
⚠️ Spec gap: The Raise OpenAPI spec doesn’t document the exact signature algorithm or the header name that carries the signature. The patterns on this page describe the general HMAC-based approach that most webhook systems use and that the
securityToken field strongly suggests Raise uses; partners building production integrations should confirm the exact algorithm and header name against the live API or with the platform team before deployment.Until the spec is updated, the practical approach is to inspect a few real webhook deliveries (via the webhook log endpoints, or by capturing a request at the partner endpoint) to identify the signature header and confirm the algorithm.Generating a strong security token
The strength of signature verification is bounded by the strength of the secret. A predictable or short secret can be guessed; a strong secret cannot. Generate thesecurityToken with a cryptographically secure random source — at least 32 bytes of entropy:
JavaScript
Store the token in your secrets manager. The partner side will read it on every incoming request to verify signatures.
The verification pattern
The general verification pattern, in pseudocode:Step 1: read the signature header
The exact header name isn’t documented in the spec. Partner integrations need to identify it by inspecting real deliveries. Likely candidates based on common webhook conventions:X-Raise-SignatureX-SignatureSignatureX-Webhook-Signature
serverResponse field on a webhook log entry, or capture an incoming request at the partner endpoint and read the headers.
JavaScript
Step 2: read the raw body
Don’t parse the JSON yet. The signature is typically computed over the exact bytes of the request body. If your HTTP framework parses the body to JSON before you can access the raw bytes, the signature comparison will silently fail because re-serializing the parsed JSON produces different bytes than the original. For Express:JavaScript
JavaScript
Step 3: compute the HMAC
The standard webhook signature algorithm is HMAC-SHA256. Until the Raise spec confirms the exact algorithm, start with this assumption:JavaScript
digest('base64')instead of'hex''sha1'instead of'sha256'- Including a timestamp prefix (
${timestamp}.${rawBody}) if Raise includes a timestamp header - A different secret encoding (base64-decoded vs. raw string)
Step 4: constant-time comparison
A naive string-equality comparison can leak information about the secret through timing attacks. Use a constant-time comparison:JavaScript
crypto.timingSafeEqual (in Node.js) and equivalent functions in other languages produce a comparison that takes the same amount of time regardless of how many characters match. This prevents an attacker from learning the signature byte-by-byte through timing observation.
Step 5: parse and process
Only after verification passes should the body be parsed and processed:JavaScript
A complete verification function
JavaScript
sha256), the digest encoding (hex), and the header name (x-raise-signature) against actual deliveries before relying on this in production. The function structure stays the same; only the specifics may need adjustment.
Rotating the secret
Webhook secrets should be rotated periodically — typically every 90 days for high-sensitivity integrations, every 6–12 months for lower-sensitivity ones. The challenge: rotation must be coordinated so both sides hold the same secret at all times, without dropping deliveries during the cutover.The dual-secret rotation pattern
The standard pattern: the partner accepts either the old or the new secret during the rotation window.1
Generate a new secret
On the partner side, generate a fresh
securityToken. Store it alongside the existing one in your secrets manager, both marked as valid.2
Update the verification to accept either secret
The verification function tries the new secret first, then falls back to the old one. Both pass during the rotation window.
JavaScript
3
Update the webhook subscription with the new secret
PUT /api/Webhook/{id} with securityToken set to the new value. Raise begins signing with the new secret immediately on the next delivery.4
Confirm new deliveries verify with the new secret
Check webhook logs for successful deliveries after the update. Confirm signatures verify with the new secret.
5
Remove the old secret
After a brief window (long enough to confirm no stragglers signed with the old secret), remove the old secret from your secrets manager. The verification now only accepts the new secret.
PUT /api/Webhook/{id} completes — but the window is what prevents any in-flight requests from being rejected during the cutover.
When to force a rotation
In addition to scheduled rotation:Handling verification failures
A signature verification failure typically indicates one of:
For each failure:
- Always reject the request with
401 Unauthorized. Don’t try to “recover” by processing anyway — a forged request that’s processed is worse than a real request that’s rejected. - Log the failure (without logging the secret or the raw signature) for diagnostic review.
- Alert on patterns — sustained verification failures over time indicate either a configuration issue or an active attack worth investigating.
Metrics worth tracking
These metrics help distinguish “the secret was rotated incorrectly” from “an attacker is probing the endpoint.”
Layered defenses
Signature verification is the primary defense against forged events. A few layered defenses add resilience:HTTPS only
The webhook URL must use HTTPS. Plain HTTP would expose the signature in transit and make man-in-the-middle attacks easier. Most modern HTTP frameworks enforce HTTPS for webhook receivers by default; confirm yours does.IP allowlisting (optional)
For partner integrations with very high security requirements, allowlisting Raise’s delivery IPs adds a network-layer defense before requests even reach the application. Coordinate with the platform team for the canonical IP ranges, and update the allowlist whenever they change. This is belt-and-suspenders — signature verification alone is sufficient for most integrations. IP allowlisting helps but doesn’t replace signature verification.Rate limiting on the webhook endpoint
Even with signature verification, an attacker can flood the endpoint with forged requests forcing the application to compute HMAC for each. Apply rate limiting at the edge (load balancer, API gateway) to prevent this.No echoing of received content
Don’t include the received request body in error responses or logs without sanitization. A misconfigured endpoint that echoes unverified content can leak information about the integration’s processing logic.Where to go next
Retry Behavior
What happens when the partner endpoint returns a non-success response — including signature failures.
Idempotency and Safe Reprocessing
Handle duplicate deliveries from retries.
Webhooks Overview
The full webhook subscription lifecycle.
Security and Credential Management
Storing and rotating webhook secrets alongside other integration credentials.