Direct Connect

Churnkey Direct

Integrate Churnkey with any billing system using Direct mode

Churnkey Direct lets you integrate retention flows with any billing system. Instead of connecting to Stripe or Chargebee, you pass customer and subscription data directly and handle billing operations through callbacks.

Use Direct mode when:

  • You use a custom or unsupported billing system
  • You have strict data privacy requirements
  • You're managing trial or freemium users without subscriptions
  • You need to test flows before setting up a full integration

How it works

  1. Pass customer data when initializing Churnkey
  2. Customer interacts with your retention flow
  3. Your handlers execute billing operations (cancel, discount, pause, etc.)
  4. Churnkey tracks results in analytics automatically

Quick Start

window.churnkey.init('show', {
  appId: 'your_app_id',
  mode: 'live',
  provider: 'direct',
  authHash: 'hmac_signature', // See Authentication section

  customer: {
    id: 'cus_12345',
    email: '[email protected]',
  },

  subscriptions: [
    {
      id: 'sub_67890',
      start: new Date('2024-06-01'), // When subscription started
      status: {
        name: 'active',
        currentPeriod: {
          start: new Date('2025-01-01'),
          end: new Date('2025-02-01'),
        },
      },
      items: [
        {
          price: {
            id: 'price_pro',
            amount: { value: 2999, currency: 'usd' },
            interval: 'month',
            intervalCount: 1,
          },
        },
      ],
    },
  ],

  async handleCancel(customer, surveyChoice, feedback, followupResponse) {
    await yourAPI.cancelSubscription(customer.id);
    return { message: 'Subscription canceled.' };
  },
});

For script installation and HMAC authentication, see the Quick Start Guide.

Customer object

Identifies who is interacting with the retention flow. Only id is required.

idstring
required

Your internal customer ID. Used for authentication and tracking.

emailstring
optional

Customer's email address. Used for Slack notifications, merge fields, and analytics dashboard.

namestring
optional

Customer's display name. Used for merge fields and analytics.

currencystring
optional

ISO 4217 currency code (e.g., 'usd', 'eur', 'gbp'). Used for customer segmentation.

metadataobject
optional

Custom key-value pairs for segmentation. Can also use customerAttributes param. Example: {plan_tier: 'enterprise', team_size: '35'}

Usage: Additional fields like email, name, and metadata are used for segmentation, Slack notifications, merge fields, and analytics.

Subscription object

Describes the customer's billing state and determines which offers are shown.

idstring
required

Your internal subscription ID

statusunion
required

Subscription status with status-specific fields. Determines which offers are shown.

itemsarray
required

At least one subscription item (plan) required

startDate
required

When subscription started. Required for accurate subscription age calculation used in segmentation (e.g., new vs. long-term customers).

endDate
optional

When the subscription ended or is scheduled to end. Used for cancel-at-period-end scenarios.

metadataobject
optional

Custom key-value pairs for segmentation. Same as using customerAttributes or customer.metadata.

Subscription status

The status field determines which offers are available. For example, trial extensions only appear for trial subscriptions.

status: {
  name: 'active',
  currentPeriod: {
    start: new Date('2025-01-01'),
    end: new Date('2025-02-01'),
  },
}

Subscription items

Items represent the products and pricing on a subscription:

items: [
  {
    id: 'si_basic',
    price: {
      id: 'price_basic_monthly',
      amount: { value: 2999, currency: 'usd' }, // $29.99
      interval: 'month',
      intervalCount: 1,
    },
    quantity: 1,
    product: {
      id: 'prod_basic',
      name: 'Basic Plan',
    },
  },
];

See Direct mode examples for usage-based billing, paused subscriptions, and complex scenarios.

Handlers

Handlers execute billing operations when customers accept offers. Each offer requires its corresponding handler—if you configure a pause offer in the Flow Builder but don't provide handlePause, the offer won't appear.

async handleCancel(customer, surveyChoice, feedback, followupResponse) {
  // surveyChoice: Selected cancellation reason (string)
  // feedback: Additional text feedback (string | null)
  // followupResponse: Follow-up question answers (object | null)

  try {
    await yourAPI.cancelSubscription(customer.id);
    return { message: 'Your subscription has been canceled.' };
  } catch (error) {
    // Error messages are shown to customers
    throw new Error('Unable to cancel. Please contact support.');
  }
}

Configuring offers

Configure offers in the Flow Builder. Churnkey automatically shows or hides offers based on:

  • Subscription status — Trial extensions only appear for trial subscriptions
  • Billing interval — Annual customers won't see pause offers by default
  • Handler availability — Offers only appear if you've implemented the handler

You configure offer values (discount percentages, pause durations, etc.) in the Flow Builder, then implement the billing changes in your handlers.

Segmentation

Create targeted flows for different customer segments based on:

  • Subscription attributes — Status, billing interval, subscription duration
  • Customer metadata — Custom attributes via customer.metadata and subscription.metadata
  • Billing amounts — MRR, subscription value, pricing tier

Configure segments in the Flow Builder under Audience Targeting. Learn more about segmentation →