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

# Invoice operations

This page covers the API operations for advancing a draft invoice to final, voiding an invoice before it is finalized, and controlling how tax and sub-lines render on the invoice PDF.

---

## Advancing a draft invoice to final

`Draft` invoices move to `Final` automatically once the 8-hour grace period ends, as described in [Invoice lifecycle](/platform-guides/invoicing/invoices/invoice-lifecycle). To advance an invoice immediately, once you've reviewed it and are ready to trigger payment collection, set `status` to `FINAL` with [PATCH /v1/invoices/\{id}](https://docs.solvimon.com/api-docs/transaction-api/invoices/patch-invoices-by-resource-id):

### Request

PATCH [https://test.api.solvimon.com/v\{version}/invoices/\{resourceId}](https://test.api.solvimon.com/v\{version}/invoices/\{resourceId})

**`Finalise a draft invoice`**

```curl Finalise a draft invoice
curl -X PATCH https://test.api.solvimon.com/v1/invoices/invo_JwDeeN0vxxHykcCOpL1d \
     -H "X-API-KEY: <apiKey>" \
     -H "Content-Type: application/json" \
     -d '{
  "status": "FINAL"
}'
```

**`Finalise a draft invoice`**

```python Finalise a draft invoice
import requests

url = "https://test.api.solvimon.com/v1/invoices/invo_JwDeeN0vxxHykcCOpL1d"

payload = { "status": "FINAL" }
headers = {
    "X-API-KEY": "<apiKey>",
    "Content-Type": "application/json"
}

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

print(response.json())
```

**`Finalise a draft invoice`**

```javascript Finalise a draft invoice
const url = 'https://test.api.solvimon.com/v1/invoices/invo_JwDeeN0vxxHykcCOpL1d';
const options = {
  method: 'PATCH',
  headers: {'X-API-KEY': '<apiKey>', 'Content-Type': 'application/json'},
  body: '{"status":"FINAL"}'
};

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

**`Finalise a draft invoice`**

```go Finalise a draft invoice
package main

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

func main() {

	url := "https://test.api.solvimon.com/v1/invoices/invo_JwDeeN0vxxHykcCOpL1d"

	payload := strings.NewReader("{\n  \"status\": \"FINAL\"\n}")

	req, _ := http.NewRequest("PATCH", 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))

}
```

**`Finalise a draft invoice`**

```ruby Finalise a draft invoice
require 'uri'
require 'net/http'

url = URI("https://test.api.solvimon.com/v1/invoices/invo_JwDeeN0vxxHykcCOpL1d")

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

request = Net::HTTP::Patch.new(url)
request["X-API-KEY"] = '<apiKey>'
request["Content-Type"] = 'application/json'
request.body = "{\n  \"status\": \"FINAL\"\n}"

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

**`Finalise a draft invoice`**

```java Finalise a draft invoice
import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.Unirest;

HttpResponse<String> response = Unirest.patch("https://test.api.solvimon.com/v1/invoices/invo_JwDeeN0vxxHykcCOpL1d")
  .header("X-API-KEY", "<apiKey>")
  .header("Content-Type", "application/json")
  .body("{\n  \"status\": \"FINAL\"\n}")
  .asString();
```

**`Finalise a draft invoice`**

```php Finalise a draft invoice
<?php
require_once('vendor/autoload.php');

$client = new \GuzzleHttp\Client();

$response = $client->request('PATCH', 'https://test.api.solvimon.com/v1/invoices/invo_JwDeeN0vxxHykcCOpL1d', [
  'body' => '{
  "status": "FINAL"
}',
  'headers' => [
    'Content-Type' => 'application/json',
    'X-API-KEY' => '<apiKey>',
  ],
]);

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

**`Finalise a draft invoice`**

```csharp Finalise a draft invoice
using RestSharp;

var client = new RestClient("https://test.api.solvimon.com/v1/invoices/invo_JwDeeN0vxxHykcCOpL1d");
var request = new RestRequest(Method.PATCH);
request.AddHeader("X-API-KEY", "<apiKey>");
request.AddHeader("Content-Type", "application/json");
request.AddParameter("application/json", "{\n  \"status\": \"FINAL\"\n}", ParameterType.RequestBody);
IRestResponse response = client.Execute(request);
```

**`Finalise a draft invoice`**

```swift Finalise a draft invoice
import Foundation

let headers = [
  "X-API-KEY": "<apiKey>",
  "Content-Type": "application/json"
]
let parameters = ["status": "FINAL"] as [String : Any]

let postData = JSONSerialization.data(withJSONObject: parameters, options: [])

let request = NSMutableURLRequest(url: NSURL(string: "https://test.api.solvimon.com/v1/invoices/invo_JwDeeN0vxxHykcCOpL1d")! as URL,
                                        cachePolicy: .useProtocolCachePolicy,
                                    timeoutInterval: 10.0)
request.httpMethod = "PATCH"
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 (200)

```json
{
  "object_type": "INVOICE",
  "id": "invo_JwDeeN0vxxHykcCOpL1d",
  "invoice_number": "INV-2026-10-000014",
  "purchase_order_number": "NWR-PO-88123",
  "customer_id": "cust_UwDeeN0vxxHxMTCJeF1K",
  "billing_entity_id": "bile_OwDeeN0vxxHxNHCWNp1c",
  "status": "FINAL",
  "on_hold": false,
  "type": "ONE_OFF",
  "created_at": "2026-10-09T16:22:05Z",
  "updated_at": "2026-10-09T16:40:12Z",
  "invoice_date": "2026-10-09T07:00:00Z",
  "due_date": "2026-11-08T00:00:00Z",
  "billing_currency": "USD",
  "invoice_amount_including_tax": {
    "quantity": "7500.00",
    "currency": "USD"
  },
  "open_invoice_amount": {
    "quantity": "7500.00",
    "currency": "USD"
  },
  "paid_invoice_amount": {
    "quantity": "0.00",
    "currency": "USD"
  },
  "updated_to_final_at": "2026-10-09T16:40:12Z",
  "payment_status": "UNPAID",
  "paid": false
}
```

> **Note**
>
> An invoice with `on_hold: true` won't advance to `Final` automatically or via this call until the hold is released. Set `on_hold` to `false` and `status` to `FINAL` in the same request to release the hold and finalize in one step.

Once `Final`, the invoice receives a permanent invoice number, becomes immutable, and payment collection is triggered. Corrections must go through a [credit note](/platform-guides/invoicing/invoice-corrections).

## Voiding an invoice

Voiding removes an invoice from revenue and accounts receivable records. Use it for invoices created in error. Voided invoices are retained for audit purposes but excluded from financial reporting.

> **Warning**
>
> Voiding is only possible for `Open` or `Draft` invoices. Correct a `Final` invoice with a [credit note](/platform-guides/invoicing/invoice-corrections) instead.

Set `status` to `VOID` with the same [PATCH /v1/invoices/\{id}](https://docs.solvimon.com/api-docs/transaction-api/invoices/patch-invoices-by-resource-id) endpoint:

### Request

PATCH [https://test.api.solvimon.com/v\{version}/invoices/\{resourceId}](https://test.api.solvimon.com/v\{version}/invoices/\{resourceId})

**`Void a draft invoice`**

```curl Void a draft invoice
curl -X PATCH https://test.api.solvimon.com/v1/invoices/invo_JwDeeN0vxxHykcCOpL1d \
     -H "X-API-KEY: <apiKey>" \
     -H "Content-Type: application/json" \
     -d '{
  "status": "VOID"
}'
```

**`Void a draft invoice`**

```python Void a draft invoice
import requests

url = "https://test.api.solvimon.com/v1/invoices/invo_JwDeeN0vxxHykcCOpL1d"

payload = { "status": "VOID" }
headers = {
    "X-API-KEY": "<apiKey>",
    "Content-Type": "application/json"
}

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

print(response.json())
```

**`Void a draft invoice`**

```javascript Void a draft invoice
const url = 'https://test.api.solvimon.com/v1/invoices/invo_JwDeeN0vxxHykcCOpL1d';
const options = {
  method: 'PATCH',
  headers: {'X-API-KEY': '<apiKey>', 'Content-Type': 'application/json'},
  body: '{"status":"VOID"}'
};

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

**`Void a draft invoice`**

```go Void a draft invoice
package main

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

func main() {

	url := "https://test.api.solvimon.com/v1/invoices/invo_JwDeeN0vxxHykcCOpL1d"

	payload := strings.NewReader("{\n  \"status\": \"VOID\"\n}")

	req, _ := http.NewRequest("PATCH", 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))

}
```

**`Void a draft invoice`**

```ruby Void a draft invoice
require 'uri'
require 'net/http'

url = URI("https://test.api.solvimon.com/v1/invoices/invo_JwDeeN0vxxHykcCOpL1d")

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

request = Net::HTTP::Patch.new(url)
request["X-API-KEY"] = '<apiKey>'
request["Content-Type"] = 'application/json'
request.body = "{\n  \"status\": \"VOID\"\n}"

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

**`Void a draft invoice`**

```java Void a draft invoice
import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.Unirest;

HttpResponse<String> response = Unirest.patch("https://test.api.solvimon.com/v1/invoices/invo_JwDeeN0vxxHykcCOpL1d")
  .header("X-API-KEY", "<apiKey>")
  .header("Content-Type", "application/json")
  .body("{\n  \"status\": \"VOID\"\n}")
  .asString();
```

**`Void a draft invoice`**

```php Void a draft invoice
<?php
require_once('vendor/autoload.php');

$client = new \GuzzleHttp\Client();

$response = $client->request('PATCH', 'https://test.api.solvimon.com/v1/invoices/invo_JwDeeN0vxxHykcCOpL1d', [
  'body' => '{
  "status": "VOID"
}',
  'headers' => [
    'Content-Type' => 'application/json',
    'X-API-KEY' => '<apiKey>',
  ],
]);

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

**`Void a draft invoice`**

```csharp Void a draft invoice
using RestSharp;

var client = new RestClient("https://test.api.solvimon.com/v1/invoices/invo_JwDeeN0vxxHykcCOpL1d");
var request = new RestRequest(Method.PATCH);
request.AddHeader("X-API-KEY", "<apiKey>");
request.AddHeader("Content-Type", "application/json");
request.AddParameter("application/json", "{\n  \"status\": \"VOID\"\n}", ParameterType.RequestBody);
IRestResponse response = client.Execute(request);
```

**`Void a draft invoice`**

```swift Void a draft invoice
import Foundation

let headers = [
  "X-API-KEY": "<apiKey>",
  "Content-Type": "application/json"
]
let parameters = ["status": "VOID"] as [String : Any]

let postData = JSONSerialization.data(withJSONObject: parameters, options: [])

let request = NSMutableURLRequest(url: NSURL(string: "https://test.api.solvimon.com/v1/invoices/invo_JwDeeN0vxxHykcCOpL1d")! as URL,
                                        cachePolicy: .useProtocolCachePolicy,
                                    timeoutInterval: 10.0)
request.httpMethod = "PATCH"
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()
```

Once voided, the status is permanent and cannot be changed.

> **Note**
>
> To void every `Draft` and `Open` invoice for a subscription at once, void the subscription itself with [POST /v1/pricing-plan-subscriptions/\{id}/void](https://docs.solvimon.com/api-docs/configuration-api/pricing-plan-subscriptions/post-pricing-plan-subscriptions-by-resource-id-void).

### Void vs. cancel

|                    | Void                            | Cancel (subscription)                    |
| ------------------ | ------------------------------- | ---------------------------------------- |
| Use when           | Invoice was created in error    | The contract is legitimately ending      |
| Effect on invoices | Sets `status` to `VOID`         | Leaves already-finalized invoices intact |
| Applies to         | `Open` or `Draft` invoices only | Ends future billing only                 |
| Reversible         | No                              | Depends on the cancellation type         |

## Configuring tax and sub-line display

Two settings control how tax and sub-lines render on the invoice PDF. Both are set on the subscription with [PATCH /v1/pricing-plan-subscriptions/\{id}](https://docs.solvimon.com/api-docs/configuration-api/pricing-plan-subscriptions/patch-pricing-plan-subscriptions-by-resource-id) and are copied onto each invoice at creation time, so already-issued documents keep rendering as originally generated.

### Show or hide the tax breakdown per line item

`show_tax_per_line_item` controls whether tax is shown per invoice line or only summarized at the invoice total. Tax is always calculated per line item; this only affects what's displayed.

* `true` (default): each line shows its tax rate and a per-subtotal "incl. tax" label.
* `false`: the tax rate column and per-line labels are removed; tax appears only in the invoice total, summarized per tax rate. Useful for self-billing setups.

### Request

PATCH [https://test.api.solvimon.com/v\{version}/pricing-plan-subscriptions/\{resourceId}](https://test.api.solvimon.com/v\{version}/pricing-plan-subscriptions/\{resourceId})

**`PricingPlanSubscriptions_patchPricingPlanSubscriptionsByResourceId_example`**

```curl PricingPlanSubscriptions_patchPricingPlanSubscriptionsByResourceId_example
curl -X PATCH https://test.api.solvimon.com/v1/pricing-plan-subscriptions/ \
     -H "X-API-KEY: <apiKey>" \
     -H "Content-Type: application/json" \
     -d '{
  "purchase_order_number": "PO-2027-0031",
  "due_date_configuration": {
    "type": "PERIOD_AFTER_INVOICE_DATE",
    "period": {
      "type": "DAY",
      "value": 30
    }
  }
}'
```

**`PricingPlanSubscriptions_patchPricingPlanSubscriptionsByResourceId_example`**

```python PricingPlanSubscriptions_patchPricingPlanSubscriptionsByResourceId_example
import requests

url = "https://test.api.solvimon.com/v1/pricing-plan-subscriptions/:resourceId"

payload = {
    "purchase_order_number": "PO-2027-0031",
    "due_date_configuration": {
        "type": "PERIOD_AFTER_INVOICE_DATE",
        "period": {
            "type": "DAY",
            "value": 30
        }
    }
}
headers = {
    "X-API-KEY": "<apiKey>",
    "Content-Type": "application/json"
}

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

print(response.json())
```

**`PricingPlanSubscriptions_patchPricingPlanSubscriptionsByResourceId_example`**

```javascript PricingPlanSubscriptions_patchPricingPlanSubscriptionsByResourceId_example
const url = 'https://test.api.solvimon.com/v1/pricing-plan-subscriptions/:resourceId';
const options = {
  method: 'PATCH',
  headers: {'X-API-KEY': '<apiKey>', 'Content-Type': 'application/json'},
  body: '{"purchase_order_number":"PO-2027-0031","due_date_configuration":{"type":"PERIOD_AFTER_INVOICE_DATE","period":{"type":"DAY","value":30}}}'
};

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

**`PricingPlanSubscriptions_patchPricingPlanSubscriptionsByResourceId_example`**

```go PricingPlanSubscriptions_patchPricingPlanSubscriptionsByResourceId_example
package main

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

func main() {

	url := "https://test.api.solvimon.com/v1/pricing-plan-subscriptions/:resourceId"

	payload := strings.NewReader("{\n  \"purchase_order_number\": \"PO-2027-0031\",\n  \"due_date_configuration\": {\n    \"type\": \"PERIOD_AFTER_INVOICE_DATE\",\n    \"period\": {\n      \"type\": \"DAY\",\n      \"value\": 30\n    }\n  }\n}")

	req, _ := http.NewRequest("PATCH", 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))

}
```

**`PricingPlanSubscriptions_patchPricingPlanSubscriptionsByResourceId_example`**

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

url = URI("https://test.api.solvimon.com/v1/pricing-plan-subscriptions/:resourceId")

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

request = Net::HTTP::Patch.new(url)
request["X-API-KEY"] = '<apiKey>'
request["Content-Type"] = 'application/json'
request.body = "{\n  \"purchase_order_number\": \"PO-2027-0031\",\n  \"due_date_configuration\": {\n    \"type\": \"PERIOD_AFTER_INVOICE_DATE\",\n    \"period\": {\n      \"type\": \"DAY\",\n      \"value\": 30\n    }\n  }\n}"

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

**`PricingPlanSubscriptions_patchPricingPlanSubscriptionsByResourceId_example`**

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

HttpResponse<String> response = Unirest.patch("https://test.api.solvimon.com/v1/pricing-plan-subscriptions/:resourceId")
  .header("X-API-KEY", "<apiKey>")
  .header("Content-Type", "application/json")
  .body("{\n  \"purchase_order_number\": \"PO-2027-0031\",\n  \"due_date_configuration\": {\n    \"type\": \"PERIOD_AFTER_INVOICE_DATE\",\n    \"period\": {\n      \"type\": \"DAY\",\n      \"value\": 30\n    }\n  }\n}")
  .asString();
```

**`PricingPlanSubscriptions_patchPricingPlanSubscriptionsByResourceId_example`**

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

$client = new \GuzzleHttp\Client();

$response = $client->request('PATCH', 'https://test.api.solvimon.com/v1/pricing-plan-subscriptions/:resourceId', [
  'body' => '{
  "purchase_order_number": "PO-2027-0031",
  "due_date_configuration": {
    "type": "PERIOD_AFTER_INVOICE_DATE",
    "period": {
      "type": "DAY",
      "value": 30
    }
  }
}',
  'headers' => [
    'Content-Type' => 'application/json',
    'X-API-KEY' => '<apiKey>',
  ],
]);

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

**`PricingPlanSubscriptions_patchPricingPlanSubscriptionsByResourceId_example`**

```csharp PricingPlanSubscriptions_patchPricingPlanSubscriptionsByResourceId_example
using RestSharp;

var client = new RestClient("https://test.api.solvimon.com/v1/pricing-plan-subscriptions/:resourceId");
var request = new RestRequest(Method.PATCH);
request.AddHeader("X-API-KEY", "<apiKey>");
request.AddHeader("Content-Type", "application/json");
request.AddParameter("application/json", "{\n  \"purchase_order_number\": \"PO-2027-0031\",\n  \"due_date_configuration\": {\n    \"type\": \"PERIOD_AFTER_INVOICE_DATE\",\n    \"period\": {\n      \"type\": \"DAY\",\n      \"value\": 30\n    }\n  }\n}", ParameterType.RequestBody);
IRestResponse response = client.Execute(request);
```

**`PricingPlanSubscriptions_patchPricingPlanSubscriptionsByResourceId_example`**

```swift PricingPlanSubscriptions_patchPricingPlanSubscriptionsByResourceId_example
import Foundation

let headers = [
  "X-API-KEY": "<apiKey>",
  "Content-Type": "application/json"
]
let parameters = [
  "purchase_order_number": "PO-2027-0031",
  "due_date_configuration": [
    "type": "PERIOD_AFTER_INVOICE_DATE",
    "period": [
      "type": "DAY",
      "value": 30
    ]
  ]
] as [String : Any]

let postData = JSONSerialization.data(withJSONObject: parameters, options: [])

let request = NSMutableURLRequest(url: NSURL(string: "https://test.api.solvimon.com/v1/pricing-plan-subscriptions/:resourceId")! as URL,
                                        cachePolicy: .useProtocolCachePolicy,
                                    timeoutInterval: 10.0)
request.httpMethod = "PATCH"
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()
```

### Show sub-lines per processing-only customer

In parent-child billing hierarchies, `display_invoice_sub_lines_per_processing_only_customer` controls whether the invoice breaks out a separate sub-line for each processing-only child customer, instead of showing a single combined line for the parent.

### Request

PATCH [https://test.api.solvimon.com/v\{version}/pricing-plan-subscriptions/\{resourceId}](https://test.api.solvimon.com/v\{version}/pricing-plan-subscriptions/\{resourceId})

**`PricingPlanSubscriptions_patchPricingPlanSubscriptionsByResourceId_example`**

```curl PricingPlanSubscriptions_patchPricingPlanSubscriptionsByResourceId_example
curl -X PATCH https://test.api.solvimon.com/v1/pricing-plan-subscriptions/ \
     -H "X-API-KEY: <apiKey>" \
     -H "Content-Type: application/json" \
     -d '{
  "purchase_order_number": "PO-2027-0031",
  "due_date_configuration": {
    "type": "PERIOD_AFTER_INVOICE_DATE",
    "period": {
      "type": "DAY",
      "value": 30
    }
  }
}'
```

**`PricingPlanSubscriptions_patchPricingPlanSubscriptionsByResourceId_example`**

```python PricingPlanSubscriptions_patchPricingPlanSubscriptionsByResourceId_example
import requests

url = "https://test.api.solvimon.com/v1/pricing-plan-subscriptions/:resourceId"

payload = {
    "purchase_order_number": "PO-2027-0031",
    "due_date_configuration": {
        "type": "PERIOD_AFTER_INVOICE_DATE",
        "period": {
            "type": "DAY",
            "value": 30
        }
    }
}
headers = {
    "X-API-KEY": "<apiKey>",
    "Content-Type": "application/json"
}

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

print(response.json())
```

**`PricingPlanSubscriptions_patchPricingPlanSubscriptionsByResourceId_example`**

```javascript PricingPlanSubscriptions_patchPricingPlanSubscriptionsByResourceId_example
const url = 'https://test.api.solvimon.com/v1/pricing-plan-subscriptions/:resourceId';
const options = {
  method: 'PATCH',
  headers: {'X-API-KEY': '<apiKey>', 'Content-Type': 'application/json'},
  body: '{"purchase_order_number":"PO-2027-0031","due_date_configuration":{"type":"PERIOD_AFTER_INVOICE_DATE","period":{"type":"DAY","value":30}}}'
};

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

**`PricingPlanSubscriptions_patchPricingPlanSubscriptionsByResourceId_example`**

```go PricingPlanSubscriptions_patchPricingPlanSubscriptionsByResourceId_example
package main

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

func main() {

	url := "https://test.api.solvimon.com/v1/pricing-plan-subscriptions/:resourceId"

	payload := strings.NewReader("{\n  \"purchase_order_number\": \"PO-2027-0031\",\n  \"due_date_configuration\": {\n    \"type\": \"PERIOD_AFTER_INVOICE_DATE\",\n    \"period\": {\n      \"type\": \"DAY\",\n      \"value\": 30\n    }\n  }\n}")

	req, _ := http.NewRequest("PATCH", 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))

}
```

**`PricingPlanSubscriptions_patchPricingPlanSubscriptionsByResourceId_example`**

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

url = URI("https://test.api.solvimon.com/v1/pricing-plan-subscriptions/:resourceId")

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

request = Net::HTTP::Patch.new(url)
request["X-API-KEY"] = '<apiKey>'
request["Content-Type"] = 'application/json'
request.body = "{\n  \"purchase_order_number\": \"PO-2027-0031\",\n  \"due_date_configuration\": {\n    \"type\": \"PERIOD_AFTER_INVOICE_DATE\",\n    \"period\": {\n      \"type\": \"DAY\",\n      \"value\": 30\n    }\n  }\n}"

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

**`PricingPlanSubscriptions_patchPricingPlanSubscriptionsByResourceId_example`**

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

HttpResponse<String> response = Unirest.patch("https://test.api.solvimon.com/v1/pricing-plan-subscriptions/:resourceId")
  .header("X-API-KEY", "<apiKey>")
  .header("Content-Type", "application/json")
  .body("{\n  \"purchase_order_number\": \"PO-2027-0031\",\n  \"due_date_configuration\": {\n    \"type\": \"PERIOD_AFTER_INVOICE_DATE\",\n    \"period\": {\n      \"type\": \"DAY\",\n      \"value\": 30\n    }\n  }\n}")
  .asString();
```

**`PricingPlanSubscriptions_patchPricingPlanSubscriptionsByResourceId_example`**

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

$client = new \GuzzleHttp\Client();

$response = $client->request('PATCH', 'https://test.api.solvimon.com/v1/pricing-plan-subscriptions/:resourceId', [
  'body' => '{
  "purchase_order_number": "PO-2027-0031",
  "due_date_configuration": {
    "type": "PERIOD_AFTER_INVOICE_DATE",
    "period": {
      "type": "DAY",
      "value": 30
    }
  }
}',
  'headers' => [
    'Content-Type' => 'application/json',
    'X-API-KEY' => '<apiKey>',
  ],
]);

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

**`PricingPlanSubscriptions_patchPricingPlanSubscriptionsByResourceId_example`**

```csharp PricingPlanSubscriptions_patchPricingPlanSubscriptionsByResourceId_example
using RestSharp;

var client = new RestClient("https://test.api.solvimon.com/v1/pricing-plan-subscriptions/:resourceId");
var request = new RestRequest(Method.PATCH);
request.AddHeader("X-API-KEY", "<apiKey>");
request.AddHeader("Content-Type", "application/json");
request.AddParameter("application/json", "{\n  \"purchase_order_number\": \"PO-2027-0031\",\n  \"due_date_configuration\": {\n    \"type\": \"PERIOD_AFTER_INVOICE_DATE\",\n    \"period\": {\n      \"type\": \"DAY\",\n      \"value\": 30\n    }\n  }\n}", ParameterType.RequestBody);
IRestResponse response = client.Execute(request);
```

**`PricingPlanSubscriptions_patchPricingPlanSubscriptionsByResourceId_example`**

```swift PricingPlanSubscriptions_patchPricingPlanSubscriptionsByResourceId_example
import Foundation

let headers = [
  "X-API-KEY": "<apiKey>",
  "Content-Type": "application/json"
]
let parameters = [
  "purchase_order_number": "PO-2027-0031",
  "due_date_configuration": [
    "type": "PERIOD_AFTER_INVOICE_DATE",
    "period": [
      "type": "DAY",
      "value": 30
    ]
  ]
] as [String : Any]

let postData = JSONSerialization.data(withJSONObject: parameters, options: [])

let request = NSMutableURLRequest(url: NSURL(string: "https://test.api.solvimon.com/v1/pricing-plan-subscriptions/:resourceId")! as URL,
                                        cachePolicy: .useProtocolCachePolicy,
                                    timeoutInterval: 10.0)
request.httpMethod = "PATCH"
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()
```

Both settings are also available in Desk under the subscription's details panel.

> **Note**
>
> These settings apply to invoices created after the change. Already-finalized invoices retain the values in effect when they were created.

## Downloading the invoice PDF

Download the invoice as a PDF with [GET /v1/invoices/\{id}/pdf](https://docs.solvimon.com/api-docs/transaction-api/invoices/get-invoices-by-resource-id-pdf):

### Request

GET [https://test.api.solvimon.com/v\{version}/invoices/\{resourceId}/pdf](https://test.api.solvimon.com/v\{version}/invoices/\{resourceId}/pdf)

```curl
curl https://test.api.solvimon.com/v1/invoices//pdf \
     -H "X-API-KEY: <apiKey>"
```

```python
import requests

url = "https://test.api.solvimon.com/v1/invoices/:resourceId/pdf"

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

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

print(response.json())
```

```javascript
const url = 'https://test.api.solvimon.com/v1/invoices/:resourceId/pdf';
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 := "https://test.api.solvimon.com/v1/invoices/:resourceId/pdf"

	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("https://test.api.solvimon.com/v1/invoices/:resourceId/pdf")

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

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("https://test.api.solvimon.com/v1/invoices/:resourceId/pdf")
  .header("X-API-KEY", "<apiKey>")
  .asString();
```

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

$client = new \GuzzleHttp\Client();

$response = $client->request('GET', 'https://test.api.solvimon.com/v1/invoices/:resourceId/pdf', [
  'headers' => [
    'X-API-KEY' => '<apiKey>',
  ],
]);

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

```csharp
using RestSharp;

var client = new RestClient("https://test.api.solvimon.com/v1/invoices/:resourceId/pdf");
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: "https://test.api.solvimon.com/v1/invoices/:resourceId/pdf")! 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()
```

This works for `Final` invoices as well as `Draft` invoices, where it renders a preview.

> **Note**
>
> A new invoice PDF renderer is in preview: the same rendering service that already produces quote PDFs, sharing one templating and localisation stack across both, with translations for every language the customer portal supports. It is opt-in while it rolls out; contact your account manager to have it enabled for your platform.

---

See also: [Invoice lifecycle](/platform-guides/invoicing/invoices/invoice-lifecycle), [Correcting invoices](/platform-guides/invoicing/invoice-corrections), and [Customising invoices](/platform-guides/platform-configuration/customising-invoices).