Webhooks
Receive real-time event notifications for charge and refund state changes.
Overview
Webhooks deliver real-time HTTP POST notifications to your server whenever a payment event occurs. Each delivery is signed with HMAC-SHA256 so you can verify the payload authenticity.
Register an endpoint
POST /v1/me/webhook_endpoints
Authorization: Bearer sk_test_...
Content-Type: application/json{
"url": "https://your-server.com/hooks/paygate",
"events": ["charge.captured", "charge.failed", "refund.created"]
}Available events
| Event | Fired when |
|---|---|
charge.created | A new charge is created |
charge.captured | A charge is successfully captured |
charge.failed | A charge fails at the provider |
charge.voided | A charge is voided |
charge.refunded | A charge is fully refunded |
refund.created | A refund is created |
refund.succeeded | A refund settles at the provider |
Response
{
"webhook_endpoint": {
"id": "we_01HXY...",
"url": "https://your-server.com/hooks/paygate",
"events": ["charge.captured", "charge.failed", "refund.created"],
"active": true,
"merchant_id": "...",
"created_at": "2024-01-15T10:00:00.000Z"
},
"webhook_secret": "whsec_abc123..."
}The webhook_secret is shown once at creation. Store it securely — you'll need it to verify delivery signatures.
Verify a delivery
Every delivery includes an X-PayGate-Signature header containing the HMAC-SHA256 signature of the raw request body.
import { createHmac } from "crypto";
function verifySignature(
rawBody: string,
signature: string,
secret: string
): boolean {
const expected = createHmac("sha256", secret)
.update(rawBody)
.digest("hex");
return `sha256=${expected}` === signature;
}Reject any delivery where the signature doesn't match.
Delivery payload
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"event_type": "charge.captured",
"created_at": "2024-01-15T10:30:01.000Z",
"data": {
"object": "charge",
"charge": {
"id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"amount": 5000,
"currency": "SAR",
"status": "captured",
"payment_method": "card",
"provider": "stripe",
"environment": "sandbox",
"created_at": "2024-01-15T10:30:00.000Z"
}
}
}For refund events, data.object is "refund" and the payload includes both data.refund and data.charge.
Retry schedule
If your endpoint returns anything other than 2xx, Paygate retries with exponential backoff:
| Attempt | Delay |
|---|---|
| 1 | Immediate |
| 2 | 5 minutes |
| 3 | 30 minutes |
| 4 | 2 hours |
| 5 | 24 hours |
After all 5 attempts fail the delivery is marked failed.
Respond quickly
Your endpoint should respond with 200 OK as fast as possible. Do your processing asynchronously — Paygate's 5-second timeout will count a slow response as a failure.
Manage endpoints
# List endpoints
GET /v1/me/webhook_endpoints
# Update events
PATCH /v1/me/webhook_endpoints/:id
# Delete
DELETE /v1/me/webhook_endpoints/:id