Skip to main content

Implement a free trial

Step-by-step API calls: custom fields, trial contract, alerts, webhooks, conversion, early end, recurring free tier, prepaid landing.

Trial data reference

Metric definitions, Data Export SQL, and in-app reports for trial starts, conversion, attrition, and retention.

Why offer a trial

Two reasons come up most often with usage-based products:
  • Adoption. A trial lowers the barrier to a first integration, which matters most when you are launching a usage-based product for the first time or moving customers over from a subscription.
  • Pricing insight. You cannot price usage well until you know what usage looks like. A trial produces real consumption data — which metrics move, how quickly, and how much they vary between customers — early enough to shape your rate card. Metering trial usage exactly as you meter paid usage is what makes that data worth having.

Choosing a trial model

Trials are bounded in two ways: by spend, using an allowance the customer draws down, and by time, using a window that closes. Almost nobody picks only one. Setting both is the market norm and the safer default, because each bound covers the case the other misses: a spend cap alone leaves a customer sitting on an allowance indefinitely, and a time cap alone leaves your costs open-ended. The interesting decision is which way you skew. A large allowance over a short window suits a fast, intensive evaluation. A smaller allowance over a long window suits products where adoption ramps slowly and the customer needs weeks to integrate. In Metronome, a credit with an access schedule bounds both at once, because the schedule carries an amount and an ending_before. A zero-price override bounds time alone. This page covers how to choose between them, and how to set up your account so a trial can be converted and measured cleanly.

Common trial patterns

Looking at a survey of the market, a handful of patterns appear. Only a few examples actually mean “free trial”; the others are worth knowing because your customers will ask for them and each maps to a different Metronome construct. The trial_model column is the value to record on the credit, per tagging and conventions; it is n/a for the patterns with no trial credit to tag.

Choosing between them

These are the drivers worth weighing:

Recommendation

  • Default: expiring credit (amount + time), converted to a paid contract. It bounds cost, produces clean end states, and is what customers already understand.
  • A deliberately oversized credit when you want the trial to feel unlimited. Grant far more than a trial customer could plausibly consume, keep the window short, and the customer never meets the cap while you still get balance tracking, alerts, and a full drawdown record. This is a common choice when you are new to usage-based pricing and want to watch real consumption before committing to a rate card.
  • Time-only override when per-unit COGS are low or adoption of a platform takes serious ramping and you want the customer to experience the whole product. This model produces no balance signals, so the schedule end is your only trial-end event. Prefer the oversized credit above if you want that same experience with visibility into spend.
  • Recurring free tier for a permanent low-cost tier or as the landing state of a reverse trial. Note that its alerts mean something different, since a drained balance signals a throttled month rather than the end of a trial (see recurring free tier).
  • Prepaid minimum as the conversion landing state, not as the trial.

Reference architecture

Trial contract → paid contract

Model the trial as its own contract and convert by creating the paid contract with transition: { type: "RENEWAL", from_contract_id } (see contract lifecycle transitions). This is preferred over a single perpetual contract because:
  • The trial package and the paid package evolve independently (different rate cards, credits, commits, subscriptions).
  • Conversion is a first-class row in contracts_transitions (Data Export) and transitioned_from/to_contract_id (in-app report), so conversion and attrition reporting is a join, not an inference.
  • The transition end-dates the trial contract at the paid contract’s starting_at, truncates the trial credit to that instant, and expires any unused balance — no rollover, no dangling credit.

Tagging and conventions

Every business models trials a little differently, so there is no single trial report that fits all of them. The queries and reports in the data reference assume the names and custom fields below. Adopt them and those queries work unchanged; use your own instead and you will need to adjust each query to match. Tagging earns its keep beyond reporting. Because trial and trial_model sit on the credit itself, you can point alert specifiers at those fields and alert on trial balances separately from every other credit and commit a customer holds. If you run more than one trial model, that also lets you give each model its own thresholds rather than sharing a single alert.
Recurring credits cannot carry custom_fields. Identify a recurring free tier by recurring_credit_id (API) / parent_recurring_credit_id (webhooks), the contract’s contract_type, the credit name, or applicable_product_tags.

Prerequisites and constraints

  1. Register custom-field keys first. Any request that sets an unregistered key fails with Invalid custom field keys: …. Entities: customer, contract, contract_credit.
  2. Timestamps are hour-aligned. Contract starting_at and credit ending_before must be on an hour boundary (… is required to be on an hour boundary (e.g. 1:00, not 1:30)). UTC midnight is not required.
  3. Enable the system notifications you need. Turn on credit.segment.start, credit.segment.end, credit.archive, and contract.end from the UI or the API — see system notifications.

Next steps

Implement a free trial

Trial data reference