Webhook API
Stream real-time payment events directly to your server. No manual polling needed — as soon as an SMS is received, an HTTP POST request is dispatched to your URL.
How Webhooks Work
When our Android agent receives a payment SMS, it notifies the SyncPay server. The server then dispatches an HTTP POST payload to your registered webhook URL. When your server responds with 200 OK, delivery is confirmed.
Webhook Setup
Register Webhook URL in Dashboard
Navigate to Settings → Webhooks → Add Endpoint and enter your server URL.
Save Secret Key
Obtain your secret key used to verify HMAC signatures on incoming requests.
Create HTTPS Endpoint
Set up an HTTP POST endpoint on your server. Webhooks are dispatched only via HTTPS.
Verify Signature and Return 200
Validate the signature and reply with a 200 OK status. Otherwise, retries occur.
Events
Webhooks are triggered for the following events:
| Event | Trigger Condition |
|---|---|
| payment.received | When a new payment SMS is detected |
| payment.verified | When a transaction is successfully verified |
| payment.failed | When transaction verification fails |
| payment.expired | When an invoice expires |
Payload Structure
{
"event": "payment.received",
"timestamp": "2024-01-15T12:01:43Z",
"data": {
"trx_id": "8J1B2C3K4L",
"amount": 500,
"provider": "bKash",
"sender": "01XXXXXXXXX",
"invoice_id": "inv_9xKj2mPq"
},
"signature": "sha256=abc123..."
}Signature Verification
Every webhook request includes an X-SyncPay-Signature header. Verify the HMAC-SHA256 hash of the request body.
// PHP — Signature verify $payload = file_get_contents('php://input'); $signature = $_SERVER['HTTP_X_SYNCPAY_SIGNATURE']; $expected = 'sha256=' . hash_hmac('sha256', $payload, $webhookSecret); if (!hash_equals($expected, $signature)) { http_response_code(401); exit('Invalid signature'); } // Valid — process order $data = json_decode($payload, true); http_response_code(200);
Retry Policy
If your server returns a non-200 code or times out, automated retries are triggered:
| Attempt | Delay |
|---|---|
| 1st retry | 30 seconds |
| 2nd retry | 5 minutes |
| 3rd retry | 30 minutes |
| 4th retry | 2 hours |
| Final | 24 hours — then marked abandoned |