MeterFlow

Usage-based billing with Polar

Polar 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 Polar subscriptions without code.

Who does what

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

PolarMeterFlow
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 Polar

    In Polar, create a webhook endpoint for the subscription events and order.paid, and keep its signing secret. It asks for a URL: enter a placeholder for now. Polar’s own guide has the clicks: Setup Webhooks.

  • 3. Add the connector

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

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

  • 5. Map each product to a plan

    On the connector, map each Polar product (its product id) to one of your plans. From then on, a customer who subscribes in Polar appears in MeterFlow on that plan.

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

What each Polar event does

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

Polar eventWhat happens in MeterFlow
subscription.created, subscription.activeThe customer gets a subscription on the plan mapped to the Polar product, with Polar’s status.
subscription.updated, subscription.uncanceled, subscription.cycled, subscription.migrated, subscription.resumedThe same subscription moves to the new plan or status.
subscription.past_due, subscription.pausedThe subscription takes that status.
subscription.canceledThe subscription keeps running and records when it will end: in Polar, canceled means “will not renew”.
subscription.revokedThe subscription is cancelled.
order.paidThe customer is granted the plan’s price in credits, once per order.
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 Polar’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 = "3f9c1a52-7d04-4b6e-9a1f-2c8e5d7b0a43"; // the customer's id in Polar

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 = "3f9c1a52-7d04-4b6e-9a1f-2c8e5d7b0a43"  # the customer's id in Polar

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

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

Which id do I use for a customer?

Polar’s own customer id, the id Polar 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 Polar 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 Polar 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 Polar product 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 product applies.

Start

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

↑