Api Reference
Test helpers
Simulate subscription renewals in test mode so you can verify recurring billing flows end to end.
Test helper endpoints
Vatly provides a small set of test helper endpoints for recurring billing scenarios. These endpoints are only available in test mode.
Use a
test_ API token for every endpoint on this page. Test helper endpoints are not available with live credentials.Fast-forward subscription renewal
POST /v1/test-helpers/subscriptions/{subscriptionId}/fast-forward-renewal
Simulate a renewal cycle for an existing subscription.
Useful for:
- testing renewal billing flows without waiting for the real billing interval
- verifying subscription lifecycle events and webhook delivery
- validating dunning or invoice follow-up automation in your sandbox flow
- forcing the renewal payment to fail so you can exercise your payment-recovery handling
Request body
The request body is optional. Omit it to advance the billing cycle and leave the renewal payment pending (this endpoint's original behaviour).
| Attribute | Type | Description |
|---|---|---|
paymentStatus | string | Optional. Outcome to force on the renewal payment. One of paid or failed. Omit to leave the renewal payment pending. failed declines the payment and starts a payment recovery for the renewal order (delivering order.payment_failed to your webhook endpoint); paid settles it. |
failureReason | string | Optional. Which decline to simulate. Only valid alongside paymentStatus: failed (sending it with paid is rejected). Soft declines (insufficient_funds, temporary_decline, general_failure) keep the payment method and retry on a multi-week timeline; every other value is a hard decline that drives the customer to supply a new payment method on a short timeline. Defaults to general_failure. Allowed values: insufficient_funds, temporary_decline, general_failure, invalid_mandate, mandate_canceled, account_closed, card_expired, card_lost_or_stolen, invalid_card_details, authentication_failed, fraud_suspected. |
Requesting an outcome for a renewal that produced no payable order, or whose payment has already settled, returns a
409 error rather than a silent no-op.curl -X POST https://api.vatly.com/v1/test-helpers/subscriptions/subscription_Lp3mNvBxKw7RjTgYcZaE/fast-forward-renewal \
-H "Authorization: Bearer test_your_api_key_here" \
-H "Content-Type: application/json" \
-d '{
"paymentStatus": "failed",
"failureReason": "card_expired"
}'
$vatly = new \Vatly\API\VatlyApiClient();
$vatly->setApiKey('test_your_api_key_here');
$subscription = $vatly->testHelpers->fastForwardRenewal('subscription_Lp3mNvBxKw7RjTgYcZaE', [
'paymentStatus' => 'failed',
'failureReason' => 'card_expired',
]);
{
"id": "subscription_Lp3mNvBxKw7RjTgYcZaE",
"resource": "subscription",
"customerId": "customer_Lp3mNvBxKw7RjTgYcZaE",
"subscriptionPlanId": "subscription_plan_Rk5pQrSvWm8NjLhYbUcP",
"testmode": true,
"name": "Pro Monthly",
"description": "Full access to all Pro features",
"billingAddress": {
"fullName": "John Doe",
"companyName": "Acme Corp",
"streetAndNumber": "123 Main Street",
"city": "Berlin",
"postalCode": "10115",
"country": "DE"
},
"basePrice": {
"value": "29.00",
"currency": "EUR"
},
"quantity": 1,
"interval": "month",
"intervalCount": 1,
"status": "active",
"mandate": {
"method": "card",
"maskedIdentifier": "4242"
},
"startedAt": "2024-01-15T10:30:00Z",
"endedAt": null,
"canceledAt": null,
"renewedAt": "2024-03-15T10:30:00Z",
"renewedUntil": "2024-04-15T10:30:00Z",
"nextRenewalAt": "2024-04-15T10:30:00Z",
"trialUntil": null,
"scheduledUpdate": null,
"links": {
"self": {
"href": "https://api.vatly.com/v1/subscriptions/subscription_Lp3mNvBxKw7RjTgYcZaE",
"type": "application/json"
},
"customer": {
"href": "https://api.vatly.com/v1/customers/customer_Lp3mNvBxKw7RjTgYcZaE",
"type": "application/json"
}
}
}
Errors
| Status | Meaning |
|---|---|
401 | Missing or invalid API key |
403 | Endpoint not available for this token or resource |
404 | Subscription not found |
409 | No payable renewal order exists, or its payment has already settled |
422 | Invalid request body (for example, failureReason sent with paymentStatus: paid) |