Who does what
The two sit side by side. Lemon Squeezy stays your merchant of record; MeterFlow never moves money.
| Lemon Squeezy | MeterFlow |
|---|---|
| Checkout, payment methods, sales tax and invoices | Usage events, counted per customer and per meter |
| The subscription and its renewals | The same subscription, mirrored, on the plan you mapped |
| The recurring charge | What that charge includes: allowances, limits and credits |
| Refunds and chargebacks | The answer to “may this customer do this now?” |
Set it up no code
Five steps in two dashboards. Your app is not involved yet.
- 1. Create a plan
In MeterFlow, define what you measure (a meter, such as
images.generated) and a plan with its limits, then publish the plan. A draft plan is not on sale: an event for it creates no subscription. - 2. Create the webhook in Lemon Squeezy
In Lemon Squeezy, create a webhook for the subscription events,
subscription_payment_successincluded, and keep its signing secret. It asks for a URL: enter a placeholder for now. Lemon Squeezy’s own guide has the clicks: Webhooks. - 3. Add the connector
In MeterFlow, open your project → Connectors and add one for Lemon Squeezy. Choose the live account or the test one and paste the signing secret. It is checked on every call and never shown back.
- 4. Give Lemon Squeezy the real URL
The connector now shows its webhook URL. Edit the webhook in Lemon Squeezy and replace the placeholder with it.
- 5. Map each variant to a plan
On the connector, map each Lemon Squeezy variant (its numeric variant id) to one of your plans. From then on, a customer who subscribes in Lemon Squeezy appears in MeterFlow on that plan.
Field by field, with the other four providers: the guide’s connector section.
What each Lemon Squeezy event does
Every delivery is checked against Lemon Squeezy’s signature, then listed in the connector’s delivery log with what it did, in a sentence.
| Lemon Squeezy event | What happens in MeterFlow |
|---|---|
| subscription_created | The customer gets a subscription on the plan mapped to the Lemon Squeezy variant, with Lemon Squeezy’s status. |
| subscription_updated, subscription_resumed, subscription_unpaused | The same subscription moves to the new plan or status. |
| subscription_paused | The subscription takes that status. |
| subscription_cancelled | The subscription keeps running and records when it will end: in Lemon Squeezy, cancelled means “will not renew”. |
| subscription_expired | The subscription is cancelled. |
| subscription_payment_success | The customer is granted the plan’s price in credits, once per payment. |
| Anything else, order_created included | Recorded in the delivery log and changes nothing. |
The code in your app two calls
Ask before the customer does the billable thing, then report that it happened. The customer id is Lemon Squeezy’s own. A recorded event is always recorded; it is the question beforehand that enforces a limit.
Node.js
npm install meterflow
import { MeterFlow } from "meterflow";
const client = new MeterFlow({ apiKey: process.env.METERFLOW_API_KEY! });
const customerId = "4821973"; // the customer's id in Lemon Squeezy
const gate = await client.entitlements.check(customerId, "images.generated");
if (!gate.allowed) {
return showUpgradePrompt(gate); // gate.reason says why: "hard_limit_reached", "insufficient_credits", ...
}
await generateImage();
await client.usage.record({ event_name: "images.generated", customer_external_id: customerId, value: 1, properties: {} }); Python
pip install meterflow
import os
from meterflow import MeterFlow
client = MeterFlow(api_key=os.environ["METERFLOW_API_KEY"])
customer_id = "4821973" # the customer's id in Lemon Squeezy
gate = client.entitlements.check(customer_id, "images.generated")
if not gate["allowed"]:
return show_upgrade_prompt(gate) # gate["reason"] says why
generate_image()
client.usage.record({"event_name": "images.generated", "customer_external_id": customer_id, "value": 1, "properties": {}}) The full reference is in the SDK READMEs: Node.js and Python.
Questions
Does MeterFlow charge my customers through Lemon Squeezy?
No. MeterFlow never moves money and creates nothing in your Lemon Squeezy account. Lemon Squeezy charges your customers; MeterFlow reads what Lemon Squeezy tells it and keeps the usage, the credits and the limits.
Which id do I use for a customer?
Lemon Squeezy’s own customer id, the number Lemon Squeezy gives each customer. The connector creates each subscription under that id, so your app passes the same id when it records usage or asks whether a customer may do something.
What happens if Lemon Squeezy sends an event twice, or out of order?
A repeated event is ignored, and a repeated payment never grants credits twice. An older event that arrives after a newer one is ignored too, so a late update cannot bring a cancelled subscription back.
Can I try it without touching live data?
Yes. A connector is created for your live Lemon Squeezy account or for its test mode. The second kind writes test data only, which your app reads with an mf_test_ key; live data is never touched.
What if a Lemon Squeezy variant has no plan mapped to it?
The event is recorded in the delivery log with the reason, and nothing changes. Add the mapping and the next event for that variant applies.
Start
The free plan is enough to connect a test Lemon Squeezy account and send test events. Paid plans start at $29 a month, a flat price that is never a percentage of your revenue.
Create an account · See the plans · Compare with Stripe Billing and Autumn