Webhooks — Digital Mastercard
PentrraWallet sends real-time webhook notifications to your server whenever a significant event occurs on one of your Digital Mastercards.
Setup
To receive webhooks, provide a publicly accessible HTTPS URL in your developer dashboard under API Settings → Webhook URL.
PentrraWallet will send a POST request to that URL with a JSON body every time an event occurs.
Verifying the webhook
Every webhook payload includes two fields you can use to verify the request genuinely comes from PentrraWallet:
| Field | Description |
|---|---|
vip_key | Your VIP key — the same key you use to authenticate API requests |
platform | Always "PentrraWallet" |
PHP example:
$payload = json_decode(file_get_contents('php://input'), true);
if ($payload['vip_key'] !== YOUR_VIP_KEY) {
http_response_code(401);
exit('Unauthorized');
}
// Process the eventNode.js example:
app.post('/webhook', (req, res) => {
const payload = req.body;
if (payload.vip_key !== process.env.VIP_KEY) {
return res.status(401).send('Unauthorized');
}
// Process the event
res.status(200).send('OK');
});Always respond with HTTP 200 as quickly as possible. If PentrraWallet does not receive a 200 response, the webhook may time out.
Event types
card.issued
card.issuedSent when a new Digital Mastercard is successfully issued.
{
"event": "card.issued",
"card_id": "crd-a1b2c3d4e5f6a7b8",
"card_type": "virtual",
"card_brand": "mastercard",
"status": "active",
"timestamp": "2026-05-09T13:00:00-04:00",
"vip_key": "vk_live_xxxxxxxxxxxx",
"platform": "PentrraWallet"
}card.funded
card.fundedSent when a Digital Mastercard is successfully funded and the balance is available for use.
{
"event": "card.funded",
"card_id": "crd-a1b2c3d4e5f6a7b8",
"amount": "25.00",
"status": "completed",
"timestamp": "2026-05-09T13:00:00-04:00",
"vip_key": "vk_live_xxxxxxxxxxxx",
"platform": "PentrraWallet"
}Note:
amountis always formatted to 2 decimal places.
card.payment.success
card.payment.successSent when a payment is successfully processed on a card.
{
"event": "card.payment.success",
"card_id": "crd-a1b2c3d4e5f6a7b8",
"merchant_name": "Amazon",
"merchant_amount": "59.99",
"merchant_currency": "USD",
"billing_amount": "59.99",
"billing_currency": "USD",
"timestamp": "2026-05-09T13:00:00-04:00",
"vip_key": "vk_live_xxxxxxxxxxxx",
"platform": "PentrraWallet"
}Note:
merchant_amountandmerchant_currencyshow the amount charged by the merchant in their local currency.billing_amountandbilling_currencyshow the amount billed to the cardholder. These may differ when a cross-currency payment is involved.
card.refund.success
card.refund.successSent when a refund is credited to a card.
{
"event": "card.refund.success",
"card_id": "crd-a1b2c3d4e5f6a7b8",
"merchant_name": "Amazon",
"merchant_amount": "59.99",
"merchant_currency": "USD",
"billing_amount": "59.99",
"billing_currency": "USD",
"timestamp": "2026-05-09T13:00:00-04:00",
"vip_key": "vk_live_xxxxxxxxxxxx",
"platform": "PentrraWallet"
}card.payment.declined
card.payment.declinedSent when a payment attempt is declined. A decline fee is automatically charged based on the number of consecutive declines since the card was last funded.
{
"event": "card.payment.declined",
"card_id": "crd-a1b2c3d4e5f6a7b8",
"merchant_name": "Netflix",
"merchant_amount": "15.99",
"merchant_currency": "USD",
"billing_amount": "15.99",
"billing_currency": "USD",
"decline_reason": "Insufficient funds",
"decline_count": 1,
"fee_charged": 0.00,
"card_terminated": false,
"timestamp": "2026-05-09T13:00:00-04:00",
"vip_key": "vk_live_xxxxxxxxxxxx",
"platform": "PentrraWallet"
}Decline fee schedule:
| Decline # | Fee |
|---|---|
| 1st | $0.00 — grace, no charge |
| 2nd | $0.50 |
| 3rd | $0.75 |
| 4th | $0.80 |
| 5th and beyond | $0.80 + $0.05 per additional decline |
Important: The rejection counter is reset each time the card is funded. After 10 consecutive rejections, the card may be cancelled.
card.3ds.pending
card.3ds.pendingSent when a 3D Secure payment authorization request is received and requires approval. Use the event_id to approve the payment via the API.
{
"event": "card.3ds.pending",
"card_id": "crd-a1b2c3d4e5f6a7b8",
"event_id": "evn-34234-erte45-joor3663",
"merchant_name": "Stripe",
"amount": "120.00",
"currency": "USD",
"timestamp": "2026-05-09T13:00:00-04:00",
"vip_key": "vk_live_xxxxxxxxxxxx",
"platform": "PentrraWallet"
}To approve: Call POST /api/v1/dmc-validate-3ds with the card_id and event_id received in this webhook.
Note: The
event_idis unique per payment request. A single card may have multiple concurrent 3DS requests — always use the specificevent_idto approve the right one.
card.wallet.activation
card.wallet.activationSent when a digital wallet activation code (Apple Pay or Google Pay) is generated for a card.
{
"event": "card.wallet.activation",
"card_id": "crd-a1b2c3d4e5f6a7b8",
"wallet_type": "google_pay",
"wallet_name": "Google Pay",
"activation_code": "123456",
"timestamp": "2026-05-09T13:00:00-04:00",
"vip_key": "vk_live_xxxxxxxxxxxx",
"platform": "PentrraWallet"
}Note:
wallet_typecan be"google_pay"or"apple_pay".
Webhook payload structure
Every webhook payload shares this common structure:
| Field | Type | Description |
|---|---|---|
event | string | Event type (e.g., card.payment.success) |
card_id | string | The card this event relates to |
timestamp | string | ISO 8601 datetime of the event |
vip_key | string | Your VIP key — use to verify authenticity |
platform | string | Always "PentrraWallet" |
Additional fields vary by event type as documented above.
Best practices
- Respond immediately. Return HTTP 200 as soon as you receive the request, before any processing. If your server takes too long to respond, the webhook may time out.
- HTTPS only. Your webhook URL must use HTTPS. HTTP endpoints will not receive notifications.
- Always verify
vip_key. Reject any request wherevip_keydoes not match your credentials.
Need help?
If you have any questions or encounter issues with your webhook integration, contact our support team:
- Email: [email protected]
- WhatsApp: +44 7451 259717
