Invoice lines
Lines on an invoice. Normally sent nested inside the invoice rather than created here.
The object#
| Field | Type | Description |
|---|---|---|
| idread-only | integer | NolaPro id. |
| invoiceid | integer | Invoiceid. Id only. |
| invoice | string(30) | The invoicenumber of the referenced invoices, instead of the id. Send this or invoiceid, not both unless they agree. |
| linenumber | integer | Position of this line on its document, starting at 1. |
| itemid | integer | Reference to items, by id. Write either this or item. |
| item | string(255) | The sku of the referenced items, instead of the id. Send this or itemid, not both unless they agree. |
| description | string(255) | Line description printed on the invoice. |
| qtyqty | string(6dp) | Quantity, 6 decimal places, as a string. Stored as decimal(6dp). |
| qtyunitnameid | integer | Reference to unitnames, by id. Write either this or qtyunitname. |
| qtyunitname | string(50) | The unitname of the referenced unitnames, instead of the id. Send this or qtyunitnameid, not both unless they agree. |
| glaccountid | integer | Reference to glaccounts, by id. Write either this or glaccount. |
| glaccount | string(20) | Code for the referenced glaccount, instead of the id. |
| taxflag | integer | Whether the first line tax applies. NolaPro carries up to three taxes per line. |
| priceachmoney | string(6dp) | Stored as decimal(19,6). |
| priceunitnameid | integer | Priceunitnameid. Id only. |
| priceunitname | string(50) | The unitname of the referenced unitnames, instead of the id. Send this or priceunitnameid, not both unless they agree. |
| qtyunitperpriceunitqty | string(6dp) | Quantity, 6 decimal places, as a string. Stored as decimal(6dp). |
| totalpricemoney | string(4dp) | Stored as decimal(19,4). |
| entrydate | string | When the record was created. |
| lastchangedateread-only | string | Last modification. Drives modifiedsince. |
| costeachmoney | string(6dp) | Stored as decimal(19,6). |
| costglaccountid | integer | Reference to glaccounts, by id. Write either this or costglaccount. |
| costglaccount | string(20) | The name of the referenced glaccounts, instead of the id. Send this or costglaccountid, not both unless they agree. |
| main_arinvoicedetailid | integer | Main arinvoicedetailid. Id only. |
| itemoptionid | integer | Itemoptionid. Id only. |
| itemoptiongroupid | integer | Itemoptiongroupid. Id only. |
| taxflag2 | integer | Whether the second line tax applies. |
| taxflag3 | integer | Whether the third line tax applies. |
| taxflagid | integer | Taxflagid. Id only. |
| taxflag2id | integer | Taxflag2id. Id only. |
| taxflag3id | integer | Taxflag3id. Id only. |
| orig_priceachmoney | string(5dp) | Stored as decimal(12,5). |
| discount_amountmoney | string(5dp) | Stored as decimal(12,5). |
| discount_percentnumber | string(5dp) | Numeric string, 5 decimal places. Not money - do not apply currency rounding. |
| old_idread-only | string(255) | Line id in the system this record was imported from. |
| pricelevelid | integer | Pricelevelid. Id only. |
| price_override | integer | 1 when the price was manually overridden, so repricing leaves it alone. |
| extended_pricemoney | string(5dp) | Stored as decimal(19,5). |
| worktypeid | integer | Reference to worktypes, by id. Write either this or worktype. |
| worktype | string(100) | Code for the referenced worktype, instead of the id. |
| worksubtypeid | integer | Worksubtypeid. Id only. |
| returnqtyqty | string(6dp) | Quantity, 6 decimal places, as a string. Stored as decimal(6dp). |
| returndetailid | integer | Returndetailid. Id only. |
| discountid | integer | Discountid. Id only. |
| discountpercentnumber | string(2dp) | Numeric string, 2 decimal places. Not money - do not apply currency rounding. |
| inventorylocationid | integer | Inventorylocationid. Id only. |
| inventorylocation | string(20) | The locationcode of the referenced inventorylocations, instead of the id. Send this or inventorylocationid, not both unless they agree. |
| linedate | string | Date recorded for the line (service and rental lines). |
| linetype | integer | Line type: 0 = standard product line, 1 = product-type tax, 2 = delivery charge, 3 = fuel charge, 4 = restock fee, 5 = billed expense. |
| partialtaxexemptionid | integer | Partial tax exemption applied to the line. |
| partialtaxexemption | string(32) | The exemptname of the referenced taxexempts, instead of the id. Send this or partialtaxexemptionid, not both unless they agree. |
| taxclassid | integer | Taxclassid. Id only. |
| taxclass | string(100) | The name of the referenced taxclasses, instead of the id. Send this or taxclassid, not both unless they agree. |
| arorderdetailid | integer | Arorderdetailid. Id only. |
| itempricespecialdetailid | integer | Itempricespecialdetailid. Id only. |
| numperiodsnumber | string(6dp) | Numeric string, 6 decimal places. Not money - do not apply currency rounding. |
| period | string(1) | Rental period the line bills by: D = daily, W = weekly, M = monthly. Empty for non-rental lines. |
| producttypetaxid | integer | Producttypetaxid. Id only. |
| rentalbegindate | string | Date the rental billing period for the line begins. |
| arserviceorder_timeid | integer | Arserviceorder timeid. Id only. |
| assetid | integer | Assetid. Id only. |
| prpaytypeid | integer | Prpaytypeid. Id only. |
| prpaytypemultipliernumber | string(2dp) | Numeric string, 2 decimal places. Not money - do not apply currency rounding. |
| externalid | string(100) | Your own key. Scoped to your company. |
Endpoints#
GET/invoicelines/{id}/tax
200422
Tax charged on one invoice line, by jurisdiction.
Documents report a tax total. This is the breakdown - which tax authority charged what, at which rate, and how much of the line was exempt. Anyone filing returns from NolaPro data, or reconciling against an external tax service, needs the per-jurisdiction detail rather than the sum.
Requires scope invoices:read.
Parameters
| Name | In | Type | Notes |
|---|---|---|---|
| idrequired | path | integer | The invoice line id. |
When it fails
| Status | Code | Meaning |
|---|---|---|
| 422 | unknown_value | No such parent record in this company. |
curl \ 'https://acme.nolapro.com/!/api/v2/invoicelines/104/tax' \ -H 'Authorization: Bearer $NP_TOKEN'
$ch = curl_init('https://acme.nolapro.com/!/api/v2/invoicelines/104/tax'); curl_setopt_array($ch, [ CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('NP_TOKEN')], CURLOPT_RETURNTRANSFER => true, ]); $res = json_decode(curl_exec($ch), true);
import os, requests r = requests.get( "https://acme.nolapro.com/!/api/v2/invoicelines/104/tax", headers={"Authorization": f"Bearer {os.environ['NP_TOKEN']}"}, ) r.raise_for_status()
const res = await fetch( 'https://acme.nolapro.com/!/api/v2/invoicelines/104/tax', { method: 'GET', headers: { Authorization: `Bearer ${process.env.NP_TOKEN}` }, } ); const data = await res.json();
using System.Net.Http.Json; var token = Environment.GetEnvironmentVariable("NP_TOKEN"); using var http = new HttpClient(); http.DefaultRequestHeaders.Add("Authorization", "Bearer " + token); var res = await http.GetAsync( "https://acme.nolapro.com/!/api/v2/invoicelines/104/tax"); res.EnsureSuccessStatusCode();
POST/invoicelines/batch
207400409422
Create many.
Requires scope invoices:write.
Parameters
| Name | In | Type | Notes |
|---|---|---|---|
Body array
| Field | Type | Description |
|---|---|---|
| invoiceidrequired | integer | The DRAFT invoice to add to. A posted invoice is refused - its voucher was written for the current total. |
| itemid | integer | Stock item. Omit for a non-stock line and send a description. |
| description | string(255) | Line text. Defaults to the item description. |
| quantityrequiredqty | string | How many. Decimal STRING, up to 6 places. |
| pricerequiredmoney | string | Unit price. Decimal STRING, not a JSON number. |
| taxable | boolean | Whether the line attracts tax. |
| externalid | string(100) | Your own identifier for this record. Stored verbatim and returned on reads; GET /<resource>?externalid=... finds it again. |
When it fails
| Status | Code | Meaning |
|---|---|---|
| 400 | invalid_request | The request was malformed. |
| 409 | invoice_already_posted | The invoice is posted; its voucher was written for the current total. |
| 422 | rule_violation | NolaPro refused the document. message carries its reason. |
| 422 | unknown_value | A reference did not resolve in this company. |
curl -X POST \ 'https://acme.nolapro.com/!/api/v2/invoicelines/batch' \ -H 'Authorization: Bearer $NP_TOKEN' \ -H 'Content-Type: application/json' \ -H 'Idempotency-Key: your-unique-key' \ -d '[ { "invoiceid": 104, "quantity": "3.000000", "price": "125.0000", "externalid": "crm-8842" } ]'
$ch = curl_init('https://acme.nolapro.com/!/api/v2/invoicelines/batch'); curl_setopt_array($ch, [ CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('NP_TOKEN')], CURLOPT_RETURNTRANSFER => true, CURLOPT_CUSTOMREQUEST => 'POST', CURLOPT_POSTFIELDS => json_encode([ [ 'invoiceid' => 104, 'quantity' => '3.000000', 'price' => '125.0000', 'externalid' => 'crm-8842', ], ]), ]); $res = json_decode(curl_exec($ch), true);
import os, requests r = requests.post( "https://acme.nolapro.com/!/api/v2/invoicelines/batch", headers={"Authorization": f"Bearer {os.environ['NP_TOKEN']}"}, json=[ { "invoiceid": 104, "quantity": "3.000000", "price": "125.0000", "externalid": "crm-8842", }, ], ) r.raise_for_status()
const res = await fetch( 'https://acme.nolapro.com/!/api/v2/invoicelines/batch', { method: 'POST', headers: { Authorization: `Bearer ${process.env.NP_TOKEN}` }, body: JSON.stringify([ { invoiceid: 104, quantity: "3.000000", price: "125.0000", externalid: "crm-8842", }, ]), } ); const data = await res.json();
using System.Net.Http.Json; var token = Environment.GetEnvironmentVariable("NP_TOKEN"); using var http = new HttpClient(); http.DefaultRequestHeaders.Add("Authorization", "Bearer " + token); var body = new[] { new { invoiceid = 104, quantity = "3.000000", price = "125.0000", externalid = "crm-8842", }, }; var req = new HttpRequestMessage(HttpMethod.Post, "https://acme.nolapro.com/!/api/v2/invoicelines/batch") { Content = JsonContent.Create(body), }; req.Headers.Add("Idempotency-Key", "your-unique-key"); var res = await http.SendAsync(req); res.EnsureSuccessStatusCode();
Response 207
{
"results": [
{
"index": 1,
"status": 1
}
]
}
GET/invoicelines
200403
List invoice lines.
Requires scope invoices:read.
Parameters
| Name | In | Type | Notes |
|---|---|---|---|
| itemid | query | string | Restrict to one itemid. |
| inventorylocationid | query | string | Restrict to one inventorylocationid. |
| invoiceid | query | string | Restrict to one invoiceid. |
| description | query | string | description. Partial match, case-insensitive. |
| modifiedsince | query | string | RFC 3339 UTC timestamp. Returns only records changed since then, including cancelled ones - so cancel defaults to any rather than false when this is used. The response carries _meta.synced_through; store it and send it back next time. |
| externalid | query | string | Exact match on your own key. |
| include | query | string | Comma-separated extras to embed. Only custom_fields is available: the extra fields this install has defined on the record. Off by default, and an unrecognised value is refused rather than ignored. See Conventions. |
When it fails
| Status | Code | Meaning |
|---|---|---|
| 403 | insufficient_scope | Token lacks read scope. |
curl \ 'https://acme.nolapro.com/!/api/v2/invoicelines' \ -H 'Authorization: Bearer $NP_TOKEN'
$ch = curl_init('https://acme.nolapro.com/!/api/v2/invoicelines'); curl_setopt_array($ch, [ CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('NP_TOKEN')], CURLOPT_RETURNTRANSFER => true, ]); $res = json_decode(curl_exec($ch), true);
import os, requests r = requests.get( "https://acme.nolapro.com/!/api/v2/invoicelines", headers={"Authorization": f"Bearer {os.environ['NP_TOKEN']}"}, ) r.raise_for_status()
const res = await fetch( 'https://acme.nolapro.com/!/api/v2/invoicelines', { method: 'GET', headers: { Authorization: `Bearer ${process.env.NP_TOKEN}` }, } ); const data = await res.json();
using System.Net.Http.Json; var token = Environment.GetEnvironmentVariable("NP_TOKEN"); using var http = new HttpClient(); http.DefaultRequestHeaders.Add("Authorization", "Bearer " + token); var res = await http.GetAsync( "https://acme.nolapro.com/!/api/v2/invoicelines"); res.EnsureSuccessStatusCode();
POST/invoicelines
201400409422
Create.
Requires scope invoices:write.
Parameters
| Name | In | Type | Notes |
|---|---|---|---|
Body
| Field | Type | Description |
|---|---|---|
| invoiceidrequired | integer | The DRAFT invoice to add to. A posted invoice is refused - its voucher was written for the current total. |
| itemid | integer | Stock item. Omit for a non-stock line and send a description. |
| description | string(255) | Line text. Defaults to the item description. |
| quantityrequiredqty | string | How many. Decimal STRING, up to 6 places. |
| pricerequiredmoney | string | Unit price. Decimal STRING, not a JSON number. |
| taxable | boolean | Whether the line attracts tax. |
| externalid | string(100) | Your own identifier for this record. Stored verbatim and returned on reads; GET /<resource>?externalid=... finds it again. |
When it fails
| Status | Code | Meaning |
|---|---|---|
| 400 | invalid_request | A required field was missing. |
| 409 | invoice_already_posted | The invoice is posted; its voucher was written for the current total. |
| 422 | rule_violation | NolaPro refused the document. message carries its reason. |
| 422 | unknown_value | A reference did not resolve in this company. |
curl -X POST \ 'https://acme.nolapro.com/!/api/v2/invoicelines' \ -H 'Authorization: Bearer $NP_TOKEN' \ -H 'Content-Type: application/json' \ -H 'Idempotency-Key: your-unique-key' \ -d '{ "invoiceid": 104, "quantity": "3.000000", "price": "125.0000", "externalid": "crm-8842" }'
$ch = curl_init('https://acme.nolapro.com/!/api/v2/invoicelines'); curl_setopt_array($ch, [ CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('NP_TOKEN')], CURLOPT_RETURNTRANSFER => true, CURLOPT_CUSTOMREQUEST => 'POST', CURLOPT_POSTFIELDS => json_encode([ 'invoiceid' => 104, 'quantity' => '3.000000', 'price' => '125.0000', 'externalid' => 'crm-8842', ]), ]); $res = json_decode(curl_exec($ch), true);
import os, requests r = requests.post( "https://acme.nolapro.com/!/api/v2/invoicelines", headers={"Authorization": f"Bearer {os.environ['NP_TOKEN']}"}, json={ "invoiceid": 104, "quantity": "3.000000", "price": "125.0000", "externalid": "crm-8842", }, ) r.raise_for_status()
const res = await fetch( 'https://acme.nolapro.com/!/api/v2/invoicelines', { method: 'POST', headers: { Authorization: `Bearer ${process.env.NP_TOKEN}` }, body: JSON.stringify({ invoiceid: 104, quantity: "3.000000", price: "125.0000", externalid: "crm-8842", }), } ); const data = await res.json();
using System.Net.Http.Json; var token = Environment.GetEnvironmentVariable("NP_TOKEN"); using var http = new HttpClient(); http.DefaultRequestHeaders.Add("Authorization", "Bearer " + token); var body = new { invoiceid = 104, quantity = "3.000000", price = "125.0000", externalid = "crm-8842", }; var req = new HttpRequestMessage(HttpMethod.Post, "https://acme.nolapro.com/!/api/v2/invoicelines") { Content = JsonContent.Create(body), }; req.Headers.Add("Idempotency-Key", "your-unique-key"); var res = await http.SendAsync(req); res.EnsureSuccessStatusCode();
Response 201
{
"invoiceid": 104,
"linenumber": 1,
"qty": "1.000000",
"priceach": "125.0000",
"totalprice": "125.0000",
"invoicetotal": "125.0000"
}
GET/invoicelines/{id}
200404
Retrieve one record.
Requires scope invoices:read.
Parameters
| Name | In | Type | Notes |
|---|---|---|---|
| idrequired | path | integer | The record id. |
| include | query | string | Comma-separated extras to embed. Only custom_fields is available: the extra fields this install has defined on the record. Off by default, and an unrecognised value is refused rather than ignored. See Conventions. |
When it fails
| Status | Code | Meaning |
|---|---|---|
| 404 | not_found | No record with that id. |
curl \ 'https://acme.nolapro.com/!/api/v2/invoicelines/104' \ -H 'Authorization: Bearer $NP_TOKEN'
$ch = curl_init('https://acme.nolapro.com/!/api/v2/invoicelines/104'); curl_setopt_array($ch, [ CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('NP_TOKEN')], CURLOPT_RETURNTRANSFER => true, ]); $res = json_decode(curl_exec($ch), true);
import os, requests r = requests.get( "https://acme.nolapro.com/!/api/v2/invoicelines/104", headers={"Authorization": f"Bearer {os.environ['NP_TOKEN']}"}, ) r.raise_for_status()
const res = await fetch( 'https://acme.nolapro.com/!/api/v2/invoicelines/104', { method: 'GET', headers: { Authorization: `Bearer ${process.env.NP_TOKEN}` }, } ); const data = await res.json();
using System.Net.Http.Json; var token = Environment.GetEnvironmentVariable("NP_TOKEN"); using var http = new HttpClient(); http.DefaultRequestHeaders.Add("Authorization", "Bearer " + token); var res = await http.GetAsync( "https://acme.nolapro.com/!/api/v2/invoicelines/104"); res.EnsureSuccessStatusCode();
Response 200
{
"invoiceid": 104,
"invoice": "Example invoice",
"linenumber": 1,
"itemid": 104,
"item": "Example item",
"description": "Example description"
}
PATCH/invoicelines/{id}
200400404409422
Update.
Requires scope invoices:write.
Parameters
| Name | In | Type | Notes |
|---|---|---|---|
| idrequired | path | integer | The record id. |
Body
| Field | Type | Description |
|---|---|---|
| description | string(255) | Free text. |
| qtyqty | string | Quantity. Re-derives the invoice total. Decimal STRING. |
| priceachmoney | string | Unit price. Re-derives the parent total. Decimal STRING. |
| externalid | string(100) | Your own identifier for this record. |
When it fails
| Status | Code | Meaning |
|---|---|---|
| 400 | invalid_request | The request was malformed. |
| 404 | not_found | No such record, or it belongs to another company. |
| 409 | invoice_already_posted | The invoice is posted; its voucher was built from the current figures. |
| 409 | stale_record | If-Match did not match; someone else changed it first. |
| 422 | rule_violation | NolaPro refused the change. message carries its reason. |
curl -X PATCH \ 'https://acme.nolapro.com/!/api/v2/invoicelines/104' \ -H 'Authorization: Bearer $NP_TOKEN' \ -H 'Content-Type: application/json' \ -H 'Idempotency-Key: your-unique-key' \ -d '{ "qty": "3.000000", "priceach": "12.5000" }'
$ch = curl_init('https://acme.nolapro.com/!/api/v2/invoicelines/104'); curl_setopt_array($ch, [ CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('NP_TOKEN')], CURLOPT_RETURNTRANSFER => true, CURLOPT_CUSTOMREQUEST => 'PATCH', CURLOPT_POSTFIELDS => json_encode([ 'qty' => '3.000000', 'priceach' => '12.5000', ]), ]); $res = json_decode(curl_exec($ch), true);
import os, requests r = requests.patch( "https://acme.nolapro.com/!/api/v2/invoicelines/104", headers={"Authorization": f"Bearer {os.environ['NP_TOKEN']}"}, json={ "qty": "3.000000", "priceach": "12.5000", }, ) r.raise_for_status()
const res = await fetch( 'https://acme.nolapro.com/!/api/v2/invoicelines/104', { method: 'PATCH', headers: { Authorization: `Bearer ${process.env.NP_TOKEN}` }, body: JSON.stringify({ qty: "3.000000", priceach: "12.5000", }), } ); const data = await res.json();
using System.Net.Http.Json; var token = Environment.GetEnvironmentVariable("NP_TOKEN"); using var http = new HttpClient(); http.DefaultRequestHeaders.Add("Authorization", "Bearer " + token); var body = new { qty = "3.000000", priceach = "12.5000", }; var req = new HttpRequestMessage(HttpMethod.Patch, "https://acme.nolapro.com/!/api/v2/invoicelines/104") { Content = JsonContent.Create(body), }; req.Headers.Add("Idempotency-Key", "your-unique-key"); var res = await http.SendAsync(req); res.EnsureSuccessStatusCode();