Tutorial: Verify a Webhook Signature
This tutorial walks you through testing webhook delivery and verifying a webhook signature end to end. You will use webhook.site as a test endpoint to inspect incoming payloads without building a server.
Time to complete: 15 minutes
Prerequisites:
- A Payrail account and JWT token
- A REST client such as Postman
- A free webhook.site account
Step 1 — Set up a test endpoint
Go to webhook.site. The page immediately generates a unique URL for you:
https://webhook.site/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
Copy this URL — you will use it as your webhook endpoint. Any POST request sent to this URL will appear in the webhook.site dashboard in real time.
Step 2 — Configure your webhook secret
Add your webhook URL and secret to your environment configuration:
WEBHOOK_SECRET=your-webhook-secret
WEBHOOK_URL=https://webhook.site/your-unique-id
Note: Use the full webhook.site URL without the
#!/view/path. For example:
- ✅ Correct:
https://webhook.site/87d0ec0c-95fd-4cbc-baef-632f1a5e50f5- ❌ Incorrect:
https://webhook.site/#!/view/87d0ec0c-95fd-4cbc-baef-632f1a5e50f5
Restart the server after updating your environment variables.
Step 3 — Create a test transaction
First register a customer and add a payment method if you haven't already. Then create a transaction:
Request
POST /api/transactions
Authorization: Bearer YOUR_TOKEN
Content-Type: application/json
Idempotency-Key: webhook-test-001
{
"customer": "YOUR_CUSTOMER_ID",
"paymentMethod": "YOUR_PAYMENT_METHOD_ID",
"amount": 15000,
"currency": "USD",
"description": "Webhook test payment"
}
Response
{
"_id": "69ba9d3e199bf8e79a8050e7",
"customer": "69ba9a90199bf8e79a8050e1",
"paymentMethod": "69ba9cef199bf8e79a8050e4",
"amount": 15000,
"currency": "USD",
"status": "pending",
"description": "Webhook test payment",
"createdAt": "2026-03-18T12:40:30.061Z"
}
Copy the _id from the response — you will need it in the next step.
Step 4 — Trigger the webhook
Update the transaction status to completed. This triggers the payment.succeeded webhook event.
Request
PUT /api/transactions/YOUR_TRANSACTION_ID
Authorization: Bearer YOUR_TOKEN
Content-Type: application/json
{
"status": "completed"
}
Response
{
"_id": "69ba9d3e199bf8e79a8050e7",
"status": "completed"
}
Step 5 — Inspect the payload
Go to webhook.site. You should see a new POST request appear in the left panel within a few seconds.
Click on the POST entry to inspect the payload:
{
"event": "payment.succeeded",
"created_at": "2026-03-18T12:46:55.681Z",
"data": {
"_id": "69ba9d3e199bf8e79a8050e7",
"customer": "69ba9a90199bf8e79a8050e1",
"paymentMethod": "69ba9cef199bf8e79a8050e4",
"amount": 15000,
"currency": "USD",
"status": "completed",
"description": "Webhook test payment",
"createdAt": "2026-03-18T12:40:30.061Z"
}
}
Check the request headers for the X-Payrail-Signature header:
X-Payrail-Signature: sha256=abc123...
This signature was generated by Payrail using HMAC-SHA256 and your webhook secret. In production, your server verifies this signature before processing the event.
Step 6 — Verify the signature in code
In production you would verify the signature on your server before processing the event. Here is how to do that in Node.js and Python.
Node.js
const crypto = require('crypto');
function verifySignature(rawBody, signature, secret) {
const hmac = crypto.createHmac('sha256', secret);
hmac.update(rawBody);
const expected = `sha256=${hmac.digest('hex')}`;
return crypto.timingSafeEqual(
Buffer.from(expected),
Buffer.from(signature)
);
}
Python
import hmac
import hashlib
def verify_signature(raw_body, signature, secret):
hmac_obj = hmac.new(
secret.encode('utf-8'),
raw_body,
hashlib.sha256
)
expected = f"sha256={hmac_obj.hexdigest()}"
return hmac.compare_digest(expected, signature)
Important: Always verify the signature against the raw request body — not the parsed JSON. See Webhooks for complete implementation examples.
What you learned
- How to use webhook.site to test webhook delivery without building a server
- How Payrail signs webhook payloads using HMAC-SHA256
- How to inspect a live webhook payload and signature
- How to verify a signature in Node.js and Python
Next steps
- Read the full Webhooks reference for retry policy and all event types
- See Handle a Failed Transaction and Retry for related error handling patterns