In a nutshellWebhooks let you set up a notification system that automatically sends you updates when certain actions happen via the Pandascrow API — like payments, escrows, or account changes.
Introduction
Most times when you hit an API, you expect an instant response — success or failure, right away. But in some cases (like payment confirmations or long-running processes), that’s not always possible.
To avoid timeouts, we might return a pending response while the request continues processing in the background.
That’s where webhooks come in.
Webhooks let us notify your server once the final state of an event is known, like when a transaction is completed, a payment fails, or an escrow is updated. By setting up a webhook URL, your system stays in sync without needing to constantly poll our API.
Create a Webhook URL
<?php
// Set content type
header('Content-Type: application/json');
// Capture raw request body
$input = file_get_contents("php://input");
$event = json_decode($input, true);
// 1️⃣ Basic validation
if (!$event || !isset($event['event']) || !isset($event['data'])) {
http_response_code(400);
echo json_encode([
'status' => false,
'message' => 'Invalid payload structure'
]);
exit;
}
// 2️⃣ Header checks
$receivedSignature = $_SERVER['HTTP_X_PANDASCROW_SIGNATURE'] ?? '';
$appKey = $_SERVER['HTTP_X_PANDASCROW_APP'] ?? '';
// 3️⃣ Fetch your expected secret (this should match what Pandascrow uses)
$expectedSecret = 'sk_live_your_own_secret_key_here'; // You must replace this securely
// 4️⃣ Signature validation
$calculatedSignature = hash_hmac('sha256', json_encode([
'event' => $event['event'],
'data' => $event['data'],
'timestamp' => $event['timestamp']
]), $expectedSecret);
if (!hash_equals($calculatedSignature, $receivedSignature)) {
http_response_code(401);
echo json_encode([
'status' => false,
'message' => 'Invalid signature'
]);
exit;
}
// ✅ If passed, process the event
$eventType = $event['event'];
$payload = $event['data'];
// You can now handle the event here...
// Respond to Pandascrow
http_response_code(200);
echo json_encode([
'status' => true,
'message' => 'Webhook received and processed successfully'
]);
// Using Express
app.post("/my/webhook/url", function(req, res) {
// Retrieve the request's body
const event = req.body;
// Do something with event
res.send(200);
});
📩 Receiving & Acknowledging Webhooks
When your webhook URL receives an event from Pandascrow, your system should do two things:
- Parse the event payload
- Acknowledge receipt by responding with a status true meaning (OK)
⚠️ If we don't receive a True (OK), we’ll assume delivery failed and retry for up to 72 hours.
🔁 Retry Behavior
- Live Mode
- First 4 retries: every 3 minutes
- Afterwards, once every hour for the next 72 hours
- Test Mode
- Retries occur hourly for up to 72 hours
🛡️ Verifying Event Origin
Because your webhook URL is publicly accessible, it’s critical to confirm that incoming events are genuinely from Pandascrow, not spoofed by third parties.
You can do this in two ways:
- Signature Validation: Each event includes a signature header you can verify using your secret key. This ensures the event hasn’t been tampered with.
- IP Whitelisting: Only accept requests coming from Pandascrow’s IP ranges.
Implementing both is highly recommended for production systems.
Supported events
{
"event": "success.virtual.account",
"data": {
"userID": 1,
"businessID": 1,
"currency": "NGN",
"accountType": "individual",
"bankcode": "058",
"accountNumber": "4444444444",
"accountName": "JOHN DOE",
"customer_code": "PS_0f3iv4y8w30z0ubkk2p3i0r0lcploqkm",
"reference": "REF_79jf081gsb7m4drtphiiihyzfbqscp55",
"dateCreated": "Fri, 16 Jun 2023 12:32:59 +0000"
}
}