Event Structure
Each meter event contains:| Field | Type | Description |
|---|---|---|
timestamp | Date | When the event occurred |
metadata.providerId | ObjectId | The provider that owns this event |
metadata.meterName | string | Which meter this event belongs to (e.g. api_requests, tool:search) |
metadata.customerId | ObjectId | The customer who triggered the event |
value | number | Numeric value (defaults to 1 for counters) |
properties | object? | Arbitrary key-value tags for filtering and analysis |
Recording Events
Via SDK Endpoint
Record events directly from your backend using the SDK API:Via Usage Endpoint
The usage endpoint provides a higher-level interface with automatic meter resolution:toolName is provided, the meter name is automatically resolved to tool:{toolName}. If no toolName or explicit meterName is given, events default to the api_requests meter.
Via NATS Event Bus
For internal services, events can be published over NATS:Automatic MCP Tool Tracking
Every MCP tool call through the SolvaPay proxy automatically records a meter event. No SDK integration needed — the proxy records against the tool’s auto-created meter (e.g.tool:search_documents) with the outcome as a property:
Querying Events
Aggregated Usage
Query total usage for a specific meter and customer within a time range:Time-Bucketed Aggregation
Get usage broken down by time intervals for charting:hour, day, week, month.
When no customerId is specified, the aggregation runs across all customers.
Analytics Queries
The meter event timeseries powers several analytics views:| Query | Description |
|---|---|
| Overall daily stats | Total events per day across all meters |
| Usage by customer | Total usage grouped by customer |
| Usage by meter | Total usage grouped by meter |
| Usage by MCP tool | Usage for meters with the tool: prefix |
How Events Power Billing and Limits
Limit Checking
When a customer makes a request to a protected endpoint, the system:- Finds the customer’s active purchase for the product
- Looks up the plan to get the
meterIdandlimit - Resolves the meter name from the
meterId - Queries
MeterEventService.sum()for usage fromperiodStartto now - Compares the total against the plan’s hard cap
End-of-Period Billing
For post-paid and hybrid plans, a daily cron job:- Finds purchases with expired billing periods
- Queries the meter timeseries for total usage in the period
- Subtracts free units from the total
- Applies the plan’s pricing (flat rate or tiered)
- Creates a payment intent for the calculated amount
Event Properties
The optionalproperties field supports arbitrary key-value pairs for filtering and analysis:
Environment Isolation
Meter events are stored in environment-specific collections:MeterEvents_sandbox— sandbox environment eventsMeterEvents_live— live environment events