Quickstart
Measurement first. This gets you real cost and margin per customer without changing how a single request behaves. Nothing here can break production: the call you add cannot throw and cannot block.
- 01
Install
bashnpm install marginfuseNode 18 or newer, zero dependencies. Works in Next.js route handlers and serverless functions.
- 02
Get a project API key
Create a project in MarginFuse and copy its key from Settings, then put it in your environment as
MARGINFUSE_KEY. Keys start withmf_live_ormf_test_, and only the hash is stored, so a lost key is rotated rather than recovered. - 03
Report each AI call
Add this after the provider call returns. It sends metadata only: token counts, the model, your customer id. There is no field for the prompt.
TypeScriptimport { MarginFuse } from "marginfuse"; const mf = new MarginFuse({ apiKey: process.env.MARGINFUSE_KEY! }); // After the AI call returns. Metadata only: there is no field for the prompt. mf.track({ customerId: "cus_8x2m91", // your Stripe customer id, or your own feature: "ai_chat", provider: "openai", model: "gpt-4.1", usage: { inputTokens: 1204, outputTokens: 388 }, });Pass
costUsdinstead of, or alongside, token counts when your provider reports the real charge. MarginFuse prefers a figure you observed over one it estimated. - 04
Connect Stripe, read only
Cost alone is not margin. Connect Stripe in Settings and MarginFuse reads subscriptions and invoices to put revenue on the other side of the equation. Read only: it cannot change a charge, a plan, or a customer.
- 05
Watch the first numbers arrive
Events appear within seconds. Margin per customer needs both sides, so it fills in once Stripe has synced and traffic has flowed. Every figure is labeled with how it was arrived at, so you always know whether you are looking at something observed or something estimated.
Configuration
Everything is optional except the key.
import { MarginFuse } from "marginfuse";
const mf = new MarginFuse({
apiKey: process.env.MARGINFUSE_KEY!,
// Point at your own deployment in development.
baseUrl: "https://api.marginfuse.com",
// How long decide() waits before giving up and allowing the request.
timeoutMs: 1500,
// The SDK never throws into your code. Transport failures arrive here.
onError: (error, context) => {
logger.warn({ err: error, context }, "marginfuse degraded");
},
});timeoutMsis the budget for a decision, not fortrack(). When it expires the request is allowed through.onErroris the only place transport failures surface. The SDK swallows them so they cannot become your outage; without this hook they are silent.
Then what
Measuring is the whole free tier and it is worth stopping there for a week. Once you can see which customers lose money, protection is the same SDK with the call moved to before the request.
NextProtectionDecide before the call runs, and act on the verdict.