Skip to main content
Enabled per organizationUsage-based billing must be enabled for your organization before these endpoints accept requests. Contact your Yuno account manager to enable it. Requests from an organization where it is not enabled return 403 PRODUCT_NOT_ENABLED.
Subscriptions bill a fixed price on a fixed cadence. Usage-based billing adds a variable part on top: you tell Yuno what to count (a meter), how much of it a plan includes and what extra units cost (a metered price), and then report how much each subscriber consumed (usage events). Yuno aggregates the usage per subscription and billing cycle and bills anything beyond the included allowance together with the subscription’s regular renewal charge. Typical uses: an AI product that includes 10,000 tokens a month and bills the rest per token, an API that includes 1,000 requests and bills per extra call, a storage product billed per gigabyte held.

How the pieces fit

  1. Meter — a named, countable action: ai_tokens, api_request, storage_gb. It defines the event_name your systems send and the aggregation (SUM, COUNT or LAST). A meter has no price of its own — at most a default_price in USD that plans can inherit. See The Meter Object.
  2. Metered price — the meter attached to a plan: how many units are included per cycle (credits) and what each unit beyond that costs (price_per_credit, optionally per country). A plan can carry any number of metered prices next to its flat price. See The Metered Price Object.
  3. Subscription — created on that plan as usual. It inherits every metered price; nothing changes in Create Subscription.
  4. Usage events — one call per unit of work, carrying the event_name, the subscription_id, a value and your own event_id for idempotency. See Report Usage Event.
  5. Renewal — at the end of the billing cycle, Yuno computes the billable quantity (max(0, usage − credits)) and adds billable × price_per_credit to the subscription’s renewal charge.
Meters are genericNothing here is specific to AI. A meter can count deliveries, minutes, messages, seats or gigabytes just as well as tokens — the meter’s unit_label / plural_unit_label are what usage is displayed in.

Quick start

The example builds a “Max” plan at $200/month that includes 10,000 AI tokens and bills $0.002 per token beyond that. Requests use the standard public-api-key / private-secret-key headers. X-Idempotency-Key is accepted on every request as elsewhere in the Yuno API, but usage events have their own dedicated dedup key — see Idempotency and timestamps.
1

Create the meter

Choose an event_name your systems will send (lowercase, _ and . allowed) and the aggregation. default_price is optional and must be USD; it saves you from repeating the unit price on every USD plan.
The response is 201 with the meter, always ACTIVE. Keep its id — you need it to attach the meter to a plan.
2

Attach it to a plan

Either create the plan with the meter inline, or attach it to a plan that already exists. Both take the same metered-price body: meter_id, credits (included units per cycle), pricing_strategy and, unless inherited, price_per_credit.
In the “New plan” example price_per_credit is omitted: the plan is USD and the meter has a default_price, so $0.002 applies and the metered price comes back with price_per_credit: null. The plan response and Retrieve Plan now carry the metered price under meters[] (an empty array on plans without meters).
Attaching a meter to a live plan does not change the plan’s flat price or any existing subscriber’s base amount — it only adds a variable line for usage beyond credits. Sending { "meters": [ ... ] } to PATCH /subscriptions/plans/{plan_id} does the same for several meters at once — atomically (one bad entry and nothing is attached) — and ignores every other plan field.
3

Subscribe customers to the plan

Nothing new here: call Create Subscription with the plan_id. The subscription inherits the plan’s metered prices. Store the subscription id — every usage event references it.
4

Report usage as it happens

Send one event per unit of work. event_id is your idempotency key; value is required for SUM and LAST meters and defaults to 1 for COUNT. The subscription must be ACTIVE, TRIALING or PAST_DUE.
A 201 confirms the event was validated and stored:
Retrying the same request (same event_id) returns this same response and never counts the 1,500 tokens twice — even if the retry carries a different value, the original is kept.

Choosing an aggregation

The aggregation is fixed when you create the meter and decides what a cycle’s quantity means:
Adds every event’s value. Report the amount consumed by each unit of work.
Three events of 1,280 / 640 / 2,100 tokens → cycle quantity 4,020 tokens. Use for tokens, minutes transcribed, messages sent, deliveries completed.

Pricing a meter on a plan

A metered price has three pricing knobs:
  • credits — the units included in the plan each billing cycle. Think “allowance”: the first credits units are covered by the plan’s flat price. 0 bills every unit. credits is measured in the meter’s unit (tokens, requests, GB) and resets each cycle — it is not a prepaid balance or wallet.
  • price_per_credit — the price of each unit beyond credits, in the plan’s base currency. On a USD plan you can omit it if the meter has a default_price; the meter’s default then applies and the metered price is returned with price_per_credit: null. On a non-USD plan, or when the meter has no default, it is required. The currency must always match the plan’s base_amount currency.
  • country_prices — optional per-unit prices by subscriber country (one entry per country), same shape as the plan’s own country_prices. A subscriber whose country is not listed pays price_per_credit. The subscriber’s country comes from the subscription — usage events carry no country or account_id — so country_prices are resolved automatically per subscriber.
pricing_strategy selects how overage is rated, and each strategy carries its own config fields at attach time:
Billable units × price_per_credit (or the subscriber’s country_prices entry). The default choice for tokens, requests, minutes.
For non-PER_UNIT strategies, the meter must be priced in every currency the plan supports — a plan with country_prices in currencies the metered price doesn’t cover is rejected (PLAN_METER_MISSING_CURRENCY), and every priced currency must match one the plan actually uses (PLAN_METER_BASE_CURRENCY_MISMATCH). All computed usage amounts (any strategy) round half-up to 4 decimal places.
Pricing config is set once, at attach time. credits, price_per_credit and country_prices can be updated on a live PER_UNIT metered price with Update Plan Meter — the new values apply to usage rated from the next billing cycle onward. package_size, package_price, package_country_prices and tiers cannot be changed after attach: switching a metered price’s pricing_strategy validates that the request carries the target strategy’s required config and clears the previous strategy’s now-inapplicable fields — a switch with no config, or with the wrong strategy’s config, is rejected. There is no detach endpoint, so to correct a PACKAGE/TIERED config you cannot re-attach the same meter — create a new meter with a new event_name, attach it with the corrected config, point your integration at the new event_name, and archive the old meter. The plan’s flat price stays immutable as before.

What happens at renewal

Usage is billed on the subscription’s renewal charge, together with the plan’s flat price — there is no separate usage invoice.
For each subscription and each metered price on its plan, at the end of the billing cycle:
  1. Quantity — events whose occurred_at falls in the cycle are aggregated with the meter’s aggregation (SUM / COUNT / LAST).
  2. Billable unitsmax(0, quantity − credits). Unused credits do not roll over.
  3. Amountbillable × price_per_credit (or the subscriber’s country_prices entry).
  4. Charge — the amount is added to the subscription’s renewal charge alongside the plan’s flat price. One charge, one payment, as today. A subscription with usage under its credits pays only the flat price.
Example, on the Max plan (10,000 tokens included, $0.002 per extra token): a subscriber consumes 13,500 tokens in August → 3,500 billable → $7.00 usage, so the renewal charges $207.00. Another subscriber consumes 8,000 → $200.00.

Idempotency and timestamps

  • event_id is required and is your idempotency key. Make it unique per event — a UUID, or the id of the request/response/job it came from — and reuse it on every retry. Yuno stores the first event under that id and answers every replay with the same response, including the original value (a different value on the retry is discarded). Usage is never double counted, however many times you retry. A request without event_id is rejected with 400.
  • Report close to real time, but you can backdate. occurred_at defaults to the receive time (returned as received_at) and can be up to 35 days in the past; older events are rejected with 400. The occurred_at (not the receive time) decides which billing cycle the event lands in.
  • X-Idempotency-Key is accepted, as on the rest of the Yuno API (same key + same body → same response), but it is optional here and not what dedupes usage — event_id is the mechanism that protects billing, and it’s the one that’s required.
  • One event per request. Aggregate on your side if you produce many small events (for example, sum tokens per response rather than per token) — a SUM meter is designed for that.
  • The subscription must be active. ACTIVE, TRIALING and PAST_DUE subscriptions accept usage (a subscription in payment retries keeps metering); events for a PAUSED, CANCELED or COMPLETED subscription are rejected with 400 SUBSCRIPTION_NOT_ACTIVE and nothing is counted.

Error handling

Validation is synchronous: a rejected event returns 400 immediately (lookup failures are 400 too, never 404) and is never counted, so treat non-201 responses as “not recorded” and retry with the same event_id after fixing the request. The codes you will meet most often: The full list, with every message, is on Meter Error Codes.

FAQ

No. Attach the meter to the live plan with Attach Meter to Plan (or the attach-only PATCH /subscriptions/plans/{plan_id} with meters[]). The flat price and existing subscribers’ base amount are unchanged; usage beyond credits starts being billed on their next renewal.
Yes, any number — for example tokens (SUM) plus API requests (COUNT) plus storage (LAST), each with its own credits and unit price. Each meter can be attached to a given plan once.
Neither. credits apply per subscription, per meter, per billing cycle. Two subscribers on the same plan each get the full allowance; unused credits do not carry over.
The event is validated against the meter and the subscription only, so it is accepted and stored — but only usage against a metered price on the subscription’s plan is rated and billed. Check the plan’s meters[] if usage isn’t showing up on the renewal.
No — both are immutable because your systems and past events depend on them; a PATCH that includes them is silently ignored. Create a new meter (with a new event_name — names stay reserved even after archiving) and archive the old one with Update Meter (status: INACTIVE). Archived meters reject new events with 400 METER_NOT_FOUND, can’t be attached to plans, and their existing metered prices are frozen; you can reactivate one at any time with status: ACTIVE.
There is no detach endpoint. Archive the meter to stop ingestion, or raise credits so no overage is billed.
Yes, per plan. The meter’s default_price is USD-only, but a metered price on a BRL plan takes price_per_credit in BRL (required — nothing is inherited for non-USD plans), and country_prices lets you set per-country unit prices in each country’s currency.
The event is rejected with 400 SUBSCRIPTION_NOT_ACTIVE and nothing is counted — only ACTIVE, TRIALING and PAST_DUE subscriptions accept usage. Resume the subscription first (Resume Subscription), then report the usage; you can backdate occurred_at up to 35 days.
No. Every event needs a subscription_id; usage is billed on that subscription’s renewal.

Reference