virling Pricing Self-host Demo Changelog Agencies GitHub Start free trial
integrations / creem

Creem revenue, joined to the visits behind it.

Virling ties each Creem payment to the visit that came before it, so you see which channel, referrer and page bring paying customers, not just visitors. Open source, one Rust binary, or hosted.

Start free trial See the demo

Virling reads Creem transactions and, when allowed, subscriptions with a scoped API key, and adds one webhook so checkouts link to visits.

Create a key

  1. In Creem, open Developers, then API keys, and create a key. Creem's guide: API introduction.
  2. Give it the transactions:read scope, plus subscriptions:read so Retention can tell who still pays, and webhooks:write so Virling can add its webhook. No other scopes are needed.
  3. Paste it into Virling.

Live and test mode keys both work. Virling tries api.creem.io first and test-api.creem.io second, or the other way round for a key that starts with creem_test_.

The webhook

Creem returns checkout metadata only in webhooks, not on transactions. When you connect, Virling adds one webhook for checkout.completed that points at https://<your Virling>/api/webhooks/creem/<site ID>, and keeps its signing secret encrypted. Each delivery is checked against the creem-signature header, an HMAC-SHA256 of the body.

The webhook needs Virling to be reachable over https. A server on plain http still imports payments, but they stay Unattributed.

What is imported

  • Transactions from the last 90 days on the first run, then new ones every minute, newest first.
  • Refunds and chargebacks. Transactions from the last 60 days are read again every 6 hours, so later refunds update them.
  • Renewals. Every payment after a customer's first is a renewal and keeps the channel of the first payment. See Renewals.
  • Free trials. A completed checkout with nothing to pay starts a trial, and the customer's first paid transaction is credited to it.
  • Subscription status, once an hour, when the key has subscriptions:read. Without it, retention falls back to payment recency.

How a payment finds its visitor

Virling reads virling_vid from, in order: the checkout's metadata, the subscription's metadata, then the customer's metadata.

Set it in metadata when you create the checkout on your server:

const res = await fetch("https://api.creem.io/v1/checkouts", {
  method: "POST",
  headers: { "x-api-key": process.env.CREEM_API_KEY, "content-type": "application/json" },
  body: JSON.stringify({
    product_id: "prod_...",
    success_url: "https://yourdomain.com/thanks",
    metadata: { virling_vid: req.cookies.virling_vid },
  }),
});
// Send the customer to (await res.json()).checkout_url

Use https://test-api.creem.io with a test mode key.

Frequently asked questions

How do I see which channel a Creem payment came from?

Connect Creem to Virling with a scoped API key and set virling_vid in the checkout metadata. Virling adds a checkout.completed webhook and ties each payment to the visit before it.

Which scopes does the Creem key need?

transactions:read, plus subscriptions:read for Retention and webhooks:write so Virling can add its webhook. No other scopes are needed.

Why does Creem need a webhook?

Creem returns checkout metadata only in webhooks, not on transactions. Without an https address for Virling, payments still import but stay Unattributed.

Full reference: Creem in the docs.