Configure your first meters and prices
Walk through creating core Solvimon resources via the Configuration API: the metering layer, the product catalogue, and the pricing plan. By the end, you’ll have a complete billing configuration ready to attach to customers.
All examples use the test environment (https://test.api.solvimon.com) with the X-API-KEY header for authentication. The example throughout—an HR platform charging per registered employee—shows how IDs flow from one resource to the next.
What you’ll build
The process happens in three stages. Each stage depends on IDs returned from the previous one, so follow the sequence as written.
Stage 1: Metering — Define what you measure. Create meter values, properties, and the meter itself, then link it all together with a meter value calculation.
Stage 2: Product Catalogue — Define what you sell. Build categories, products, and revenue items. Usage-based items link back to the meter value calculation from Stage 1.
Stage 3: Pricing — Define how you charge. Create a pricing plan, a version, and the pricing configurations that attach prices to revenue items. You can condition prices on meter properties.
1. Meters
A Meter sits on top of two building blocks: Meter Values (the numeric inputs) and Meter Properties (the dimensions). Both must exist before you create the Meter that uses them. Once the Meter exists, define a Meter Value Calculation that aggregates a Value (or counts a Property) into a billable number.
1.1 Create a Meter Value
A Meter Value is a numeric or monetary input—the thing you actually count or sum. Create one per quantity you want to measure.
Response:
Field notes:
reference— your own slug; must be unique and contain no whitespace. You’ll use it as a stable handle in your code.type—NUMBERfor counts/quantities,AMOUNTfor monetary values.status— set toACTIVEif you want to start using it immediately; otherwise it lands inDRAFT.
Save the returned id (metv_owDe9k0tsIY5LkBAel1P). The Meter step references it.
1.2 Create a Meter Property
A Meter Property is a dimension—country, plan tier, employee type—that gives context to each measurement and lets you slice or condition pricing on it.
Field notes:
type—NUMBER,STRING, orENUM. ENUM is what you’ll most often want for pricing conditions; supply the allowed values viaenum_values.- Only
ENUMproperties can be added to an active meter later; plan accordingly.
Save the returned id (e.g. metp_owDe9k0tsIY5LkBAel1X).
1.3 Create the Meter
The Meter ties Values and Properties together. It’s the resource your event ingestion will target.
Field notes:
meter_values[].idandmeter_properties[].idare the IDs returned by steps 1.1 and 1.2.required: truemeans an ingest event missing this field will be rejected. Required is also what makes a property usable in pricing conditions.
Save the returned Meter id (e.g. metr_kwDeeN0tv5UDtxADed1o).
1.4 Create the Meter Value Calculation
The Meter Value Calculation (MVC) turns raw events into a billable number. You pick an aggregation type and point it at a Meter Value (most common) or a Meter Property (for things like distinct-count by country).
Field notes:
calculation_type—SUM(counts, tokens, GB),MAX(peak concurrent),MIN,AVERAGE, orUNIQUE(distinct values).meter_value_idvsmeter_property_id— supply one. Use a value when aggregating a number; use a property when counting distinct dimension values (e.g. UNIQUE onemployee_country).persist: falseis the default and fine for most cases. Settrueonly when you need the calculated value carried into the next billing period.
Save the returned id (e.g. mvca_AwDeeF0tu31PTQAbeN1t). This links a usage Revenue Item to this calculation in step 2.3.
2. Product Catalogue
The catalogue itself is conceptual—there’s no POST /catalogue call. What you create are Product Categories, Products inside them, and Revenue Items (called Product Items in the API) inside each Product.
2.1 Create a Product Category
A Product Category is the top grouping (e.g. “ExpenseIt products”). At minimum you need a name, a reference, and a tax category.
Field notes:
tax_category—STANDARD,NO_TAX, orEXEMPT. This becomes the default for products in the category but each product can override.
Save the returned id (e.g. proc_iwDeeN0tvaMQ3nAies1C).
2.2 Create a Product
A Product belongs to one Category and groups one or more Revenue Items.
Field notes:
product_type—DEFAULTfor a normal sellable product,ADDONfor something attached to another product.- The product is created in
DRAFTstatus by default. You can activate it later withPOST /products/:id/activateonce its Revenue Items are in place.
Save the returned id (e.g. prod_jwDeAN0tsJCV11BBeT1h).
2.3 Create Revenue Items
Revenue Items (called product-items in the API) are the actual billable units inside a Product. The model_type field determines the flavor—and only USAGE_BASED requires a Meter Value Calculation link.
A usage-based Revenue Item linked to the MVC from step 1.4:
Field notes:
model_typeaccepts (among others)USAGE_BASED,RECURRING,SEATS, andONE_OFF.- For
USAGE_BASED, the Meter Value Calculation ID must be supplied inside the nestedusage_basedobject. The legacy top-levelmeter_value_calculation_idfield is deprecated; use the nested form going forward. - For
RECURRING,SEATS, andONE_OFF, you can omit theusage_basedblock entirely.
Repeat the call once per Revenue Item your Product needs. Save the returned IDs (e.g. proi_jwDeAN0tsJCV11BBeT1h). They’re referenced by the pricing plan step.
3. Price plan
A Price Plan is the container for one or more versions; a Version holds one or more Pricings; each Pricing is the actual price attached to a Revenue Item. Create them in that order.
3.1 Create the Price Plan
The Price Plan itself is a thin shell—name, reference, currencies. The pricing details live on the version.
Field notes:
amount_type—EXCLUDING_TAX(default) orINCLUDING_TAX. This is plan-wide; once set, every pricing inside is interpreted accordingly.pricing_currencies— the currencies allowed in this plan’s pricings. Add every currency you might charge in.
Save the returned id (e.g. ppla_RwDeAC0tsJAiH2BOeq1d).
3.2 Create a Pricing Plan Version
Versions exist so you can iterate pricing without breaking existing subscriptions. The first version is typically created in DRAFT, then activated.
A minimal version, no pricings yet:
If you’re cloning from an existing version (typical when introducing a price change), supply copied_from_pricing_plan_version_id to seed it with the previous version’s pricings:
Save the returned id (e.g. ppve_gwDeep0tDRcSvkAfeN1Z).
3.3 Create Pricings
A Pricing attaches a price configuration to one or more Revenue Items inside a specific Price Plan Version.
Field notes:
product_ids— the Products covered by this pricing (the Pricing sits at the Product level;itemsthen narrows to specific Revenue Items).items[].product_item_ids— the Revenue Items the pricing applies to.configs[].type—FLAT,TIERED,VOLUME,PACKAGE, etc.FLATis the simplest: one band, one amount.configs[].bands[].amount— the monetary value. Passquantityas a string ("0.50", not the number0.50) to avoid floating-point rounding.
For non-usage Revenue Items (Recurring, Seats, One Offs), the structure is the same—you swap the band shape (e.g. add a billing_period for recurring) and target a different product_item_ids.
3.4 Usage-based pricing with conditions
A common pattern is charging different rates for the same Revenue Item depending on a Meter Property—for instance, the cost of a registered employee differs by country. You express this by attaching multiple configs to one item, each guarded by a conditions block that matches a Meter Property value.
The example below puts two configs on the same usage-based Revenue Item: $0.50 EUR per employee in Germany, $0.40 USD per employee in the US. The Meter Property employee_country (created in step 1.2) is what each config matches against.
Field notes:
conditions.meter_properties[].id— the Meter Property ID from step 1.2. The property must be on a Meter that’s wired into the MVC linked to this Revenue Item, and it must berequired: trueto be usable in conditions.conditions.meter_properties[].value— forENUMproperties, one of theenum_valuesyou defined. Usevalues(array) instead ofvaluetogether withcomparator: "IN"to match multiple at once.comparator—EQUALS,NOT_EQUALS,IN,NOT_IN, plus numeric ones (GREATER_THAN,LESS_THAN_OR_EQUAL, etc.) forNUMBER-typed properties.order— controls evaluation order when configs are checked. The first config whose conditions match is the one that applies, so put the most specific configs first.- Cover the catch-all case. If an event arrives with
employee_country: "GBR", neither config above matches and the event won’t be priced. Either add a config with noconditionsblock as a fallback, or constrain ingestion to the supported enum values.
The same pattern works with more than one Meter Property at once—list them all under meter_properties and they’re combined with AND. For OR or nested logic, use the expression form (with operator: "AND" or "OR" and operands) instead of the flat meter_properties list.
4. Activate and create subscriptions
At this point you have a complete pricing configuration. Now link it to customers.
Activate the pricing plan version
Before you can subscribe customers, activate the version you just created:
Once activated, the version and its pricings are locked. You cannot edit them—only create a new version if pricing needs to change.
Create a customer
A customer is who you bill. Create one with their contact and billing info:
The response returns a customer id (e.g. cust_kwDeAF0ts1CV11BBet2i). Save it.
Activate the customer
Customers start in DRAFT. Activate them before creating subscriptions:
Create a subscription
Before creating subscriptions, configure at least one billing entity under Settings → Billing entities in Desk. This is required for invoice generation.
A subscription links a customer to a pricing plan and defines billing terms (currency, period, start date):
Field notes:
billing_time: "EXACT"— invoices are generated on the same day of the month asstart_at.billing_entity_reference— the entity issuing invoices. Get this from your Desk billing settings.- The subscription starts in
DRAFTand activates automatically once the first billing period begins.
The response returns a subscription id you can reference later.
5. Send usage events
Once the subscription is active, start sending usage events. Events are matched to the customer and meter, then aggregated into the invoice.
Field notes:
reference— a unique ID for this event. If sent twice, the second is deduplicated.timestamp— when the usage occurred. Defaults to now if omitted.meter_values— the measured quantity. Pass as a string ("5", not the number 5).meter_properties— the dimensions matching a meter property value. Required if the property isrequired: true.
A 200 response means the event was accepted. Events are matched to invoices based on their timestamp and the subscription’s billing period.
6. View your first invoice
Solvimon generates a draft invoice for the current billing period. Retrieve it to see your metered charges:
Response:
The invoice stays in DRAFT during the billing period. New usage events continue to be added to it. At the end of the period, it automatically transitions to FINAL.
How it all fits together
You now have a complete billing pipeline:
- Metering (
metr_...) — defines what you measure via meter values and properties - Calculation (
mvca_...) — aggregates events into billable quantities - Catalog (
prod_...→proi_...) — defines what you sell - Pricing (
ppla_...→ppve_...→ pricing configs) — defines how much you charge - Subscription — links a customer to a pricing plan
- Events — raw usage data
- Invoice — automatically generated from the subscription and events
For a visual reference of how these resources connect, see the Concepts page.
Common gotchas
Order of activation. Resources are created in DRAFT by default. Activate Meter Values and Properties before the Meter, the Meter before the MVC, and the Product before its items. Activating a Pricing Plan Version locks its Pricings–make all edits in DRAFT.
References must be unique and slug-shaped. ^\S+$ is enforced–no whitespace. Pick a naming convention (e.g. domain_object_purpose) and stick with it; references are how you’ll find resources without juggling IDs.
required: true on Meter Values/Properties. Required fields make the property usable in pricing conditions and cause ingestion to fail if the field is missing. If you want flexibility, start permissive; you can tighten later.
amount.quantity is always a string. This applies to every monetary field across the API. Pass "0.50" not 0.50.
The Catalogue isn’t a resource. There’s no endpoint for it–it’s just the conceptual envelope around Categories.