> 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.

# Revenue Recognition

> **Info**
>
> Please contact our commercial team if you are interested in using this functionality.

Revenue recognition is an accounting approach used to ascertain how revenue should be recorded during the period when a service is utilized. In addition to the data export, we also offer reports in which we pre-calculate revenue recognition metrics.

Billing tells you what a customer owes; recognition tells you what you have earned. The two rarely coincide: an annual subscription invoiced up front is cash and a receivable on day one, but revenue only as the service is delivered. Solvimon calculates that split for you, per invoice line and per month, and passes the service periods to your ERP so the journals follow.

---

## How recognition works

Solvimon's revenue recognition reports comply with **ASC 606** and **IFRS 15**. Both standards recognise revenue when the performance obligation is satisfied rather than when the invoice is raised, and Solvimon applies that rule per invoice line:

* **Recurring revenue invoiced in advance is deferred and released.** The obligation is satisfied continuously across the service period, so the amount is held as deferred revenue and released straight-line per day over that period.
* **Usage revenue is recognised in the period it is delivered.** Usage is metered and billed after consumption, so the obligation is already satisfied at invoicing. There is nothing to defer.
* **Commitments and discounts are allocated across the period they relate to.** The transaction price is spread over the same service period as the item it belongs to, so a discounted annual commitment recognises its discounted value evenly rather than front-loading the discount.
* **One-off fees are recognised at a point in time.** A one-off charge whose service period starts and ends on the same date has nothing to spread: the full base amount is recognised in that month and never enters the deferred balance.

Every calculation runs off the service period stored on the invoice line, which is printed on the invoice, exposed in the report downloads, and synced to your ERP. Because a finalised invoice in Solvimon is immutable and corrections run through linked credit notes, each recognised amount traces back to a specific line on a specific invoice. This provides further confidence during audits.

### Terms used on this page

| Term                  | Meaning                                                                                                                                              |
| :-------------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------- |
| Service period        | The window an invoice line covers, held as a start and end date per line. This drives the entire schedule.                                           |
| Base amount           | The invoice amount excluding tax. Recognition is always calculated on the base amount.                                                               |
| Recognised revenue    | The base amount attributable to a given month, because the service was delivered in it.                                                              |
| Deferred revenue      | The base amount invoiced but not yet earned, measured at month end.                                                                                  |
| Release               | The movement of an amount out of deferred revenue and into recognised revenue as time passes.                                                        |
| Straight-line per day | The allocation method: the base amount is divided by the number of days in the service period and attributed to each day, then aggregated per month. |

> **Note**
>
> The schedule covers invoiced revenue: lines on final and draft invoices. Revenue for billing periods that have not been invoiced yet, such as year two of a multi-year subscription, is not part of the schedule.

### One-off fees versus spread subscription charges

Whether an amount is deferred is decided by its service period, not by the kind of item it is:

| Charge                                       | Service period on the line          | Recognition                                           |
| :------------------------------------------- | :---------------------------------- | :---------------------------------------------------- |
| Annual subscription fee invoiced up front    | The full year                       | Deferred at invoicing, released straight-line per day |
| Monthly subscription fee invoiced in advance | The coming month                    | Deferred at invoicing, released across that month     |
| Monthly subscription fee invoiced in arrears | The month just ended                | Recognised in full, nothing to defer                  |
| Usage charge                                 | The metered period, already elapsed | Recognised in full, nothing to defer                  |
| Setup or implementation fee                  | A single date                       | Recognised in full in that month                      |
| Activation fee spread over a contracted term | The contracted term                 | Deferred and released across the term                 |

The practical consequence: to change whether a fee is deferred, change the service period the invoice line carries. A setup fee that should be earned over the first year needs a twelve-month service period, not a single date.

> **Warning**
>
> A one-off fee recognised at a point in time is still a performance obligation for accounting purposes. If the fee pays for something delivered over time, such as onboarding or migration work, recognising it on the invoice date front-loads revenue that has not been earned. Set the service period to the delivery window instead.

---

## Reports

At this moment we offer the following reports on Revenue recognition:

* **[Recognised Revenue:](#recognised-and-deferred-revenue)** The revenue that can be recognized according to recognition guidelines (ASC 606 and IFRS 15).
* **[Deferred Revenue:](#recognised-and-deferred-revenue)** The deferred or pending revenue that will recognise at a later moment in time, depending on when the underlying service obligation is fulfilled (captured through the service periods).

The two reports are the same schedule seen from two sides: what has been earned, and what is still owed to the customer in service. Read together they reconcile, so the closing deferred balance of one month plus the revenue released in the next equals the opening balance you started with.

In addition to the offered reports, we also include information on the applicable revenue recognition periods in the downloadable invoice line report, refer to [report downloads](/platform-guides/analytics-reporting/report-downloads).

### Recognised and deferred revenue

The recognised revenue report provides the base amount to be recognized for each month. Additionally, it incorporates the anticipated recognized revenue for coming months, which is already present in either Final or Draft invoices.

The deferred revenue report provides the base amount that is pending for the remainder of the service period. The two are complementary: what leaves the deferred balance in a month is what the recognised report reports for that month.

**Example of a straight line per day revenue recognition schedule**

In this example we assume that a customer has an annual subscription that has a flat fee of €365 that is invoiced on Jan 1, 2023 for the period of Jan 1, 2023 to Dec 31, 2023.

Both amounts are calculated on the base amount (invoice amount minus tax) and aggregated by month. The recognised amount will be €31 for Jan 2023 and €28 for Feb 2023, and the deferred balance will be €365 - €31 = €334 at the end of Jan 2023 and €334 - €28 = €306 at the end of Feb 2023.

The full year, as the balance moves out of the deferred bucket and into the recognised bucket:

<title>
  Each month a slice of the deferred balance moves into recognised revenue, until the deferred balance reaches zero
</title>

<defs>
  <linearGradient id="revrecDeferred" x1="0" y1="0" x2="0" y2="1" />

  <linearGradient id="revrecRecognised" x1="0" y1="0" x2="0" y2="1" />

  <linearGradient id="revrecStream" x1="0" y1="0" x2="1" y2="0" />

  <filter id="revrecGlow" x="-40%" y="-40%" width="180%" height="180%" />

  <clipPath id="revrecClipLeft">
    <rect x="180" y="44" width="104" height="150" rx="16" />
  </clipPath>

  <clipPath id="revrecClipRight">
    <rect x="436" y="44" width="104" height="150" rx="16" />
  </clipPath>
</defs>

one month of service, every month

<rect x="180" y="44" width="104" height="150" rx="16" fill="currentColor" opacity="0.045" />

<rect class="revrec-flow__deferred" x="180" y="106" width="104" height="88" fill="url(#revrecDeferred)" />

<rect x="436" y="44" width="104" height="150" rx="16" fill="currentColor" opacity="0.045" />

<rect class="revrec-flow__recognised" x="436" y="132" width="104" height="62" fill="url(#revrecRecognised)" />

Deferred

365 down to 0

Recognised

0 up to 365

Reading the visual: the **light blue bar** is the deferred balance, everything invoiced but not yet earned, and the **dark blue bar** is revenue recognised to date. Each month a slice of one month's service crosses from left to right, and the two always sum to the €365 on the invoice. That crossing amount is the release your ledger posts. By the end of the service period the deferred bar is empty and the full €365 has been recognised.

| Month | Released in month | Recognised to date | Deferred balance |
| :---- | ----------------: | -----------------: | ---------------: |
| Jan   |               €31 |                €31 |             €334 |
| Feb   |               €28 |                €59 |             €306 |
| Mar   |               €31 |                €90 |             €275 |
| Apr   |               €30 |               €120 |             €245 |
| May   |               €31 |               €151 |             €214 |
| Jun   |               €30 |               €181 |             €184 |
| Jul   |               €31 |               €212 |             €153 |
| Aug   |               €31 |               €243 |             €122 |
| Sep   |               €30 |               €273 |              €92 |
| Oct   |               €31 |               €304 |              €61 |
| Nov   |               €30 |               €334 |              €31 |
| Dec   |               €31 |               €365 |               €0 |

On the last day of the service period the deferred balance is zero and the full €365 has been recognised. That closing balance is what your deferred revenue account in the ledger should show each month, which makes the report the reconciliation document for the account.

Each month therefore carries one day of revenue for every day of service in it, which is why February is smaller than January rather than every month being one twelfth. This holds where the service is delivered at a constant rate across the period, which is the assumption behind straight-line recognition. Where delivery is not constant, for example a milestone-based implementation fee or usage that varies month to month, the service periods on the invoice lines are what determine the pattern instead. Commitments and discounts are also applied and spread over the entire period.

---

## Revenue recognition with your ERP

Solvimon calculates the schedule for every customer, and every finalised invoice line carries the service period it belongs to. What differs per ERP is whether that ERP turns those periods into deferral and release journals by itself, or whether the journals are posted from Solvimon's recognition report.

There are three patterns:

* **The ERP recognises automatically.** Solvimon posts the invoice with a service period on each line, and the ERP builds the schedule and posts the monthly release. This is how Exact Online, NetSuite, QuickBooks Advanced, Campfire, and Rillet work.
* **The ERP has no period-based deferral.** Solvimon posts the invoice, and the deferral and monthly release journals are entered manually from Solvimon's recognition report. This is how Xero works.
* **No ERP recognition.** Solvimon's recognised and deferred revenue reports are the schedule of record, and journals are posted wherever you keep your ledger.

In all three cases the reports above stay available, so you always have a schedule to reconcile against.

### Capability overview

| ERP                                                                            | Service period sent per invoice line                                                     | Recognition schedule built in the ERP    | Monthly release journals                             | One-time setup required                                                                                                                                                          |
| :----------------------------------------------------------------------------- | :--------------------------------------------------------------------------------------- | :--------------------------------------- | :--------------------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| [Exact Online](/integrations/enterprise-resource-planning-erp/exact-online)    | Yes. `start_at` and `end_at` map to `From` and `To` on the sales entry line              | Yes, native                              | Posted by Exact automatically                        | A deferred revenue account (for example 493000) and revenue spreading configured on the accounts Solvimon posts to, plus GL codes mapped per product through `EXACT_ITEM_GLCODE` |
| [Xero](/integrations/enterprise-resource-planning-erp/xero)                    | No. Xero invoice lines carry description, amount, and tax only                           | No. Xero has no period-based deferral    | Posted manually from the Solvimon recognition report | An account code per revenue item, and a deferred revenue account for the manual journal                                                                                          |
| [NetSuite](/integrations/enterprise-resource-planning-erp/netsuite)            | Yes. Service period start and end map to `Revenue Recognition Start Date` and `End Date` | Yes, with the Revenue Recognition module | Posted by NetSuite automatically                     | The Revenue Recognition module enabled (SuiteTax for VAT), and Service For Sale items for commitment, discount, and one-off lines                                                |
| [QuickBooks Online](/integrations/enterprise-resource-planning-erp/quickbooks) | Yes. Service-period start and end per line                                               | Yes, on QuickBooks Online Advanced only  | Posted by QuickBooks automatically                   | A QuickBooks Online Advanced subscription, and a recognition method and template assigned per item                                                                               |
| [Campfire](/integrations/enterprise-resource-planning-erp/campfire)            | Yes. Contract start and end from the subscription, and `service_date` per invoice line   | Yes, native                              | Posted by Campfire automatically                     | Contract sync on subscription activation, the option to create subscriptions on a contract enabled, and Campfire IDs stored on customers, products, and entities                 |
| [Rillet](/integrations/enterprise-resource-planning-erp/rillet)                | Yes. `start_at` and `end_at` map to `revenue.period.start` and `.end`                    | Yes, native                              | Posted by Rillet automatically                       | Rillet product IDs stored on Solvimon products                                                                                                                                   |
| [DATEV (via MidTech)](/integrations/enterprise-resource-planning-erp/datev)    | Invoice export only                                                                      | No                                       | Posted manually from the Solvimon recognition report | The MidTech connector and a DATEV ID per customer                                                                                                                                |
| No ERP integration                                                             | Not applicable                                                                           | Not applicable                           | Posted manually from the Solvimon recognition report | None                                                                                                                                                                             |

> **Note**
>
> The setup in the right-hand column is done once, in the ERP, by you or your accountant. Solvimon does not post the release journal itself; it supplies the invoice, the service period on every line, and the calculated schedule. Solvimon can support the setup and the integration with your ERP, including the mapping of accounts and service periods. Talk to your Sales Executive to enable that support.

### Posting the release manually

For Xero, DATEV, or any ledger without period-based deferral:

1. Pull the recognised revenue report for the month you are closing.
2. Post a journal per revenue account that debits deferred revenue and credits revenue for the recognised amount.
3. Use the deferred revenue report as the closing balance check on the deferral account.

Because both reports are pre-calculated per month, the journal is a transcription of the report rather than a re-derivation of the schedule. Usage lines need no entry: they were recognised when the invoice posted.

---

## Querying the schedule

### Generating the report through the API

The recognition schedule is retrieved by generating the revenue recognition report. Request the report with `report_code` set to `REVENUE_RECOGNITION`:

### Request

POST [http://localhost:10004/v\{version}/report-generate-requests](http://localhost:10004/v\{version}/report-generate-requests)

**`Generate an invoice report`**

```curl Generate an invoice report
curl -X POST http://localhost:10004/v1/report-generate-requests \
     -H "X-API-KEY: <apiKey>" \
     -H "Content-Type: application/json" \
     -d '{
  "generate_at": "2024-01-15T09:30:00Z",
  "report_code": "INVOICE",
  "parameter_values": [
    {
      "name": "report_date",
      "value": "2024-01-01"
    }
  ],
  "report_configuration_id": "rcf_RaLou6Fzg2ynN1UU6Vm9"
}'
```

**`Generate an invoice report`**

```python Generate an invoice report
import requests

url = "http://localhost:10004/v1/report-generate-requests"

payload = {
    "generate_at": "2024-01-15T09:30:00Z",
    "report_code": "INVOICE",
    "parameter_values": [
        {
            "name": "report_date",
            "value": "2024-01-01"
        }
    ],
    "report_configuration_id": "rcf_RaLou6Fzg2ynN1UU6Vm9"
}
headers = {
    "X-API-KEY": "<apiKey>",
    "Content-Type": "application/json"
}

response = requests.post(url, json=payload, headers=headers)

print(response.json())
```

**`Generate an invoice report`**

```javascript Generate an invoice report
const url = 'http://localhost:10004/v1/report-generate-requests';
const options = {
  method: 'POST',
  headers: {'X-API-KEY': '<apiKey>', 'Content-Type': 'application/json'},
  body: '{"generate_at":"2024-01-15T09:30:00Z","report_code":"INVOICE","parameter_values":[{"name":"report_date","value":"2024-01-01"}],"report_configuration_id":"rcf_RaLou6Fzg2ynN1UU6Vm9"}'
};

try {
  const response = await fetch(url, options);
  const data = await response.json();
  console.log(data);
} catch (error) {
  console.error(error);
}
```

**`Generate an invoice report`**

```go Generate an invoice report
package main

import (
	"fmt"
	"strings"
	"net/http"
	"io"
)

func main() {

	url := "http://localhost:10004/v1/report-generate-requests"

	payload := strings.NewReader("{\n  \"generate_at\": \"2024-01-15T09:30:00Z\",\n  \"report_code\": \"INVOICE\",\n  \"parameter_values\": [\n    {\n      \"name\": \"report_date\",\n      \"value\": \"2024-01-01\"\n    }\n  ],\n  \"report_configuration_id\": \"rcf_RaLou6Fzg2ynN1UU6Vm9\"\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))

}
```

**`Generate an invoice report`**

```ruby Generate an invoice 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  \"generate_at\": \"2024-01-15T09:30:00Z\",\n  \"report_code\": \"INVOICE\",\n  \"parameter_values\": [\n    {\n      \"name\": \"report_date\",\n      \"value\": \"2024-01-01\"\n    }\n  ],\n  \"report_configuration_id\": \"rcf_RaLou6Fzg2ynN1UU6Vm9\"\n}"

response = http.request(request)
puts response.read_body
```

**`Generate an invoice report`**

```java Generate an invoice 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  \"generate_at\": \"2024-01-15T09:30:00Z\",\n  \"report_code\": \"INVOICE\",\n  \"parameter_values\": [\n    {\n      \"name\": \"report_date\",\n      \"value\": \"2024-01-01\"\n    }\n  ],\n  \"report_configuration_id\": \"rcf_RaLou6Fzg2ynN1UU6Vm9\"\n}")
  .asString();
```

**`Generate an invoice report`**

```php Generate an invoice report
<?php
require_once('vendor/autoload.php');

$client = new \GuzzleHttp\Client();

$response = $client->request('POST', 'http://localhost:10004/v1/report-generate-requests', [
  'body' => '{
  "generate_at": "2024-01-15T09:30:00Z",
  "report_code": "INVOICE",
  "parameter_values": [
    {
      "name": "report_date",
      "value": "2024-01-01"
    }
  ],
  "report_configuration_id": "rcf_RaLou6Fzg2ynN1UU6Vm9"
}',
  'headers' => [
    'Content-Type' => 'application/json',
    'X-API-KEY' => '<apiKey>',
  ],
]);

echo $response->getBody();
```

**`Generate an invoice report`**

```csharp Generate an invoice 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  \"generate_at\": \"2024-01-15T09:30:00Z\",\n  \"report_code\": \"INVOICE\",\n  \"parameter_values\": [\n    {\n      \"name\": \"report_date\",\n      \"value\": \"2024-01-01\"\n    }\n  ],\n  \"report_configuration_id\": \"rcf_RaLou6Fzg2ynN1UU6Vm9\"\n}", ParameterType.RequestBody);
IRestResponse response = client.Execute(request);
```

**`Generate an invoice report`**

```swift Generate an invoice report
import Foundation

let headers = [
  "X-API-KEY": "<apiKey>",
  "Content-Type": "application/json"
]
let parameters = [
  "generate_at": "2024-01-15T09:30:00Z",
  "report_code": "INVOICE",
  "parameter_values": [
    [
      "name": "report_date",
      "value": "2024-01-01"
    ]
  ],
  "report_configuration_id": "rcf_RaLou6Fzg2ynN1UU6Vm9"
] 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",
  "customer_id": "cust_AbD3DqausjOYiMNDZY11F",
  "invoice_id": "invo_MwGkq2Bvc7ujJ6YY2Rg5",
  "generate_at": "2024-01-15T09:30:00Z",
  "report_code": "INVOICE",
  "parameter_values": [
    {
      "name": "report_date",
      "value": "2024-01-01"
    }
  ],
  "status": "COMPLETED",
  "report_subscription_id": "sub_SbMpv7Ghh3zoP2TT7Wn1",
  "report_configuration_id": "rcf_RaLou6Fzg2ynN1UU6Vm9",
  "run_type": "MANUAL"
}
```

Generation is asynchronous. Poll the request until it completes, then download the file:

### Request

GET [http://localhost:10004/v\{version}/report-generate-requests/\{resourceId}](http://localhost:10004/v\{version}/report-generate-requests/\{resourceId})

```curl
curl http://localhost:10004/v1/report-generate-requests/ \
     -H "X-API-KEY: <apiKey>"
```

```python
import requests

url = "http://localhost:10004/v1/report-generate-requests/:resourceId"

headers = {"X-API-KEY": "<apiKey>"}

response = requests.get(url, headers=headers)

print(response.json())
```

```javascript
const url = 'http://localhost:10004/v1/report-generate-requests/:resourceId';
const options = {method: 'GET', headers: {'X-API-KEY': '<apiKey>'}};

try {
  const response = await fetch(url, options);
  const data = await response.json();
  console.log(data);
} catch (error) {
  console.error(error);
}
```

```go
package main

import (
	"fmt"
	"net/http"
	"io"
)

func main() {

	url := "http://localhost:10004/v1/report-generate-requests/:resourceId"

	req, _ := http.NewRequest("GET", url, nil)

	req.Header.Add("X-API-KEY", "<apiKey>")

	res, _ := http.DefaultClient.Do(req)

	defer res.Body.Close()
	body, _ := io.ReadAll(res.Body)

	fmt.Println(res)
	fmt.Println(string(body))

}
```

```ruby
require 'uri'
require 'net/http'

url = URI("http://localhost:10004/v1/report-generate-requests/:resourceId")

http = Net::HTTP.new(url.host, url.port)

request = Net::HTTP::Get.new(url)
request["X-API-KEY"] = '<apiKey>'

response = http.request(request)
puts response.read_body
```

```java
import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.Unirest;

HttpResponse<String> response = Unirest.get("http://localhost:10004/v1/report-generate-requests/:resourceId")
  .header("X-API-KEY", "<apiKey>")
  .asString();
```

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

$client = new \GuzzleHttp\Client();

$response = $client->request('GET', 'http://localhost:10004/v1/report-generate-requests/:resourceId', [
  'headers' => [
    'X-API-KEY' => '<apiKey>',
  ],
]);

echo $response->getBody();
```

```csharp
using RestSharp;

var client = new RestClient("http://localhost:10004/v1/report-generate-requests/:resourceId");
var request = new RestRequest(Method.GET);
request.AddHeader("X-API-KEY", "<apiKey>");
IRestResponse response = client.Execute(request);
```

```swift
import Foundation

let headers = ["X-API-KEY": "<apiKey>"]

let request = NSMutableURLRequest(url: NSURL(string: "http://localhost:10004/v1/report-generate-requests/:resourceId")! as URL,
                                        cachePolicy: .useProtocolCachePolicy,
                                    timeoutInterval: 10.0)
request.httpMethod = "GET"
request.allHTTPHeaderFields = headers

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 (200)

```json
{
  "object_type": "string",
  "id": "string",
  "customer_id": "string",
  "invoice_id": "string",
  "generate_at": "2024-01-15T09:30:00Z",
  "report_code": "INVOICE",
  "parameter_values": [
    {
      "name": "report_date",
      "value": "string"
    }
  ],
  "status": "string",
  "report_subscription_id": "string",
  "report_configuration_id": "string",
  "run_type": "string",
  "export_location": {
    "integration_id": "string",
    "variant": "BIGQUERY",
    "stream_name": "string",
    "bigquery": {
      "dataset_id": "string"
    },
    "s3": {
      "bucket_path": "string",
      "path_format": "string",
      "format_type": "CSV"
    },
    "gcs": {
      "bucket_path": "string",
      "path_format": "string",
      "format_type": "CSV"
    }
  }
}
```

Fetch the finished report from `GET /v{version}/report-generate-requests/{resourceId}/report`. Automating this call as part of month-end close gives you the same schedule the Desk download produces, without anyone exporting a file by hand.

### Is there a subledger?

Solvimon does not expose a revenue subledger as a separate object with its own journal entries. The recognition report is the subledger: it is calculated per invoice line and per month, it traces back to an immutable finalised invoice, and its closing deferred balance is what your deferred revenue account should show. The journals themselves are posted in your ERP, either automatically from the service periods Solvimon sends or manually from this report, per the capability table above.

For prepaid credits, the deferred balance sits on the wallet grant rather than on an invoice line, and unconsumed credits become breakage at expiry. That side of the schedule is assembled from the wallet data; see [Credit revenue & breakage](/platform-guides/wallets-credits/credit-revenue-and-breakage).

### Analytics and MCP

Recognition data is also available in the analytics datasets exposed through the API and the [Solvimon MCP server](/integrations/ai-assistants/claude), so you can ask for recognised and deferred revenue per month and per customer without exporting a file.

---