Plans And Subscriptions

Define billing plans and manage recurring subscriptions.

Plans define price and interval. Subscriptions bill a customer against a plan. Create the plan first.

kyshi.plans

MethodEndpoint
create(params, options?)POST /v1/plans
list(params?, options?)GET /v1/plans
retrieve(idOrCode, options?)GET /v1/plans/{id}
const plan = await kyshi.plans.create({
  name: 'Pro Monthly',
  interval: 'monthly',
  amount: 20,
  amountCurrency: 'settlement',
  localCurrency: 'NGN',
});

await store(plan.code);   // Subscriptions reference the code.

amountCurrency decides who absorbs FX movement and cannot be changed safely once subscriptions exist. See Plans.

kyshi.subscriptions

MethodEndpoint
create(params, options?)POST /v1/subscriptions
list(params?, options?)GET /v1/subscriptions
retrieve(idOrCode, options?)GET /v1/subscriptions/{id}
manage(idOrCode, params, options?)PATCH /v1/subscriptions/{id}/manage
charge(params, options?)POST /v1/subscriptions/charge
updateCard(idOrCode, params?, options?)POST /v1/subscriptions/{id}/update-card
retryPayment(idOrCode, params?, options?)POST /v1/subscriptions/{id}/retry-payment
simulate(idOrCode, params, options?)POST /v1/subscriptions/{id}/simulate
listInvoices(idOrCode, params?, options?)GET /v1/subscriptions/{id}/invoices
retrieveInvoice(invoiceId, options?)GET /v1/subscriptions/invoices/{invoiceId}
listPaymentAttempts(idOrCode, params?, options?)GET /v1/subscriptions/{id}/payment-attempts
listInvoicePaymentAttempts(invoiceId, params?, options?)GET /v1/subscriptions/invoices/{invoiceId}/payment-attempts

updateStatus() is deprecated — it calls an undocumented alias of manage(). Use manage().

const subscription = await kyshi.subscriptions.create(
  {
    planCode: plan.code,
    customer: '[email protected]',
    paymentMethod: 'card',
    card: 'AUTH_abc123',
    maxRetryCount: 3,
    gracePeriodDays: 3,
  },
  { idempotencyKey: 'SUB-10001' },
);

A new subscription is PENDING. Wait for subscription.active before granting access.

Cancelling

await kyshi.subscriptions.manage(subscription.code, {
  action: 'cancel_at_period_end',
});

Prefer cancel_at_period_end over cancel. An immediate cancel takes access the customer has already paid for.

Recovering a past-due subscription

await kyshi.subscriptions.updateCard(code, { card: 'AUTH_new123' });
await kyshi.subscriptions.retryPayment(code);

Updating the card does not trigger a charge — you must retry. And check the failure category first: retrying a CARD_EXPIRED burns an attempt against the retry limit. See Failure Codes.

const attempts = await kyshi.subscriptions.listPaymentAttempts(code);

Testing the lifecycle

await kyshi.subscriptions.simulate(code, { event: 'payment_failed' });

Drives a billing event immediately instead of waiting for the real cycle. Test mode only. See Simulate Subscription.

Next


Did this page help you?