You can receive Prava webhooks in any backend language or framework. Verify each request on your server using the endpoint signing secret before processing the event. Your application API secret (sk_test_... or sk_live_...) is a different credential and must not be used for webhook signature verification.
Every request carries Prava-Signature, Prava-Event-Id, and Prava-Delivery-Id. Use the signed body id as your authoritative deduplication key. Delivery IDs identify delivery generations and can change on replay.
Prava-Signature has the form t=UNIX_SECONDS,v1=HEX_DIGEST. The digest is HMAC-SHA256 over timestamp + "." + raw_body with the complete whsec_... secret as the UTF-8 key. The header can contain multiple v1 values during a 24-hour rotation overlap. A matching signature from either active secret is sufficient.
Verify before JSON parsing, reserialization, or application processing. Reject missing/malformed signatures, duplicate timestamps, and timestamps more than five minutes in the past or future. Keep your receiver clock synchronized.
Example: verify a signature in JavaScript
The following function illustrates the verification steps. Pass the exact request bytes from your HTTP framework as rawBody; parsing and rebuilding JSON changes those bytes.
After verification, parse the body and check the expected environment/account. Handle webhook.endpoint_verification by echoing its challenge as JSON with HTTP 200. Ignore test: true events for financial side effects while still acknowledging a successful test.
For any subscribed event, atomically store its ID and enqueue your work before responding with 2xx. Use a unique database constraint on the event ID. A duplicate already stored event should still receive 2xx. Process slow business logic asynchronously. A receiver timeout is an unknown outcome and Prava may send the same event again.
Rotate your signing secret
Administrators can rotate an endpoint secret. Save the new secret when it is shown; Prava dual-signs for 24 hours. Deploy verification with the new secret during that overlap, then retire the old secret. A second rotation is blocked until the overlap ends. The secret cannot be retrieved later; idempotent retries return completion status without disclosing it again.
Optional receiver examples
For a runnable starting point, use the Node.js or Python receiver examples. Their runtime and storage requirements apply only to those examples. You can implement the same verification and delivery handling in your existing application.
See Test your integration to verify your destination, send test events, and check retries and secret rotation.