Customer onboarding via APIs


Overview

This integration guide provides a comprehensive walkthrough for implementing a subscription-based checkout flow using Zenskar and Stripe. It focuses on a use case where you need to:

  1. Offer both free and paid subscription plans
  2. Collect payment methods before account provisioning
  3. Process payments for paid plans
  4. Handle automatic synchronization of payment methods between Stripe and Zenskar
  5. Manage recurring billing based on subscriptions and usage

Use case scenario

You want to implement a checkout flow where:

  • Customers can choose between free and paid plans.
  • All customers, including those on the free plan, must provide payment details.
  • The logic differs by plan:
PlanFlow summary
FreePayment method is saved but no immediate charge. Future upgrades reuse the saved method.
PaidPayment is processed immediately. Account is provisioned after successful payment. Recurring billing is handled automatically.

Usage tracking and overage billing are managed through Zenskar.


Integration components

ComponentRole
Your applicationManages customer interface and checkout flow
StripeHandles payment method collection and processing
ZenskarManages billing, contracts, and usage tracking

sequenceDiagram
    autonumber
    actor U as Customer
    participant A as Your Application
    participant S as Stripe
    participant Z as Zenskar

    %% Customer initiates checkout
    U ->> A: Selects plan (free or paid)
    A ->> Z: POST /v1/customers<br/>Create customer in Zenskar
    Z -->> S: Automatically creates corresponding Stripe customer
    Z -->> A: Returns Zenskar & Stripe customer IDs

    %% Payment method collection
    A ->> S: Load Stripe.js and Elements
    U ->> S: Enters card details securely
    Note over S: Card details handled only by Stripe

    %% Payment processing logic
    alt Free plan
        A ->> S: Create SetupIntent<br/>(save payment method)
        S -->> Z: Sync payment method via integration
        Z -->> A: Confirmation of stored method
    else Paid plan
        A ->> S: Create PaymentIntent<br/>(charge immediately)
        S ->> A: Payment confirmation
        S -->> Z: Sync payment details & status
        Z -->> A: Update successful payment
    end

    %% Product and contract setup
    A ->> Z: POST /products<br/>Create subscription & usage products
    A ->> Z: POST /entitlements<br/>Define measurable units (e.g., GB)
    A ->> Z: POST /products<br/>type: group<br/>Create product bundle
    A ->> Z: POST /pricing<br/>Configure pricing tiers
    A ->> Z: POST /contracts<br/>Create contract for customer

    %% Billing cycle
    Z ->> A: Contract activated
    Z ->> S: Generates invoice, processes charge
    S ->> Z: Payment confirmation webhook
    Z ->> A: Invoice & payment status updates
    A ->> U: Displays active subscription & billing info

Creating customers

Overview

When a customer initiates checkout, the first step is to create a customer record in Zenskar. If Stripe integration is enabled, Zenskar automatically creates a corresponding Stripe customer and maintains synchronization between both platforms.

1. Create customer in Zenskar

Endpoint

POST https://api.zenskar.com/v1/customers

Headers

Authorization: YOUR_API_KEY
Content-Type: application/json

Request body

{
  "company_name": "Acme Corp",
  "email": "[email protected]",
  "phone": "+1234567890",
  "billing_address": {
    "line1": "123 Main St",
    "line2": "Suite 100",
    "city": "San Francisco",
    "state": "CA",
    "country": "US",
    "postal_code": "94105"
  },
  "tax_id": "US123456789",
  "metadata": {
    "plan_type": "free",
    "source": "checkout_flow"
  }
}

2. Retrieve Stripe customer details

After customer creation, retrieve the corresponding Stripe customer ID using the Zenskar connector API.

Endpoint

GET https://api.zenskar.com/connectors/customers/{ZENSKAR_CUSTOMER_ID}?connector=stripe

Headers

Authorization: YOUR_API_KEY

Sample response

{
  "id": "aca0bd27-7ec8-45ad-9b16-2ae5c4a7e883",
  "email": null,
  "customer_name": "test100",
  "address": {
    "line1": "",
    "line2": "",
    "city": "",
    "state": "",
    "postal_code": "",
    "country": "United States of America"
  },
  "reference_id": "cus_RCNosq3L6KYmUL"
}

Note: reference_id is the Stripe customer ID used for payment method collection and processing.


Payment methods and processing

Overview

After creating the customer in Zenskar and retrieving the Stripe customer ID, collect and store payment methods using Stripe Elements. The process differs slightly between free and paid plans.


Frontend integration

1. Include Stripe.js

<script src="https://js.stripe.com/v3/"></script>

2. Initialize Stripe Elements

const stripe = Stripe('YOUR_STRIPE_PUBLISHABLE_KEY');
const elements = stripe.elements();

const card = elements.create('card');
card.mount('#card-element');

3. Payment collection form

<form id="payment-form">
  <div id="card-element"></div>
  <div id="card-errors" role="alert"></div>
  <button type="submit">Save Payment Method</button>
</form>

Free plan implementation

For free plan customers, use a SetupIntent to save the card for future use without charging immediately:

const setupIntent = await stripe.setupIntents.create({
  customer: stripeCustomerId,
  payment_method_types: ['card']
});

const result = await stripe.confirmCardSetup(setupIntent.client_secret, {
  payment_method: {
    card: card,
    billing_details: { email: customerEmail }
  }
});

if (result.error) {
  // Handle error
  document.getElementById('card-errors').textContent = result.error.message;
} else {
  // Payment method saved
  // Proceed with account provisioning
}

Paid plan implementation

For paid plan customers, use a PaymentIntent to charge immediately and save the card for future use:

const paymentIntent = await stripe.paymentIntents.create({
  customer: stripeCustomerId,
  amount: planAmount,
  currency: 'usd',
  payment_method_types: ['card'],
  setup_future_usage: 'off_session'
});

const result = await stripe.confirmCardPayment(paymentIntent.client_secret, {
  payment_method: {
    card: card,
    billing_details: { email: customerEmail }
  }
});

if (result.error) {
  // Handle error
} else {
  // Payment successful
  // Proceed with account provisioning
}

Styling Stripe Elements

const style = {
  base: {
    fontSize: '16px',
    color: '#32325d',
    fontFamily: '"Helvetica Neue", Helvetica, sans-serif',
    fontSmoothing: 'antialiased',
    '::placeholder': { color: '#aab7c4' }
  },
  invalid: { color: '#fa755a', iconColor: '#fa755a' }
};

const card = elements.create('card', { style });

Behind the scenes: Zenskar automatically synchronizes payment method details from Stripe. No manual API calls or webhooks are required.


Product and pricing setup

Overview

Before creating contracts, you must set up your products, bundles, and pricing tiers.

Flow:

  1. Create individual products (subscription and usage-based)
  2. Create a product bundle to group them
  3. Configure pricing tiers for each bundle

Product structure example

Accelerate Package (Bundle)
│
├── Base Subscription
│   ├── Free Tier – $0/month, includes 5 GB
│   ├── Pro Tier – $49/month, includes 20 GB
│   └── Enterprise Tier – $199/month, includes 100 GB
│
└── Data Storage Overage – $0.50 per additional GB

1. Create products

Endpoint

POST https://api.zenskar.com/products

Headers

Authorization: YOUR_API_KEY
Content-Type: application/json

Example request (base subscription)

{
  "type": "product",
  "name": "Base Subscription",
  "description": "Monthly subscription with included storage",
  "sku": "sub_001",
  "tax_codes": { "tax_code": "digital_service" },
  "is_active": true
}

Example response

{
  "id": "bd895144-f62d-4dec-9bc9-2f3b62f6de1f",
  "name": "Base Subscription",
  "sku": "sub_001",
  "type": "product",
  "tax_codes": { "tax_code": "digital_service" },
  "is_active": true
}

Usage overage product

{
  "type": "product",
  "name": "Storage Overage",
  "description": "Additional storage usage charges",
  "sku": "storage_001",
  "tax_codes": { "tax_code": "digital_service" }
}

2. Create product bundle

Endpoint

POST https://api.zenskar.com/products

Request

{
  "type": "group",
  "name": "Accelerate",
  "description": "Complete storage solution with flexible usage",
  "sku": "bundle_001",
  "tax_codes": { "tax_code": "digital_service" }
}

Response

{
  "id": "9a8b7c6d-5e4f-3a2b-1c0d-9e8f7a6b5c4d",
  "name": "Accelerate",
  "type": "group",
  "sku": "bundle_001",
  "is_active": true
}

The bundle groups related products, enabling flexible contracts with multiple pricing tiers.


Creating entitlements

Overview

Entitlements define what customers receive with your product (e.g., GB of storage, number of API calls, etc.). They are used to track and bill for measurable usage.

Endpoint

POST https://api.zenskar.com/entitlements

Headers

Authorization: YOUR_API_KEY
Content-Type: application/json

Request

{
  "name": "GB USED",
  "description": "",
  "entitlement_type": "Quantity",
  "units": "gb",
  "is_active": true
}

Response

{
  "id": "entitlement_id",
  "name": "GB USED",
  "entitlement_type": "Quantity",
  "units": "gb",
  "is_active": true
}

Use the entitlement ID when configuring pricing tiers and tracking usage.


Product bundle pricing configuration

Overview

Create pricing tiers for your product bundle. Each tier includes:

  • A base subscription (prepaid)
  • Storage allocation (grants)
  • Overage charges (postpaid)

Example: 50 GB tier configuration

Headers

Authorization: YOUR_API_KEY
Content-Type: application/json

Request

{
  "pricing_data": { "pricing_type": "features" },
  "link_id": "50gb",
  "products": [
    {
      "product_id": "SUBSCRIPTION_PRODUCT_ID",
      "product_pricing_data": {
        "name": "Subscription",
        "is_recurring": true,
        "pricing_data": {
          "unit_amount": 200,
          "currency": "USD",
          "pricing_type": "flat_fee"
        },
        "billing_period": { "cadence": "P1M", "offset": "prepaid" },
        "grants": [
          {
            "label": "Grants",
            "type": "Quantity",
            "trigger_event": "invoice_approval",
            "unit_amount": 50,
            "entitlement_id": "GB_ENTITLEMENT_ID",
            "expires_at": "end_of_product_billing_period",
            "grant_frequency_same_as_product": true
          }
        ]
      }
    },
    {
      "product_id": "OVERAGE_PRODUCT_ID",
      "product_pricing_data": {
        "name": "50GB Plan Overage",
        "quantity": {
          "type": "metered",
          "aggregate_id": "AGGREGATE_ID",
          "unit": "unit"
        },
        "is_recurring": true,
        "pricing_data": {
          "unit_amount": 0.05,
          "currency": "USD",
          "pricing_type": "per_unit"
        },
        "billing_period": { "cadence": "P1M", "offset": "postpaid" },
        "consumptions": [
          {
            "label": "Consumption",
            "type": "Quantity",
            "entitlement_id": "GB_ENTITLEMENT_ID"
          }
        ]
      }
    }
  ]
}

Example: 60 GB tier configuration

{
  "pricing_data": { "pricing_type": "features" },
  "link_id": "60gb",
  "products": [
    {
      "product_id": "SUBSCRIPTION_PRODUCT_ID",
      "product_pricing_data": {
        "name": "60GB Plan",
        "is_recurring": true,
        "pricing_data": {
          "unit_amount": 230,
          "currency": "USD",
          "pricing_type": "flat_fee"
        },
        "billing_period": { "cadence": "P1M", "offset": "prepaid" },
        "grants": [
          {
            "label": "Grants",
            "type": "Quantity",
            "trigger_event": "invoice_approval",
            "unit_amount": 60,
            "entitlement_id": "GB_ENTITLEMENT_ID",
            "expires_at": "end_of_product_billing_period",
            "grant_frequency_same_as_product": true
          }
        ]
      }
    },
    {
      "product_id": "OVERAGE_PRODUCT_ID",
      "product_pricing_data": {
        "name": "60GB Plan Overage",
        "quantity": {
          "type": "metered",
          "aggregate_id": "AGGREGATE_ID",
          "unit": "unit"
        },
        "is_recurring": true,
        "pricing_data": {
          "unit_amount": 0.045,
          "currency": "USD",
          "pricing_type": "per_unit"
        },
        "billing_period": { "cadence": "P1M", "offset": "postpaid" },
        "consumptions": [
          {
            "label": "Consumption",
            "type": "Quantity",
            "entitlement_id": "GB_ENTITLEMENT_ID"
          }
        ]
      }
    }
  ]
}

Retrieve pricing details

Endpoint

GET https://api.zenskar.com/products/link_id/{LINK_ID}

Headers

Authorization: YOUR_API_KEY
Content-Type: application/json

Contract creation

Overview

Once products, entitlements, and pricing are configured — and the customer’s payment method is ready — create a contract to associate the customer with their pricing plan. This initiates the billing cycle in Zenskar.

Create contract

Headers

Authorization: YOUR_API_KEY
Content-Type: application/json

Request

{
  "name": "test100",
  "description": "",
  "status": "active",
  "start_date": "2024-10-01T00:00:00.000000",
  "end_date": "2025-09-30T23:59:59.999999",
  "currency": "USD",
  "anchor_date": "2024-10-01T00:00:00.000000",
  "renewal_policy": "do_not_renew",
  "invoice_generation_offset": 0,
  "phases": [
    {
      "name": "Phase 1",
      "start_date": "2024-10-01T00:00:00.000000",
      "end_date": "2025-09-30T23:59:59.999999",
      "pricings": [
        {
          "product_id": "BUNDLE_PRODUCT_ID",
          "pricing_id": "PRICING_ID"
        }
      ],
      "features": {
        "pricing_data": { "pricing_type": "features" }
      }
    }
  ],
  "customer_id": "CUSTOMER_ID"
}

Once activated, Zenskar automatically generates invoices at each billing cycle according to the contract’s pricing configuration.


Summary

This guide demonstrated how to implement a complete subscription onboarding flow using Zenskar APIs integrated with Stripe:

  1. Create a customer (auto-synced with Stripe)
  2. Collect and store payment methods securely
  3. Define products, entitlements, and pricing tiers
  4. Create a contract to start recurring billing

For detailed parameter definitions, refer to the Zenskar API Reference.