To implement the Cancel action, you need to implement an endpoint and define features
If you don't implement this action, the Cancel Flow will not be available to your customers, even if you implemented other actions.
Prerequisites
SDK
If you are using the SDK, you can implement the Cancel action by following the code example below. You don't need to get into the details of the API endpoints, the SDK will take care of that for you.
import { Integrator } from '@churnkey/sdk'
import { Subscriptions } from '../controllers/Subscriptions'
export const Cancel = Integrator.Cancel.config({
Subscriptions: Subscriptions,
features: {
// define which schedules are supported, at least one is required
schedules: {
[Integrator.Cancel.Schedule.Immediate]: true,
[Integrator.Cancel.Schedule.EndOfPeriod]: true
}
},
async handle(ctx, options) {
const subscription = await this.subscriptions.retrieve({
customerId: options.customerId,
id: options.subscriptionId
})
switch (options.scheduledAt) {
case Integrator.Cancel.Schedule.Immediate:
await ctx.db.cancelSubscription(subscription)
break
case Integrator.Cancel.Schedule.EndOfPeriod:
await ctx.db.cancelSubscriptionAtThePeriodEnd(subscription)
break
}
}
})
Endpoints
Handle Required
POST /churnkey/actions/subscription/cancel
This endpoints handles the single subscription cancellation. You should find the subscription by customerId and subscriptionId and cancel it.
Options for cancellation, provided in the request body.
Unique identifier of the customer.
Unique identifier of the subscription.
immediate end-of-period
When the cancellation should take effect. Subscription can be cancelled immediately or at the end of the current period.
If true, the subscription is required to be unpaused before it is cancelled.
Must return empty response.
See Error Responses.
app.post('/churnkey/actions/subscription/cancel', async (req, res) => {
const subscription = await db.findSubscription(req.body.customerId, req.body.subscriptionId)
switch (req.body.scheduledAt) {
case 'immediate':
await db.cancelSubscription(subscription)
break
case 'end_of_period':
await db.cancelSubscriptionAtThePeriodEnd(subscription)
break
}
res.send()
})
Handle All optional
POST /churnkey/actions/customer/cancel
This endpoint handles cancellation of all customer's subscriptions. You should find all subscriptions by customerId and cancel them.
This endpoint is optional. By default, when we need to cancel all subscriptions, we will call the Handle endpoint for each subscription. You can implement this endpoint to reduce the number of API calls and improve performance/end-user UX.
Options for cancellation, provided in the request body.
Unique identifier of the customer.
immediate end-of-period
When the cancellation should take effect. Subscription can be cancelled immediately or at the end of the current period.
If true, the subscription is required to be unpaused before it is cancelled.
Must return empty response.
See Error Responses.
app.post('/churnkey/actions/customer/cancel', async (req, res) => {
const subscriptions = await db.findSubscriptionsByCustomerId(req.body.customerId)
switch (req.body.scheduledAt) {
case 'immediate':
await db.cancelSubscriptions(subscriptions)
break
case 'end_of_period':
await db.cancelSubscriptionsAtThePeriodEnd(subscriptions)
break
}
res.send()
})
Features
Features define which behavior is supported for the Cancel action. Depending on the features you enabled, requests body will have different options.
For example, if you enable only end-of-period schedule, the request.body.scheduledAt will be always end-of-period. If you enable both schedules, request.body.scheduledAt can be either immediate or end-of-period.
If true, the action is enabled and can be used by Churnkey, otherwise it is disabled. This action should be enabled for Cancel Flow to work.
Defines what schedules are available for subscription cancellation. If your system doesn't support some of the schedules, you should set them to false. At least one schedule should be enabled.
export interface Features {
enabled: boolean
schedules: {
immediate: boolean
end_of_period: boolean
}
}
export const features: Features = {
enabled: true,
schedules: {
immediate: true,
end_of_period: false // this schedule will be disabled
}
}