Skip to main content
This is the creem_io wrapper package, which provides convenience methods and webhook helpers for common use cases.For full API access with all endpoints and maximum flexibility, see the Core SDK (creem).

Overview

The creem_io package is a convenience wrapper around the Creem API that provides:
  • Simplified webhook handling with onGrantAccess and onRevokeAccess callbacks
  • Automatic signature verification for webhook events
  • Type-safe event handlers for all webhook events
  • Framework-agnostic webhook processing
This wrapper is ideal if you want to get started quickly with minimal configuration, especially for handling subscription access management.

Installation

Install with your preferred package manager:
npm install creem_io

Quick Start

import { createCreem } from 'creem_io';

const creem = createCreem({
  apiKey: process.env.CREEM_API_KEY!,
  webhookSecret: process.env.CREEM_WEBHOOK_SECRET, // optional, for webhooks
  testMode: false, // set to true for test mode
});

// Retrieve a product
const product = await creem.products.get({
  productId: 'prod_7CIbZEZnRC5DWibmoOboOu',
});
console.log(product);

// Create a checkout session
const checkout = await creem.checkouts.create({
  productId: 'prod_xxxxx',
  successUrl: 'https://yourapp.com/success',
  metadata: {
    userId: 'user_123',
  },
});
console.log(checkout.checkoutUrl); // Redirect user to this URL

Environment Variables

We recommend storing your credentials in environment variables:
CREEM_API_KEY=your_api_key
CREEM_WEBHOOK_SECRET=your_webhook_secret

API Resources

The SDK organizes all operations into logical resources:

Products

// List products
const products = await creem.products.list({
  page: 1,
  limit: 10,
});

// Get a product
const product = await creem.products.get({
  productId: 'prod_7CIbb...',
});

// Create a product
creem.products.create({
  name: 'Test Product',
  description: 'Test Product Description',
  price: 1000, // In cents
  currency: 'USD',
  billingType: 'recurring',
  billingPeriod: 'every-month',
});

// Search products
const products = await creem.products.list({
  page: 1,
  limit: 10,
});

Checkouts

// Create a checkout session
const checkout = await creem.checkouts.create({
  productId: 'prod_xxxxx',
  units: 2, // Optional: Number of units (default: 1)
  discountCode: 'SUMMER2024', // Optional: Apply discount
  customer: {
    email: '[email protected]', // Optional: Pre-fill customer info
  },
  customField: [
    // Optional: Max 3 custom fields
    {
      key: 'company',
      label: 'Company Name',
      type: 'text',
      optional: false,
    },
  ],
  successUrl: 'https://yourapp.com/success',
  metadata: {
    userId: 'user_123',
    source: 'web',
  },
});

console.log(checkout.checkoutUrl); // Redirect user to this URL

// Get a checkout session
const retrievedCheckout = await creem.checkouts.get({
  checkoutId: 'chck_1234567890',
});

Customers

// List customers
const customers = await creem.customers.list({
  page: 1,
  limit: 10,
});

// Get a customer by ID
const customer = await creem.customers.get({
  customerId: 'cust_abc123',
});

// Get a customer by email
const customerByEmail = await creem.customers.get({
  email: '[email protected]',
});

// Create customer portal link
const portal = await creem.customers.createPortal({
  customerId: 'cust_abc123',
});

console.log(portal.customerPortalLink); // Redirect user to portal

Subscriptions

// Get a subscription
const subscription = await creem.subscriptions.get({
  subscriptionId: 'sub_abc123',
});

// Cancel a subscription
const canceledSubscription = await creem.subscriptions.cancel({
  subscriptionId: 'sub_abc123',
});

// Update a subscription (change units/seats)
const updated = await creem.subscriptions.update({
  subscriptionId: 'sub_abc123',
  items: [
    {
      id: 'item_abc123', // Subscription item ID
      units: 5, // Update to 5 seats
    },
  ],
  updateBehavior: 'proration-charge-immediately',
});

// Upgrade a subscription to a different product
const upgraded = await creem.subscriptions.upgrade({
  subscriptionId: 'sub_abc123',
  productId: 'prod_premium', // New product ID
  updateBehavior: 'proration-charge-immediately',
});
Update Behavior Options: - proration-charge-immediately: Calculate proration and charge immediately - proration-charge: Calculate proration and charge at next billing cycle - proration-none: No proration, just switch the plan

Licenses

// Activate a license
const license = await creem.licenses.activate({
  key: 'license_key_here',
  instanceName: 'Production Server',
});

console.log(license.instance?.id); // Use this instance ID for validation

// Validate a license
const validatedLicense = await creem.licenses.validate({
  key: 'license_key_here',
  instanceId: 'inst_abc123',
});

console.log(validatedLicense.status); // "active" | "inactive" | "expired" | "disabled"

// Deactivate a license
const deactivatedLicense = await creem.licenses.deactivate({
  key: 'license_key_here',
  instanceId: 'inst_abc123',
});

Discounts

// Create a discount code
const discount = await creem.discounts.create({
  name: 'Summer Sale 2024',
  code: 'SUMMER2024', // Optional: Auto-generated if not provided
  type: 'percentage',
  percentage: 20, // 20% off
  duration: 'forever', // "forever" | "once" | "repeating"
  maxRedemptions: 100,
});

// Retrieve a discount by ID
const discount = await creem.discounts.get({
  discountId: 'disc_xxxxx',
});

// Retrieve a discount by code
const discountByCode = await creem.discounts.get({
  discountCode: 'SUMMER2024',
});

// Delete a discount
await creem.discounts.delete({
  discountId: 'disc_xxxxx',
});

Transactions

// Get a transaction
const transaction = await creem.transactions.get({
  transactionId: 'txn_xxxxx',
});

// List transactions
const transactions = await creem.transactions.list({
  customerId: 'cust_xxxxx', // Optional: filter by customer
  page: 1,
  limit: 50,
});

Webhooks

Handle Creem webhook events in your application. The SDK provides automatic signature verification and type-safe event handlers.

Basic Webhook Setup

import { createCreem } from 'creem_io';

const creem = createCreem({
  apiKey: process.env.CREEM_API_KEY!,
  webhookSecret: process.env.CREEM_WEBHOOK_SECRET!,
});

// In your webhook endpoint
app.post('/webhook', async (req, res) => {
  try {
    await creem.webhooks.handleEvents(
      req.body, // raw body as string
      req.headers['creem-signature'],
      {
        onCheckoutCompleted: async (data) => {
          console.log('Checkout completed:', data.customer?.email);
        },

        onGrantAccess: async (context) => {
          // Grant user access when subscription is active/trialing/paid
          const userId = context.metadata?.userId;
          await grantUserAccess(userId);
        },

        onRevokeAccess: async (context) => {
          // Revoke access when subscription is paused/expired
          const userId = context.metadata?.userId;
          await revokeUserAccess(userId);
        },
      }
    );

    res.status(200).send('OK');
  } catch (error) {
    console.error('Webhook error:', error);
    res.status(400).send('Invalid signature');
  }
});

Access Management Callbacks

The onGrantAccess and onRevokeAccess callbacks simplify subscription access management:
onGrantAccess: async ({ reason, customer, product, metadata }) => {
  // Called for: subscription.active, subscription.trialing, subscription.paid
  const userId = metadata?.userId as string;

  await db.user.update({
    where: { id: userId },
    data: { subscriptionActive: true },
  });

  console.log(`Granted ${reason} to ${customer.email}`);
},

onRevokeAccess: async ({ reason, customer, product, metadata }) => {
  // Called for: subscription.paused, subscription.expired
  const userId = metadata?.userId as string;

  await db.user.update({
    where: { id: userId },
    data: { subscriptionActive: false },
  });

  console.log(`Revoked access (${reason}) from ${customer.email}`);
},

All Available Webhook Events

await creem.webhooks.handleEvents(body, signature, {
  // Checkout events
  onCheckoutCompleted: async (data) => {},

  // Access management (simplified)
  onGrantAccess: async (context) => {},
  onRevokeAccess: async (context) => {},

  // Individual subscription events
  onSubscriptionActive: async (data) => {},
  onSubscriptionTrialing: async (data) => {},
  onSubscriptionCanceled: async (data) => {},
  onSubscriptionPaid: async (data) => {},
  onSubscriptionExpired: async (data) => {},
  onSubscriptionUnpaid: async (data) => {},
  onSubscriptionPastDue: async (data) => {},
  onSubscriptionPaused: async (data) => {},
  onSubscriptionUpdate: async (data) => {},

  // Other events
  onRefundCreated: async (data) => {},
  onDisputeCreated: async (data) => {},
});

Framework-Specific Examples

import { NextRequest } from "next/server";
import { createCreem } from "creem_io";

const creem = createCreem({
apiKey: process.env.CREEM_API_KEY!,
webhookSecret: process.env.CREEM_WEBHOOK_SECRET!,
});

export async function POST(req: NextRequest) {
  try {
    const body = await req.text();
    const signature = req.headers.get("creem-signature")!;

    await creem.webhooks.handleEvents(body, signature, {
      onCheckoutCompleted: async (data) => {
        // Handle checkout completion
      },
      onGrantAccess: async (context) => {
        // Grant access to user
      },
    });

    return new Response("OK", { status: 200 });

} catch (error) {
return new Response("Invalid signature", { status: 400 });
}
}


TypeScript Support

The SDK is written in TypeScript and provides comprehensive type definitions:
import type {
  Checkout,
  Customer,
  Product,
  Subscription,
  Transaction,
  License,
  Discount,
  WebhookOptions,
  CheckoutCompletedEvent,
  SubscriptionEvent,
  GrantAccessContext,
  RevokeAccessContext,
} from "creem_io";
All API responses are fully typed, and the SDK automatically converts snake_case to camelCase for better TypeScript/JavaScript experience.

Error Handling

The SDK throws errors when API calls fail. Always wrap SDK calls in try-catch blocks:
try {
  const product = await creem.products.get({
    productId: 'prod_xxxxx',
  });
} catch (error) {
  console.error('Failed to retrieve product:', error);
  // Handle error appropriately
}

References


For feedback or issues, open a PR or issue on the Creem SDK GitHub.