Invoices
AR invoices. Lines go in the same request - see Conventions on nested writes.
The object#
| Field | Type | Description |
|---|---|---|
| idread-only | integer | NolaPro id. |
| invoicenumber | string(30) | Invoice number. Auto-assigned from the company counter when not supplied. |
| ponumber | string(30) | The customer's purchase order number. |
| wherefrom | integer | Module that raised the invoice: 2 = manual AR entry, 4 = billed from an order, fulfillment, or service order, 7 = billed from Estimating (print orders), 12 = generated by a payment-plan run, 44 = created by an RMA return. |
| orderid | integer | Orderid. Id only. |
| orderbycompanyid | integer | Orderbycompanyid. Id only. |
| shiptocompanyid | integer | Shiptocompanyid. Id only. |
| status | string | Where the invoice is in its life. Labels are Arinvoice_model::$statuses. Stored as int -1/0/1/2/3/4; never exposed or accepted (D35). unposted means no GL voucher has been written yet, so lines can still be added; everything else means the ledger has been told. One of abandoned, unposted, open, paid, writeoff, refundedcredit. |
| customerbillcode | string(20) | Customer Bill Code printed on the invoice. |
| shipcostmoney | string(4dp) | Stored as decimal(19,4). |
| invoicetotalmoney | string(4dp) | Stored as decimal(19,4). |
| invoicetermsid | integer | Invoicetermsid. Id only. |
| invoiceterms | string(30) | The verbal of the referenced invoiceterms, instead of the id. Send this or invoicetermsid, not both unless they agree. |
| salesmanid | integer | Salesmanid. Id only. |
| salesman | string(50) | The name of the referenced salesmen, instead of the id. Send this or salesmanid, not both unless they agree. |
| invoicedate | string | Invoice date - the accounting date the invoice posts under. |
| duedate | string | Date payment is due. |
| discountdate | string | Last date the early-payment discount applies. |
| discountamountmoney | string(4dp) | Stored as decimal(19,4). |
| accruedinterestmoney | string(4dp) | Stored as decimal(19,4). |
| datelastinterestcalcread-only | string | When finance-charge interest was last assessed on the invoice. |
| cancel | boolean | Cancelled. NolaPro cancels rather than deletes, so a cancelled row is still readable. |
| entrydate | string | When the record was created. |
| lastchangedateread-only | string | Last modification. Drives modifiedsince. |
| pricelevelid | integer | Pricelevelid. Id only. |
| 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. |
| payment_method | string(12) | Payment method text carried in from the web store order the invoice came from. |
| shipping_method | string(32) | Shipping method text carried in from the web store order the invoice came from. |
| currency | string(10) | Currency the invoice is raised in. |
| transaction_id | string(32) | Gateway transaction id of the payment taken with the invoice (web store and POS sales). |
| customers_id | integer | Customers id. Id only. |
| customers | string(30) | The customercode of the referenced customers, instead of the id. Send this or customers_id, not both unless they agree. |
| currency_valuenumber | string(6dp) | Numeric string, 6 decimal places. Not money - do not apply currency rounding. |
| servicerepid | integer | Servicerepid. Id only. |
| servicerep | string(50) | The name of the referenced salesmen, instead of the id. Send this or servicerepid, not both unless they agree. |
| discountappliedmoney | string(4dp) | Stored as decimal(19,4). |
| payplan | boolean | True when the invoice is a payment-plan template that generates recurring invoices. |
| payplan_period | integer | Recurrence period of the payment plan: 1 = daily, 2 = weekly, 3 = monthly, 4 = quarterly, 5 = yearly; anything else repeats every payplan_days days. |
| payplan_days | integer | Interval in days between generated invoices, when payplan_period does not name a standard period. |
| payplan_next | string | Next date the payment plan generates an invoice. |
| payplan_numtimes | integer | Remaining number of invoices the plan will generate; -1 repeats indefinitely. |
| sales_categoriesid | integer | Sales categoriesid. Id only. |
| sales_categories | string(50) | The description of the referenced salescategories, instead of the id. Send this or sales_categoriesid, not both unless they agree. |
| coverage | integer | 1 prints the coverage period - the date range the recurring invoice covers - on generated invoices. |
| formnumber | string(50) | Form Number of the printed piece, for invoices billed from Estimating. |
| shiptoattn | string(100) | Attention line printed with the ship-to address. |
| old_idread-only | string(255) | Invoice id in the system this record was imported from. |
| client_po | string(30) | The customer’s PO number for the invoice. |
| curratenumber | string(10dp) | Numeric string, 10 decimal places. Not money - do not apply currency rounding. |
| arglaccountid | integer | Arglaccountid. Id only. |
| arglaccount | string(20) | The name of the referenced glaccounts, instead of the id. Send this or arglaccountid, not both unless they agree. |
| leaseid | integer | Leaseid. Id only. |
| costcodeid | integer | Cost code. |
| costcode | string(20) | Code for the referenced costcode, instead of the id. |
| delivered | integer | 1 once the invoiced goods are recorded as delivered. |
| carrierserviceid_preferred | integer | Carrier service the customer prefers for this shipment. |
| b2bhidden | boolean | True hides the invoice from the customer’s B2B portal. |
| billtrustsentread-only | string | Date the invoice was sent to the Billtrust delivery service. Maintained by the send flow, so it cannot be written through the API. |
| contactnameid | integer | Contactnameid. Id only. |
| glcategoryid | integer | Glcategoryid. Id only. |
| glcategory | string(20) | The code of the referenced glcategories, instead of the id. Send this or glcategoryid, not both unless they agree. |
| interestforinvoiceid | integer | Interestforinvoiceid. Id only. |
| interestforinvoice | string(30) | The invoicenumber of the referenced invoices, instead of the id. Send this or interestforinvoiceid, not both unless they agree. |
| invoicenotificationmethod | string(1) | How the customer wants this invoice delivered: E = email, M = mail, F = fax. Empty uses the customer default. |
| jobid | integer | Jobid. Id only. |
| 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. |
| zlienid | integer | Zlienid. Id only. |
| emailsentread-only | string | Date the invoice was emailed. Maintained by the send flow, so it cannot be written through the API. |
| faxsentread-only | string | Date the invoice was faxed. Maintained by the send flow, so it cannot be written through the API. |
| isacustomerreturn | string(1) | 1 when the invoice is a credit raised for a customer return. |
| modifiedfromarinvoiceid | integer | Modifiedfromarinvoiceid. Id only. |
| modifiedfromarinvoice | string(30) | The invoicenumber of the referenced invoices, instead of the id. Send this or modifiedfromarinvoiceid, not both unless they agree. |
| paiddateread-only | string | Date the invoice was fully paid. |
| paymeth | integer | Payment method: 1 = cash, 2 = check, 3 = credit card, 4 = ACH/EFT, 5 = card terminal; 0 = on account or unset. |
| priceadjustmentforinvoiceid | integer | Priceadjustmentforinvoiceid. Id only. |
| priceadjustmentforinvoice | string(30) | The invoicenumber of the referenced invoices, instead of the id. Send this or priceadjustmentforinvoiceid, not both unless they agree. |
| rental | integer | 1 when the invoice bills a rental. |
| rentalconverttosale | boolean | True when the invoice converts a rental into a sale. |
| taxadjustmentforinvoiceid | integer | Taxadjustmentforinvoiceid. Id only. |
| taxadjustmentforinvoice | string(30) | The invoicenumber of the referenced invoices, instead of the id. Send this or taxadjustmentforinvoiceid, not both unless they agree. |
| taxexemptid | integer | Taxexemptid. Id only. |
| taxexempt | string(32) | The exemptname of the referenced taxexempts, instead of the id. Send this or taxexemptid, not both unless they agree. |
| voucherid | integer | Voucherid. Id only. |
| voucher | string(50) | The voucher of the referenced gltransactions, instead of the id. Send this or voucherid, not both unless they agree. |
| billtoshiptoid | integer | Billtoshiptoid. Id only. |
| defaultassetid | integer | Defaultassetid. Id only. |
| passthruarinvoiceid | integer | Passthruarinvoiceid. Id only. |
| passthruarinvoice | string(30) | The invoicenumber of the referenced invoices, instead of the id. Send this or passthruarinvoiceid, not both unless they agree. |
| passthrucontactid | integer | Passthrucontactid. Id only. |
| passthrucustomerbilltoshiptoid | integer | Passthrucustomerbilltoshiptoid. Id only. |
| passthrucustomerid | integer | Passthrucustomerid. Id only. |
| passthrucustomer | string(30) | The customercode of the referenced customers, instead of the id. Send this or passthrucustomerid, not both unless they agree. |
| passthrufromarinvoiceid | integer | Passthrufromarinvoiceid. Id only. |
| passthrufromarinvoice | string(30) | The invoicenumber of the referenced invoices, instead of the id. Send this or passthrufromarinvoiceid, not both unless they agree. |
| specialpurposeread-only | string(15) | Marker on system-generated invoices with a special purpose - e.g. CCFEE for credit-card fee invoices - so sales reports can exclude them. |
| externalid | string(100) | Your own key. Scoped to your company. |
| lines | array of InvoiceLine | |
| _metaread-only | object | Present only when the server has something to report, e.g. the invoice posted but the customer is now over their credit limit. |
| affectsinventory | boolean | Whether this invoice withdraws stock. Leave it out. Omitted, it is derived, and derived is right in every normal case:
- Invoice raised from an order or shipment - stock already left at the shipment, so the invoice moves nothing. Sending true here is rejected: it would withdraw the same units twice.
- Direct invoice with stocked lines - it withdraws, because nothing else ever will.
Send false only when importing history whose stock was already adjusted by another route. The response then carries an inventory_not_adjusted warning, because an invoice that sold goods and moved no stock is a discrepancy someone will chase later. |
Endpoints#
Notes on an invoice.
Operational context that lives with the document - why a price was changed, what a customer asked for, what to tell the driver.
hide keeps a note off the printed invoice. A note with linenumber set belongs to that line rather than the document as a whole.
Requires scope invoices:read.
| Name | In | Type | Notes |
|---|---|---|---|
| idrequired | path | integer | The invoice id. |
| Status | Code | Meaning |
|---|---|---|
| 422 | unknown_value | No such parent record in this company. |
curl \ 'https://acme.nolapro.com/!/api/v2/invoices/104/notes' \ -H 'Authorization: Bearer $NP_TOKEN'
$ch = curl_init('https://acme.nolapro.com/!/api/v2/invoices/104/notes'); 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/invoices/104/notes", headers={"Authorization": f"Bearer {os.environ['NP_TOKEN']}"}, ) r.raise_for_status()
const res = await fetch( 'https://acme.nolapro.com/!/api/v2/invoices/104/notes', { 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/invoices/104/notes"); res.EnsureSuccessStatusCode();
List invoices.
Requires scope invoices:read.
| Name | In | Type | Notes |
|---|---|---|---|
| status | query | string | Restrict to one status. |
| orderbycompanyid | query | string | Restrict to one orderbycompanyid. |
| shiptocompanyid | query | string | Restrict to one shiptocompanyid. |
| inventorylocationid | query | string | Restrict to one inventorylocationid. |
| salesmanid | query | string | Restrict to one salesmanid. |
| jobid | query | string | Restrict to one jobid. |
| orderid | query | string | Restrict to one orderid. |
| ponumber | query | string | ponumber. Partial match, case-insensitive. |
| invoicenumber | query | string | Partial match, case insensitive. |
| cancel | query | string | Defaults to false. Pass true or any. |
| 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. |
| Status | Code | Meaning |
|---|---|---|
| 403 | insufficient_scope | Token lacks read scope. |
curl \ 'https://acme.nolapro.com/!/api/v2/invoices' \ -H 'Authorization: Bearer $NP_TOKEN'
$ch = curl_init('https://acme.nolapro.com/!/api/v2/invoices'); 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/invoices", headers={"Authorization": f"Bearer {os.environ['NP_TOKEN']}"}, ) r.raise_for_status()
const res = await fetch( 'https://acme.nolapro.com/!/api/v2/invoices', { 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/invoices"); res.EnsureSuccessStatusCode();
Create.
Requires scope invoices:write.
| Name | In | Type | Notes |
|---|---|---|---|
| Field | Type | Description |
|---|---|---|
| customeridrequired | integer | Who is being invoiced. |
| date | string | Invoice date. Defaults to today. |
| post | boolean | Post the invoice to the general ledger. Defaults to true. Send false to create it as a DRAFT: no GL voucher is written, so lines can still be added with POST /invoicelines or changed with PATCH /invoicelines/{id}. Post it later by cancelling and re-raising, or build it fully before posting. Once an invoice carries a voucher its lines are closed to further change. |
| duedate | string | Payment due date. Defaults to the invoice date. |
| ponumber | string(30) | The customer's PO number. |
| shiptoid | integer | Ship-to company, if different from the customer. |
| number | string(30) | Invoice number. Leave it out and NolaPro allocates the next one. |
| externalid | string(100) | Your own identifier for this record. Stored verbatim and returned on reads; GET /<resource>?externalid=... finds it again. |
| linesrequired | array of object | At least one line. The tax and the total are derived by NolaPro - do not send them. |
| Status | Code | Meaning |
|---|---|---|
| 400 | invalid_request | A required field was missing. |
| 422 | period_closed | The GL period containing the date is closed. |
| 422 | rule_violation | NolaPro refused the document. message carries its reason. |
| 422 | shipto_mismatch | The shiptoid belongs to a different customer. |
| 422 | unknown_value | A reference did not resolve in this company. |
curl -X POST \ 'https://acme.nolapro.com/!/api/v2/invoices' \ -H 'Authorization: Bearer $NP_TOKEN' \ -H 'Content-Type: application/json' \ -H 'Idempotency-Key: your-unique-key' \ -d '{ "customerid": 104, "date": "2026-08-02", "post": false, "duedate": "2026-08-02", "externalid": "crm-8842", "lines": [ { "quantity": "3.000000", "price": "125.0000" } ] }'
$ch = curl_init('https://acme.nolapro.com/!/api/v2/invoices'); curl_setopt_array($ch, [ CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('NP_TOKEN')], CURLOPT_RETURNTRANSFER => true, CURLOPT_CUSTOMREQUEST => 'POST', CURLOPT_POSTFIELDS => json_encode([ 'customerid' => 104, 'date' => '2026-08-02', 'post' => false, 'duedate' => '2026-08-02', 'externalid' => 'crm-8842', 'lines' => [ [ 'quantity' => '3.000000', 'price' => '125.0000', ], ], ]), ]); $res = json_decode(curl_exec($ch), true);
import os, requests r = requests.post( "https://acme.nolapro.com/!/api/v2/invoices", headers={"Authorization": f"Bearer {os.environ['NP_TOKEN']}"}, json={ "customerid": 104, "date": "2026-08-02", "post": False, "duedate": "2026-08-02", "externalid": "crm-8842", "lines": [ { "quantity": "3.000000", "price": "125.0000", }, ], }, ) r.raise_for_status()
const res = await fetch( 'https://acme.nolapro.com/!/api/v2/invoices', { method: 'POST', headers: { Authorization: `Bearer ${process.env.NP_TOKEN}` }, body: JSON.stringify({ customerid: 104, date: "2026-08-02", post: false, duedate: "2026-08-02", externalid: "crm-8842", lines: [ { quantity: "3.000000", price: "125.0000", }, ], }), } ); 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 { customerid = 104, date = "2026-08-02", post = false, duedate = "2026-08-02", externalid = "crm-8842", lines = new[] { new { quantity = "3.000000", price = "125.0000", }, }, }; var req = new HttpRequestMessage(HttpMethod.Post, "https://acme.nolapro.com/!/api/v2/invoices") { Content = JsonContent.Create(body), }; req.Headers.Add("Idempotency-Key", "your-unique-key"); var res = await http.SendAsync(req); res.EnsureSuccessStatusCode();
{
"invoicenumber": "INV-88421",
"total": "125.0000",
"posted": false,
"voucherid": 104
}
Create many.
Requires scope invoices:write.
| Name | In | Type | Notes |
|---|---|---|---|
| Field | Type | Description |
|---|---|---|
| customeridrequired | integer | Who is being invoiced. |
| date | string | Invoice date. Defaults to today. |
| post | boolean | Post the invoice to the general ledger. Defaults to true. Send false to create it as a DRAFT: no GL voucher is written, so lines can still be added with POST /invoicelines or changed with PATCH /invoicelines/{id}. Post it later by cancelling and re-raising, or build it fully before posting. Once an invoice carries a voucher its lines are closed to further change. |
| duedate | string | Payment due date. Defaults to the invoice date. |
| ponumber | string(30) | The customer's PO number. |
| shiptoid | integer | Ship-to company, if different from the customer. |
| number | string(30) | Invoice number. Leave it out and NolaPro allocates the next one. |
| externalid | string(100) | Your own identifier for this record. Stored verbatim and returned on reads; GET /<resource>?externalid=... finds it again. |
| linesrequired | array of object | At least one line. The tax and the total are derived by NolaPro - do not send them. |
| Status | Code | Meaning |
|---|---|---|
| 400 | invalid_request | The request was malformed. |
| 422 | period_closed | The GL period containing the date is closed. |
| 422 | rule_violation | NolaPro refused the document. message carries its reason. |
| 422 | shipto_mismatch | The shiptoid belongs to a different customer. |
| 422 | unknown_value | A reference did not resolve in this company. |
curl -X POST \ 'https://acme.nolapro.com/!/api/v2/invoices/batch' \ -H 'Authorization: Bearer $NP_TOKEN' \ -H 'Content-Type: application/json' \ -H 'Idempotency-Key: your-unique-key' \ -d '[ { "customerid": 104, "date": "2026-08-02", "post": false, "duedate": "2026-08-02", "externalid": "crm-8842", "lines": [ { "quantity": "3.000000", "price": "125.0000" } ] } ]'
$ch = curl_init('https://acme.nolapro.com/!/api/v2/invoices/batch'); curl_setopt_array($ch, [ CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('NP_TOKEN')], CURLOPT_RETURNTRANSFER => true, CURLOPT_CUSTOMREQUEST => 'POST', CURLOPT_POSTFIELDS => json_encode([ [ 'customerid' => 104, 'date' => '2026-08-02', 'post' => false, 'duedate' => '2026-08-02', 'externalid' => 'crm-8842', 'lines' => [ [ 'quantity' => '3.000000', 'price' => '125.0000', ], ], ], ]), ]); $res = json_decode(curl_exec($ch), true);
import os, requests r = requests.post( "https://acme.nolapro.com/!/api/v2/invoices/batch", headers={"Authorization": f"Bearer {os.environ['NP_TOKEN']}"}, json=[ { "customerid": 104, "date": "2026-08-02", "post": False, "duedate": "2026-08-02", "externalid": "crm-8842", "lines": [ { "quantity": "3.000000", "price": "125.0000", }, ], }, ], ) r.raise_for_status()
const res = await fetch( 'https://acme.nolapro.com/!/api/v2/invoices/batch', { method: 'POST', headers: { Authorization: `Bearer ${process.env.NP_TOKEN}` }, body: JSON.stringify([ { customerid: 104, date: "2026-08-02", post: false, duedate: "2026-08-02", externalid: "crm-8842", lines: [ { quantity: "3.000000", price: "125.0000", }, ], }, ]), } ); 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 { customerid = 104, date = "2026-08-02", post = false, duedate = "2026-08-02", externalid = "crm-8842", lines = new[] { new { quantity = "3.000000", price = "125.0000", }, }, }, }; var req = new HttpRequestMessage(HttpMethod.Post, "https://acme.nolapro.com/!/api/v2/invoices/batch") { Content = JsonContent.Create(body), }; req.Headers.Add("Idempotency-Key", "your-unique-key"); var res = await http.SendAsync(req); res.EnsureSuccessStatusCode();
{
"results": [
{
"index": 1,
"status": 1
}
]
}
Retrieve one record.
Requires scope invoices:read.
| 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. |
| Status | Code | Meaning |
|---|---|---|
| 404 | not_found | No record with that id. |
curl \ 'https://acme.nolapro.com/!/api/v2/invoices/104' \ -H 'Authorization: Bearer $NP_TOKEN'
$ch = curl_init('https://acme.nolapro.com/!/api/v2/invoices/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/invoices/104", headers={"Authorization": f"Bearer {os.environ['NP_TOKEN']}"}, ) r.raise_for_status()
const res = await fetch( 'https://acme.nolapro.com/!/api/v2/invoices/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/invoices/104"); res.EnsureSuccessStatusCode();
{
"status": "abandoned",
"lines": [
{
"itemid": 3391,
"item": "WIDGET-1",
"description": "Bracket, 4in galvanised",
"quantity": "24.000000",
"price": "14.2500",
"taxable": true
}
]
}
Update.
Requires scope invoices:write.
| Name | In | Type | Notes |
|---|---|---|---|
| idrequired | path | integer | The record id. |
| Field | Type | Description |
|---|---|---|
| ponumber | string(30) | The customer's own PO reference. Amendable whatever the invoice has done. |
| duedate | string | When payment is expected. Unposted invoices only - returns 422 once posted. |
| externalid | string(100) | Your own identifier for this record. |
| Status | Code | Meaning |
|---|---|---|
| 400 | invalid_request | The request was malformed. |
| 404 | not_found | No such record, or it belongs to another company. |
| 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/invoices/104' \ -H 'Authorization: Bearer $NP_TOKEN' \ -H 'Content-Type: application/json' \ -H 'Idempotency-Key: your-unique-key' \ -d '{ "ponumber": "INV-88421", "duedate": "2026-08-01" }'
$ch = curl_init('https://acme.nolapro.com/!/api/v2/invoices/104'); curl_setopt_array($ch, [ CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('NP_TOKEN')], CURLOPT_RETURNTRANSFER => true, CURLOPT_CUSTOMREQUEST => 'PATCH', CURLOPT_POSTFIELDS => json_encode([ 'ponumber' => 'INV-88421', 'duedate' => '2026-08-01', ]), ]); $res = json_decode(curl_exec($ch), true);
import os, requests r = requests.patch( "https://acme.nolapro.com/!/api/v2/invoices/104", headers={"Authorization": f"Bearer {os.environ['NP_TOKEN']}"}, json={ "ponumber": "INV-88421", "duedate": "2026-08-01", }, ) r.raise_for_status()
const res = await fetch( 'https://acme.nolapro.com/!/api/v2/invoices/104', { method: 'PATCH', headers: { Authorization: `Bearer ${process.env.NP_TOKEN}` }, body: JSON.stringify({ ponumber: "INV-88421", duedate: "2026-08-01", }), } ); 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 { ponumber = "INV-88421", duedate = "2026-08-01", }; var req = new HttpRequestMessage(HttpMethod.Patch, "https://acme.nolapro.com/!/api/v2/invoices/104") { Content = JsonContent.Create(body), }; req.Headers.Add("Idempotency-Key", "your-unique-key"); var res = await http.SendAsync(req); res.EnsureSuccessStatusCode();
Cancel.
Requires scope invoices:cancel.
| Name | In | Type | Notes |
|---|---|---|---|
| idrequired | path | integer | The record id. |
| Status | Code | Meaning |
|---|---|---|
| 400 | invalid_request | The request was malformed. |
| 409 | cannot_cancel | Something already depends on this document - a payment, a shipment, an invoice. |
| 422 | period_closed | The current GL period is closed, so a reversal has nowhere to post. |
| 422 | unknown_value | No such record in this company. |
curl -X DELETE \ 'https://acme.nolapro.com/!/api/v2/invoices/104' \ -H 'Authorization: Bearer $NP_TOKEN'
$ch = curl_init('https://acme.nolapro.com/!/api/v2/invoices/104'); curl_setopt_array($ch, [ CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('NP_TOKEN')], CURLOPT_RETURNTRANSFER => true, CURLOPT_CUSTOMREQUEST => 'DELETE', ]); $res = json_decode(curl_exec($ch), true);
import os, requests r = requests.delete( "https://acme.nolapro.com/!/api/v2/invoices/104", headers={"Authorization": f"Bearer {os.environ['NP_TOKEN']}"}, ) r.raise_for_status()
const res = await fetch( 'https://acme.nolapro.com/!/api/v2/invoices/104', { method: 'DELETE', 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 req = new HttpRequestMessage(HttpMethod.Delete, "https://acme.nolapro.com/!/api/v2/invoices/104"); var res = await http.SendAsync(req); res.EnsureSuccessStatusCode();
Post this invoice to the general ledger.
Writes the GL voucher for a DRAFT invoice - one created with post: false.
Until it is posted an invoice has no voucher, which is exactly what lets POST /invoicelines and PATCH /invoicelines/{id} change it. Posting closes it: the ledger has been told what the invoice is worth, so its lines stop being amendable.
An already-posted invoice answers 409 rather than writing a second voucher.
Requires scope invoices:write.
| Name | In | Type | Notes |
|---|---|---|---|
| idrequired | path | integer | |
| Status | Code | Meaning |
|---|---|---|
| 404 | not_found | No invoice with that id in this company. |
| 409 | invoice_already_posted | Already posted. Nothing was written a second time. |
| 422 | rule_violation | NolaPro refused the document. message carries its reason. |
| 422 | unknown_value | A reference did not resolve in this company. |
| 422 | period_closed | The GL period the document posts into is closed, so the voucher has nowhere to go. |
curl -X POST \ 'https://acme.nolapro.com/!/api/v2/invoices/104/post' \ -H 'Authorization: Bearer $NP_TOKEN'
$ch = curl_init('https://acme.nolapro.com/!/api/v2/invoices/104/post'); curl_setopt_array($ch, [ CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('NP_TOKEN')], CURLOPT_RETURNTRANSFER => true, CURLOPT_CUSTOMREQUEST => 'POST', ]); $res = json_decode(curl_exec($ch), true);
import os, requests r = requests.post( "https://acme.nolapro.com/!/api/v2/invoices/104/post", headers={"Authorization": f"Bearer {os.environ['NP_TOKEN']}"}, ) r.raise_for_status()
const res = await fetch( 'https://acme.nolapro.com/!/api/v2/invoices/104/post', { method: 'POST', 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 req = new HttpRequestMessage(HttpMethod.Post, "https://acme.nolapro.com/!/api/v2/invoices/104/post"); var res = await http.SendAsync(req); res.EnsureSuccessStatusCode();
Printed invoice as a PDF
The invoice exactly as NolaPro prints it, including any attachments the Document Center is set to combine.
Answers application/pdf, not JSON. Because the body is binary it cannot be carried inside a /batch results array; asking for it there returns 415 not_batchable.
A draft is refused with 409 not_posted: the totals on an unposted invoice can still change, so there is no document to print yet. The screens do not offer it either.
Requires scope invoices:read.
| Name | In | Type | Notes |
|---|---|---|---|
| idrequired | path | integer | The invoice id. |
| Status | Code | Meaning |
|---|---|---|
| 409 | The invoice is still a draft. |
curl \ 'https://acme.nolapro.com/!/api/v2/invoices/104/pdf' \ -H 'Authorization: Bearer $NP_TOKEN'
$ch = curl_init('https://acme.nolapro.com/!/api/v2/invoices/104/pdf'); 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/invoices/104/pdf", headers={"Authorization": f"Bearer {os.environ['NP_TOKEN']}"}, ) r.raise_for_status()
const res = await fetch( 'https://acme.nolapro.com/!/api/v2/invoices/104/pdf', { 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/invoices/104/pdf"); res.EnsureSuccessStatusCode();