Recurring Billing
Charge a customer on a repeating schedule with a contract and subscription
Recurring billing charges a customer automatically on a repeating schedule — a monthly membership, an annual renewal, or a fixed installment plan. You set it up once by creating a contract (the schedule, amount, and line items) and a subscription (the customer, the saved card, and the status), and PCE bills each cycle for you. For the full field list, jump to the Request reference.
A single call to /checkout/v3/contractsubscription creates both objects together. To bill a customer once instead of on a schedule, use Sale. To collect with an emailed bill instead of an automatic charge, use invoicing (a companion page in this section).
Common use cases
- Bill a subscription or membership every month or year
- Spread a purchase across a fixed number of installments
- Renew a service automatically on a saved card, with receipts each cycle
Make your first recurring plan
The fastest way to see it work: create a monthly plan on a customer's saved card. You'll need a customerId and a saved-card cardAccountId first — vault a card with Card Vaulting. The full set of options is in the Request reference.
POST /checkout/v3/contractsubscription
{
"contract": {
"merchantId": 1000157980,
"type": "Recurring",
"interval": "Monthly",
"frequency": 1,
"totalAmount": 49.99
},
"subscription": {
"customerId": 10000001524400,
"cardAccountId": 10000001225823,
"invoiceMethod": "Autopay",
"status": "Active",
"startDate": "2026-02-01"
}
}You'll get back a 200 OK with the created contract and subscription, each with a server-assigned id. Store contract.id (to update or cancel the plan) and subscription.id.
{
"contract": {
"id": 10000000027043,
"merchantId": 1000157980,
"interval": "Monthly",
"frequency": 1,
"totalAmount": "49.99",
"subTotalAmount": "49.99",
"subscriptionCount": 1,
"prorated": false,
"billNow": false
},
"subscription": {
"id": 10000000015147,
"contractId": 10000000027043,
"startDate": "2026-02-01T05:00:00Z",
"invoiceMethod": "AutoPay",
"cardAccountId": 10000001225823,
"customerId": 10000001524400,
"status": "Active",
"sendReceipt": "Always",
"allowPartialPayment": false,
"eftAgreementRequested": false,
"created": "2026-01-06T20:15:40.853Z",
"modified": "2026-01-06T20:15:40.853Z"
}
}The endpoint is documented in the API reference at POST /checkout/v3/contractsubscription.
Scenarios
Every recurring plan is a contract + subscription pair. What changes per scenario is the schedule and how the first cycle is billed. Pick the one that matches the problem you're solving.
sequenceDiagram
participant You as Your Application
participant PCE as PCE
participant Issuer as Cardholder's Bank
You->>PCE: POST /checkout/v3/contractsubscription
PCE->>PCE: Create contract + subscription (status: Active)
PCE-->>You: 200 OK (contract.id, subscription.id)
loop Each billing cycle
PCE->>Issuer: Charge saved card for the cycle amount
Issuer-->>PCE: Approved / Declined
PCE-->>You: Webhook (PaymentSuccess / PaymentFail)
end
Before you begin (all scenarios)
- The customer exists and you have their
customerId(see Create a customer). - A card is vaulted for that customer and you have its
cardAccountId(see Card Vaulting).
Scenario 1: Monthly subscription on a saved card
(recurring plan, billed automatically)
Use this for memberships and subscriptions billed the same amount every month. Set interval to Monthly and frequency to 1, point the subscription at the customer's saved card, and set invoiceMethod to Autopay so PCE charges the card each cycle.
You'll also need: the customer's customerId and a saved cardAccountId.
Request
POST /checkout/v3/contractsubscription
{
"contract": {
"merchantId": 1000157980,
"type": "Recurring",
"interval": "Monthly",
"frequency": 1,
"totalAmount": 49.99
},
"subscription": {
"customerId": 10000001524400,
"cardAccountId": 10000001225823,
"invoiceMethod": "Autopay",
"status": "Active",
"sendReceipt": "Always",
"startDate": "2026-02-01"
}
}Response
{
"contract": {
"id": 10000000027043,
"merchantId": 1000157980,
"interval": "Monthly",
"frequency": 1,
"totalAmount": "49.99",
"subscriptionCount": 1,
"billNow": false
},
"subscription": {
"id": 10000000015147,
"contractId": 10000000027043,
"startDate": "2026-02-01T05:00:00Z",
"invoiceMethod": "AutoPay",
"cardAccountId": 10000001225823,
"customerId": 10000001524400,
"status": "Active",
"sendReceipt": "Always"
}
}Scenario 2: Annual plan billed on a fixed date
(yearly interval on a specific calendar day)
Use this for annual renewals that must land on a set date. Set interval to Yearly, then pin the day with month, dayNumber, and dayType. Here the plan bills every January 1.
You'll also need: the calendar date the renewal should charge.
Request
POST /checkout/v3/contractsubscription
{
"contract": {
"merchantId": 1000157980,
"type": "Recurring",
"interval": "Yearly",
"frequency": 1,
"month": "January",
"dayNumber": 1,
"dayType": "Day",
"totalAmount": 240.00
},
"subscription": {
"customerId": 10000001524400,
"cardAccountId": 10000001225823,
"invoiceMethod": "Autopay",
"status": "Active",
"startDate": "2026-01-01"
}
}Response
{
"contract": {
"id": 10000000027050,
"merchantId": 1000157980,
"interval": "Yearly",
"frequency": 1,
"month": "January",
"dayNumber": 1,
"dayType": "Day",
"totalAmount": "240.00",
"billNow": false
},
"subscription": {
"id": 10000000015160,
"contractId": 10000000027050,
"startDate": "2026-01-01T05:00:00Z",
"invoiceMethod": "AutoPay",
"cardAccountId": 10000001225823,
"customerId": 10000001524400,
"status": "Active"
}
}Scenario 3: Plan with line items, tax, and a discount, billed now
(itemized contract with the first cycle charged immediately)
Use this when the plan has itemized products, sales tax, and a discount, and you want to charge the first cycle at creation. Provide purchases[], taxes[], and discounts[], and set billNow to true.
You'll also need: the product line items, applicable tax rate, and any discount to apply.
Request
POST /checkout/v3/contractsubscription
{
"contract": {
"merchantId": 1000157980,
"type": "Recurring",
"interval": "Monthly",
"frequency": 1,
"prorated": false,
"billNow": true,
"purchases": [
{
"productName": "Mittens",
"description": "Warm Gloves",
"price": 4.99,
"quantity": 5,
"subTotalAmount": "24.95",
"taxRate": "0.089",
"taxAmount": "1.93"
}
],
"taxes": [
{ "name": "Sales Tax", "rate": "0.089", "taxAmount": "1.93" }
],
"discounts": [
{
"name": "Loyalty 13%",
"discountType": "Order",
"discountRateType": "Percent",
"discountApplicationType": "Automatic",
"rate": "0.13",
"code": "LOYAL13"
}
],
"subTotalAmount": "24.95",
"taxAmount": "1.93",
"discountAmount": "3.24",
"totalAmount": 23.64
},
"subscription": {
"customerId": 10000001524400,
"cardAccountId": 10000001225823,
"invoiceMethod": "Autopay",
"status": "Active",
"allowPartialPayment": false,
"startDate": "2026-02-01"
}
}Response
{
"contract": {
"id": 10000000027055,
"merchantId": 1000157980,
"interval": "Monthly",
"frequency": 1,
"purchases": [
{
"id": 10000000027413,
"productName": "Mittens",
"description": "Warm Gloves",
"quantity": 5,
"price": "4.99",
"subTotalAmount": "24.95",
"taxAmount": "1.93"
}
],
"subTotalAmount": "24.95",
"taxAmount": "1.93",
"totalAmount": "23.64",
"prorated": false,
"billNow": true
},
"subscription": {
"id": 10000000015170,
"contractId": 10000000027055,
"startDate": "2026-02-01T05:00:00Z",
"invoiceMethod": "AutoPay",
"cardAccountId": 10000001225823,
"customerId": 10000001524400,
"status": "Active",
"allowPartialPayment": false
}
}Track the plan
Read the subscription.status on the response for the immediate outcome. To follow a plan afterwards:
- Retrieve the subscription with
GET/checkout/v3/contractsubscription/{id}. - Retrieve the contract with
GET/checkout/v3/contract/{id}. - List the payments a contract has generated with
GET/checkout/v3/contract/payment. - Read the audit trail (created, activated, cancelled, payment, sent, and ACH-authorization events) with
GET/checkout/v3/contract/history.
Each scheduled charge is a payment, so subscribe to the payment webhooks to track cycles without polling:
- PaymentSuccess: a cycle charge was approved.
- PaymentFail: a cycle charge was declined.
Manage a plan
| Job | Call | Reference |
|---|---|---|
| Cancel / remove a subscription | DELETE /checkout/v3/contractsubscription/{id} | Remove a subscription |
| Update the underlying contract | PUT /checkout/v3/contract/{id} | Update a contract |
| Delete the contract | DELETE /checkout/v3/contract/{id} | Delete a contract |
To pause billing without deleting the plan, update the subscription status to Inactive; set it back to Active to resume.
Additional operations. Contracts also support file attachments (attach / read / delete). For reconciling contracts against settlement and deposits, see Reports & Reconciliation.
Request reference
The complete set of fields for the create request. The body is a { "contract": { … }, "subscription": { … } } envelope. Scenarios above use subsets of these.
Contract object
The schedule, amounts, and line items.
| Parameter | Required | Description |
|---|---|---|
merchantId | ✓ | Your PCE merchant identifier that owns the contract. |
type | Recommended | Billing behavior. Possible values: Recurring, Installment. |
interval | Required for billing | How often the contract bills. Possible values: Once, Daily, Weekly, Monthly, Yearly. |
frequency | Required for billing | Number of intervals between each billing cycle (for example, interval: Monthly + frequency: 3 bills quarterly). |
weekDay | Optional | Day of the week billing occurs. Possible values: Sunday–Saturday. |
month | Optional | Month billing is scheduled. Possible values: January–December. |
dayNumber | Optional | Day number of the month on which billing occurs. |
dayType | Optional | How the billing day is calculated. Possible values: Day, First, Second, Third, Fourth, Last. |
day | Optional | Specific day configuration. Possible values: Sunday–Saturday, Day, Weekday, Weekend. |
purchases | Optional | Array of line items on the contract (product name, price, quantity, per-item tax). |
taxes | Optional | Array of tax breakdowns applied to the contract. |
discounts | Optional | Array of discounts applied to the contract. |
totalAmount | Recommended | Final amount charged each cycle, including taxes and discounts. |
subTotalAmount | Optional | Amount before taxes and discounts. |
taxAmount | Optional | Total tax applied to the contract. |
discountAmount | Optional | Total discount applied to the contract. |
prorated | Optional | Set to true to prorate the first invoice amount. |
billNow | Optional | Set to true to charge the first cycle immediately at creation. |
Subscription object
The customer, the funding card, and the status.
| Parameter | Required | Description |
|---|---|---|
customerId | ✓ | The customer being billed. See Create a customer. |
cardAccountId | Required for billing | The saved card used for billing. Vault a card with Card Vaulting. |
startDate | Recommended | Date the subscription becomes active and billing begins. |
invoiceMethod | Recommended | How each cycle is collected. Use Autopay to charge the saved card automatically. |
status | Recommended | Subscription status. Possible values: Active, Inactive, Cancelled, Trial, Pending, Completed, PendingAuthorization, Deleted. |
sendReceipt | Optional | When to send receipts. Possible values: Always, Never, First. |
allowPartialPayment | Optional | Set to true to allow partial payments against a cycle's invoice. |
eftAgreementRequested | Optional | Set to true to request an EFT/ACH agreement for the subscription. |
Validation
The prerequisites above are the validations, and PCE enforces them when you submit. Only contract.merchantId and subscription.customerId are required by the schema; to actually bill, you must also supply a schedule (interval + frequency) and a funding method (cardAccountId). A submission is checked synchronously; if a check fails, the request returns an error and no contract is created.
Submission checks:
- Required fields are present and correctly formatted.
- The
customerIdandcardAccountIdresolve to a real customer and a chargeable saved card. - Your merchant account is permitted to create recurring contracts.
Statuses
A subscription carries one of these statuses. Active bills on schedule; Inactive pauses billing; Cancelled and Deleted stop it; Trial and Pending/PendingAuthorization cover pre-active states; Completed applies when a fixed plan has run its course.
| Status | Meaning |
|---|---|
Active | Billing on schedule. |
Inactive | Paused; not billing until reactivated. |
Trial | In a trial period before regular billing. |
Pending | Created but not yet active. |
PendingAuthorization | Awaiting authorization (for example, an EFT/ACH agreement). |
Completed | All scheduled cycles have run (installment plans). |
Cancelled | Stopped by request; no further billing. |
Deleted | Removed. |
Go live
The shared pre-production checklist (production credentials, webhook subscription, and sandbox testing) is in Getting Started. Specific to recurring billing, also confirm:
- Customers and cards are vaulted before you create their plans (you need
customerIdandcardAccountId). - You subscribe to
PaymentSuccessandPaymentFailand handle a declined cycle (retry, dunning, or pause the plan). - The schedule fields (
interval,frequency, and where usedmonth/dayNumber/dayType) produce the billing date you expect. - Receipts (
sendReceipt) and any EFT agreement (eftAgreementRequested) match your business and compliance requirements.
Best practices
General practices (subscribe to webhooks, test in sandbox) are in Getting Started. Specific to recurring billing:
| Practice | Description |
|---|---|
| Vault first | Create the customer and vault their card before the plan, so customerId and cardAccountId are ready. |
| Handle failed cycles | Watch PaymentFail and apply dunning or retry logic; a declined cycle shouldn't silently stop revenue. |
| Pause, don't delete | To hold billing temporarily, set status: Inactive rather than deleting — you keep the plan and history. |
| Reconcile with history | Use /checkout/v3/contract/payment and /checkout/v3/contract/history to reconcile what a plan has billed. |
| Keep amounts explicit | Send subTotalAmount, taxAmount, discountAmount, and totalAmount so the billed amount is unambiguous. |
Next steps
See also
- Sale: charge a customer once instead of on a schedule
- Card Vaulting: vault cards for recurring charges
- Payment Lifecycle: statuses and settlement for each cycle's payment
- Payment Response Codes: resolve a declined cycle
- Webhook Event Types: the events that track each cycle
Updated about 4 hours ago