Skip to main content
This guide shows how to bill an AI product the way customers expect: they fund a prepaid wallet, your agent meters usage (tokens, calls, seconds…) as events, and Monigo debits the wallet in real time as the usage accrues. When the balance runs out, metering pauses; when they top up, it resumes automatically. It ties together three Monigo primitives:
PrimitiveRole in this flow
Events + MetricsYour agent emits usage events; a metric turns them into a billable quantity (e.g. summed tokens). See Metering.
Real-time billing planPrices the metered usage and debits the wallet continuously (~5s) instead of at period end.
Prepaid walletThe customer’s balance. Funded inline in your app via the wallet widget; debited automatically as usage accrues.
The shape of the model: customer funds wallet → agent runs → usage metered → wallet debited in near-real-time → balance hits zero → metering pauses → customer tops up → metering resumes. No invoices to chase, no surprise bills — the customer only spends what they’ve funded.

How it works

  your agent                 Monigo                          customer's app
  ──────────                 ──────                          ──────────────
  emit usage  ──ingest──▶  events → metric (cumulative usage)

                              ├─ every ~5s: marginal = price(usage) − charged_so_far
                              ├─ debit the prepaid wallet for the marginal
                              └─ balance empty? → pause + webhook ──────────▶  <WalletWidget/>
                                                                              (live balance,
   top up ◀──────────────────  auto-resume on wallet credit  ◀── customer funds ─┘   Top up button)
Charging is asynchronous and batched (~5s latency), so it never sits on your ingest hot path. The wallet’s double-entry ledger is the system of record; at the end of each billing period Monigo emits one paid summary invoice for the customer’s books (no extra debit — the money was already taken).

Prerequisites

  • A Monigo account and a secret API key (mk_live_…). All steps below run server-side — never expose the key in client code.
  • The @monigo/sdk package (examples use TypeScript; the REST endpoints are shown alongside).
Two different customer identifiers — read this once. When you create a customer you give it your own external_id and Monigo returns its id (a UUID).
  • Events reference the customer by your external_id (so you never have to look up a Monigo ID on your hot path).
  • Management APIs (wallet, subscription) reference the customer by the Monigo id (UUID).
The examples below are explicit about which one to use at each step.

Step 1 — Create the customer

const customer = await client.customers.create({
  external_id: 'org_12345',          // YOUR id for this customer
  name: 'Acme Robotics',
  email: 'billing@acme.example',
})
// customer.id is the Monigo UUID; customer.external_id is "org_12345"

Step 2 — Define your usage metric

A metric turns raw events into a billable quantity. For token billing, sum a tokens property from your agent_token_usage events.
const metric = await client.metrics.create({
  name: 'AI Agent Tokens',
  event_name: 'agent_token_usage',   // events with this name feed this metric
  aggregation: 'sum',                // count | sum | max | minimum | average | unique
  aggregation_property: 'tokens',    // the event property to sum
  description: 'Total tokens consumed by the agent',
})
Use aggregation: "count" (no aggregation_property) if you bill per-request instead of per-token. See Pricing models for tiered, package, and overage shapes — they all work with real-time billing.

Step 3 — Create a real-time prepaid plan

Set billing_mode: "realtime" and attach a price for your metric. Here, ₦0.10 per token via a per_unit price.
const plan = await client.plans.create({
  name: 'AI Prepaid — ₦0.10 / token',
  currency: 'NGN',
  plan_type: 'collection',           // required for realtime
  billing_period: 'monthly',         // required for realtime
  billing_mode: 'realtime',
  prices: [
    { metric_id: metric.id, model: 'per_unit', unit_price: '0.100000' },
  ],
})
billing_mode: "realtime" requires plan_type: "collection" and billing_period: "monthly" (usage is aggregated per calendar month). Other combinations are rejected at plan creation. All pricing models (per_unit, tiered, package, overage, cap) are supported.

Step 4 — Create the wallet and subscribe

The wallet holds the prepaid balance; the subscription connects the customer to the plan. Both use the Monigo customer id (not the external_id).
const wallet = await client.wallets.getOrCreate({
  customer_id: customer.id,          // Monigo UUID
  currency: 'NGN',
})

const subscription = await client.subscriptions.create({
  customer_id: customer.id,          // Monigo UUID
  plan_id: plan.id,
})

Step 5 — Let the customer fund the wallet

Drop the prepaid wallet UI into your app. Mint a customer-scoped portal token on your server, then render <WalletWidget> — it shows the live balance, opens the provider’s inline checkout on Top up, and refreshes automatically. Full details in Wallet management and Embedding the portal.
// Mint with the customer's external_id; pass only the raw token string to the client.
const pt = await client.portalTokens.create({
  customer_external_id: 'org_12345',
  label: 'Agent wallet',
})
return { portalToken: pt.token, walletId: wallet.id }
<WalletWidget> is available for React, Svelte, and Vue (@monigo/{react,svelte,vue}). The provider webhook is the source of truth for crediting — never credit the wallet from the browser; Monigo credits it automatically when the payment provider confirms.

Step 6 — Meter usage

As your agent runs, send a agent_token_usage event for each unit of work. Reference the customer by your external_id, put the token count in properties, and always include an idempotency_key so retries never double-charge.
const res = await client.events.ingest({
  events: [
    {
      event_name: 'agent_token_usage',
      customer_id: 'org_12345',                 // YOUR external_id (not the UUID)
      idempotency_key: 'run_2026_06_17_abc',    // stable per unit of work
      timestamp: new Date(),
      properties: { tokens: 15000, model: 'gpt-4' },
    },
  ],
})
// res.ingested: accepted keys; res.duplicates: keys already seen
Batch up to 1,000 events per ingest call. The idempotency_key should be a stable id from your own system (a run id, request id, etc.) so re-sending the same event is a no-op — critical when money moves automatically. See Idempotency.
That’s the whole integration. Everything below happens automatically.

What happens automatically

Within a few seconds of each event, Monigo:
  1. Reconciles and debits. It recomputes the period’s cumulative cost from the metric and debits the wallet for the marginal increase since the last charge — so the running cost is always exactly price(total usage so far). Typical latency is ~5 seconds.
  2. Updates the live balance. The <WalletWidget> poll picks up the new (lower) balance, so the customer watches their balance draw down as the agent works.
  3. Pauses on empty. When the wallet can’t cover the next charge, the subscription is paused, further events for that customer are dropped, and a subscription.prepaid_balance_insufficient webhook fires.
  4. Resumes on top-up. When the customer funds the wallet, the subscription reactivates, the accrued (unpaid) usage is charged from the new balance, and metering continues.
  5. Closes the period. At month end, Monigo emits one paid summary invoice (per-metric line items, total = what was actually debited) for the customer’s records — with no additional debit.

Step 7 — Handle the webhooks

Register an endpoint (Dashboard → Webhooks) and react to these events. See Webhooks for signature verification.
EventWhenWhat to do
subscription.prepaid_balance_insufficientWallet can’t cover the next charge; subscription pausedNotify the customer to top up; surface the wallet widget / a “fund wallet” CTA
customer.wallet.topped_upWallet credited (the customer funded it)Optionally confirm in-app; the subscription auto-resumes — no action required
invoice.paidMonthly summary invoice issued (already paid from the wallet)Store/forward for the customer’s billing records
subscription.prepaid_balance_insufficient
{
  "subscription_id": "sub_...",
  "customer_id": "cus_...",
  "amount_due": "120.000000",
  "currency": "NGN",
  "reason": "insufficient_balance"
}

How real-time charging works

For the curious — and for reasoning about edge cases:
  • Marginal reconcile, not per-event pricing. Each cycle charges price(cumulative usage) − already_charged. This keeps tiered/package/overage pricing exact across a period and makes cap charge its flat fee exactly once.
  • Crash-safe and idempotent. Each debit carries a deterministic idempotency key, so a retry after a failure can never double-charge.
  • Bounded free usage. Because charging trails ingestion by a few seconds, a tiny amount of usage can be metered in the window between the balance hitting zero and the pause taking effect. This is bounded to roughly the charge interval.
  • Wallet is the source of truth. Real-time debits are ordinary usage ledger entries; the monthly invoice merely records the total. There is never a second debit at period end.

A working example

A minimal SvelteKit app — mint a portal token, render <WalletWidget>, and simulate agent spend — lives at platform/samples/ai-agent-wallet.

Next steps

Wallet management

Wallet operations, virtual accounts, and the <WalletWidget> in depth.

Metering

Event ingestion patterns, batching, and idempotency.

Pricing models

Tiered, package, overage, and cap pricing — all work with real-time billing.

Embedding the portal

Drop-in components for React, Svelte, and Vue.