Paygate Docs

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

EventFired when
charge.createdA new charge is created
charge.capturedA charge is successfully captured
charge.failedA charge fails at the provider
charge.voidedA charge is voided
charge.refundedA charge is fully refunded
refund.createdA refund is created
refund.succeededA 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:

AttemptDelay
1Immediate
25 minutes
330 minutes
42 hours
524 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

On this page