> For clean Markdown of any page, append .md to the page URL. > For a complete documentation index, see https://docs.solvimon.com/platform-guides/getting-started/onboarding-and-tutorials/configure-your-first-meters-and-prices/llms.txt. > For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.solvimon.com/_mcp/server. # Configure your first meters and prices Walk through creating core Solvimon resources via the Configuration API: the metering layer, the product catalog, 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 Catalog** — 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. ```mermaid graph LR A["Metering"] --> B["Product Catalog"] B --> C["Pricing"] C --> D["Ready to bill"] style A fill:#e8f4f8,stroke:#4965f2,color:#000 style B fill:#f0e8f8,stroke:#4965f2,color:#000 style C fill:#f8f0e8,stroke:#4965f2,color:#000 style D fill:#e8f8f0,stroke:#4965f2,color:#000 ``` > **Note** > > In Desk, the [guided billing metric setup](/platform-guides/products-and-pricing/product-catalog/products-1) collapses stages 1 and 2 into one flow: you can create the meter, its values, and the calculation inline while adding a revenue item. The stages below use the API, where each resource is created explicitly and IDs flow from one call to the next. --- ## 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. ```bash curl -X POST https://test.api.solvimon.com/v1/meter-values \ -H "X-API-KEY: " \ -H "Content-Type: application/json" \ -d '{ "reference": "employee_count", "name": "Employee Count", "type": "NUMBER", "description": "The number of employees registered by the platform", "status": "ACTIVE" }' ``` Response: ```json { "id": "metv_owDe9k0tsIY5LkBAel1P", "reference": "employee_count", "name": "Employee Count", "type": "NUMBER", "description": "The number of employees registered by the platform", "status": "ACTIVE", "created_at": "2025-05-06T10:30:00Z" } ``` 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` — `NUMBER` for counts/quantities, `AMOUNT` for monetary values. * `status` — set to `ACTIVE` if you want to start using it immediately; otherwise it lands in `DRAFT`. Save the returned `id` (`metv_owDe9k0tsIY5LkBAel1P`). The Meter step references it. 📖 [API reference](https://docs.solvimon.com/api-docs/configuration-api/meter-values/post-meter-values) ### 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. ```bash curl -X POST https://test.api.solvimon.com/v1/meter-properties \ -H "X-API-KEY: " \ -H "Content-Type: application/json" \ -d '{ "reference": "employee_country", "name": "Employee Country", "type": "ENUM", "description": "Country where the employee is based.", "status": "ACTIVE", "enum_values": ["CAN", "DNK", "FIN", "GBR", "IRL", "JPN", "NOR", "SWE", "USA"] }' ``` Field notes: * `type` — `NUMBER`, `STRING`, or `ENUM`. ENUM is what you'll most often want for pricing conditions; supply the allowed values via `enum_values`. * Only `ENUM` properties can be added to an active meter later; plan accordingly. Save the returned `id` (e.g. `metp_owDe9k0tsIY5LkBAel1X`). 📖 [API reference](https://docs.solvimon.com/api-docs/configuration-api/meter-properties/post-meter-properties) ### 1.3 Create the Meter The Meter ties Values and Properties together. It's the resource your event ingestion will target. ```bash curl -X POST https://test.api.solvimon.com/v1/meters \ -H "X-API-KEY: " \ -H "Content-Type: application/json" \ -d '{ "reference": "meter_registered_employee", "name": "registered_employees", "description": "The amount of employees registered with a customer.", "meter_values": [ { "id": "metv_owDe9k0tsIY5LkBAel1P", "reference": "Employee count", "required": true } ], "meter_properties": [ { "id": "metp_owDe9k0tsIY5LkBAel1X", "reference": "Employee type", "required": true } ] }' ``` Field notes: * `meter_values[].id` and `meter_properties[].id` are the IDs returned by steps 1.1 and 1.2. * `required: true` means 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`). 📖 [API reference](https://docs.solvimon.com/api-docs/configuration-api/meters/post-meters) ### 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). ```bash curl -X POST https://test.api.solvimon.com/v1/meter-value-calculations \ -H "X-API-KEY: " \ -H "Content-Type: application/json" \ -d '{ "reference": "mvc_employee_count_sum", "calculation_type": "SUM", "meter_id": "metr_kwDeeN0tv5UDtxADed1o", "name": "Employee count (sum)", "description": "Total registered employees per billing period", "persist": false, "meter_value_id": "metv_owDe9k0tsIY5LkBAel1P" }' ``` Field notes: * `calculation_type` — `SUM` (counts, tokens, GB), `MAX` (peak concurrent), `MIN`, `AVERAGE`, or `UNIQUE` (distinct values). * `meter_value_id` vs `meter_property_id` — supply one. Use a value when aggregating a number; use a property when counting distinct dimension values (e.g. UNIQUE on `employee_country`). * `persist: false` is the default and fine for most cases. Set `true` only 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. 📖 [API reference](https://docs.solvimon.com/api-docs/configuration-api/meter-value-calculations/post-meter-value-calculations) --- ## 2. Product Catalog The catalog itself is conceptual—there's no `POST /catalog` 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. ```bash curl -X POST https://test.api.solvimon.com/v1/product-categories \ -H "X-API-KEY: " \ -H "Content-Type: application/json" \ -d '{ "name": "ExpenseIt products", "reference": "expenseit_products", "description": "All products that are offered and developed by ExpenseIt", "tax_category": "STANDARD" }' ``` Field notes: * `tax_category` — `STANDARD`, `NO_TAX`, or `EXEMPT`. This becomes the default for products in the category but each product can override. Save the returned `id` (e.g. `proc_iwDeeN0tvaMQ3nAies1C`). 📖 [API reference](https://docs.solvimon.com/api-docs/configuration-api/product-categories/post-product-categories) ### 2.2 Create a Product A Product belongs to one Category and groups one or more Revenue Items. ```bash curl -X POST https://test.api.solvimon.com/v1/products \ -H "X-API-KEY: " \ -H "Content-Type: application/json" \ -d '{ "category_id": "proc_iwDeeN0tvaMQ3nAies1C", "name": "Receipt Scanning", "reference": "receipt_scanning", "description": "Giving customer employees the possibility to scan receipts.", "product_type": "DEFAULT", "tax_category": "STANDARD" }' ``` Field notes: * `product_type` — `DEFAULT` for a normal sellable product, `ADDON` for something attached to another product. * The product is created in `DRAFT` status by default. You can activate it later with `POST /products/:id/activate` once its Revenue Items are in place. Save the returned `id` (e.g. `prod_jwDeAN0tsJCV11BBeT1h`). 📖 [API reference](https://docs.solvimon.com/api-docs/configuration-api/products/post-products) ### 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: ```bash curl -X POST https://test.api.solvimon.com/v1/product-items \ -H "X-API-KEY: " \ -H "Content-Type: application/json" \ -d '{ "product_id": "prod_jwDeAN0tsJCV11BBeT1h", "name": "Reimbursed amount", "reference": "reimbursed_amount", "description": "Reimbursed amount per scanned receipt", "model_type": "USAGE_BASED", "tax_category": "STANDARD", "usage_based": { "meter_value_calculation_id": "mvca_AwDeeF0tu31PTQAbeN1t" } }' ``` Field notes: * `model_type` accepts (among others) `USAGE_BASED`, `RECURRING`, `SEATS`, and `ONE_OFF`. * For `USAGE_BASED`, the Meter Value Calculation ID must be supplied inside the nested `usage_based` object. The legacy top-level `meter_value_calculation_id` field is deprecated; use the nested form going forward. * For `RECURRING`, `SEATS`, and `ONE_OFF`, you can omit the `usage_based` block 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. 📖 [API reference](https://docs.solvimon.com/api-docs/configuration-api/product-items/post-product-items) --- ## 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. ```bash curl -X POST https://test.api.solvimon.com/v1/pricing-plans \ -H "X-API-KEY: " \ -H "Content-Type: application/json" \ -d '{ "reference": "default_pricing", "name": "Default Pricing Plan", "description": "Standard pricing plan for self-serve customers", "amount_type": "EXCLUDING_TAX", "pricing_currencies": ["EUR", "USD"] }' ``` Field notes: * `amount_type` — `EXCLUDING_TAX` (default) or `INCLUDING_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`). 📖 [API reference](https://docs.solvimon.com/api-docs/configuration-api/pricing-plans/post-pricing-plans) ### 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: ```bash curl -X POST https://test.api.solvimon.com/v1/pricing-plan-versions \ -H "X-API-KEY: " \ -H "Content-Type: application/json" \ -d '{ "pricing_plan_id": "ppla_RwDeAC0tsJAiH2BOeq1d", "version": 1, "status": "DRAFT" }' ``` 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: ```bash curl -X POST https://test.api.solvimon.com/v1/pricing-plan-versions \ -H "X-API-KEY: " \ -H "Content-Type: application/json" \ -d '{ "pricing_plan_id": "ppla_RwDeAC0tsJAiH2BOeq1d", "version": 2, "status": "DRAFT", "copied_from_pricing_plan_version_id": "ppve_gwDeep0tDRcSvkAfeN1Z" }' ``` Save the returned `id` (e.g. `ppve_gwDeep0tDRcSvkAfeN1Z`). 📖 [API reference](https://docs.solvimon.com/api-docs/configuration-api/pricing-plan-versions/post-pricing-plan-versions) ### 3.3 Create Pricings A Pricing attaches a price configuration to one or more Revenue Items inside a specific Price Plan Version. ```bash curl -X POST https://test.api.solvimon.com/v1/pricings \ -H "X-API-KEY: " \ -H "Content-Type: application/json" \ -d '{ "pricing_plan_version_id": "ppve_gwDeep0tDRcSvkAfeN1Z", "name": "Receipt scanning – per receipt", "product_ids": ["prod_jwDeAN0tsJCV11BBeT1h"], "items": [ { "product_item_ids": ["proi_jwDeAN0tsJCV11BBeT1h"], "configs": [ { "type": "FLAT", "order": 1, "bands": [ { "amount": { "quantity": "0.50", "currency": "EUR" } } ] } ] } ] }' ``` Field notes: * `product_ids` — the Products covered by this pricing (the Pricing sits at the Product level; `items` then narrows to specific Revenue Items). * `items[].product_item_ids` — the Revenue Items the pricing applies to. * `configs[].type` — `FLAT`, `TIERED`, `VOLUME`, `PACKAGE`, etc. `FLAT` is the simplest: one band, one amount. * `configs[].bands[].amount` — the monetary value. Pass `quantity` as a string (`"0.50"`, not the number `0.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`. 📖 [API reference](https://docs.solvimon.com/api-docs/configuration-api/pricings/post-pricings) ### 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. ```bash curl -X POST https://test.api.solvimon.com/v1/pricings \ -H "X-API-KEY: " \ -H "Content-Type: application/json" \ -d '{ "pricing_plan_version_id": "ppve_gwDeep0tDRcSvkAfeN1Z", "name": "Registered employees – by country", "product_ids": ["prod_jwDeAN0tsJCV11BBeT1h"], "items": [ { "product_item_ids": ["proi_jwDeAN0tsJCV11BBeT1h"], "configs": [ { "type": "FLAT", "order": 1, "conditions": { "name": "Germany", "meter_properties": [ { "id": "metp_owDe9k0tsIY5LkBAel1X", "value": "DEU", "comparator": "EQUALS" } ] }, "bands": [ { "amount": { "quantity": "0.50", "currency": "EUR" } } ] }, { "type": "FLAT", "order": 2, "conditions": { "name": "United States", "meter_properties": [ { "id": "metp_owDe9k0tsIY5LkBAel1X", "value": "USA", "comparator": "EQUALS" } ] }, "bands": [ { "amount": { "quantity": "0.40", "currency": "USD" } } ] } ] } ] }' ``` 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 be `required: true` to be usable in conditions. * `conditions.meter_properties[].value` — for `ENUM` properties, one of the `enum_values` you defined. Use `values` (array) instead of `value` together with `comparator: "IN"` to match multiple at once. * `comparator` — `EQUALS`, `NOT_EQUALS`, `IN`, `NOT_IN`, plus numeric ones (`GREATER_THAN`, `LESS_THAN_OR_EQUAL`, etc.) for `NUMBER`-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 no `conditions` block 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. 📖 [API reference](https://docs.solvimon.com/api-docs/configuration-api/pricings/post-pricings) --- ## 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: ```bash curl -X POST https://test.api.solvimon.com/v1/pricing-plan-versions/ppve_gwDeep0tDRcSvkAfeN1Z/activate \ -H "X-API-KEY: " ``` Once activated, the version and its pricings are locked. You cannot edit them—only create a new version if pricing needs to change. 📖 API reference ### Create a customer A customer is who you bill. Create one with their contact and billing info: ```bash curl -X POST https://test.api.solvimon.com/v1/customers \ -H "X-API-KEY: " \ -H "Content-Type: application/json" \ -d '{ "reference": "acme-001", "type": "ORGANIZATION", "email": "billing@acme.com", "status": "DRAFT", "timezone": "Europe/London", "organization": { "legal_name": "ACME Corp", "registered_address": { "line1": "123 Business St", "city": "London", "postal_code": "SW1A 1AA", "country": "GB" } } }' ``` The response returns a customer `id` (e.g. `cust_kwDeAF0ts1CV11BBet2i`). Save it. 📖 [API reference](https://docs.solvimon.com/api-docs/configuration-api/customers/post-customers) ### Activate the customer Customers start in `DRAFT`. Activate them before creating subscriptions: ```bash curl -X POST https://test.api.solvimon.com/v1/customers/acme-001/activate \ -H "X-API-KEY: " ``` ### Create a subscription > **Info** > > Before creating subscriptions, configure at least one billing entity under **Settings → Billing entities** in [Desk](https://test.desk.solvimon.com). This is required for invoice generation. A subscription links a customer to a pricing plan and defines billing terms (currency, period, start date): ```bash curl -X POST https://test.api.solvimon.com/v1/pricing-plan-subscriptions/init \ -H "X-API-KEY: " \ -H "Content-Type: application/json" \ -d '{ "pricing_plan_subscription": { "reference": "acme-001-sub", "customer_reference": "acme-001", "billing_entity_reference": "", "billing_currency": "EUR", "billing_time": "EXACT" }, "pricing_plan_schedules": [ { "pricing_plan_version_selector": { "pricing_plan_reference": "default_pricing" }, "start_at": "2025-05-06T00:00:00Z" } ] }' ``` Field notes: * `billing_time: "EXACT"` — invoices are generated on the same day of the month as `start_at`. * `billing_entity_reference` — the entity issuing invoices. Get this from your Desk billing settings. * The subscription starts in `DRAFT` and activates automatically once the first billing period begins. The response returns a subscription `id` you can reference later. 📖 [API reference](https://docs.solvimon.com/api-docs/configuration-api/pricing-plan-subscriptions/post-pricing-plan-subscriptions-init) --- ## 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. ```bash curl -X POST https://test.api.solvimon.com/v1/ingest/meter-data \ -H "X-API-KEY: " \ -H "Content-Type: application/json" \ -d '{ "meter_reference": "meter_registered_employee", "customer_reference": "acme-001", "reference": "evt_20250506_001", "timestamp": "2025-05-06T14:30:00Z", "meter_values": [ { "reference": "employee_count", "number": "5" } ], "meter_properties": [ { "reference": "employee_country", "value": "GBR" } ] }' ``` 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 is `required: true`. A `200` response means the event was accepted. Events are matched to invoices based on their `timestamp` and the subscription's billing period. 📖 [API reference](https://docs.solvimon.com/api-docs/event-api/ingest/post-ingest-meter-data) --- ## 6. View your first invoice Solvimon generates a draft invoice for the current billing period. Retrieve it to see your metered charges: ```bash curl "https://test.api.solvimon.com/v1/invoices?customer_reference=acme-001" \ -H "X-API-KEY: " ``` Response: ```json { "data": [ { "id": "inv_kwDeAF0ts1CV11BBet2i", "status": "DRAFT", "customer_reference": "acme-001", "billing_period_start": "2025-05-06T00:00:00Z", "billing_period_end": "2025-06-06T00:00:00Z", "total_amount": { "quantity": "2.50", "currency": "EUR" }, "line_items": [ { "product_item_reference": "reimbursed_amount", "description": "Registered employees – by country", "quantity": "5", "unit_price": { "quantity": "0.50", "currency": "EUR" }, "total": { "quantity": "2.50", "currency": "EUR" } } ] } ] } ``` 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`. 📖 [API reference](https://docs.solvimon.com/api-docs/transaction-api/invoices/get-invoices) --- ## How it all fits together You now have a complete billing pipeline: 1. **Metering** (`metr_...`) — defines what you measure via meter values and properties 2. **Calculation** (`mvca_...`) — aggregates events into billable quantities 3. **Catalog** (`prod_...` → `proi_...`) — defines what you sell 4. **Pricing** (`ppla_...` → `ppve_...` → pricing configs) — defines how much you charge 5. **Subscription** — links a customer to a pricing plan 6. **Events** — raw usage data 7. **Invoice** — automatically generated from the subscription and events For a visual reference of how these resources connect, see the [Concepts](/platform-guides/getting-started/how-solvimon-works) page. --- ## Common gotchas > **Warning** > > **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`. > **Tip** > > **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. > **Check** > > **`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. > **Note** > > **`amount.quantity` is always a string.** This applies to every monetary field across the API. Pass `"0.50"` not `0.50`. > **Note** > > **The Catalog isn't a resource.** There's no endpoint for it–it's just the conceptual envelope around Categories.