Skip to main content

Webhooks

SplashPay uses webhooks to notify your application whenever a payment reaches a final state. Instead of continuously polling the Payment Status endpoint, configure a webhook endpoint to receive instant updates.

Real-time Notifications

SplashPay automatically sends an HTTP POST request to your webhook URL whenever a payment status changes.

Configure Your Webhook URL

You can configure your webhook URL from the SplashPay Merchant Dashboard or via the Merchant API. Example:
https://merchant.example.com/webhooks/splashpay
Your endpoint must:
  • Support HTTPS
  • Accept HTTP POST requests
  • Return HTTP 200 OK after successful processing
  • Be publicly accessible

Webhook Events

SplashPay currently sends the following events.
EventDescription
payment.successPayment completed successfully.
payment.failedPayment failed.
payment.cancelledPayment was cancelled by the customer or provider.
payment.expiredPayment expired before completion.

Sample Webhook

SplashPay sends webhook notifications using the following JSON structure.
{
  "event": "payment.success",
  "created_at": "2026-06-24T09:59:24.430757Z",
  "data": {
    "reference": "INV-xcxoddfudjhg",
    "amount": "1000.00",
    "fee": "15.00",
    "net_amount": "985.00",
    "currency": "TZS",
    "status": "success",
    "customer_name": "John Doe",
    "customer_email": "john.doe@example.com",
    "customer_phone": "255744123456",
    "payment_method": "mobile_money",
    "provider": "selcom",
    "channel": "TIGOPESATZ",
    "provider_reference": "1769142083",
    "metadata": null
  }
}

Webhook Payload

FieldTypeDescription
eventstringEvent name.
created_atdatetimeTime the webhook was generated.
data.referencestringMerchant payment reference.
data.amountdecimalPayment amount.
data.feedecimalProcessing fee charged.
data.net_amountdecimalAmount settled after fees.
data.currencystringTransaction currency.
data.statusstringPayment status.
data.customer_namestringCustomer full name.
data.customer_emailstringCustomer email.
data.customer_phonestringCustomer phone number.
data.payment_methodstringPayment method used.
data.providerstringPayment provider.
data.channelstringProvider channel or network.
data.provider_referencestringProvider transaction reference.
data.metadataobject/nullMerchant-defined metadata.

Verify Webhook Signature

Every webhook request includes a signature that allows you to verify the payload originated from SplashPay.
HeaderDescription
X-SPLASHPAY-SIGNATUREHMAC SHA-256 signature of the payload
X-SPLASHPAY-TIMESTAMPUnix timestamp used to generate the signature
Compute the HMAC using your Webhook Secret.
HMAC_SHA256(
    timestamp + "." + request_body,
    WEBHOOK_SECRET
)
If the computed signature matches the X-SPLASHPAY-SIGNATURE header, the request is authentic.

Example Verification (PHP)

$timestamp = $_SERVER['HTTP_X_SPLASHPAY_TIMESTAMP'];
$signature = $_SERVER['HTTP_X_SPLASHPAY_SIGNATURE'];

$payload = file_get_contents('php://input');

$expected = hash_hmac(
    'sha256',
    $timestamp.'.'.$payload,
    env('SPLASHPAY_WEBHOOK_SECRET')
);

if (!hash_equals($expected, $signature)) {
    abort(401, 'Invalid Signature');
}

Example Verification (Node.js)

import crypto from "crypto";

const payload = JSON.stringify(req.body);

const expected = crypto
    .createHmac(
        "sha256",
        process.env.SPLASHPAY_WEBHOOK_SECRET
    )
    .update(
        `${req.headers["x-splashpay-timestamp"]}.${payload}`
    )
    .digest("hex");

if (
    expected !==
    req.headers["x-splashpay-signature"]
) {
    return res.status(401).send("Invalid signature");
}

Return HTTP 200

After successfully processing the webhook, return:
HTTP/1.1 200 OK
Example
{
    "success": true
}

Retry Policy

If SplashPay does not receive a successful response (HTTP 200), the webhook will be retried automatically.
AttemptDelay
1Immediately
21 minute
35 minutes
415 minutes
530 minutes
61 hour
76 hours
824 hours
After the final retry, the webhook is marked as failed.

Best Practices

1

Always verify signatures

Reject webhook requests with invalid signatures.
2

Process asynchronously

Respond with HTTP 200 immediately, then process the webhook in the background.
3

Use idempotent processing

The same webhook may be delivered more than once. Use the payment reference to avoid duplicate processing.
4

Store provider references

Persist both the merchant reference and provider reference for reconciliation.
5

Do not trust browser redirects

Always rely on webhooks to determine the final payment status.

Event Lifecycle

Payment Created


Customer Pays


SplashPay


Webhook Sent


Merchant Server


HTTP 200 OK

Testing Webhooks

During development you can expose your local server using tools such as:
  • ngrok
  • Cloudflare Tunnel
  • LocalTunnel
Example:
https://abc123.ngrok.io/webhooks/splashpay

Supported Payment Methods

Webhooks are sent for all SplashPay collection methods:
  • Mobile Money
  • Card Payments
  • Dynamic TANQR

Next Steps

Payment Status

Retrieve the latest status of any payment.

Collections Overview

Learn more about SplashPay Collections.