> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.solvimon.com/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: <apiKey>" \
     -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": "<apiKey>",
    "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': '<apiKey>', '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", "<apiKey>")
	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"] = '<apiKey>'
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<String> response = Unirest.post("http://localhost:10004/v1/report-generate-requests")
  .header("X-API-KEY", "<apiKey>")
  .header("Content-Type", "application/json")
  .body("{\n  \"report_code\": \"NOT_MATCHED_METER_DATA\"\n}")
  .asString();
```

**`Unmatched events report`**

```php Unmatched events report
<?php
require_once('vendor/autoload.php');

$client = new \GuzzleHttp\Client();

$response = $client->request('POST', 'http://localhost:10004/v1/report-generate-requests', [
  'body' => '{
  "report_code": "NOT_MATCHED_METER_DATA"
}',
  'headers' => [
    'Content-Type' => 'application/json',
    'X-API-KEY' => '<apiKey>',
  ],
]);

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", "<apiKey>");
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": "<apiKey>",
  "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).

---