> For clean Markdown of any page, append .md to the page URL. > For a complete documentation index, see https://docs.solvimon.com/platform-guides/meter-and-event-design/unmatched-events/llms.txt. > For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.solvimon.com/_mcp/server. # Unmatched events Find events that were accepted by Solvimon but never matched to a subscription and pricing item, so you can fix the configuration and bill them. --- ## Why some events are rejected An accepted event isn't necessarily a billed event. After ingestion, Solvimon matches each event to a customer subscription and a pricing item; when no match is found, the event is stored but not billed. Every unmatched event is revenue leakage, so you want to catch them early in the billing period, not after the invoice went out. ## How events become unmatched ```mermaid flowchart TD A[Event accepted] --> B{Product item on the customer's subscription?} B -- No --> U[Unmatched] B -- Yes --> C{Pricing rule conditions met?} C -- No --> U C -- Yes --> M[Matched and billed] ``` The two most common causes: | Cause | Fix | | ---------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | The event belongs to a product item that isn't configured on the customer's subscription | Add the product item to the subscription, or correct the `customer_reference` on the event | | The product item is configured, but the event doesn't meet any pricing rule conditions | Adjust the [pricing rules](/platform-guides/products-and-pricing/pricing-plans/usage-based-pricing-methods/pricing-rules) or the meter properties sent on the event | ## Generating the report Trigger the unmatched events report with [POST /v1/report-generate-requests](https://docs.solvimon.com/api-docs/transaction-api/reports/post-report-generate-requests) using report code `NOT_MATCHED_METER_DATA`: ### Request POST [http://localhost:10004/v\{version}/report-generate-requests](http://localhost:10004/v\{version}/report-generate-requests) **`Unmatched events report`** ```curl Unmatched events report curl -X POST http://localhost:10004/v1/report-generate-requests \ -H "X-API-KEY: " \ -H "Content-Type: application/json" \ -d '{ "report_code": "NOT_MATCHED_METER_DATA" }' ``` **`Unmatched events report`** ```python Unmatched events report import requests url = "http://localhost:10004/v1/report-generate-requests" payload = { "report_code": "NOT_MATCHED_METER_DATA" } headers = { "X-API-KEY": "", "Content-Type": "application/json" } response = requests.post(url, json=payload, headers=headers) print(response.json()) ``` **`Unmatched events report`** ```javascript Unmatched events report const url = 'http://localhost:10004/v1/report-generate-requests'; const options = { method: 'POST', headers: {'X-API-KEY': '', 'Content-Type': 'application/json'}, body: '{"report_code":"NOT_MATCHED_METER_DATA"}' }; try { const response = await fetch(url, options); const data = await response.json(); console.log(data); } catch (error) { console.error(error); } ``` **`Unmatched events report`** ```go Unmatched events report package main import ( "fmt" "strings" "net/http" "io" ) func main() { url := "http://localhost:10004/v1/report-generate-requests" payload := strings.NewReader("{\n \"report_code\": \"NOT_MATCHED_METER_DATA\"\n}") req, _ := http.NewRequest("POST", url, payload) req.Header.Add("X-API-KEY", "") req.Header.Add("Content-Type", "application/json") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(res) fmt.Println(string(body)) } ``` **`Unmatched events report`** ```ruby Unmatched events report require 'uri' require 'net/http' url = URI("http://localhost:10004/v1/report-generate-requests") http = Net::HTTP.new(url.host, url.port) request = Net::HTTP::Post.new(url) request["X-API-KEY"] = '' request["Content-Type"] = 'application/json' request.body = "{\n \"report_code\": \"NOT_MATCHED_METER_DATA\"\n}" response = http.request(request) puts response.read_body ``` **`Unmatched events report`** ```java Unmatched events report import com.mashape.unirest.http.HttpResponse; import com.mashape.unirest.http.Unirest; HttpResponse response = Unirest.post("http://localhost:10004/v1/report-generate-requests") .header("X-API-KEY", "") .header("Content-Type", "application/json") .body("{\n \"report_code\": \"NOT_MATCHED_METER_DATA\"\n}") .asString(); ``` **`Unmatched events report`** ```php Unmatched events report request('POST', 'http://localhost:10004/v1/report-generate-requests', [ 'body' => '{ "report_code": "NOT_MATCHED_METER_DATA" }', 'headers' => [ 'Content-Type' => 'application/json', 'X-API-KEY' => '', ], ]); echo $response->getBody(); ``` **`Unmatched events report`** ```csharp Unmatched events report using RestSharp; var client = new RestClient("http://localhost:10004/v1/report-generate-requests"); var request = new RestRequest(Method.POST); request.AddHeader("X-API-KEY", ""); request.AddHeader("Content-Type", "application/json"); request.AddParameter("application/json", "{\n \"report_code\": \"NOT_MATCHED_METER_DATA\"\n}", ParameterType.RequestBody); IRestResponse response = client.Execute(request); ``` **`Unmatched events report`** ```swift Unmatched events report import Foundation let headers = [ "X-API-KEY": "", "Content-Type": "application/json" ] let parameters = ["report_code": "NOT_MATCHED_METER_DATA"] as [String : Any] let postData = JSONSerialization.data(withJSONObject: parameters, options: []) let request = NSMutableURLRequest(url: NSURL(string: "http://localhost:10004/v1/report-generate-requests")! as URL, cachePolicy: .useProtocolCachePolicy, timeoutInterval: 10.0) request.httpMethod = "POST" request.allHTTPHeaderFields = headers request.httpBody = postData as Data let session = URLSession.shared let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in if (error != nil) { print(error as Any) } else { let httpResponse = response as? HTTPURLResponse print(httpResponse) } }) dataTask.resume() ``` ### Response (201) ```json { "id": "rgr_QzKnt5Eyf1xmM9VV5Uk8", "generate_at": "2024-01-15T09:30:00Z", "report_code": "NOT_MATCHED_METER_DATA", "status": "PENDING", "run_type": "MANUAL" } ``` Generation is asynchronous. The finished report is written to your Solvimon Google Cloud Storage bucket, where each row contains the raw event data exactly as Solvimon received it, which makes it possible to trace an unmatched event back to what your system actually sent. > **Note** > > If you don't have access to your Solvimon bucket, reach out to support to get access. > **Note** > > Scheduled generation of this report is an upcoming feature; for now, trigger it via the API when you need it. ## After fixing the configuration Correcting the subscription, pricing plan or pricing rules doesn't retroactively bill events that already failed to match. Reprocess the affected customer's events so they are matched against the updated setup. See [Event reprocessing](/platform-guides/meter-and-event-design/event-reprocessing). ---