Sent as each subscription billing cycle is charged, succeeds or fails.
subscription-payment-status-changed follows the payment for one billing cycle of a subscription. Each cycle has its own subscription payment, with an ID that starts with RP-.
When it fires
- A billing cycle is due. Payment Labs creates the cycle's payment and charges the subscription's instrument. The payment is
PENDING. - A charge attempt succeeds: the payment becomes
COMPLETED. - A charge attempt fails: the payment becomes
FAILED.
A failed cycle is retried about 24 hours later, up to three attempts within four days. Each retry sends this event again, so a payment can go from FAILED to COMPLETED. Treat FAILED as final only once subscription-status-changed reports the subscription as OVERDUE.
Refunds do not fire this event. Follow them with refund-status-changed.
What to do
data.status | Suggested action |
|---|---|
PENDING | No action. |
COMPLETED | Record the cycle as paid. |
FAILED | Optionally ask the buyer to update their payment method. Payment Labs retries on its own. |
Payload
data is the subscription payment as List Subscription Payments describes it, read when the webhook is sent. Fields with no value are omitted. Amounts use the Money object.
| Field | Type | Description |
|---|---|---|
id | string | Subscription payment ID, for example RP-01JD6B2D4F6H8K0M2P4R6T8V0X. |
status | string | PENDING (due or being charged), COMPLETED (paid) or FAILED (the latest attempt failed). |
subscriptionId | string | ID of the subscription. |
subscriptionPlanId | string | ID of the subscription's plan. |
subscriptionPlanName | string | Name of that plan. |
merchantId | string | Your merchant ID. |
userId | string | ID of the buyer. |
dueDate | string | Billing date of this cycle, as YYYY-MM-DD. |
amount | Money | Amount charged for this cycle. |
checkoutInstrumentId | string | ID of the card or account charged. |
instrumentType | string | Type of that instrument, for example payment-card-3. Same values as enabledCheckoutInstruments on checkout-status-changed. |
checkoutId | string | ID of the checkout used to charge this cycle. |
hasRefunds | boolean | true once a refund has been created for this payment. |
Example
The full request body Payment Labs sends:
{
"payorId": "C-01JBX2Q8F4H6K8M0N2P4R6T8VW",
"event": "subscription-payment-status-changed",
"timestamp": "2026-04-01T00:11:05.731Z",
"data": {
"id": "RP-01JD6B2D4F6H8K0M2P4R6T8V0X",
"subscriptionPlanId": "RD-01JD49X1Z3B5D7F9H1K3M5P7R9",
"subscriptionPlanName": "Monthly membership",
"merchantId": "C-01JBX2Q8F4H6K8M0N2P4R6T8VW",
"userId": "U-01JBX5K7M9P1Q3R5S7T9V1W3X5",
"subscriptionId": "R-01JD5A1C3E5G7J9L1N3Q5S7U9W",
"dueDate": "2026-04-01",
"checkoutInstrumentId": "SI-01JD3K7M9P1R3T5V7X9Z1B3D5F",
"instrumentType": "payment-card-3",
"amount": {
"value": 19.99,
"wholeValue": 1999,
"currency": "USD",
"formattedValue": "$19.99",
"digits": 2
},
"status": "COMPLETED",
"hasRefunds": false,
"checkoutId": "S-01JD6B1C3E5G7J9L1N3Q5S7U9W"
}
}