Quickstart
Marginal tracks where your AI spend goes — per customer, feature, model, or any other field you define. This page takes you from zero to seeing spend in the dashboard in about five minutes.
1. Create a project#
Sign up and create a project. A project represents one application; events, API keys, and dashboards are all scoped to it. Pick the project's timezone while you're at it — every day-based number (the overview's daily chart, the explorer's date ranges) is computed in it.
2. Register your fields#
On the project's Fields page, declare the keys your events may carry — this is your project's vocabulary, and it's what keeps dashboards free of typo'd keys. The suggested conventions are one click away:
customer— who this cost is attributable tofeature— which part of your product made the call
(Don't register model — it's part of the event itself, not a field. And
don't model environments as a field — create one project per environment,
each with its own API key.)
You can register anything you like (up to 20 keys). Events may only carry registered keys — anything else is stripped on arrival and reported back, so nothing lands silently. See Field conventions for how to pick good ones.
3. Create an API key#
On the API keys page, create a key. It looks like mgl_… and is how
events authenticate and route to your project.
The key is a secret — use it server-side only. Anyone holding it can write events into your project.
4. Pick your connection#
There are three ways to send events — the TypeScript SDK, the Python SDK, or the HTTP API directly (one endpoint; any language). Pick one on any snippet's tabs and every example in these docs follows:
npm install marginal-sdk # TypeScript / JavaScript (Node 18+)pip install marginal-sdk # Python (3.9+)# Nothing to install — POST JSON straight to the API (next step).5. Send your first event#
One event per LLM request: name the provider, paste the response's model
and usage — Marginal detects the provider's usage shape and computes the
cost server-side against its model price catalog. The SDKs are
fire-and-forget: track never throws and never blocks; events are buffered
and sent in batches in the background.
import { Marginal } from "marginal-sdk";
const marginal = new Marginal({ apiKey: process.env.MARGINAL_API_KEY });
const response = await openai.chat.completions.create({ /* … */ });
marginal.track({
provider: "openai",
model: response.model, // the response-reported model
usage: response.usage, // pasted as-is; Marginal does the math
fields: {
customer: "acme",
feature: "chat",
},
});
// On shutdown, flush anything still buffered:
await marginal.shutdown();import os
from marginal import Marginal
marginal = Marginal(api_key=os.environ["MARGINAL_API_KEY"])
response = client.chat.completions.create(...)
marginal.track(
provider="openai",
model=response.model,
usage=response.usage.model_dump(),
fields={
"customer": "acme",
"feature": "chat",
},
)
# Buffered events are flushed automatically at exit;
# call marginal.shutdown() to flush explicitly.curl -X POST https://api.marginalhq.com/v1/events \
-H "Authorization: Bearer $MARGINAL_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"events": [
{ "provider": "openai",
"model": "gpt-4o-2024-08-06",
"usage": { "prompt_tokens": 2006, "completion_tokens": 300 },
"fields": { "customer": "acme", "feature": "chat" } }
]
}'For anything Marginal can't price — voice minutes, image generation, or a
cost you've already computed — send an explicit cost in dollars instead:
marginal.track({ cost: 0.05, fields: { customer: "acme", feature: "voice" } });marginal.track(cost=0.05, fields={"customer": "acme", "feature": "voice"})curl -X POST https://api.marginalhq.com/v1/events \
-H "Authorization: Bearer $MARGINAL_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "events": [{ "cost": 0.05, "fields": { "customer": "acme", "feature": "voice" } }] }'Timestamps are assigned by the server when events arrive — clients don't send them and the API doesn't accept them.
6. Watch it land#
- Ingest log — every API request shows up as it arrives, tagged
success,warn, orerror, with any problems (rejected events, stripped field keys, unpriced models) spelled out. - Explorer — your event appears in the list with one column per registered field. Pick a Group by to slice spend — Model and Provider are built in, and every registered field joins them.
- Overview — the all-time total, daily cards, and the spend chart.
That's the whole integration. For copy-paste recipes per stack — OpenAI, Anthropic, Vercel AI SDK, Gemini, Bedrock, streaming included — see Integrations; for the full wire contract and SDK options, see Event shape & API; for what the dashboard can do with the data, see Dashboard.