Choose the path that works best for you:
Code Integration
Integrate Creem directly into your application. It’s as easy as the following:
1. Get your API key
Navigate to the Developers section in your dashboard and copy your API key.
Use Test Mode to develop without processing real
payments.
2. Install and create a checkout
Next.js
TypeScript SDK
Better Auth
REST API
Install the Next.js adapter for the fastest integration with built-in routes and components. npm install @creem_io/nextjs
Add your API Key as environment variable: # .env
CREEM_API_KEY = your_api_key_here
Create a checkout API route: // app/api/checkout/route.ts
import { Checkout } from '@creem_io/nextjs' ;
export const GET = Checkout ({
apiKey: process . env . CREEM_API_KEY ! ,
testMode: true ,
defaultSuccessUrl: '/success' ,
});
Add a checkout button to your page: // app/page.tsx
import { CreemCheckout } from '@creem_io/nextjs' ;
export default function Page () {
return (
< CreemCheckout productId = "prod_YOUR_PRODUCT_ID" >
< button > Subscribe Now </ button >
</ CreemCheckout >
);
}
Next.js Adapter Docs Learn about advanced features, webhooks, and server components.
Install the TypeScript SDK for full type-safety and flexibility. Add your API Key as environment variable: # .env
CREEM_API_KEY = your_api_key_here
See the API Keys page for more information. Create a checkout session: import { createCreem } from 'creem_io' ;
const creem = createCreem ({
apiKey: process . env . CREEM_API_KEY ! ,
testMode: true , // Set to false for production
});
const checkout = await creem . checkouts . create ({
productId: 'prod_abc123' ,
successUrl: 'https://yoursite.com/success' ,
});
// Redirect to checkout.checkout_url
console . log ( checkout . checkout_url );
TypeScript SDK Docs Explore the full SDK API reference and advanced usage.
Integrate Creem with Better Auth for seamless authentication and billing. npm install @creem_io/better-auth better-auth
Add your API Key as environment variable: # .env
CREEM_API_KEY = your_api_key_here
See the API Keys page for more information. Configure Better Auth with the Creem plugin: // 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: true ,
}),
],
});
Client configuration: // 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 ()],
});
Creating a checkout: import { authClient } from '@/lib/auth-client' ;
// Client-side integration
const { data , error } = await authClient . creem . createCheckout ({
productId ,
successUrl: '/success' ,
});
Better Auth Integration Learn how to sync with your database users, manage access, and handle
webhooks.
Use our REST API directly from any language or framework. 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",
"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 payment.
API Reference View the complete API documentation and endpoint reference.
3. Handle successful payments
After payment, users are redirected to your success_url with payment details:
https://yoursite.com/success?checkout_id=ch_xxx&order_id=ord_xxx&customer_id=cust_xxx&product_id=prod_xxx
For production apps, use Webhooks to reliably receive
payment events on your server.
Complete Working Example
Here’s a full Next.js App Router example you can copy and run. This includes everything: checkout creation, success page, and webhook handling.
Project Structure
your-app/
├── app/
│ ├── api/
│ │ ├── checkout/
│ │ │ └── route.ts # Creates checkout sessions
│ │ └── webhooks/
│ │ └── creem/
│ │ └── route.ts # Handles payment webhooks
│ ├── success/
│ │ └── page.tsx # Success page after payment
│ └── page.tsx # Main page with buy button
├── lib/
│ └── creem.ts # Creem client setup
└── .env.local
1. Environment Variables
# .env.local
CREEM_API_KEY = creem_test_your_api_key
CREEM_WEBHOOK_SECRET = whsec_your_webhook_secret
NEXT_PUBLIC_APP_URL = http://localhost:3000
2. Creem Client Setup
// lib/creem.ts
import { createCreem } from 'creem_io' ;
export const creem = createCreem ({
apiKey: process . env . CREEM_API_KEY ! ,
testMode: true , // Set to false for production
});
3. Checkout API Route
// app/api/checkout/route.ts
import { NextRequest , NextResponse } from 'next/server' ;
import { creem } from '@/lib/creem' ;
export async function POST ( request : NextRequest ) {
try {
const { productId } = await request . json ();
const checkout = await creem . checkouts . create ({
productId ,
successUrl: ` ${ process . env . NEXT_PUBLIC_APP_URL } /success` ,
});
return NextResponse . json ({
checkoutUrl: checkout . checkout_url
});
} catch ( error ) {
console . error ( 'Checkout error:' , error );
return NextResponse . json (
{ error: 'Failed to create checkout' },
{ status: 500 }
);
}
}
4. Webhook Handler
// app/api/webhooks/creem/route.ts
import { NextRequest , NextResponse } from 'next/server' ;
import crypto from 'crypto' ;
export async function POST ( request : NextRequest ) {
const body = await request . text ();
const signature = request . headers . get ( 'creem-signature' );
// Verify webhook signature
const expectedSignature = crypto
. createHmac ( 'sha256' , process . env . CREEM_WEBHOOK_SECRET ! )
. update ( body )
. digest ( 'hex' );
if ( signature !== expectedSignature ) {
return NextResponse . json (
{ error: 'Invalid signature' },
{ status: 401 }
);
}
const event = JSON . parse ( body );
// Handle different event types
switch ( event . type ) {
case 'checkout.completed' :
console . log ( 'Payment successful!' , {
checkoutId: event . data . id ,
customerId: event . data . customer_id ,
productId: event . data . product_id ,
});
// Grant access, send email, update database, etc.
break ;
case 'subscription.created' :
console . log ( 'New subscription:' , event . data );
break ;
case 'subscription.canceled' :
console . log ( 'Subscription canceled:' , event . data );
// Revoke access
break ;
}
return NextResponse . json ({ received: true });
}
// app/page.tsx
'use client' ;
import { useState } from 'react' ;
export default function Home () {
const [ loading , setLoading ] = useState ( false );
const handleCheckout = async () => {
setLoading ( true );
try {
const response = await fetch ( '/api/checkout' , {
method: 'POST' ,
headers: { 'Content-Type' : 'application/json' },
body: JSON . stringify ({
productId: 'prod_YOUR_PRODUCT_ID' , // Replace with your product ID
}),
});
const { checkoutUrl } = await response . json ();
// Redirect to Creem checkout
window . location . href = checkoutUrl ;
} catch ( error ) {
console . error ( 'Checkout failed:' , error );
alert ( 'Something went wrong. Please try again.' );
} finally {
setLoading ( false );
}
};
return (
< main className = "flex min-h-screen flex-col items-center justify-center p-24" >
< h1 className = "text-4xl font-bold mb-8" > My Awesome Product </ h1 >
< button
onClick = { handleCheckout }
disabled = { loading }
className = "bg-blue-600 hover:bg-blue-700 text-white font-bold py-3 px-6 rounded-lg disabled:opacity-50"
>
{ loading ? 'Loading...' : 'Buy Now - $29' }
</ button >
</ main >
);
}
6. Success Page
// app/success/page.tsx
import { Suspense } from 'react' ;
function SuccessContent ({ searchParams } : { searchParams : { checkout_id ?: string } }) {
return (
< main className = "flex min-h-screen flex-col items-center justify-center p-24" >
< div className = "text-center" >
< h1 className = "text-4xl font-bold text-green-600 mb-4" >
🎉 Payment Successful!
</ h1 >
< p className = "text-lg text-gray-600 mb-8" >
Thank you for your purchase. You should receive a confirmation email shortly.
</ p >
{ searchParams . checkout_id && (
< p className = "text-sm text-gray-400" >
Order ID: { searchParams . checkout_id }
</ p >
) }
< a
href = "/"
className = "inline-block mt-8 bg-blue-600 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded"
>
Back to Home
</ a >
</ div >
</ main >
);
}
export default function SuccessPage ({
searchParams
} : {
searchParams : { checkout_id ?: string }
}) {
return (
< Suspense fallback = { < div > Loading... </ div > } >
< SuccessContent searchParams = { searchParams } />
</ Suspense >
);
}
Running the Example
Install dependencies:
Create a product in the Creem dashboard
Copy the product ID (starts with prod_) and update app/page.tsx
Get your webhook secret from the dashboard and add to .env.local
Run the development server:
Visit http://localhost:3000 and click “Buy Now”
In test mode, use test card number 4242 4242 4242 4242 with any future expiry date and any CVC.
No-Code Solution
Perfect for creators, vibe coders, and anyone who wants to start selling quickly without code.
1. Create a product
Go to the products tab in your dashboard and create your first product with a name, description, and price.
2. Share your payment link
Click the Share button on your product to get your payment link. Send it to customers via email, social media, or anywhere else.
That’s it! You’re ready to accept payments.
Learn More About Payment Links Explore advanced customization options, custom fields, and more.
Next Steps