curl --request POST \
--url https://api.salesbricks.com/api/v2/invoices/{invoice_id}/finalize \
--header 'Content-Type: application/json' \
--header 'X-SALESBRICKS-KEY: <api-key>' \
--data '
{
"due_at": "2023-12-25"
}
'import requests
url = "https://api.salesbricks.com/api/v2/invoices/{invoice_id}/finalize"
payload = { "due_at": "2023-12-25" }
headers = {
"X-SALESBRICKS-KEY": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'X-SALESBRICKS-KEY': '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({due_at: '2023-12-25'})
};
fetch('https://api.salesbricks.com/api/v2/invoices/{invoice_id}/finalize', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.salesbricks.com/api/v2/invoices/{invoice_id}/finalize",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'due_at' => '2023-12-25'
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"X-SALESBRICKS-KEY: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.salesbricks.com/api/v2/invoices/{invoice_id}/finalize"
payload := strings.NewReader("{\n \"due_at\": \"2023-12-25\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("X-SALESBRICKS-KEY", "<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(string(body))
}HttpResponse<String> response = Unirest.post("https://api.salesbricks.com/api/v2/invoices/{invoice_id}/finalize")
.header("X-SALESBRICKS-KEY", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"due_at\": \"2023-12-25\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.salesbricks.com/api/v2/invoices/{invoice_id}/finalize")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["X-SALESBRICKS-KEY"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"due_at\": \"2023-12-25\"\n}"
response = http.request(request)
puts response.read_body{
"invoice_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"subscription_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"customer_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"billed_company_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"invoice_number": "<string>",
"due_at": "2023-11-07T05:31:56Z",
"bill_at": "2023-11-07T05:31:56Z",
"issued_at": "2023-11-07T05:31:56Z",
"status": "<string>",
"fully_paid_at": "2023-11-07T05:31:56Z",
"grand_total": 123,
"remaining_amount": 123,
"currency": "<string>",
"is_renewal_estimate": true,
"customer_name": "<string>",
"time_zone": "<string>",
"payments": [
{
"payment_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"invoice_number": "<string>",
"invoice_version_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"paid_amount": 123,
"paid_at": "2023-11-07T05:31:56Z",
"currency": "<string>",
"error": "<string>"
}
],
"attachments": [
"<unknown>"
],
"line_items": [
{
"brick_name": "<string>",
"brick_id": "<string>",
"quantity": 123,
"tax": 123,
"grand_total": 123,
"starts_at": "2023-11-07T05:31:56Z",
"ends_at": "2023-11-07T05:31:56Z"
}
],
"metadata": "<unknown>",
"purchase_order": {
"code": "<string>"
}
}{
"invoice_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"subscription_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"customer_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"billed_company_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"invoice_number": "<string>",
"due_at": "2023-11-07T05:31:56Z",
"bill_at": "2023-11-07T05:31:56Z",
"issued_at": "2023-11-07T05:31:56Z",
"status": "<string>",
"fully_paid_at": "2023-11-07T05:31:56Z",
"grand_total": 123,
"remaining_amount": 123,
"currency": "<string>",
"is_renewal_estimate": true,
"customer_name": "<string>",
"time_zone": "<string>",
"payments": [
{
"payment_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"invoice_number": "<string>",
"invoice_version_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"paid_amount": 123,
"paid_at": "2023-11-07T05:31:56Z",
"currency": "<string>",
"error": "<string>"
}
],
"attachments": [
"<unknown>"
],
"line_items": [
{
"brick_name": "<string>",
"brick_id": "<string>",
"quantity": 123,
"tax": 123,
"grand_total": 123,
"starts_at": "2023-11-07T05:31:56Z",
"ends_at": "2023-11-07T05:31:56Z"
}
],
"metadata": "<unknown>",
"purchase_order": {
"code": "<string>"
}
}{
"error": {
"code": "ERR_BAD_REQUEST",
"message": "Bad request — the input payload is malformed, missing required fields, or contains invalid data."
}
}{
"error": {
"code": "ERR_NOT_FOUND",
"message": "Not found — the resource you are looking for does not exist."
}
}Finalize an invoice
Issues a draft invoice. Final tax is committed, the date of issue and due date are stamped, the invoice leaves draft for its terminal status, and it is sent to the customer’s invoice recipients. Only drafts can be issued.
due_date_basis is optional — omit it and the invoice inherits the order’s default, or keeps a due date already set by editing it. Sending a basis re-derives the due date and replaces an edited one. Send CUSTOM with a due_at to name the due date outright; either one without the other is rejected.
Waiting for the document
By default the request is held until the invoice’s PDF has rendered, so a 200 means the invoice is issued and its document is ready to retrieve.
Pass async=true to queue the issue and get an answer immediately, with the draft as it stands. Poll the invoice to see it issued.
A 202 means the work is still in flight: with async=true the invoice has been accepted for issuing, and without it the invoice is issued but its PDF is still rendering. Neither is a failure — an invoice that could not be issued at all comes back 400.
curl --request POST \
--url https://api.salesbricks.com/api/v2/invoices/{invoice_id}/finalize \
--header 'Content-Type: application/json' \
--header 'X-SALESBRICKS-KEY: <api-key>' \
--data '
{
"due_at": "2023-12-25"
}
'import requests
url = "https://api.salesbricks.com/api/v2/invoices/{invoice_id}/finalize"
payload = { "due_at": "2023-12-25" }
headers = {
"X-SALESBRICKS-KEY": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'X-SALESBRICKS-KEY': '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({due_at: '2023-12-25'})
};
fetch('https://api.salesbricks.com/api/v2/invoices/{invoice_id}/finalize', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.salesbricks.com/api/v2/invoices/{invoice_id}/finalize",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'due_at' => '2023-12-25'
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"X-SALESBRICKS-KEY: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.salesbricks.com/api/v2/invoices/{invoice_id}/finalize"
payload := strings.NewReader("{\n \"due_at\": \"2023-12-25\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("X-SALESBRICKS-KEY", "<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(string(body))
}HttpResponse<String> response = Unirest.post("https://api.salesbricks.com/api/v2/invoices/{invoice_id}/finalize")
.header("X-SALESBRICKS-KEY", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"due_at\": \"2023-12-25\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.salesbricks.com/api/v2/invoices/{invoice_id}/finalize")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["X-SALESBRICKS-KEY"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"due_at\": \"2023-12-25\"\n}"
response = http.request(request)
puts response.read_body{
"invoice_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"subscription_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"customer_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"billed_company_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"invoice_number": "<string>",
"due_at": "2023-11-07T05:31:56Z",
"bill_at": "2023-11-07T05:31:56Z",
"issued_at": "2023-11-07T05:31:56Z",
"status": "<string>",
"fully_paid_at": "2023-11-07T05:31:56Z",
"grand_total": 123,
"remaining_amount": 123,
"currency": "<string>",
"is_renewal_estimate": true,
"customer_name": "<string>",
"time_zone": "<string>",
"payments": [
{
"payment_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"invoice_number": "<string>",
"invoice_version_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"paid_amount": 123,
"paid_at": "2023-11-07T05:31:56Z",
"currency": "<string>",
"error": "<string>"
}
],
"attachments": [
"<unknown>"
],
"line_items": [
{
"brick_name": "<string>",
"brick_id": "<string>",
"quantity": 123,
"tax": 123,
"grand_total": 123,
"starts_at": "2023-11-07T05:31:56Z",
"ends_at": "2023-11-07T05:31:56Z"
}
],
"metadata": "<unknown>",
"purchase_order": {
"code": "<string>"
}
}{
"invoice_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"subscription_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"customer_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"billed_company_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"invoice_number": "<string>",
"due_at": "2023-11-07T05:31:56Z",
"bill_at": "2023-11-07T05:31:56Z",
"issued_at": "2023-11-07T05:31:56Z",
"status": "<string>",
"fully_paid_at": "2023-11-07T05:31:56Z",
"grand_total": 123,
"remaining_amount": 123,
"currency": "<string>",
"is_renewal_estimate": true,
"customer_name": "<string>",
"time_zone": "<string>",
"payments": [
{
"payment_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"invoice_number": "<string>",
"invoice_version_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"paid_amount": 123,
"paid_at": "2023-11-07T05:31:56Z",
"currency": "<string>",
"error": "<string>"
}
],
"attachments": [
"<unknown>"
],
"line_items": [
{
"brick_name": "<string>",
"brick_id": "<string>",
"quantity": 123,
"tax": 123,
"grand_total": 123,
"starts_at": "2023-11-07T05:31:56Z",
"ends_at": "2023-11-07T05:31:56Z"
}
],
"metadata": "<unknown>",
"purchase_order": {
"code": "<string>"
}
}{
"error": {
"code": "ERR_BAD_REQUEST",
"message": "Bad request — the input payload is malformed, missing required fields, or contains invalid data."
}
}{
"error": {
"code": "ERR_NOT_FOUND",
"message": "Not found — the resource you are looking for does not exist."
}
}Authorizations
API key for authentication
Path Parameters
^([a-zA-Z\d\-]+)$Query Parameters
Set to true to queue the issue and answer immediately instead of waiting for the invoice's PDF.
Body
What the issued invoice's due date follows. Omit it to inherit the order's default — unless the invoice already carries a due date you set by editing it, which is kept. Sending a basis re-derives the due date and replaces an edited one. CUSTOM names the date outright and must be sent with due_at.
ISSUE_DATE- Issue dateSERVICE_PERIOD- Service periodCUSTOM- Custom
ISSUE_DATE, SERVICE_PERIOD, CUSTOM The due date to issue under. Only valid with a CUSTOM due_date_basis, and cannot be earlier than the date of issue.
Response
Unique identifier for the invoice. If the id is null, this is an estimate
ID of the subscription this invoice belongs to. Null for standalone (one-off) invoices.
ID of the end customer this invoice is for — the company that consumes the subscription. Never collect or charge payment methods against this id: on a partner-billed invoice the paying party is a different company, and billed_company_id is always the id to collect against.
ID of the company actually billed for this invoice — the party whose Stripe customer POST /invoices/{invoice_id}/pay charges. Equal to customer_id unless the invoice is partner-billed, in which case it is the partner's company. Collect and list payment methods against this id, never customer_id. Always present and never null, including on the renewal estimate returned by GET /subscriptions/{subscription_id}/invoices/next, which resolves the company its renewal would bill.
Short form identifier for the invoice. If the invoice_number is null, this is an estimate
The date on which this invoice is expected to be paid by.
The date on which this invoice will be issued and potentially charged.
The date on which this invoice was issued.
Current status of the invoice. One of:
MUTED— Invoice will not be sent. Muted invoices come from migration cut-overs or from muting invoices in the product settings.SCHEDULED— Scheduled to be issued on a future date.OUTSTANDING— Issued and awaiting payment.DUE— Payment is due.PAST_DUE— Payment is past its due date.PAID— Fully paid.PARTIALLY_PAID— Partially paid, with a remaining balance.ADJUSTED— Adjusted after issuance.CREDITED— Settled by applying credit.UNPAID— Unpaid.PAUSED— Collection is paused.VOIDED— Voided and no longer collectible.
The date on which this invoice was fully paid.
Total amount due for this invoice.
Invoices that have not been generated yet (e.g. SCHEDULED) report the total expected at the time they were created. That figure does NOT include usage metered since — a usage invoice whose meters have not been priced reports 0. Pass ?calculate_expected_usage=true to re-price against the order and include estimated usage instead; it is slower, so it is off by default on list endpoints.
Remaining amount for this invoice.
The currency in which the invoice is denominated (e.g., USD, EUR).
This is an estimate for a renewal that has not yet closed, but is expected to.
Name of the customer who will pay this invoice
Invoice timezone
All payments made against this invoice, newest first.
Show child attributes
Show child attributes
Current attachments for this invoice as a flat array. Each item includes 'target' field indicating invoice or subscription level. Sorted by unified order.
Line item breakdown for this invoice
Show child attributes
Show child attributes
Optional metadata stored against the invoice.
Purchase order shown on this invoice: the invoice's own purchase order when it has one, otherwise the subscription's. Matches the PO printed on the invoice PDF. Null when neither carries one.
Show child attributes
Show child attributes