Integration Basics
Project Structure
We recommend organizing your integration code in the following structure:
churnkey/
├── controllers/ # Data access endpoints
│ ├── Customers.ts
│ ├── Prices.ts
│ ├── Subscriptions.ts
│ ├── Coupons.ts # optional
│ ├── Families.ts # optional
| └── Products.ts # optional
├── models/ # Data models
│ ├── Customer.ts
│ ├── Price.ts
│ ├── Subscription.ts
│ ├── Coupon.ts # optional
│ ├── Family.ts # optional
│ └── Product.ts # optional
├── actions/ # Subscription modifications
│ ├── Cancel.ts # optional
│ ├── ApplyCoupon.ts # optional
│ ├── ExtendTrial.ts # optional
│ ├── ChangePrice.ts # optional
│ └── Pause.ts # optional
└── index.ts # Integration entry point
Pagination
All list endpoints should support pagination to handle large datasets efficiently. Each list()
method accepts pagination parameters and returns a paginated response. You can skip implementation of pagination if you are sure that the number of items will be small. However, it is strongly recommended to implement pagination just in case.
Request Parameters
Pagination is controlled through query parameters:
GET /churnkey/customers?limit=10&cursor=abc123
Response Format
List endpoints return paginated responses in this format:
Error Handling
When an error occurs, return an appropriate HTTP status code along with a structured error response:
{
"code": 500, // HTTP status code
"message": "A human-readable error message"
}
Common status codes:
400
- Bad Request (invalid parameters)401
- Unauthorized (invalid or missing token)404
- Not Found (resource doesn't exist)500
- Internal Server Error
Test Mode
Every request includes an X-Churnkey-Mode
header indicating whether it's a test or live request:
X-Churnkey-Mode: test # Test mode
X-Churnkey-Mode: live # Live mode (default)
Use this header to determine which environment (test or production) to use for your billing system operations. Test mode must be explicitly enabled in the Churnkey dashboard.
Authentication
Every request to your integration endpoints will include an Authorization
header with your integration token:
Authorization: Bearer your_integration_token
Verify this token matches the one from your Churnkey dashboard before processing any requests.
Features Manifest
Your integration must expose a /churnkey/features
endpoint that describes which functionality is supported. This helps Churnkey understand which cancel flow options to enable.
The manifest includes:
- Supported controllers (required and optional)
- Available actions and their configurations
- Supported features for each action (e.g., immediate vs end-of-period cancellation)
Implementing Context
Your custom context should extend the SDK Integrator.Context
class. You can add any properties/methods you need to the context object.
import { Integrator } from '@churnkey/sdk'
export class Context extends Integrator.Context {
db: DbConnection
constructor(mode: Integrator.Mode, db: DbConnection) {
super(mode)
this.db = db
}
}
Instantiating Context
When you expose your integration to the internet, you should provide a function that returns a new instance of your context. This function will be called for every request.
import { Integrator } from './churnkey/Integration'
const app = express()
Integration.expose({
app: app, // express app instance
token: process.env.CK_INTEGRATION_TOKEN, // your integration token
ctx(req, req) {
return new Context(
req.headers['X-Churnkey-Mode'],
req.db
)
}
})