Recurring Payments
Subscriptions & installments · Automated billing · Card on file · Retry logic
Summary
Recurring Payments (Subscriptions) allow merchants to set up automated billing cycles for customers. Merchants can create open-ended subscriptions or fixed installment plans with configurable frequencies ranging from weekly to annual. The card can be entered by the merchant or by the customer via a hosted payment page.
RapidCents automatically charges stored cards on the scheduled billing date, sends success/decline notifications to both parties, and retries failed payments on a configurable schedule.
Subscription Lifecycle
- Create — Merchant creates a subscription with amount, customer, frequency, start date, and optionally a card. If the merchant enters the card, the subscription is active immediately.
- Customer Activation — If the customer enters the card, they receive an email with a link to the hosted page. The customer enters card details and the subscription becomes active.
- Scheduled Billing — The billing engine runs daily, identifies subscriptions due for charging, and adds them to the payment queue.
- Charge — The payment queue processor charges the stored card. On success, the bill count increments and notifications are sent. On decline, a retry is scheduled.
- Completion / Cancellation — Installment plans complete after the specified number of bills. Subscriptions continue until manually cancelled.
Subscription Statuses
INACTIVE (Awaiting Card)
Customer-entered card flow: subscription is created but waiting for the customer to provide card details.
ACTIVE
Subscription is active and will be charged on the next billing date. Card is on file.
CANCELLED
Subscription has been cancelled. No further charges will be made.
Processing Flow
Merchant-Entered Card
Customer-Entered Card
Authentication
Merchant API (Private)
Authorization: Bearer {access_token}
Content-Type: application/json
Base URL pattern: /api/{business_id}/recurring_payments
Customer API (Public)
Public endpoints do not require authentication:
GET /api/recurring_payments/{subscription_id}/subscribe
POST /api/recurring_payments/{subscription_id}/subscribe
PUT /api/recurring/cancel
Create Subscription
POST /api/{business}/recurring_payments
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
amount | number | Yes | Charge amount per billing cycle |
customerId | string (UUID) | Yes | Customer who will be billed |
startDate | date | Yes | First charge date |
sequence | integer | Yes | Billing frequency (1–6, see Frequency Options) |
cardEntryByMerchant | boolean | Yes | true = merchant enters card, false = customer enters card |
isInstallment | boolean | No | true = installment plan with fixed number of payments |
numberOfBills | integer | If installment | Total number of payments in the installment plan |
endDate | date | No | End date for the subscription |
merchant_description | string | No | Description visible to merchant and customer |
threeDSecure | boolean | No | Enable 3D Secure for customer card entry. Default: true |
cardData | object | If merchant & new card | Card details (see below) |
selectedCardId | string (UUID) | If merchant & saved card | ID of a previously stored card |
Card Data (when merchant enters a new card)
| Field | Type | Required | Description |
|---|---|---|---|
cardData.cardNumber | string | Yes | Full card number |
cardData.nameOnCard | string | Yes | Cardholder name |
cardData.month | string | Yes | Expiry month (01–12) |
cardData.year | string | Yes | Expiry year |
cardData.cvv | string | Yes | Security code |
POST /api/{business}/recurring_payments
Content-Type: application/json
Authorization: Bearer {token}
{
"amount": 99.99,
"customerId": "customer-uuid",
"startDate": "2026-03-01",
"sequence": 3,
"cardEntryByMerchant": false,
"merchant_description": "Monthly membership",
"threeDSecure": true
}
{
"ok": true,
"message": "Subscription created successfully",
"subscription": {
"id": "subscription-uuid",
"amount": 99.99,
"is_active": 0,
"sequence": 3,
"start_date": "2026-03-01"
}
}
List Subscriptions
GET /api/{business}/recurring_payments
Returns a paginated list of all subscriptions for the business.
{
"ok": true,
"recurring_payments": { /* paginated collection */ },
"filters": {
"fromDate": "2026-01-01",
"toDate": "2026-02-19",
"perPage": 10
}
}
Get Subscription Details
GET /api/{business}/recurring_payments/{subscription}
Update Subscription
PUT /api/{business}/recurring_payments/{subscription}
Updates subscription details such as amount, frequency, or description.
Delete Subscription
DELETE /api/{business}/recurring_payments/{subscription}
Resend Notification
POST /api/{business}/recurring_payments/{subscription}/resend
Re-sends the subscription activation email to the customer.
Export Subscriptions
GET /api/{business}/recurring_payments/export
Returns all subscriptions matching the filter criteria for export purposes.
View Subscription (Public)
GET /api/recurring_payments/{subscription}/subscribe
Loads the subscription details for the customer to view and activate by entering card details.
{
"ok": true,
"payload": {
"reoccurringPayment": {
"id": "subscription-uuid",
"amount": 99.99,
"sequence": 3,
"start_date": "2026-03-01"
},
"invoice": null,
"business": {
"dbaName": "Acme Corp",
"address": { /* ... */ }
},
"customerEmail": "[email protected]",
"logo": "https://s3.amazonaws.com/..."
}
}
Activate Subscription (Public)
POST /api/recurring_payments/{subscription}/subscribe
Customer submits card details to activate the subscription. The card is stored securely and the subscription becomes active.
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
cardData.cardNumber | string | Yes | Full card number |
cardData.nameOnCard | string | Yes | Cardholder name |
cardData.month | string | Yes | Expiry month (01–12) |
cardData.year | string | Yes | Expiry year |
cardData.cvv | string | Yes | Security code |
{
"ok": true,
"payload": {
"subscription": {
"id": "subscription-uuid",
"is_active": 1,
"card_id": "stored-card-uuid"
}
}
}
Cancel Subscription (Public)
PUT /api/recurring/cancel
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
id | string (UUID) | Yes | Subscription ID to cancel |
{
"ok": true,
"message": "Subscription cancelled successfully"
}
Frequency Options
| Sequence Value | Label | Interval |
|---|---|---|
1 | Weekly | Every 1 week |
2 | Bi-Weekly | Every 2 weeks |
3 | Monthly | Every 1 month |
4 | Quarterly | Every 3 months |
5 | Twice a Year | Every 6 months |
6 | Annual | Every 12 months |
Scheduling & Payment Queue
RapidCents uses a two-stage billing engine to process recurring payments:
Stage 1 — Subscription Scheduler
The handle:subscriptions command runs daily and evaluates all active subscriptions. For each subscription:
- Calculates the next billing date from
last_transaction_date(orstart_date) andsequence - If today is the billing date and no queue entry exists, creates a
PaymentQueuerecord with statusPENDING - Skips subscriptions that have reached their installment limit
Stage 2 — Payment Queue Processor
The app:handle-payment-queue command processes all pending queue items:
- Charges the stored card via Visa, Mastercard, Discover, or Amex
- On success: marks the queue item as
FULFILLED, incrementsnumber_of_paid_bills, sends success notification - On decline: increments the retry counter, updates
last_failed_attempt_at, sends decline notification
Retry Logic
When a payment is declined, the system automatically retries based on a configurable strategy.
| Attempt | Delay | Description |
|---|---|---|
| 1st attempt | Day 0 | Initial charge on the billing date |
| 2nd attempt | +3 days | First retry after 3 days |
| 3rd attempt | +3 days | Second retry after 6 days total |
| 4th attempt | +3 days | Final retry after 9 days total |
The retry strategy is encoded as "0 3 3 3" where each number represents the number of days before the next attempt. Both merchant and customer receive email notifications for each failed attempt.
Card on File
Recurring payments use securely stored card tokens. The card can be stored in two ways:
- Merchant-entered card: The card is tokenized at subscription creation time and linked to the subscription.
- Customer-entered card: The customer enters card details via the hosted page, which are tokenized and stored.
- Existing saved card: The merchant can select a previously stored card using
selectedCardId.
All subsequent charges use the stored card token — the raw card data is never stored or re-transmitted.
All Endpoints
Merchant Endpoints (Authenticated)
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/{business}/recurring_payments | List subscriptions |
| POST | /api/{business}/recurring_payments | Create subscription |
| GET | /api/{business}/recurring_payments/{id} | Get details |
| PUT | /api/{business}/recurring_payments/{id} | Update subscription |
| DELETE | /api/{business}/recurring_payments/{id} | Delete subscription |
| POST | /api/{business}/recurring_payments/{id}/resend | Resend notification |
| GET | /api/{business}/recurring_payments/export | Export subscriptions |
Public Endpoints (No Authentication)
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/recurring_payments/{id}/subscribe | View subscription page |
| POST | /api/recurring_payments/{id}/subscribe | Activate subscription |
| PUT | /api/recurring/cancel | Cancel subscription |
Notifications
| Event | Recipient | Subject | Content |
|---|---|---|---|
| Subscription created (customer card) | Customer | Your Recurring payment is Ready | Amount, frequency, “Pay Now” link |
| Subscription created (merchant card) | Customer | Your Upcoming Recurring Payment & Invoice | Amount, frequency, PDF invoice attachment |
| Payment success | Customer | Your Subscription Payment Was Successful | Amount, card, installment info, transaction date |
| Payment success | Merchant | Subscription Payment Received from {customer} | Amount, card, installment info, transaction date |
| Payment declined | Customer | Your Subscription Payment Was Declined | Decline reason, attempt count |
| Payment declined | Merchant | Subscription Payment Failed for {customer} | Decline reason, attempt count |
Error Handling
| HTTP Code | Scenario | Description |
|---|---|---|
422 | Validation error | Missing or invalid required fields |
404 | Not found | Subscription does not exist |
403 | Contract unsigned | Linked contract must be signed before activation |
500 | Server error | Unexpected processing error |