Payments
Payments are initiated against active mandates and progress through submission, collection, and settlement states. This guide outlines the lifecycle, constraints, and best practices for integrating with the VRP Billing payments API.
Creating a Payment
POST /payments
Required Fields
Field | Type | Description |
---|---|---|
mandate_id |
string | Identifier of the mandate authorising the collection. |
amount |
string (decimal) | Amount to collect, formatted with two decimal places. |
currency |
string | Must match the mandate currency. |
Optional Fields
description
: Displayed on customer statements where supported.metadata
: JSON object for internal tracking (20 key limit).capture_at
: ISO 8601 timestamp requesting a delayed submission (max 7 days ahead).
Validation Rules
- Amount cannot exceed mandate limit or fall below 1.00.
- Payments scheduled via
capture_at
must be at least 10 minutes in the future. metadata
keys must be unique per request.
Example
{
"mandate_id": "mandate_f9d3",
"amount": "42.50",
"currency": "GBP",
"description": "April membership",
"metadata": {
"invoice_number": "INV-10045"
}
}
Payment Lifecycle
Status | Description |
---|---|
pending_submission |
Payment accepted but waiting for capture window. |
submitted |
Sent to the customer's bank for processing. |
settled |
Funds have cleared and will appear in the merchant payout. |
failed |
Bank declined the request. Inspect failure_code . |
cancelled |
Merchant cancelled before submission or mandate was revoked. |
refunded |
Payment has an associated refund totalling the original amount. |
Failure Codes
Code | Meaning | Recovery |
---|---|---|
insufficient_funds |
Customer account balance was too low. | Retry using POST /payments/{id}/retry . |
mandate_revoked |
Mandate was cancelled prior to collection. | Notify customer to re-authorise. |
bank_offline |
Bank could not process at the time. | Automatic retry occurs within 30 minutes. |
limit_exceeded |
Amount breached bank- or mandate-level limits. | Reduce amount and retry within limit. |
Retrying Payments
POST /payments/{payment_id}/retry
- Retries are permitted for
failed
payments only. - Retries inherit the original
amount
andmetadata
. - A payment can be retried up to three times with a minimum interval of one hour.
Listing Payments
GET /payments?mandate_id=mandate_f9d3&page_size=50
Use the cursor
parameter for pagination. Sort order defaults to reverse chronological by created_at
and can be changed with the order
parameter described in Pagination. Responses return results
, next_cursor
, previous_cursor
, and page_size
.
Payment Notifications
Subscribe to these webhooks to track status changes:
payment.submitted
payment.settled
payment.failed
payment.refunded
Webhook payloads include mandate_id
, amount
, and failure_code
when applicable.
Reporting
GET /payments/summary?from=2024-01-01&to=2024-01-31
The summary endpoint aggregates payments by status and currency. It is subject to rate limits documented in Rate Limits.
Reconciliation Tips
- Use the
metadata.invoice_number
field to map payments to internal invoices. - Store the
settlement_date
returned onGET /payments/{id}
to align with payouts. - When reconciling refunds, combine payment and refund CSV exports to track net amounts.