Creem integration
Creem analytics: MRR, churn and revenue by traffic source
BugOtter reads your Creem store and shows what each app earns, net of the tax Creem collects: MRR and how it moved, revenue after refunds, trials, cancellations and declined payments. Pass the visit id in your checkout's metadata and subscriptions are linked to the traffic source that brought them.
- Net of taxrevenue and MRR
- Test modecreem_test_ keys
- Every 15 minsync
Three things to know
Net of tax
Creem is the merchant of record. Its tax is subtracted from both revenue and MRR.Subscribers by source
Add the visit id to the checkout's metadata, and every renewal keeps its source.Try it in test mode
Acreem_test_key reads Creem's test API and is labelled Test mode.
Connect Creem
Copy one key. Test keys work the same way.
Paste it on Revenue
BugOtter checks the key by reading one product, then stores it encrypted.Let the first sync run
Every product and subscription, and 90 days of transactions.Match products to apps
BugOtter suggests an app for each product from its URL and name. Confirm it once.
- Live keys start with
creem_. For test mode, flip the test mode switch in Creem's sidebar first; that key starts withcreem_test_. - Only the key's last 4 characters are shown. A test key is labelled Test mode and read from Creem's separate test API.
- Once matched, that product's revenue, MRR and declined payments land on the right app.
Every 15 min
After the first sync, it repeats every 15 minutes.
Key location, test mode and API hosts checked Nov 4, 2026 in Creem's API introduction.
What you'll see
One app's revenue in the live demo. Creem, Stripe, Polar and Lemon Squeezy all feed the same view.

- MRR per app, net of tax.
- How it moved: new, upgrades, downgrades and cancellations.
- A 30-day forecast if the last 30 days repeat.
- Trials, and what they're worth if they pay.
- Revenue after refunds, from paid, refunded and partly refunded transactions. Chargebacks count as refunded.
- Leaving soon: subscriptions with a scheduled cancellation, and the day they end.
- Declined payments. Declined and uncollectible charges open an issue on the app and alert you.
- Customers, anonymous: paying, cancelling or at risk, lifetime paid, and first-visit source for subscribers.
- Revenue per traffic source for subscriptions whose checkout carried the visit id.
Link Creem subscriptions to traffic sources
Add the visit id to the checkout's metadata. BugOtter reads it from the subscription, so every renewal keeps its source.

- By source: revenue per traffic source, for linked subscriptions.
- By product, with payments and share of revenue.
First, read the visit id in the browser and send it with your checkout request:
// In the browser, before you start the checkout
const visitorId = window.bo?.visitorId?.(); // "bo_…" or undefined
await fetch("/api/checkout", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ productId, visitorId }),
});Then add it to the checkout's metadata as bugotter_visitor_id:
// On your server: create the Creem checkout
const base = process.env.CREEM_API_KEY!.startsWith("creem_test_")
? "https://test-api.creem.io"
: "https://api.creem.io";
const res = await fetch(`${base}/v1/checkouts`, {
method: "POST",
headers: { "x-api-key": process.env.CREEM_API_KEY!, "Content-Type": "application/json" },
body: JSON.stringify({
product_id: productId,
success_url: "https://yourapp.com/thanks",
...(typeof visitorId === "string" && visitorId
? { metadata: { bugotter_visitor_id: visitorId } }
: {}),
}),
});
const { checkout_url } = await res.json(); // send the customer hereThat's your app's existing call to POST /v1/checkouts with one more field. Using the Creem SDK or a framework plugin? Pass the same metadata object to its checkout call.
Two limits, honestly:
- One-time purchases aren't linked, because Creem transactions don't carry metadata and there's no subscription to read it from.
- By default the visit id lasts for the browser tab, so someone who comes back days later in a new tab starts a new visit.
How MRR is counted for Creem
Yearly ÷ 12
What the subscription last actually paid, minus tax, turned into a month.
- What counts: active, past-due and unpaid subscriptions, and ones with a scheduled cancellation until they end. Trials count once they pay. Canceled, paused and expired don't.
- Amount: since it's what was actually paid, discounts are already in, and a subscription with several units counts all of them. If it hasn't paid yet, the product's price times units is the fallback.
- Tax: left out of both MRR and revenue. It's Creem's to pay as merchant of record, not your income.
- Currencies stay separate, never converted.
Curious how annual plans move the number? The MRR calculator shows it.
Read-only toward Creem
BugOtter never creates checkouts, issues refunds, cancels subscriptions or emails your customers. Because a Creem key can't be limited, that promise is in BugOtter's code: it only calls Creem's read endpoints.
Connecting and disconnecting are only in the app, never through the MCP server. Disconnecting deletes the Creem data BugOtter copied; delete the key in Creem too if you're done.
Creem next to the other payment providers
BugOtter reads four providers. Here's what each one gives you.
| Feature | Stripe | Polar | Lemon Squeezy | Creem |
|---|---|---|---|---|
| Access | ||||
| The key you give BugOtter | YesRestricted key, Read only | YesOrganization token, read scopes | PartlyAPI key (can't be limited) | PartlyAPI key (can't be limited) |
| Revenue | ||||
| Revenue after refunds | Yes | Yes | Yes | Yes |
| MRR and how it moved | Yes | Yes | Yes | Yes |
| Trials and when they end | Yes | Yes | Yes | Yes |
| Cancellations scheduled (leaving soon) | Yes | Yes | Yes | Yes |
| Why customers cancelled | Yes | Yes | No | No |
| Refunds on the day they happened | Yes | PartlyWith refunds:read | PartlyOrders from the last 90 days | PartlyDated by the payment |
| Failed payment alerts | Yes | No | Yes | Yes |
| Linking and testing | ||||
| Revenue by traffic source | YesPayment Links: automatic. Your checkout: metadata | YesCheckout metadata | NoNot yet | PartlySubscriptions, via checkout metadata |
| Test mode | Yesrk_test_ keys, marked Test mode | NoNot yet (the sandbox is a separate API) | YesTest-mode API keys | Yescreem_test_ keys, marked Test mode |
Questions
Is a Creem key safe to give BugOtter?
Creem API keys can't be limited to reading yet, so the key could make changes in principle. BugOtter's Creem code only sends read requests to three search endpoints (products, subscriptions, transactions). It never creates checkouts, refunds or cancels anything, and coding agents can't reach the connection over MCP. Delete the key in Creem whenever you like.
Does BugOtter count the tax Creem collects?
No. Creem is the merchant of record and collects the tax. BugOtter takes what the customer paid and subtracts the tax amount Creem reports on each transaction, for both revenue and MRR.
Why aren't my one-time Creem sales linked to traffic sources?
BugOtter links Creem payments through the subscription's metadata. One-time purchases have no subscription, and Creem transactions don't carry metadata, so there's nothing to read the visit id from. They still count fully in revenue.
Can I try it in Creem's test mode?
Yes. Turn on test mode in Creem, copy the creem_test_ key, and BugOtter reads Creem's test API and labels the connection Test mode. Disconnect and paste the live key when you're ready.
Why don't refunds show on the day they happened?
Creem doesn't say when a refund was made, only that a transaction was refunded. BugOtter subtracts it from the original payment's day. Chargebacks count as fully refunded.
Is there a size limit?
BugOtter reads up to 50,000 products, subscriptions or transactions per list. A bigger store gets a clear sync error rather than quietly missing numbers. Tell us and we'll raise it.
Know which post brought each Creem subscriber.
14 days of everything, no card needed. Plans from $10 a month, billed yearly.