API reference
Sales order
https://v2.cartage.ai/p/v2/salesOrder reads (GET) and creates (POST) sales orders.
A sales order is a customer's order for goods: who ordered, what lines, when it must ship, and which shipments fulfil it.
Authentication, the create envelope, error format and shared objects are in Shared rules.
GET /p/v2/salesOrder
Read one order by id or by referenceNumber. Send exactly one of the two.
| Parameter | Required | Description |
|---|---|---|
orgId |
Yes | Your organization ID |
id |
One of the two | Sales order id |
referenceNumber |
One of the two | Your order number, for example SO-1042 |
curl "https://v2.cartage.ai/p/v2/salesOrder?orgId=<yourOrgId>&referenceNumber=SO-1042" \
-H "X-API-Key: <yourApiKey>"
Returns the order (see Schema). shipmentIds comes back as ids; read each one through /p/v2/shipment.
POST /p/v2/salesOrder
Create one sales order.
Required fields
| Field | Required | If missing |
|---|---|---|
status |
Always | 400 |
shipmentIds |
Always. Send [] if there is no shipment yet. |
400 |
customerName |
When status is anything other than open |
422 SALES_ORDER_CUSTOMER_NAME |
commodities with at least one line |
When status is anything other than open |
422 SALES_ORDER_COMMODITIES |
commodities[].id, commodities[].name |
On every line you send | 400 |
stops[].sequenceNumber |
On every stop you send | 400 |
Smallest valid salesOrder:
- At
open:{ "status": "open", "shipmentIds": [] } - At any other status:
{ "status": "fulfilled", "shipmentIds": [], "customerName": "Acme Foods", "commodities": [ { "id": "line-1", "name": "Oat Flour 25kg" } ] }
Leave referenceNumber out and one is created for you (SO-####). Reference numbers are not checked for duplicates. If two orders share one, read them by id.
Example
curl -X POST "https://v2.cartage.ai/p/v2/salesOrder" \
-H "X-API-Key: <yourApiKey>" \
-H "Content-Type: application/json" \
-d '{
"orgId": "<yourOrgId>",
"salesOrder": {
"referenceNumber": "SO-1042",
"status": "open",
"shipmentIds": [],
"customerName": "Acme Foods",
"customerReferenceNumber": "PO-77120",
"requestedDeliveryDate": "2026-09-18",
"commodities": [
{ "id": "line-1", "name": "Oat Flour 25kg", "quantity": 400 }
]
}
}'
{
"status": "CREATED",
"salesOrder": { "id": "so_123", "referenceNumber": "SO-1042", "status": "open", "…": "…" }
}
Errors
| Status | Code | Meaning and fix |
|---|---|---|
| 400 | — | On GET, missing orgId, or both or neither of id and referenceNumber. On POST, a missing status or shipmentIds, a wrong type, an unknown enum value, or a field not in the Schema. issues[] names each one. |
| 401 | — | Missing or invalid API key |
| 404 | SALES_ORDER_NOT_FOUND |
No matching order in your organization |
| 409 | SALES_ORDER_REFERENCE_NUMBER_AMBIGUOUS |
GET only. More than one order has that referenceNumber. Read the one you mean by id. |
| 422 | REQUIRED_FIELDS_MISSING |
The order is missing what its status requires. Each issues[] entry carries one of the codes in Required fields. Fill them, or send status: "open". |
Schema
Optional unless marked Required. id, orgId, createdAt, updatedAt and activityLog are returned on every order and cannot be sent.
| Field | Type | Description |
|---|---|---|
status |
enum | Required. open | partialFulfilled | fulfilled | closed | cancelled |
shipmentIds |
string[] | Required (may be []). Shipments fulfilling the order |
customerName |
string | Required unless open. Buyer's company name |
commodities |
object[] | Required unless open. Ordered lines. Each needs id and name; also takes productId, quantity, unitWeight, totalWeight, dimensions, freightClass, nmfcItemCode. |
referenceNumber |
string | Your order number. Created as SO-#### if left out. |
fulfillmentStatus |
enum | unfulfilled | partial | fulfilled |
customerContact |
Contact | Buyer contact |
customerReferenceNumber |
string | The customer's own PO number |
orderDate |
string | YYYY-MM-DD the order was placed. Leave out if unknown. |
requestedDeliveryDate |
string | YYYY-MM-DD the order must ship or deliver |
subtotal / tax / shippingCost |
Money | Order amounts |
paymentTerms |
enum | net0 | net7 | net15 | net28 | net30 | net60 | net90 |
stops |
object[] | Route, in order. Each is an Address plus a required sequenceNumber (0 = origin). |
vendorIds |
string[] | Vendors involved |
externalNote |
string | Customer-facing notes |
notes |
string | Free-form working notes |
fileIds |
string[] | Attached files |
Read-only fields
| Field | Type | Description |
|---|---|---|
origin / destination |
Address | First and last stop |
totalAmount |
Money | Order total |
productIds |
string[] | Products named on the commodity lines |