Creem
Creem is an EU-based Merchant of Record (MoR) with low, transparent fees. As a MoR, Creem handles sales tax/VAT, invoicing, and compliance on your behalf. ShipFree ships a first-class Creem adapter that implements the samePaymentAdapter interface as Stripe, Polar, and Lemon Squeezy, so switching to Creem is just configuration.
1. Get your API key
- Sign up at creem.io and open the dashboard.
- Go to the Developers menu and copy your API key.
Creem uses separate API keys for test mode and production. The test key only works
against
test-api.creem.io. Set CREEM_TEST_MODE=true while developing.2. Create your products
Create one product per paid plan (Starter, Pro, Enterprise) in the Creem dashboard and copy each product ID.3. Configure environment variables
src/config/payments.ts. Adjust the amount, currency,
and interval there to match what you configured in Creem.
4. Configure the webhook
Point a Creem webhook at your deployment:creem-signature header (HMAC-SHA256 of the raw body using
CREEM_WEBHOOK_SECRET). The shared webhook handler verifies the signature and updates the
customer, subscription, and payment tables.
Handled events:
checkout.completed— persists a new subscription (recurring) or payment (one-time)subscription.active,subscription.paid,subscription.trialing,subscription.updatesubscription.past_due,subscription.unpaid,subscription.pausedsubscription.canceled,subscription.expired
5. Test the flow
- With
CREEM_TEST_MODE=trueand your test key set, start checkout from the pricing page. - Complete a payment using Creem’s test card.
- Confirm the
subscriptionrow is created/updated after the webhook fires.
How it works
The adapter lives atsrc/lib/payments/providers/creem.ts and uses the official
creem SDK:
createCheckout— creates a Creem checkout session withuserId/planmetadatagetSubscription/cancelSubscription— read and cancel subscriptionscreatePortal— generates a Creem customer portal link so users can manage billingprocessWebhook/validateWebhook— verify and map Creem events to ShipFree’s tables
Creem creates the customer record during checkout, so
createCustomer returns a pending
placeholder that the checkout.completed webhook reconciles with the real Creem customer ID.