> ## Documentation Index
> Fetch the complete documentation index at: https://docs.creem.io/llms.txt
> Use this file to discover all available pages before exploring further.

# SDK Wrapper (creem_io, deprecated)

> Deprecated convenience wrapper SDK with helper functions for webhooks, access management, and simplified API interactions. Use the Core SDK (creem) for new integrations.

<Warning>
  **Deprecation Notice:** The `creem_io` wrapper package is deprecated. Existing integrations will continue to work, but new integrations should use the [TypeScript SDK (creem)](/code/sdks/typescript). To update an existing integration, follow the [migration guide](/code/sdks/migrate-from-creem-io).
</Warning>

<Info>
  This page is kept as a reference for existing `creem_io` integrations.
</Info>

<Card title="Migrate to the creem SDK" icon="arrow-right" href="/code/sdks/migrate-from-creem-io">
  Replace `creem_io` imports, update API calls, and move webhook handling to the
  typed `creem` SDK helpers.
</Card>

## Overview

The deprecated `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

For new projects, use the [TypeScript SDK (creem)](/code/sdks/typescript), which is the recommended SDK with full API coverage and active support.

***

## Installation

For existing `creem_io` integrations, install with your preferred package manager:

<CodeGroup>
  ```bash npm theme={null}
  npm install creem_io
  ```

  ```bash yarn theme={null}
  yarn add creem_io
  ```

  ```bash pnpm theme={null}
  pnpm add creem_io
  ```

  ```bash bun theme={null}
  bun add creem_io
  ```
</CodeGroup>

***

## Quick Start

```ts theme={null}
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:

```bash theme={null}
CREEM_API_KEY=your_api_key
CREEM_WEBHOOK_SECRET=your_webhook_secret
```

***

## API Resources

The SDK organizes all operations into logical resources:

### Products

```ts theme={null}
// 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

```ts theme={null}
// 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: 'customer@example.com', // 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

```ts theme={null}
// 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: 'customer@example.com',
});

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

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

### Subscriptions

```ts theme={null}
// 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',
});
```

<Note>
  **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
</Note>

### Licenses

```ts theme={null}
// 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

```ts theme={null}
// 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

```ts theme={null}
// 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

```ts theme={null}
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:

```ts theme={null}
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

```ts theme={null}
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

<Tabs>
  <Tab title="Next.js App Router">
    ```ts theme={null}
    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 });
    }
    }

    ```
  </Tab>

  <Tab title="Express">
    ```ts theme={null}
    import express from "express";

    app.post(
      "/webhook",
      express.raw({ type: "application/json" }),
      async (req, res) => {
        try {
          await creem.webhooks.handleEvents(
            req.body,
            req.headers["creem-signature"],
            {
              onCheckoutCompleted: async (data) => {
                // Handle checkout
              },
            }
          );
          res.status(200).send("OK");
        } catch (error) {
          res.status(400).send("Invalid signature");
        }
      }
    );
    ```
  </Tab>

  <Tab title="Fastify">
    ```ts theme={null}
    fastify.post("/webhook", async (request, reply) => {
      try {
        await creem.webhooks.handleEvents(
          request.rawBody,
          request.headers["creem-signature"],
          {
            onCheckoutCompleted: async (data) => {
              // Handle checkout
            },
          }
        );
        reply.code(200).send("OK");
      } catch (error) {
        reply.code(400).send("Invalid signature");
      }
    });
    ```
  </Tab>

  <Tab title="Hono">
    ```ts theme={null}
    app.post("/webhook", async (c) => {
      try {
        const body = await c.req.text();
        const signature = c.req.header("creem-signature");

        await creem.webhooks.handleEvents(body, signature, {
          onCheckoutCompleted: async (data) => {
            // Handle checkout
          },
        });

        return c.text("OK");

    } catch (error) {
    return c.text("Invalid signature", 400);
    }
    });

    ```
  </Tab>
</Tabs>

***

## TypeScript Support

The SDK is written in TypeScript and provides comprehensive type definitions:

```ts theme={null}
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:

```ts theme={null}
try {
  const product = await creem.products.get({
    productId: 'prod_xxxxx',
  });
} catch (error) {
  console.error('Failed to retrieve product:', error);
  // Handle error appropriately
}
```

***

## References

* [Creem SDK on GitHub](https://github.com/armitage-labs/creem_io)
* [Creem API Documentation](https://docs.creem.io/api-reference/introduction)
* [Creem Dashboard](https://creem.io/dashboard)
* [Webhook Setup Guide](https://docs.creem.io/code/webhooks)

***

> For feedback or issues, open a PR or issue on the [Creem SDK GitHub](https://github.com/armitage-labs/creem_io).
