Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.gosurge.xyz/llms.txt

Use this file to discover all available pages before exploring further.

The Source of Truth

Important: Do not use the frontend onSuccess callback as the trigger to fulfill orders. Frontend state can be manipulated. Always rely on Webhooks as the final source of truth.

Registering your Webhook

Set your webhookUrl and webhookSecret in the Surge Merchant Dashboard under Settings → Webhooks.

Security

Surge signs every outbound webhook with an HMAC-SHA512 signature in the X-Surge-Signature header. Verify this against your webhookSecret before processing any event.
const crypto = require('crypto');

function verifySurgeWebhook(rawBody, signature, secret) {
  const expected = crypto
    .createHmac('sha512', secret)
    .update(rawBody)
    .digest('hex');
  return crypto.timingSafeEqual(
    Buffer.from(expected),
    Buffer.from(signature)
  );
}
Always verify the signature before acting on webhook data. Never trust the payload without this check.

Outbound Events (Surge → Your Server)

These are the events Surge sends to your registered webhookUrl.

payment.success

Fires when the customer pays the initial deposit and the installment plan is activated.
{
  "eventId": "evt_abc123...",
  "eventType": "payment.success",
  "merchantId": "mer_998877",
  "createdAt": "2026-03-11T12:25:00Z",
  "data": {
    "resourceType": "payment_plan",
    "resourceId": "pp_554433",
    "orderReference": "ORD-9912384",
    "amount": 120000,
    "currency": "NGN"
  }
}

payment.failed

Fires when a deposit or installment charge attempt fails (e.g. insufficient funds, expired card).
{
  "eventId": "evt_fail789...",
  "eventType": "payment.failed",
  "merchantId": "mer_998877",
  "createdAt": "2026-04-11T06:15:00Z",
  "data": {
    "resourceType": "payment_plan",
    "resourceId": "pp_554433",
    "orderReference": "ORD-9912384",
    "reason": "insufficient_funds"
  }
}

payment_plan.installment_paid

Fires each time the Auto-Debit engine successfully collects a scheduled installment. Also emitted as installment.paid — both are identical events with different names for compatibility.
You receive payment.success once when the plan is created, and one payment_plan.installment_paid event for each subsequent installment collected.
{
  "eventId": "evt_def456...",
  "eventType": "payment_plan.installment_paid",
  "merchantId": "mer_998877",
  "createdAt": "2026-04-11T06:15:00Z",
  "data": {
    "resourceType": "installment",
    "resourceId": "inst_778899",
    "paymentPlanId": "pp_554433",
    "customerId": "cus_112233",
    "orderReference": "ORD-9912384",
    "amount": 40000,
    "currency": "NGN",
    "processorReference": "PST_abc123"
  }
}

goods.release

Fires when the merchant’s configured release rule is satisfied — typically after the deposit is paid. This is the trigger to ship physical goods or unlock digital access.
{
  "eventId": "evt_rel321...",
  "eventType": "goods.release",
  "merchantId": "mer_998877",
  "createdAt": "2026-04-11T06:15:00Z",
  "data": {
    "resourceType": "payment_plan",
    "resourceId": "pp_554433",
    "orderReference": "ORD-9912384"
  }
}

debit.scheduled

Fires when an auto-debit job is registered for a future installment.

transfer.success

Fires when a merchant payout (settlement transfer) to your registered bank account completes successfully.

Fulfillment Trigger

When your server receives goods.release or payment.success (and the signature is valid):
  1. Mark the order as Paid in your database.
  2. Trigger the release or shipping of physical or digital goods to the customer.
Return a 200 OK immediately and process fulfillment asynchronously to avoid timeout-based retries from Surge.

Inbound Events (Paystack → Surge)

These endpoints let Surge receive events from Paystack. You do not need to implement or call these yourself — just register the URL with Paystack alongside your own webhook URL.

POST /api/v1/webhooks/paystack

Point your Paystack webhook URL to this endpoint. Surge uses it to handle successful charges, failed charges, and transfer confirmations.
https://api.gosurge.xyz/api/v1/webhooks/paystack
Surge validates every inbound Paystack event using HMAC-SHA512 against your Paystack secret key.

POST /api/v1/webhooks/payment-gateway

Handles payment method revocation events from Paystack:
  • charge.dispute.create — card dispute opened
  • authorization.revoked — card authorization revoked
  • mandate.revoked / mandate.cancelled — direct debit mandate cancelled
  • subscription.disable — recurring charge subscription disabled
When Surge receives a revocation event, it deactivates the customer’s payment method and recalculates their Surge Score.
https://api.gosurge.xyz/api/v1/webhooks/payment-gateway

Testing Your Webhook

You can send a signed test event to your configured endpoint directly from the API:
POST /api/v1/webhooks/test
Authorization: Bearer <YOUR_SECRET_KEY>
Content-Type: application/json

{
  "webhook_url": "https://yourstore.com/webhooks/surge",
  "webhook_secret": "whsec_..."
}
Response
{
  "ok": true,
  "delivered": true,
  "status_code": 200,
  "latency_ms": 142
}
If delivery fails, delivered is false and an error field describes the failure.

Replaying Failed Events

If your server was down when a webhook was delivered, you can manually replay any event from the dashboard or via the API:
POST /api/v1/webhooks/events/{event_id}/replay
Authorization: Bearer <YOUR_SECRET_KEY>
Failed delivery attempts are visible via:
GET /api/v1/webhooks/failed-attempts
Authorization: Bearer <YOUR_SECRET_KEY>