Skip to main content
Version: v2

Webhook — Payment Events

Overview

The wallet-payment-service emits webhook events to notify merchant systems of payment state changes. Events are delivered as HTTP POST requests to the merchant's registered webhook URL. All events use at-least-once delivery — merchants must handle duplicate events idempotently.


Event Catalog

Event NameTriggerPayment MethodsPayment Types
PAYMENT_SUCCEEDEDAll allocations completed successfullyCARD, BANK_ACCOUNTSALE, PRE-AUTH (after capture)
PAYMENT_AUTHORIZEDAll allocations authorized (pre-auth)CARDPRE-AUTH
PAYMENT_ACCEPTEDACH accepted by processorBANK_ACCOUNTSALE
PAYMENT_CANCELLEDAll allocations cancelledCARD, BANK_ACCOUNTSALE, PRE-AUTH
PAYMENT_FAILEDPayment processing failedCARD, BANK_ACCOUNTSALE, PRE-AUTH

Common Payload Envelope

Every webhook event follows this envelope structure:

{
"name": "<EVENT_NAME>",
"source": "<x-source header value or null>",
"payload": {
"id": "<paymentId>",
"merchantTransactionId": "<merchantTransactionId>",
"checkoutId": "<checkoutId or null>",
"amount": 15000,
"currencyCode": "USD",
"status": "<payment status>",
"authorizeCard": false,
"partialAuthorization": false,
"customer": { ... },
"merchant": { ... },
"paymentAllocations": [ ... ],
"paymentDateUtc": "2026-04-04T10:30:00Z",
"metadata": { ... }
}
}

PAYMENT_SUCCEEDED

Trigger: All payment allocations processed successfully (card charged, ACH settled).

Sample Payload — Single Card
{
"name": "PAYMENT_SUCCEEDED",
"source": "merchant-portal",
"payload": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"merchantTransactionId": "order-20260404-001",
"amount": 15000,
"currencyCode": "USD",
"status": "COMPLETED",
"authorizeCard": false,
"partialAuthorization": false,
"customer": {
"firstName": "John",
"lastName": "Doe",
"email": "john.doe@example.com"
},
"paymentAllocations": [
{
"id": "a1b2c3d4-e5f6-7890-1234-567890abcdef",
"amount": 15000,
"authorizedAmount": 15000,
"capturedAmount": 15000,
"status": "COMPLETED",
"paymentMethod": {
"type": "CARD",
"card": {
"lastFour": "4242",
"brand": "visa",
"expMonth": 12,
"expYear": 2028
}
},
"vendor": {
"name": "STRIPE",
"transactionId": "pi_3NabcXYZ123456789"
}
}
],
"paymentDateUtc": "2026-04-04T10:30:00Z"
}
}
Sample Payload — Split-Tender (2 Cards)
{
"name": "PAYMENT_SUCCEEDED",
"source": "merchant-portal",
"payload": {
"id": "660e8400-e29b-41d4-a716-446655440000",
"merchantTransactionId": "split-20260404-001",
"amount": 20000,
"status": "COMPLETED",
"paymentAllocations": [
{
"id": "aaaa1111-2222-3333-4444-555566667777",
"amount": 12000,
"status": "COMPLETED",
"paymentMethod": { "type": "CARD", "card": { "lastFour": "4242", "brand": "visa" } }
},
{
"id": "bbbb1111-2222-3333-4444-555566667777",
"amount": 8000,
"status": "COMPLETED",
"paymentMethod": { "type": "CARD", "card": { "lastFour": "1234", "brand": "mastercard" } }
}
]
}
}

PAYMENT_AUTHORIZED

Trigger: Pre-auth hold placed on card. Awaiting explicit capture.

Sample Payload
{
"name": "PAYMENT_AUTHORIZED",
"source": "merchant-portal",
"payload": {
"id": "770e8400-e29b-41d4-a716-446655440000",
"merchantTransactionId": "preauth-20260404-001",
"amount": 25000,
"status": "AUTHORIZED",
"authorizeCard": true,
"partialAuthorization": true,
"paymentAllocations": [
{
"id": "cccc1111-2222-3333-4444-555566667777",
"amount": 25000,
"authorizedAmount": 25000,
"capturedAmount": 0,
"status": "AUTHORIZED"
}
]
}
}

PAYMENT_ACCEPTED

Trigger: ACH bank account payment accepted by processor (not yet settled).

Sample Payload
{
"name": "PAYMENT_ACCEPTED",
"source": "merchant-portal",
"payload": {
"id": "880e8400-e29b-41d4-a716-446655440000",
"merchantTransactionId": "ach-20260404-001",
"amount": 50000,
"status": "ACCEPTED",
"paymentAllocations": [
{
"id": "dddd1111-2222-3333-4444-555566667777",
"amount": 50000,
"status": "ACCEPTED",
"paymentMethod": {
"type": "BANK_ACCOUNT",
"bankAccount": { "lastFour": "6789", "bankName": "Chase" }
}
}
]
}
}

PAYMENT_CANCELLED

Trigger: Payment successfully cancelled (void completed).

Sample Payload
{
"name": "PAYMENT_CANCELLED",
"source": "merchant-portal",
"payload": {
"id": "770e8400-e29b-41d4-a716-446655440000",
"merchantTransactionId": "preauth-20260404-001",
"amount": 25000,
"status": "CANCELLED",
"paymentAllocations": [
{
"id": "cccc1111-2222-3333-4444-555566667777",
"amount": 25000,
"status": "CANCELED"
}
]
}
}

PAYMENT_FAILED

Trigger: Payment processing failed (card declined, vendor error, etc.).

Sample Payload — Single Failure
{
"name": "PAYMENT_FAILED",
"source": "merchant-portal",
"payload": {
"id": "990e8400-e29b-41d4-a716-446655440000",
"merchantTransactionId": "failed-20260404-001",
"amount": 10000,
"status": "FAILED",
"paymentAllocations": [
{
"id": "eeee1111-2222-3333-4444-555566667777",
"amount": 10000,
"status": "FAILED",
"error": {
"code": "card_declined",
"message": "Your card was declined."
}
}
]
}
}
Sample Payload — Split-Tender with Rollback
{
"name": "PAYMENT_FAILED",
"source": "merchant-portal",
"payload": {
"id": "660e8400-e29b-41d4-a716-446655440000",
"amount": 20000,
"status": "FAILED",
"paymentAllocations": [
{
"id": "aaaa1111-2222-3333-4444-555566667777",
"amount": 12000,
"status": "ROLLED_BACK"
},
{
"id": "bbbb1111-2222-3333-4444-555566667777",
"amount": 8000,
"status": "FAILED",
"error": {
"code": "card_declined",
"message": "Your card was declined."
}
}
]
}
}

Delivery Guarantees

PropertyBehavior
Delivery modelAt-least-once (merchants must handle duplicates)
Retry policyExponential backoff on delivery failure
OrderingNot guaranteed — events may arrive out of order
IdempotencyUse paymentId + name (event) to detect duplicates
SecurityHMAC signature verification, OAuth2/JWT authentication
TimeoutMerchant endpoint must respond within 30 seconds
Expected response2xx status code to acknowledge receipt