Skip to main content
Subscription Merchant API v2.0 enables recurring billing via credit card. Create a plan, direct the customer through a one-time card linking flow, and Singapay automatically charges the saved card on every cycle — no customer action required after the initial setup.
This is a Money In operation. Each cycle charge transfers funds from the customer’s tokenized card to your Singapay Payment Gateway account.

API Version

v2.0

Base Path

/api/v2.0/recurring/plans

Auth

Bearer Token (JWT)

Channel

Credit Card (recurring)

Subscription lifecycle


Plan status lifecycle


Initial card linking — auto-cancel on hard failure

When a plan is created with charge_immediately = true and the customer’s first card-linking attempt is rejected by the issuer or acquirer, the platform auto-cancels the plan immediately.There is no saved card to retry against, so retrying would never succeed.
When an auto-cancel occurs:
  • The bill for that cycle moves to cancelled
  • The plan transitions from pending_payment / pending_card_linking directly to cancelled
  • The active payment link is expired — the customer cannot complete a charge against the cancelled plan
  • A subscription.plan.status_changed webhook fires with plan.metadata.cancellation_reason = initial_linking_failed
Plans created with charge_immediately = false are not affected by this rule. To re-attempt after a hard failure, create a new plan.

Amount vs. items

A plan is either amount-only or itemized — never both. This is enforced on both Create and Update.

Amount-only

Send amount. The entire recurring charge is a single line item — simple and straightforward.

Itemized

Send items[]. The per-cycle charge is the sum of quantity × unit_price across all items.
Sending both amount and items in the same request returns a 422 validation error. On Update, the patch shape must match the plan’s existing type — mixing returns 409 with response code SP102.

Retry policy

When a cycle charge fails, Singapay automatically retries based on the plan’s configured policy.

Error reference


Important notes

Subscriptions run exclusively on credit card recurring. The initial card linking uses one-time 3DS; all subsequent cycle charges use the tokenized card silently — no customer action needed.
The per-cycle charge must clear the card channel minimum. Plans below this floor are rejected on both Create and Update with a 422 validation error.
subscription_id is a globally unique merchant-supplied identifier across all plans for the merchant. merchant_reff_no is an optional, non-unique label for grouping and reporting — echoed back on every cycle webhook.
A PATCH that changes amount or items triggers the full upgrade flow — the existing plan is closed and a new plan is created with parent_plan_id pointing at it, plus an optional proration and a fresh payment link.A PATCH that only changes name, merchant_reff_no, or metadata patches the plan in place without creating a new plan.
All Merchant API routes require IP whitelisting. Ensure your server IP is registered for the merchant account before making any API calls.

Available endpoints

Create Recurring Plan

Register a new plan. Returns a payment_link_url for the customer’s one-time card linking.

Get Recurring Plan

Fetch current plan state — status, schedule progress, next payment date, retry policy, and lineage.

Update or Upgrade Plan

Patch cosmetic fields in place, or change amount / items to trigger the upgrade flow with a new plan and optional proration.

Cancel Plan

Stop a plan immediately. Active plans go through the lifecycle service; pending plans are cancelled outright.
All endpoints require authentication. See Authentication.

Changelog