Shipments

A shipment against an order. Can be sent nested in POST /orders or created on its own afterwards; both go through the same code path. A quote cannot ship.

The object#

FieldTypeDescription
idread-onlyintegerNolaPro id.
orderidintegerOrderid. Id only.
carrierserviceidintegerCarrier service the shipment goes out by.
carrierservicestring(100)Code for the referenced carrierservice, instead of the id.
shipdatestringWhen it went out.
locationidintegerInventory location to receive into.
locationstring(20)The locationcode of the referenced inventorylocations, instead of the id. Send this or locationid, not both unless they agree.
entrydatestringWhen the record was created.
lastchangedateread-onlystringLast modification. Drives modifiedsince.
shiptoidintegerShiptoid. Id only.
voucheridintegerVoucherid. Id only.
voucherstring(50)The voucher of the referenced gltransactions, instead of the id. Send this or voucherid, not both unless they agree.
cancelbooleanCancelled. Always a boolean on the wire, whatever integer width the column uses (D23).
invoiceidintegerInvoiceid. Id only.
invoicestring(30)The invoicenumber of the referenced invoices, instead of the id. Send this or invoiceid, not both unless they agree.
externalidstring(100)Your own key. Scoped to your company.

Endpoints#

GET/shipments/{id}/packages 200422

Packages in a shipment, with their tracking numbers.

Parcel-level detail: what went in which box, what it weighed, what the carrier charged, and the tracking number. This is where tracking numbers live. The order-level audit trail records that a shipment happened; the number a customer types into a carrier's site is here, per package - which matters because one shipment is often several boxes with several numbers.

Requires scope shipments:read.

Parameters
NameInTypeNotes
idrequiredpathintegerThe shipment id.
When it fails
StatusCodeMeaning
422unknown_valueNo such parent record in this company.
curl \
  'https://acme.nolapro.com/!/api/v2/shipments/104/packages' \
  -H 'Authorization: Bearer $NP_TOKEN'
POST/shipments/batch 207400422

Create many.

Requires scope shipments:write.

Parameters
NameInTypeNotes
Body array
FieldTypeDescription
orderidrequiredintegerThe order being shipped against.
externalidstring(100)Your own identifier for this record. Stored verbatim and returned on reads; GET /<resource>?externalid=... finds it again.
linesrequiredarray of objectWhat is going out. Each line ships against an order line and cannot exceed what is left on it.
When it fails
StatusCodeMeaning
400invalid_requestThe request was malformed.
422cannot_ship_quoteThe order is still a quote, so nothing is committed to ship.
422rule_violationNolaPro refused the document. message carries its reason.
422shipqty_exceeds_remainingMore than qtyorder - qtyship was sent.
422unknown_valueA reference did not resolve in this company.
curl -X POST \
  'https://acme.nolapro.com/!/api/v2/shipments/batch' \
  -H 'Authorization: Bearer $NP_TOKEN' \
  -H 'Content-Type: application/json' \
  -H 'Idempotency-Key: your-unique-key' \
  -d '[
    {
        "orderid": 104,
        "externalid": "crm-8842",
        "lines": [
            {
                "orderlineid": 104,
                "quantity": "3.000000"
            }
        ]
    }
]'
Response 207
{
    "results": [
        {
            "index": 1,
            "status": 1
        }
    ]
}
GET/shipments 200403

List shipments.

Requires scope shipments:read.

Parameters
NameInTypeNotes
locationidquerystringRestrict to one locationid.
orderidquerystringRestrict to one orderid.
invoiceidquerystringRestrict to one invoiceid.
cancelquerystringDefaults to false. Pass true or any.
modifiedsincequerystringRFC 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.
externalidquerystringExact match on your own key.
includequerystringComma-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
StatusCodeMeaning
403insufficient_scopeToken lacks read scope.
curl \
  'https://acme.nolapro.com/!/api/v2/shipments' \
  -H 'Authorization: Bearer $NP_TOKEN'
POST/shipments 201400422

Create.

Requires scope shipments:write.

Parameters
NameInTypeNotes
Body
FieldTypeDescription
orderidrequiredintegerThe order being shipped against.
externalidstring(100)Your own identifier for this record. Stored verbatim and returned on reads; GET /<resource>?externalid=... finds it again.
linesrequiredarray of objectWhat is going out. Each line ships against an order line and cannot exceed what is left on it.
When it fails
StatusCodeMeaning
400invalid_requestA required field was missing.
422cannot_ship_quoteThe order is still a quote, so nothing is committed to ship.
422rule_violationNolaPro refused the document. message carries its reason.
422shipqty_exceeds_remainingMore than qtyorder - qtyship was sent.
422unknown_valueA reference did not resolve in this company.
curl -X POST \
  'https://acme.nolapro.com/!/api/v2/shipments' \
  -H 'Authorization: Bearer $NP_TOKEN' \
  -H 'Content-Type: application/json' \
  -H 'Idempotency-Key: your-unique-key' \
  -d '{
    "orderid": 104,
    "externalid": "crm-8842",
    "lines": [
        {
            "orderlineid": 104,
            "quantity": "3.000000"
        }
    ]
}'
Response 201
{
    "orderid": 104,
    "shipdate": "2026-08-01"
}
GET/shipments/{id} 200404

Retrieve one record.

Requires scope shipments:read.

Parameters
NameInTypeNotes
idrequiredpathintegerThe record id.
includequerystringComma-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
StatusCodeMeaning
404not_foundNo record with that id.
curl \
  'https://acme.nolapro.com/!/api/v2/shipments/104' \
  -H 'Authorization: Bearer $NP_TOKEN'
Response 200
{
    "orderid": 104,
    "carrierserviceid": 104,
    "carrierservice": "Example carrierservice",
    "shipdate": "2026-08-01T14:22:05Z",
    "locationid": 104,
    "location": "Example location"
}
PATCH/shipments/{id} 200400404409422

Update.

Requires scope shipments:write.

Parameters
NameInTypeNotes
idrequiredpathintegerThe record id.
Body
FieldTypeDescription
carrierserviceidintegerCarrier service the shipment goes out by.
shipdatestringWhen it went out.
externalidstring(100)Your own identifier for this record.
When it fails
StatusCodeMeaning
400invalid_requestThe request was malformed.
404not_foundNo such record, or it belongs to another company.
409stale_recordIf-Match did not match; someone else changed it first.
422rule_violationNolaPro refused the change. message carries its reason.
curl -X PATCH \
  'https://acme.nolapro.com/!/api/v2/shipments/104' \
  -H 'Authorization: Bearer $NP_TOKEN' \
  -H 'Content-Type: application/json' \
  -H 'Idempotency-Key: your-unique-key' \
  -d '{
    "carrierserviceid": 104,
    "shipdate": "2026-08-01"
}'
DELETE/shipments/{id} 200400409422

Cancel.

Requires scope shipments:cancel.

Parameters
NameInTypeNotes
idrequiredpathintegerThe record id.
When it fails
StatusCodeMeaning
400invalid_requestThe request was malformed.
409cannot_cancelSomething already depends on this document - a payment, a shipment, an invoice.
409shipment_already_invoicedThe shipment has been invoiced; the customer has been billed for it.
422unknown_valueNo such record in this company.
curl -X DELETE \
  'https://acme.nolapro.com/!/api/v2/shipments/104' \
  -H 'Authorization: Bearer $NP_TOKEN'
POST/shipments/{id}/invoice 200404409422

Invoice this shipment.

Not available through the API yet. The single-shipment branch of arorder2invoice.php terminates the request with its own page output, so this cannot be served as JSON without changing page code. Invoice the whole order with POST /orders/{id}/invoice, which is live. This endpoint answers 501 in the meantime.

Requires scope invoices:write.

Parameters
NameInTypeNotes
idrequiredpathinteger
Body
FieldTypeDescription
invoicedatestringInvoice date. Defaults to what NolaPro would use.
When it fails
StatusCodeMeaning
404not_foundNo shipment with that id.
409shipment_already_invoicedThe shipment is cancelled, or already invoiced.
422nothing_to_invoiceNothing on the shipment is billable.
curl -X POST \
  'https://acme.nolapro.com/!/api/v2/shipments/104/invoice' \
  -H 'Authorization: Bearer $NP_TOKEN' \
  -H 'Content-Type: application/json' \
  -H 'Idempotency-Key: your-unique-key' \
  -d '{
    "invoicedate": "2026-08-02"
}'
Response 200
{
    "orderstatus": "quote"
}
GET/shipments/{id}/pdf 200

Packing slip as a PDF

The packing slip for the shipment: what is in the boxes, without prices. 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.

Requires scope shipments:read.

Parameters
NameInTypeNotes
idrequiredpathintegerThe record id.
curl \
  'https://acme.nolapro.com/!/api/v2/shipments/104/pdf' \
  -H 'Authorization: Bearer $NP_TOKEN'
GET/shipments/{id}/boxlabels 200

Box labels as a PDF

Shipping labels for the cartons in this shipment, laid out for a label printer. 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.

Requires scope shipments:read.

Parameters
NameInTypeNotes
idrequiredpathintegerThe record id.
curl \
  'https://acme.nolapro.com/!/api/v2/shipments/104/boxlabels' \
  -H 'Authorization: Bearer $NP_TOKEN'