Checkout sessions give you programmatic control over the payment flow. Unlike static payment links, checkout sessions are generated dynamically, allowing you to:
Pass custom tracking IDs for each payment
Pre-fill customer information like email
Set dynamic success URLs based on your app’s context
Apply discount codes programmatically
Add metadata for internal tracking
Prerequisites
Before creating checkout sessions, you’ll need:
A Creem account with an API key (Get your key )
At least one product created in your dashboard
Find your product ID by going to the Products
tab , clicking on a product, and
selecting “Copy ID” from the options menu.
Creating a Checkout Session
Choose the integration method that works best for your stack:
Next.js
TypeScript SDK
Better Auth
REST API
The Next.js adapter provides a route handler and React component for seamless integration. Install the package npm install @creem_io/nextjs
Create the checkout route // app/api/checkout/route.ts
import { Checkout } from '@creem_io/nextjs' ;
export const GET = Checkout ({
apiKey: process . env . CREEM_API_KEY ! ,
testMode: process . env . NODE_ENV !== 'production' ,
defaultSuccessUrl: '/success' ,
});
// app/page.tsx
'use client' ; // Optional: CreemCheckout also works in Server Components
import { CreemCheckout } from '@creem_io/nextjs' ;
export function CheckoutButton () {
return (
< CreemCheckout
productId = "prod_YOUR_PRODUCT_ID"
referenceId = "user_123" // Optional: Track this payment in your system
>
< button > Buy Now </ button >
</ CreemCheckout >
);
}
The CreemCheckout component automatically handles the checkout session creation and redirects the user to the payment page.
Next.js SDK Documentation Explore advanced features, server components, and webhook handling.
The TypeScript SDK provides full type-safety and works with any JavaScript framework. Install the SDK Create a checkout session import { createCreem } from 'creem_io' ;
const creem = createCreem ({
apiKey: process . env . CREEM_API_KEY ! ,
testMode: process . env . NODE_ENV !== 'production' ,
});
// Create a checkout session
const checkout = await creem . checkouts . create ({
productId: 'prod_YOUR_PRODUCT_ID' ,
requestId: 'order_123' , // Optional: Track this payment
successUrl: 'https://yoursite.com/success' ,
customer: {
email: '[email protected] ' , // Optional: Pre-fill email
},
});
// Redirect to the checkout URL
console . log ( checkout . checkout_url );
// In the browser: window.location.href = checkout.checkout_url;
TypeScript SDK Documentation View the full SDK API reference and advanced usage examples.
The Better Auth integration automatically syncs payments with your authenticated users. Install the plugin npm install @creem_io/better-auth better-auth
// auth.ts
import { betterAuth } from 'better-auth' ;
import { creem } from '@creem_io/better-auth' ;
export const auth = betterAuth ({
database: {
// your database config
},
plugins: [
creem ({
apiKey: process . env . CREEM_API_KEY ! ,
testMode: process . env . NODE_ENV !== 'production' ,
defaultSuccessUrl: '/dashboard' ,
}),
],
});
Client setup // lib/auth-client.ts
import { createAuthClient } from 'better-auth/react' ;
import { creemClient } from '@creem_io/better-auth/client' ;
export const authClient = createAuthClient ({
baseURL: process . env . NEXT_PUBLIC_APP_URL ,
plugins: [ creemClient ()],
});
Create a checkout "use client" ;
import { authClient } from "@/lib/auth-client" ;
export function CheckoutButton ({ productId } : { productId : string }) {
const handleCheckout = async () => {
const { data , error } = await authClient . creem . createCheckout ({
productId ,
successUrl: "/dashboard" ,
});
if ( data ?. url ) {
window . location . href = data . url ;
}
};
return < button onClick ={ handleCheckout }> Subscribe Now </ button > ;
}
The Better Auth integration automatically tracks the authenticated user and syncs subscription status with your database.
Better Auth Integration Learn about database persistence, access management, and webhook handling.
Use the REST API directly from any language or framework. Create a checkout session If you’re in test mode, use https://test-api.creem.io instead of
https://api.creem.io. Learn more about Test
Mode . curl -X POST https://api.creem.io/v1/checkouts \
-H "x-api-key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"product_id": "prod_YOUR_PRODUCT_ID",
"request_id": "order_123",
"success_url": "https://yoursite.com/success"
}'
Response {
"id" : "ch_1QyIQDw9cbFWdA1ry5Qc6I" ,
"checkout_url" : "https://checkout.creem.io/ch_1QyIQDw9cbFWdA1ry5Qc6I" ,
"product_id" : "prod_YOUR_PRODUCT_ID" ,
"status" : "pending"
}
Redirect your user to the checkout_url to complete the payment.
API Reference View the complete endpoint documentation with all available parameters.
Handling Successful Payments
After a successful payment, users are redirected to your success_url with payment details as query parameters:
https://yoursite.com/success?checkout_id=ch_xxx&order_id=ord_xxx&customer_id=cust_xxx&product_id=prod_xxx
Query parameter Description checkout_idThe ID of the checkout session created for this payment. order_idThe ID of the order created after successful payment. customer_idThe customer ID, based on the email that executed the successful payment. subscription_idThe subscription ID of the product. product_idThe product ID that the payment is related to. 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 payment events.
Advanced Features
Add custom metadata to track additional information with each payment. Metadata is included in webhook events and can be retrieved later.
Next.js
TypeScript SDK
Better Auth
REST API
< CreemCheckout
productId = "prod_YOUR_PRODUCT_ID"
referenceId = "user_123"
metadata = { {
userId: 'internal_user_id' ,
planType: 'premium' ,
source: 'marketing_campaign' ,
} }
>
< button > Subscribe </ button >
</ CreemCheckout >
const checkout = await creem . checkouts . create ({
productId: 'prod_YOUR_PRODUCT_ID' ,
requestId: 'order_123' ,
metadata: {
userId: 'internal_user_id' ,
planType: 'premium' ,
source: 'marketing_campaign' ,
},
});
const { data } = await authClient . creem . createCheckout ({
productId: 'prod_YOUR_PRODUCT_ID' ,
metadata: {
planType: 'premium' ,
source: 'marketing_campaign' ,
},
});
curl -X POST https://api.creem.io/v1/checkouts \
-H "x-api-key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"product_id": "prod_YOUR_PRODUCT_ID",
"metadata": {
"userId": "internal_user_id",
"planType": "premium",
"source": "marketing_campaign"
}
}'
Metadata is especially useful for tracking internal IDs, campaign sources, or
any custom information you need to associate with a payment.
Custom Success URL
Override the default success URL on a per-checkout basis. This is useful for directing users to specific pages after payment based on context.
Next.js
TypeScript SDK
Better Auth
REST API
< CreemCheckout
productId = "prod_YOUR_PRODUCT_ID"
successUrl = "/account/welcome" // Overrides defaultSuccessUrl
>
< button > Get Started </ button >
</ CreemCheckout >
const checkout = await creem . checkouts . create ({
productId: 'prod_YOUR_PRODUCT_ID' ,
successUrl: 'https://yoursite.com/account/welcome' ,
});
const { data } = await authClient . creem . createCheckout ({
productId: 'prod_YOUR_PRODUCT_ID' ,
successUrl: '/account/welcome' ,
});
curl -X POST https://api.creem.io/v1/checkouts \
-H "x-api-key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"product_id": "prod_YOUR_PRODUCT_ID",
"success_url": "https://yoursite.com/account/welcome"
}'
Pre-fill Customer Email
Lock the customer email at checkout to ensure users complete payment with the email they registered with on your platform.
Next.js
TypeScript SDK
Better Auth
REST API
< CreemCheckout
productId = "prod_YOUR_PRODUCT_ID"
customer = { { email: '[email protected] ' } }
>
< button > Complete Purchase </ button >
</ CreemCheckout >
const checkout = await creem . checkouts . create ({
productId: 'prod_YOUR_PRODUCT_ID' ,
customer: {
email: '[email protected] ' ,
},
});
// Email is automatically set from the authenticated user
const { data } = await authClient . creem . createCheckout ({
productId: 'prod_YOUR_PRODUCT_ID' ,
customer: {
email: '[email protected] ' , // Optional: if you want to overwrite the session
},
});
The Better Auth integration automatically uses the authenticated user’s email.
curl -X POST https://api.creem.io/v1/checkouts \
-H "x-api-key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"product_id": "prod_YOUR_PRODUCT_ID",
"customer": {
"email": "[email protected] "
}
}'
Apply Discount Codes
Apply discount codes programmatically to pre-fill them at checkout.
Next.js
TypeScript SDK
Better Auth
REST API
< CreemCheckout productId = "prod_YOUR_PRODUCT_ID" discountCode = "LAUNCH50" >
< button > Claim Offer </ button >
</ CreemCheckout >
const checkout = await creem . checkouts . create ({
productId: 'prod_YOUR_PRODUCT_ID' ,
discountCode: 'LAUNCH50' ,
});
const { data } = await authClient . creem . createCheckout ({
productId: 'prod_YOUR_PRODUCT_ID' ,
discountCode: 'LAUNCH50' ,
});
curl -X POST https://api.creem.io/v1/checkouts \
-H "x-api-key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"product_id": "prod_YOUR_PRODUCT_ID",
"discount_code": "LAUNCH50"
}'
Discount Codes Learn how to create and manage discount codes in your dashboard.
Seat-Based Billing
Charge for multiple units or seats by specifying the units parameter. The total price will be calculated as base_price × units.
Next.js
TypeScript SDK
Better Auth
REST API
< CreemCheckout
productId = "prod_YOUR_PRODUCT_ID"
units = { seatCount } // Charge for 5 seats
>
< button > Add { seatCount } Seats </ button >
</ CreemCheckout >
const checkout = await creem . checkouts . create ({
productId: 'prod_YOUR_PRODUCT_ID' ,
units: 5 , // Charge for 5 seats
});
const { data } = await authClient . creem . createCheckout ({
productId: 'prod_YOUR_PRODUCT_ID' ,
units: 5 , // Charge for 5 seats
});
curl -X POST https://api.creem.io/v1/checkouts \
-H "x-api-key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"product_id": "prod_YOUR_PRODUCT_ID",
"units": 5
}'
Seat-Based Billing Learn more about implementing and managing seat-based pricing models.
Next Steps