> For clean Markdown of any page, append .md to the page URL. > For a complete documentation index, see https://docs.solvimon.com/platform-guides/invoicing/invoice-corrections/llms.txt. > For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.solvimon.com/_mcp/server. # Correcting invoices Correct an invoice after it was generated: negate wrongly ingested usage, adjust its lines, or issue a credit note once it's `FINAL`. --- ## Why this matters Invoices need corrections for predictable reasons: a billing mistake (wrong quantity, price, tax, or discount), a service issue such as downtime or an SLA breach, a partial cancellation or return, or a goodwill gesture where you reduce what the customer owes. Which correction method to use depends on the invoice's status and what you want the customer to see on the final document. ## Choosing a correction method | Method | Invoice status | What the customer sees | | ----------------------------------------- | ---------------- | --------------------------------------------------------------- | | [Adjustment events](#adjustment-events) | `DRAFT` / `OPEN` | Corrected usage totals; no extra invoice line. | | [Manual adjustments](#manual-adjustments) | `OPEN` | A separate invoice line, clearly marked as an adjustment. | | [Credit notes](#credit-notes) | `FINAL` | A separate credit note document linked to the original invoice. | ## Adjustment events The cleanest way to correct wrongfully ingested usage is to ingest negative events that negate the incorrect ones. This makes sure the total invoice quantity and events are correct, so the customer sees the right usage without an extra refund line. Create the correction event as a 'mirror' event with the same meter properties as the original, in case you have price rules that are triggered by the event. Ingest it through [the API](/platform-guides/meter-and-event-design/usage-events/event-ingestion-api), [manually](/platform-guides/meter-and-event-design/usage-events/manual), or with a [file upload](/platform-guides/meter-and-event-design/usage-events/file-uploads), just like your regular ingestion process. ![](/_fern-img/2bb2cbcf9b8af47264468ed46d5197c78b0f931aeaa1a80341aeafb0dd7d201c.webp) ## Manual adjustments When an invoice has status `OPEN`, you can correct mistakes or add extra charges by adjusting its lines directly. An adjustment has the type `charge` or `refund`, can have its currency set manually, and is shown in the product section as a separate invoice line, clearly marked as an adjustment. Adjustments cannot be made on `FINAL` invoices. Via the API, add a line with [POST /v1/invoices/\{id}/add-line](https://docs.solvimon.com/api-docs/transaction-api/invoices/post-invoices-by-resource-id-add-line) and remove one with [POST /v1/invoices/\{id}/delete-line](https://docs.solvimon.com/api-docs/transaction-api/invoices/post-invoices-by-resource-id-delete-line): ### Request POST [https://test.api.solvimon.com/v\{version}/invoices/\{resourceId}/add-line](https://test.api.solvimon.com/v\{version}/invoices/\{resourceId}/add-line) **`Invoices_postInvoicesByResourceIdAddLine_example`** ```curl Invoices_postInvoicesByResourceIdAddLine_example curl -X POST https://test.api.solvimon.com/v1/invoices//add-line \ -H "X-API-KEY: " \ -H "Content-Type: application/json" \ -d '{ "pricing_type": "FIXED", "product_item_id": "proi_ZwDeeN0vxxHxUQCHhy1J", "pricing_name": "Solutions engineering onboarding – Oct 2026", "start_at": "2026-10-01T00:00:00-07:00", "end_at": "2026-11-01T00:00:00-07:00", "pricing_band": { "fixed_amount": { "quantity": "7500.00", "currency": "USD" } } }' ``` **`Invoices_postInvoicesByResourceIdAddLine_example`** ```python Invoices_postInvoicesByResourceIdAddLine_example import requests url = "https://test.api.solvimon.com/v1/invoices/:resourceId/add-line" payload = { "pricing_type": "FIXED", "product_item_id": "proi_ZwDeeN0vxxHxUQCHhy1J", "pricing_name": "Solutions engineering onboarding – Oct 2026", "start_at": "2026-10-01T00:00:00-07:00", "end_at": "2026-11-01T00:00:00-07:00", "pricing_band": { "fixed_amount": { "quantity": "7500.00", "currency": "USD" } } } headers = { "X-API-KEY": "", "Content-Type": "application/json" } response = requests.post(url, json=payload, headers=headers) print(response.json()) ``` **`Invoices_postInvoicesByResourceIdAddLine_example`** ```javascript Invoices_postInvoicesByResourceIdAddLine_example const url = 'https://test.api.solvimon.com/v1/invoices/:resourceId/add-line'; const options = { method: 'POST', headers: {'X-API-KEY': '', 'Content-Type': 'application/json'}, body: '{"pricing_type":"FIXED","product_item_id":"proi_ZwDeeN0vxxHxUQCHhy1J","pricing_name":"Solutions engineering onboarding – Oct 2026","start_at":"2026-10-01T00:00:00-07:00","end_at":"2026-11-01T00:00:00-07:00","pricing_band":{"fixed_amount":{"quantity":"7500.00","currency":"USD"}}}' }; try { const response = await fetch(url, options); const data = await response.json(); console.log(data); } catch (error) { console.error(error); } ``` **`Invoices_postInvoicesByResourceIdAddLine_example`** ```go Invoices_postInvoicesByResourceIdAddLine_example package main import ( "fmt" "strings" "net/http" "io" ) func main() { url := "https://test.api.solvimon.com/v1/invoices/:resourceId/add-line" payload := strings.NewReader("{\n \"pricing_type\": \"FIXED\",\n \"product_item_id\": \"proi_ZwDeeN0vxxHxUQCHhy1J\",\n \"pricing_name\": \"Solutions engineering onboarding – Oct 2026\",\n \"start_at\": \"2026-10-01T00:00:00-07:00\",\n \"end_at\": \"2026-11-01T00:00:00-07:00\",\n \"pricing_band\": {\n \"fixed_amount\": {\n \"quantity\": \"7500.00\",\n \"currency\": \"USD\"\n }\n }\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)) } ``` **`Invoices_postInvoicesByResourceIdAddLine_example`** ```ruby Invoices_postInvoicesByResourceIdAddLine_example require 'uri' require 'net/http' url = URI("https://test.api.solvimon.com/v1/invoices/:resourceId/add-line") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Post.new(url) request["X-API-KEY"] = '' request["Content-Type"] = 'application/json' request.body = "{\n \"pricing_type\": \"FIXED\",\n \"product_item_id\": \"proi_ZwDeeN0vxxHxUQCHhy1J\",\n \"pricing_name\": \"Solutions engineering onboarding – Oct 2026\",\n \"start_at\": \"2026-10-01T00:00:00-07:00\",\n \"end_at\": \"2026-11-01T00:00:00-07:00\",\n \"pricing_band\": {\n \"fixed_amount\": {\n \"quantity\": \"7500.00\",\n \"currency\": \"USD\"\n }\n }\n}" response = http.request(request) puts response.read_body ``` **`Invoices_postInvoicesByResourceIdAddLine_example`** ```java Invoices_postInvoicesByResourceIdAddLine_example import com.mashape.unirest.http.HttpResponse; import com.mashape.unirest.http.Unirest; HttpResponse response = Unirest.post("https://test.api.solvimon.com/v1/invoices/:resourceId/add-line") .header("X-API-KEY", "") .header("Content-Type", "application/json") .body("{\n \"pricing_type\": \"FIXED\",\n \"product_item_id\": \"proi_ZwDeeN0vxxHxUQCHhy1J\",\n \"pricing_name\": \"Solutions engineering onboarding – Oct 2026\",\n \"start_at\": \"2026-10-01T00:00:00-07:00\",\n \"end_at\": \"2026-11-01T00:00:00-07:00\",\n \"pricing_band\": {\n \"fixed_amount\": {\n \"quantity\": \"7500.00\",\n \"currency\": \"USD\"\n }\n }\n}") .asString(); ``` **`Invoices_postInvoicesByResourceIdAddLine_example`** ```php Invoices_postInvoicesByResourceIdAddLine_example request('POST', 'https://test.api.solvimon.com/v1/invoices/:resourceId/add-line', [ 'body' => '{ "pricing_type": "FIXED", "product_item_id": "proi_ZwDeeN0vxxHxUQCHhy1J", "pricing_name": "Solutions engineering onboarding – Oct 2026", "start_at": "2026-10-01T00:00:00-07:00", "end_at": "2026-11-01T00:00:00-07:00", "pricing_band": { "fixed_amount": { "quantity": "7500.00", "currency": "USD" } } }', 'headers' => [ 'Content-Type' => 'application/json', 'X-API-KEY' => '', ], ]); echo $response->getBody(); ``` **`Invoices_postInvoicesByResourceIdAddLine_example`** ```csharp Invoices_postInvoicesByResourceIdAddLine_example using RestSharp; var client = new RestClient("https://test.api.solvimon.com/v1/invoices/:resourceId/add-line"); var request = new RestRequest(Method.POST); request.AddHeader("X-API-KEY", ""); request.AddHeader("Content-Type", "application/json"); request.AddParameter("application/json", "{\n \"pricing_type\": \"FIXED\",\n \"product_item_id\": \"proi_ZwDeeN0vxxHxUQCHhy1J\",\n \"pricing_name\": \"Solutions engineering onboarding – Oct 2026\",\n \"start_at\": \"2026-10-01T00:00:00-07:00\",\n \"end_at\": \"2026-11-01T00:00:00-07:00\",\n \"pricing_band\": {\n \"fixed_amount\": {\n \"quantity\": \"7500.00\",\n \"currency\": \"USD\"\n }\n }\n}", ParameterType.RequestBody); IRestResponse response = client.Execute(request); ``` **`Invoices_postInvoicesByResourceIdAddLine_example`** ```swift Invoices_postInvoicesByResourceIdAddLine_example import Foundation let headers = [ "X-API-KEY": "", "Content-Type": "application/json" ] let parameters = [ "pricing_type": "FIXED", "product_item_id": "proi_ZwDeeN0vxxHxUQCHhy1J", "pricing_name": "Solutions engineering onboarding – Oct 2026", "start_at": "2026-10-01T00:00:00-07:00", "end_at": "2026-11-01T00:00:00-07:00", "pricing_band": ["fixed_amount": [ "quantity": "7500.00", "currency": "USD" ]] ] as [String : Any] let postData = JSONSerialization.data(withJSONObject: parameters, options: []) let request = NSMutableURLRequest(url: NSURL(string: "https://test.api.solvimon.com/v1/invoices/:resourceId/add-line")! 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() ``` In Desk, open the invoice and add the adjustment from the invoice lines section: ![](/_fern-img/2133d55d62f1bec578a28e3d7b1a5bf2b50fb18f39c0918cf78008db4931ae6a.webp) > **Tip** > > Adjustment events are created for every manual adjustment on an invoice, and reports are available so your team can analyse how often manual invoice corrections occur. ## Credit notes A credit note is an official accounting document that reduces the amount a customer owes on an invoice after that invoice has been finalized. It is the inverse of an invoice: instead of asking the customer to pay more, you formally acknowledge that they should pay less or receive money back. Once an invoice is `FINAL` it cannot be changed, so any correction happens through a credit note: a new document linked to the original invoice, crediting it in full or in part. See [Credit notes](/platform-guides/invoicing/invoice-corrections/credit-invoices) for creating them and controlling which customer details they carry. If the original invoice was paid through a PSP, crediting alone doesn't return any money. Trigger a [referenced refund](/platform-guides/invoicing/invoice-corrections/referenced-refunds-on-credited-invoices) on the finalized credit note to refund the original payment back to the customer's payment method. ## Refreshing invoice data A correction isn't always about amounts. If details like the customer's name or address, the billing entity, or custom field values changed after an invoice was generated, refresh the invoice to reflect the new values with [POST /v1/invoices/\{id}/refresh](https://docs.solvimon.com/api-docs/transaction-api/invoices/post-invoices-by-resource-id-refresh): ### Request POST [https://test.api.solvimon.com/v\{version}/invoices/\{resourceId}/refresh](https://test.api.solvimon.com/v\{version}/invoices/\{resourceId}/refresh) **`Invoices_postInvoicesByResourceIdRefresh_example`** ```curl Invoices_postInvoicesByResourceIdRefresh_example curl -X POST https://test.api.solvimon.com/v1/invoices//refresh \ -H "X-API-KEY: " \ -H "Content-Type: application/json" \ -d '{ "types": [ "CUSTOMER", "PO_NUMBER" ] }' ``` **`Invoices_postInvoicesByResourceIdRefresh_example`** ```python Invoices_postInvoicesByResourceIdRefresh_example import requests url = "https://test.api.solvimon.com/v1/invoices/:resourceId/refresh" payload = { "types": ["CUSTOMER", "PO_NUMBER"] } headers = { "X-API-KEY": "", "Content-Type": "application/json" } response = requests.post(url, json=payload, headers=headers) print(response.json()) ``` **`Invoices_postInvoicesByResourceIdRefresh_example`** ```javascript Invoices_postInvoicesByResourceIdRefresh_example const url = 'https://test.api.solvimon.com/v1/invoices/:resourceId/refresh'; const options = { method: 'POST', headers: {'X-API-KEY': '', 'Content-Type': 'application/json'}, body: '{"types":["CUSTOMER","PO_NUMBER"]}' }; try { const response = await fetch(url, options); const data = await response.json(); console.log(data); } catch (error) { console.error(error); } ``` **`Invoices_postInvoicesByResourceIdRefresh_example`** ```go Invoices_postInvoicesByResourceIdRefresh_example package main import ( "fmt" "strings" "net/http" "io" ) func main() { url := "https://test.api.solvimon.com/v1/invoices/:resourceId/refresh" payload := strings.NewReader("{\n \"types\": [\n \"CUSTOMER\",\n \"PO_NUMBER\"\n ]\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)) } ``` **`Invoices_postInvoicesByResourceIdRefresh_example`** ```ruby Invoices_postInvoicesByResourceIdRefresh_example require 'uri' require 'net/http' url = URI("https://test.api.solvimon.com/v1/invoices/:resourceId/refresh") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Post.new(url) request["X-API-KEY"] = '' request["Content-Type"] = 'application/json' request.body = "{\n \"types\": [\n \"CUSTOMER\",\n \"PO_NUMBER\"\n ]\n}" response = http.request(request) puts response.read_body ``` **`Invoices_postInvoicesByResourceIdRefresh_example`** ```java Invoices_postInvoicesByResourceIdRefresh_example import com.mashape.unirest.http.HttpResponse; import com.mashape.unirest.http.Unirest; HttpResponse response = Unirest.post("https://test.api.solvimon.com/v1/invoices/:resourceId/refresh") .header("X-API-KEY", "") .header("Content-Type", "application/json") .body("{\n \"types\": [\n \"CUSTOMER\",\n \"PO_NUMBER\"\n ]\n}") .asString(); ``` **`Invoices_postInvoicesByResourceIdRefresh_example`** ```php Invoices_postInvoicesByResourceIdRefresh_example request('POST', 'https://test.api.solvimon.com/v1/invoices/:resourceId/refresh', [ 'body' => '{ "types": [ "CUSTOMER", "PO_NUMBER" ] }', 'headers' => [ 'Content-Type' => 'application/json', 'X-API-KEY' => '', ], ]); echo $response->getBody(); ``` **`Invoices_postInvoicesByResourceIdRefresh_example`** ```csharp Invoices_postInvoicesByResourceIdRefresh_example using RestSharp; var client = new RestClient("https://test.api.solvimon.com/v1/invoices/:resourceId/refresh"); var request = new RestRequest(Method.POST); request.AddHeader("X-API-KEY", ""); request.AddHeader("Content-Type", "application/json"); request.AddParameter("application/json", "{\n \"types\": [\n \"CUSTOMER\",\n \"PO_NUMBER\"\n ]\n}", ParameterType.RequestBody); IRestResponse response = client.Execute(request); ``` **`Invoices_postInvoicesByResourceIdRefresh_example`** ```swift Invoices_postInvoicesByResourceIdRefresh_example import Foundation let headers = [ "X-API-KEY": "", "Content-Type": "application/json" ] let parameters = ["types": ["CUSTOMER", "PO_NUMBER"]] as [String : Any] let postData = JSONSerialization.data(withJSONObject: parameters, options: []) let request = NSMutableURLRequest(url: NSURL(string: "https://test.api.solvimon.com/v1/invoices/:resourceId/refresh")! 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() ``` In Desk, use the refresh action on the invoice page: ![](/_fern-img/3f57f48a2c77c8b04b370c10e3715579332ed60825ba84f2f86334d4fcf516d0.webp) --- See also: [Invoice lifecycle](/platform-guides/invoicing/invoices/invoice-lifecycle) and [Credit notes](/platform-guides/invoicing/invoice-corrections/credit-invoices). ## Docs - [Credit notes](https://docs.solvimon.com/platform-guides/invoicing/invoice-corrections/credit-invoices.md) - [Referenced refunds](https://docs.solvimon.com/platform-guides/invoicing/invoice-corrections/referenced-refunds-on-credited-invoices.md)