Documentation Index
Fetch the complete documentation index at: https://docs.ozura.com/llms.txt
Use this file to discover all available pages before exploring further.
Recurring mode lets you create a checkout session that, on successful payment, automatically enrolls the customer in a billing plan. The customer fills in their card details once; OzuraPay handles every subsequent charge on the schedule you define.
How it works under the hood: When the customer pays, Checkout calls PayAPI’s createRecurringPlan endpoint rather than the standard cardSale endpoint. The customer’s card is tokenized by the vault and never stored by your server.
Enable Recurring Mode
Set checkoutMode to "recurring" and include a recurringConfig object:
{
"merchantId": "your_merchant_id",
"merchantName": "My App",
"amount": "29.99",
"currency": "USD",
"checkoutMode": "recurring",
"recurringConfig": {
"planName": "Monthly Pro",
"interval": "monthly",
"startDate": "2026-06-01"
},
"successUrl": "https://yoursite.com/welcome",
"cancelUrl": "https://yoursite.com/pricing",
"errorUrl": "https://yoursite.com/error"
}
recurringConfig is required when checkoutMode is "recurring". Omitting it returns a 400 validation error.
recurringConfig Fields
Required
| Field | Type | Constraints | Description |
|---|
planName | string | Max 50 chars | Label for this subscription plan, shown to the customer in the checkout UI |
interval | string | "daily", "weekly", "monthly", "yearly" | Billing frequency keyword. Combine with intervalCount for non-standard periods (e.g. every 3 months) |
startDate | string | YYYY-MM-DD | First billing date shown to the customer for legal disclosure. Not forwarded to the payment processor — the processor starts billing based on when the plan is created, not this date |
Optional
All fields below are optional. When omitted, they are not stored on the session and not sent to PayAPI — any defaults listed are applied by the PayAPI, not by Checkout.
Type note: intervalCount, initialCycles, maxCycles, and maxAttempts must be JSON numbers (not strings). initialAmount and setupFee must be JSON strings (quoted decimals like "9.99"). This matches how PayAPI expects them.
| Field | Type | PayAPI default | Description |
|---|
planDescription | string (max 100 chars) | — | Short description shown below the plan name in the checkout UI |
intervalCount | integer ≥ 1 | 1 | Billing period multiplier. Combined with interval to define the billing period. interval: "monthly" + intervalCount: 3 = billed every 3 months (quarterly). interval: "weekly" + intervalCount: 2 = every 2 weeks |
endDate | string (YYYY-MM-DD) | indefinite | Date after which the processor stops billing automatically. Omit for an ongoing plan |
maxCycles | integer ≥ 1 | indefinite | Maximum number of billing cycles before the plan completes automatically. Omit for an ongoing plan. Can be set alongside endDate — whichever limit is hit first stops billing |
maxAttempts | integer ≥ 0 | 3 | How many times PayAPI retries a failed charge before marking the attempt failed. Pass 0 to disable retries |
setupFee | string (decimal, e.g. "9.99") | — | One-time fee charged on the first billing cycle only, in addition to the regular amount. Does not repeat |
initialAmount | string (decimal, e.g. "9.99") | — | Override the billing amount for the first N cycles (introductory / trial pricing). Must be paired with initialCycles to have effect. See Trial Pricing |
initialCycles | integer ≥ 1 | — | Number of cycles at the initialAmount before switching to the standard session amount. Has no effect if initialAmount is not also set |
merchantRecurringReference | string (max 50 chars) | — | Your own subscription or customer ID forwarded to PayAPI. Use this to correlate the plan back to your records — it is the recommended way to look up a plan ID after enrollment |
amount Field
The amount on the session is the standard recurring charge — what the customer is billed on each normal billing cycle.
{
"amount": "29.99",
"checkoutMode": "recurring",
"recurringConfig": { ... }
}
What gets charged on the first cycle?
Checkout forwards amount, setupFee, initialAmount, and initialCycles as separate fields to PayAPI. PayAPI combines them and calculates the actual charge — Checkout does not compute a combined total locally.
| Configuration | Effective first cycle charge | Subsequent cycles |
|---|
| No trial fields | amount | amount |
setupFee only | setupFee + amount (PayAPI adds them) | amount |
initialAmount + initialCycles | initialAmount (repeated for N cycles) | amount |
| All three | setupFee + initialAmount (PayAPI adds them) | amount (after initialCycles expire) |
There is no field called intervalAmount. The field that overrides the billing amount for the first N cycles is initialAmount.
items arrays are not supported for recurring mode. Recurring charges are a fixed scalar amount, not a cart total. Providing items returns a 400 error.
Surcharge
Add a credit card surcharge to the recurring charge using surchargePercent. The surcharge is shown as a line item in the order summary and forwarded to the payment processor.
{
"amount": "29.99",
"checkoutMode": "recurring",
"surchargePercent": "2.00",
"recurringConfig": {
"planName": "Monthly Pro",
"interval": "monthly",
"startDate": "2026-06-01"
}
}
- Accepts a string (
"2.00") or number (2.0)
- Maximum
"3.00" (Florida 3% cap)
- Displayed as a separate line item:
Surcharge (2.00%)
- Applied to the base
amount before tax
See Surcharge below for the full reference.
Trial Pricing
Use setupFee, initialAmount, and initialCycles together to offer introductory pricing.
Setup Fee Only
A one-time fee added to the first billing cycle:
{
"amount": "29.99",
"recurringConfig": {
"planName": "Pro Monthly",
"interval": "monthly",
"startDate": "2026-06-01",
"setupFee": "9.99"
}
}
| Cycle | Charged |
|---|
| Cycle 1 | $9.99 + $29.99 = $39.98 |
| Cycle 2+ | $29.99 |
Introductory Rate
Override the amount for the first N cycles:
{
"amount": "29.99",
"recurringConfig": {
"planName": "Pro Monthly",
"interval": "monthly",
"startDate": "2026-06-01",
"initialAmount": "9.99",
"initialCycles": 2
}
}
| Cycle | Charged |
|---|
| Cycle 1–2 | $9.99 |
| Cycle 3+ | $29.99 |
Combined (Setup Fee + Trial)
{
"amount": "49.99",
"recurringConfig": {
"planName": "Annual Premium",
"interval": "yearly",
"startDate": "2026-07-01",
"setupFee": "10.00",
"initialAmount": "19.99",
"initialCycles": 1
}
}
| Cycle | Charged |
|---|
| Cycle 1 | $10.00 (setup) + $19.99 (trial) = $29.99 |
| Cycle 2+ | $49.99 |
Interval Examples
Use interval alone for standard periods. Add intervalCount to create any custom period — the two fields multiply together.
{ "interval": "daily" } // Every day
{ "interval": "weekly" } // Every week
{ "interval": "monthly" } // Every month
{ "interval": "yearly" } // Every year (annual)
{ "interval": "weekly", "intervalCount": 2 } // Every 2 weeks (biweekly)
{ "interval": "monthly", "intervalCount": 3 } // Every 3 months (quarterly)
{ "interval": "monthly", "intervalCount": 6 } // Every 6 months (semi-annual)
{ "interval": "daily", "intervalCount": 30 } // Every 30 days
intervalCount is a JSON number (not a string). "intervalCount": "3" will return a 400 validation error.
Capped Plans
Use endDate or maxCycles to automatically stop billing:
{
"amount": "9.99",
"checkoutMode": "recurring",
"recurringConfig": {
"planName": "12-Month Plan",
"interval": "monthly",
"startDate": "2026-06-01",
"maxCycles": 12,
"endDate": "2027-06-01"
}
}
Either field alone is sufficient; you can set both for belt-and-suspenders control.
Full Example
Monthly subscription with a 3% surcharge, 1-month trial, and a 12-cycle cap:
curl -X POST https://checkout.ozura.com/api/sessions/create \
-H "X-API-KEY: your_vault_key" \
-H "X-OZURA-API-KEY: your_merchant_key" \
-H "Content-Type: application/json" \
-d '{
"merchantId": "your_merchant_id",
"merchantName": "My SaaS",
"amount": "49.99",
"currency": "USD",
"checkoutMode": "recurring",
"surchargePercent": "3.00",
"successUrl": "https://yoursite.com/welcome",
"cancelUrl": "https://yoursite.com/pricing",
"errorUrl": "https://yoursite.com/error",
"recurringConfig": {
"planName": "Pro Monthly",
"planDescription": "Unlimited access to all Pro features",
"interval": "monthly",
"startDate": "2026-06-01",
"initialAmount": "0.00",
"initialCycles": 1,
"setupFee": "5.00",
"maxCycles": 12,
"maxAttempts": 3,
"merchantRecurringReference": "cus_abc123"
}
}'
What the Customer Sees
The checkout page displays a Subscription Summary block above the payment form showing:
- Plan name and description
- Billing interval and start date
- Surcharge row (if
surchargePercent is set)
- End date and cycle cap (if configured)
- Setup fee and trial pricing (if applicable)
The payment form and button are identical to a standard payment session.
Success Redirect
After a successful recurring signup, the customer is redirected to your successUrl with the standard transaction parameters:
https://yoursite.com/welcome?success=true&sessionId=session_xxx&checkoutMode=recurring&transactionId=250107000019C4E1B&transactionType=sale&amount=49.99¤cy=USD&ozuraMerchantId=ozu_xxx&surchargeAmount=1.50&cardLastFour=1111&cardBrand=VISA&transDate=2026-06-01T12:00:00.000Z
| Parameter | Description |
|---|
checkoutMode | "recurring" |
transactionType | "sale" (the initial CIT charge that enrolled the customer) |
transactionId | The initial charge transaction ID from the payment processor |
surchargeAmount | Calculated surcharge amount in the session currency |
| (all other standard params) | Same as a standard payment — see Handle the Result |
planId is not included in the success URL redirect. The PayAPI plan ID is part of the raw payment processor response but is not appended to the redirect URL. To retrieve the plan ID for subscription management (pause, cancel, lookup), query the PayAPI recurring plan endpoints using your merchant credentials — PayAPI associates plans with the merchantRecurringReference or by listing plans for your merchant account.
Combine with Payment Links
Create a shareable recurring subscription link:
{
"merchantId": "your_merchant_id",
"merchantName": "My SaaS",
"amount": "29.99",
"currency": "USD",
"checkoutMode": "recurring",
"recurringConfig": {
"planName": "Monthly Pro",
"interval": "monthly",
"startDate": "2026-06-01"
},
"successUrl": "https://yoursite.com/welcome",
"cancelUrl": "https://yoursite.com/pricing",
"errorUrl": "https://yoursite.com/error"
}
Post this to POST /api/payment-links/create and share the returned url. Each customer who visits the link and pays is enrolled in their own plan. See Payment Links for full details.
Surcharge Reference
surchargePercent is independent of checkoutMode — it works on standard payment sessions too.
| Field | Type | Required | Behaviour when omitted | Constraints |
|---|
surchargePercent | string or number | No | Treated as 0% at charge time — no surcharge line item shown, "0.00" sent to the payment processor | 0 – 3.00 (Florida maximum). Normalised internally to two decimal places (e.g. 2.5 → "2.50") |
The surcharge is:
- Displayed as a line item in the order summary:
Surcharge (X.XX%)
- Applied to the base
amount (before tax)
- Forwarded to the payment processor on every charge (including recurring cycles)
- Applied to debit cards at the processor’s discretion — PayAPI performs a BIN lookup and excludes debit cards automatically where required
{
"amount": "100.00",
"surchargePercent": "3.00"
}
Order summary: Subtotal $100.00 + Surcharge (3.00%) $3.00 = Total $103.00