MeterFlow

Usage-based billing with Paddle

Paddle takes the payment and handles the tax. Counting what each customer uses, keeping their credit balance and deciding whether they may do the next thing is left to your app. MeterFlow does that part, and it follows your Paddle subscriptions without code.

Who does what

The two sit side by side. Paddle stays your merchant of record; MeterFlow never moves money.

PaddleMeterFlow
Checkout, payment methods, sales tax and invoicesUsage events, counted per customer and per meter
The subscription and its renewalsThe same subscription, mirrored, on the plan you mapped
The recurring chargeWhat that charge includes: allowances, limits and credits
Refunds and chargebacksThe 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 Paddle

    In Paddle, create a webhook notification destination for the subscription events and transaction.completed, and keep its signing secret. It asks for a URL: enter a placeholder for now. Paddle’s own guide has the clicks: Create or update notification destinations.

  • 3. Add the connector

    In MeterFlow, open your project → Connectors and add one for Paddle. 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 Paddle the real URL

    The connector now shows its webhook URL. Edit the webhook in Paddle and replace the placeholder with it.

  • 5. Map each price to a plan

    On the connector, map each Paddle price (pri_…) to one of your plans. From then on, a customer who subscribes in Paddle appears in MeterFlow on that plan.

Field by field, with the other four providers: the guide’s connector section.

What each Paddle event does

Every delivery is checked against Paddle’s signature, then listed in the connector’s delivery log with what it did, in a sentence.

Paddle eventWhat happens in MeterFlow
subscription.created, subscription.activatedThe customer gets a subscription on the plan mapped to the Paddle price, with Paddle’s status.
subscription.updated, subscription.resumedThe same subscription moves to the new plan or status.
subscription.past_due, subscription.pausedThe subscription takes that status.
subscription.canceledThe subscription is cancelled.
transaction.completedThe customer is granted the plan’s price in credits, once per transaction.
Anything elseRecorded 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 Paddle’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 = "ctm_01hv6y1f8k"; // the customer's id in Paddle

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 = "ctm_01hv6y1f8k"  # the customer's id in Paddle

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 Paddle?

No. MeterFlow never moves money and creates nothing in your Paddle account. Paddle charges your customers; MeterFlow reads what Paddle tells it and keeps the usage, the credits and the limits.

Which id do I use for a customer?

Paddle’s own customer id, the one that starts with ctm_. 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 Paddle 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 Paddle account or for its sandbox. The second kind writes test data only, which your app reads with an mf_test_ key; live data is never touched.

What if a Paddle price 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 price applies.

Start

The free plan is enough to connect a test Paddle 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

↑