Payment Plans
A payment plan is a live subscription instance that ties a plan template to a specific customer and stored payment method. Once created, AccruPay charges the stored payment method on the renewal schedule defined by the template.
Prerequisites
Before creating a plan you need:
- A plan template — see Plan Templates
- A stored customer payment method — obtained by completing a checkout or save-a-card flow with
storePaymentMethod: true
Create a plan
import AccruPay, { CURRENCY, PAYMENT_PLAN_STATUS } from '@accrupay/node';
const sdk = new AccruPay({
apiSecret: process.env.ACCRUPAY_API_SECRET!,
});
const plan = await sdk.paymentPlans.createOne({
merchantTransactionProviderId: process.env.ACCRUPAY_PROVIDER_ID,
data: {
merchantInternalPaymentPlanCode: 'plan-customer-123',
templateId: template.id,
paymentMethodId: storedPaymentMethod.id,
amount: 2999n,
currency: CURRENCY.USD,
customer: {
merchantInternalCustomerCode: 'customer-123',
},
// Override template intervals if needed:
renewalIntervalMonths: 1,
endsAfterMonths: 12,
trialPeriodDays: 14,
},
});
console.log(plan.id, plan.status);
note
templateId and paymentMethodId are both required. The plan will be rejected if either references an invalid or inactive record.
Plan lifecycle
INITIALIZING
│
▼
ACTIVE ──────────────────────────────────────────────► ENDED
│ (endsAfterX reached)
│──────────────────────────────────────────────────► CANCELED
│ (cancelOne() called)
│──────────────────────────────────────────────────► INACTIVE
│ (provider paused)
└──────────────────────────────────────────────────► ERROR
(provider failure)
| Status | Description |
|---|---|
INITIALIZING | Plan is being set up on the provider |
ACTIVE | Plan is running — renewals will be charged automatically |
INACTIVE | Plan is paused by the provider but not canceled |
CANCELED | Plan was explicitly canceled via cancelOne() |
ENDED | Plan reached its natural end date (endsAfterX condition met) |
ERROR | Provider encountered an unrecoverable error |
Cancel a plan
await sdk.paymentPlans.cancelOne({
merchantPaymentPlanId: plan.id,
merchantTransactionProviderId: process.env.ACCRUPAY_PROVIDER_ID,
});
Cancellation stops future renewals. Any already-charged periods are not refunded automatically.
Query plans
List plans
getMany() supports rich filtering:
const plans = await sdk.paymentPlans.getMany({
// Filter options (all optional)
merchantInternalCustomerCode: 'customer-123',
templateId: template.id,
currency: CURRENCY.USD,
status: PAYMENT_PLAN_STATUS.ACTIVE,
take: 20,
skip: 0,
});
Fetch a single plan
const plan = await sdk.paymentPlans.getOne({
merchantPaymentPlanId: plan.id,
});
Sync a plan
Pull the latest plan state from the provider. Use this after a webhook or to confirm a cancellation took effect:
const synced = await sdk.paymentPlans.syncOne({
merchantTransactionProviderId: process.env.ACCRUPAY_PROVIDER_ID,
providerCode: plan.providerCode,
});
Plan field reference
Key fields on the plan object returned by the API:
| Field | Type | Description |
|---|---|---|
status | PAYMENT_PLAN_STATUS | Current lifecycle status |
currentPeriodStart | string (ISO 8601) | Start of the current billing period |
currentPeriodEnd | string (ISO 8601) | End of the current billing period |
startedAt | string (ISO 8601) | When the plan became active |
endsAt | string | null (ISO 8601) | Scheduled end date if endsAfterX was set |
trialEndsAt | string | null (ISO 8601) | When the trial period ends, if applicable |
canceledAt | string | null (ISO 8601) | When the plan was canceled |
periodCount | number | Number of completed billing cycles |
Next steps
- Plan Templates — manage the billing schedule definition
- Charge a Stored Card — manually charge a stored method without a plan