Skip to main content
Subscriptions in Creem allow you to create recurring payment agreements with your customers. When a customer subscribes to your product, they agree to be billed periodically (monthly, yearly, etc.) until they cancel their subscription.

Understanding Subscriptions

A subscription represents a recurring payment agreement between you and your customer. Subscriptions automatically handle billing cycles, payment retries, and customer management. The diagram below shows how subscription access is managed based on different states: Subscription Access States
Use the onGrantAccess and onRevokeAccess callbacks to automatically handle access management. See Managing Subscription Access below.

Subscription Status

A subscription can be in different states throughout its lifecycle:
  • Active: The subscription is current and payments are being processed normally.
  • Canceled: The subscription has been terminated and will not renew or bill again.
  • Unpaid: Payment for the subscription has failed or is overdue; access may be restricted until payment is made.
  • Paused: The subscription is temporarily paused (no charges are processed and billing is on hold).
  • Trialing: The subscription is in a trial period before the first payment is collected.
  • Scheduled Cancel: The subscription is scheduled to cancel at the end of the current billing period but is still active until then.

Billing Cycles

Subscriptions operate on billing cycles that determine when payments are collected:
  • Monthly billing - Charged every month
  • 3 month billing - Charged every 3 months
  • 6 month billing - Charged every 6 months
  • Yearly billing - Charged annually

Creating a Subscription

To create a subscription:
  1. Create a subscription product in your Creem dashboard (set billing type to “recurring”)
  2. Generate a checkout session for the subscription
  3. Direct your customer to the checkout URL
  • Next.js
  • TypeScript SDK
  • Better Auth
  • REST API
"use client"; // Optional: Works with server components

import { CreemCheckout } from "@creem_io/nextjs";

export function SubscribeButton() {
  return (
    <CreemCheckout
      productId="prod_YOUR_SUBSCRIPTION_ID"
      metadata={{
        userId: "user_123",
        source: "web"
      }}
    >
      <button>Subscribe Now</button>
    </CreemCheckout>
  );
}

Next.js SDK Documentation

Learn more about the Next.js adapter and advanced features.

Handling Successful Subscriptions

After a successful subscription creation, users are redirected to your success_url with subscription details as query parameters:
https://yoursite.com/success?checkout_id=ch_xxx&subscription_id=sub_xxx&customer_id=cust_xxx&product_id=prod_xxx
Query parameterDescription
checkout_idThe ID of the checkout session created for this subscription.
subscription_idThe ID of the subscription created.
customer_idThe customer ID associated with this subscription.
product_idThe product ID that the subscription is for.
request_idOptional. The request/reference ID you provided when creating this checkout.
signatureAll previous parameters signed by Creem using your API-key, verifiable by you.
For production applications, we recommend using Webhooks to handle subscription events like renewals, cancellations, and payment failures.

Managing Subscription Access

Creem makes it incredibly simple to grant and revoke access based on subscription status. Instead of manually handling multiple webhook events, you can use the high-level onGrantAccess and onRevokeAccess callbacks that automatically fire at the right times in your subscription lifecycle.

How It Works

  • onGrantAccess - Automatically called when a customer should have access (when subscription is active, trialing, or paid)
  • onRevokeAccess - Automatically called when a customer should lose access (when subscription is paused or expired)
This abstraction means you don’t need to track individual subscription events. Just implement these two callbacks to handle your entire access management flow.
  • Next.js
  • TypeScript SDK
  • Better Auth
  • Manual Webhook
// app/api/webhook/creem/route.ts
import { Webhook } from "@creem_io/nextjs";

export const POST = Webhook({
  webhookSecret: process.env.CREEM_WEBHOOK_SECRET!,
  
  onGrantAccess: async ({ customer, metadata, reason, product }) => {
    // Grant access when subscription becomes active/trialing/paid
    const userId = metadata?.referenceId as string;
    
    await db.user.update({
      where: { id: userId },
      data: { 
        subscriptionActive: true,
        subscriptionTier: product.name,
      },
    });
    
    console.log(`Granted access to ${customer.email} - Reason: ${reason}`);
  },
  
  onRevokeAccess: async ({ customer, metadata, reason }) => {
    // Revoke access when subscription is paused/expired
    const userId = metadata?.referenceId as string;
    
    await db.user.update({
      where: { id: userId },
      data: { subscriptionActive: false },
    });
    
    console.log(`Revoked access from ${customer.email} - Reason: ${reason}`);
  },
});

Next.js Adapter Documentation

Learn more about webhook handling and server functions.
If you want to remove access when your customer cancels the subscription (even though the billing period might still be active), you should listen to the subscription.canceled event.

Key Features