StarPay SGH

Webhooks

StarPay SGH sends a webhook to your server whenever a payment event happens — the reliable way to know a payment succeeded, rather than waiting on your customer's browser to redirect back.

Setting your webhook URL

Set this from your dashboard's API Keys page. It must be a publicly reachable HTTPS URL.

Events

EventFired when
charge.successA payment completes successfully
charge.failedA payment attempt fails or is declined
refund.processedA refund is issued, by you or by StarPay after a dispute

Payload

{
  "event": "charge.success",
  "data": {
    "reference": "TXN-XXXXXXXXXXXXXX",
    "amount": "50.00",
    "currency": "GHS",
    "status": "success",
    "customer_email": "customer@example.com",
    "paid_at": "2026-07-25T01:19:56+00:00"
  }
}

Verifying the signature

Every webhook request includes an X-StarPay-Signature header — an HMAC-SHA256 hash of the raw request body, signed with your Webhook Secret. Always verify it before trusting a webhook.

$payload = file_get_contents('php://input');
$signature = hash_hmac('sha256', $payload, $webhookSecret);

if (hash_equals($signature, $_SERVER['HTTP_X_STARPAY_SIGNATURE'])) {
    $event = json_decode($payload, true);
    // Safe to process $event['event'] and $event['data']
} else {
    http_response_code(401);
    exit;
}
const crypto = require('crypto');

const expected = crypto
  .createHmac('sha256', webhookSecret)
  .update(rawBody)
  .digest('hex');

if (crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(signatureHeader))) {
  // Safe to process
}
import hmac
import hashlib

expected = hmac.new(webhook_secret.encode(), raw_body, hashlib.sha256).hexdigest()

if hmac.compare_digest(expected, signature_header):
    # Safe to process
    pass

Retry behavior

If your endpoint doesn't return a 2xx response, StarPay retries up to 3 times, with a delay of 10s, 30s, then 60s. Respond quickly (within a few seconds) and process the event asynchronously on your end if needed.

Idempotency

Because of retries, your endpoint may receive the same event more than once. Use the reference field to deduplicate on your side.