NutraSoft food manufacturing ERP software
Esc
  • GuideGetting startedThree steps to your first call and your first order, then the two shapes every response takes.
  • GuideAuthentication and keysBearer keys, test and live environments, rotation without an outage, and what each scope grants.
  • GuideTest modeA second NutraSoft account of your own, seeded with realistic data, that you can safely break.
  • PageErrorsEvery error code the API returns, what it means, what to do about it and whether to retry.
  • PageConventionsThe rules every operation follows: money, time, paging, sorting, nulls, PATCH and identifiers.
Menu

Sales orders

Orders from your customers, with their lines in both the ordered unit and base units.

sales:readsales:writehttps://public-api.nutrasoft.ca/v1

The Sales order object

  • idinteger
  • billing_addressobject
    Show 5 fields of billing_address
    • citystringnullable
    • line1stringnullable
    • line2stringnullable
    • postal_codestringnullable
    • statestringnullable
  • companystringnullable

    The customer name as it stood on this order.

  • created_atstringnullable
    • UTC timestamp
  • customer_idintegernullable
  • customer_purchase_order_nostringnullable

    The customer's own purchase order reference. Free text.

  • expected_datestringnullable
    • date YYYY-MM-DD
  • linesarray of objectsnullable

    On a single order and on writes; null on the list.

    Show 14 fields of lines
    • idinteger

      Send it back on PATCH to keep this line.

    • cancelled_qty_basenumbernullable

      Written off, in the product's base unit.

    • discount_ratenumbernullable

      Percent off this line. Requires cost:read.

    • notesstringnullable
    • order_qtynumbernullable

      Ordered, in uom_type units.

    • order_qty_basenumbernullable

      Ordered, in the product's base unit.

    • pricenumbernullable

      Per uom_type unit. Requires cost:read.

    • product_codestringnullable
    • product_idintegernullable
    • product_namestringnullable
    • shipped_qty_basenumbernullable

      Shipped, in the product's base unit.

    • tax1booleannullable

      Whether tax 1 applies to this line. Requires cost:read.

    • tax2booleannullable

      Whether tax 2 applies to this line. Requires cost:read.

    • uom_typestringnullable

      The unit order_qty and price are in.

      • one ofINVENTORY_UNITPACKAGING_SIZEBASE_UOM
  • order_datestringnullable
    • date YYYY-MM-DD
  • sales_order_nointegernullable

    The order number, unique in your account.

Show 10 more attributes
  • ship_datestringnullable
    • date YYYY-MM-DD
  • shipping_addressobject
    Show 5 fields of shipping_address
    • citystringnullable
    • line1stringnullable
    • line2stringnullable
    • postal_codestringnullable
    • statestringnullable
  • statusstring

    Note CLOSE, where a purchase order status uses CLOSED.

    • one ofOPENBACK_ORDERPREPARINGCANCELLEDCLOSESHIPPED
  • subtotalnumbernullable

    Sum of the lines after line discounts, before tax. Requires cost:read; null means redacted, not zero.

  • tax1booleannullable

    Whether tax 1 applies to this document. Requires cost:read; null means redacted, not false.

  • tax1_ratenumbernullable

    Tax 1 percentage, e.g. 5.0 for 5%. Requires cost:read.

  • tax2booleannullable

    Whether tax 2 applies to this document. Requires cost:read; null means redacted, not false.

  • tax2_ratenumbernullable

    Tax 2 percentage, e.g. 5.0 for 5%. Requires cost:read.

  • tracking_numberstringnullable
  • updated_atstringnullable
    • UTC timestamp

Operations

List sales orders

get/sales-orderssales:read

Money fields require cost:read. Addresses are those the order was raised with.

Query parameters

  • customer_idintegernullable
    • > 0
  • statusarray of stringnullable

    Repeat the parameter to match any of several statuses.

    • one ofOPENBACK_ORDERPREPARINGCANCELLEDCLOSESHIPPED
  • order_date_fromstringnullable
    • date YYYY-MM-DD
  • order_date_tostringnullable
    • date YYYY-MM-DD
  • searchstringnullable

    Free-text match.

  • sortstringnullable

    Comma-separated field:direction pairs, e.g. id:desc. Sortable: created_at, expected_date, id, order_date, sales_order_no, status, updated_at. id is always added last, so paging is stable.

  • limitinteger

    Rows to return. Maximum 200.

    • >= 1
    • <= 200
    • default 50
  • offsetinteger

    Rows to skip. Maximum 10000: to read further, narrow the filters or page with updated_since.

    • >= 0
    • <= 10000
    • default 0
  • updated_sincestringnullable

    Only rows changed after this instant, as an ISO 8601 timestamp; without an offset it is read as UTC. Tracks the record itself, not its child rows, and deletions are not reported, so reconcile by re-listing from time to time.

    • UTC timestamp
Returns
200 A page of SalesOrder objects in data, with pagination.
Errors
400 401 403 429 500 503
GET /sales-orders
curl "https://public-api.nutrasoft.ca/v1/sales-orders?limit=50" \
  -H "Authorization: Bearer $NUTRASOFT_API_KEY"
Response200
{
  "data": [
    {
      "id": 123,
      "billing_address": {
        "city": "Montreal",
        "line1": "123 Example Street",
        "line2": "Suite 200",
        "postal_code": "H4S 2C1",
        "state": "QC"
      },
      "company": "Example Foods Inc.",
      "created_at": "2026-09-10T14:30:00Z",
      "customer_id": 123,
      "customer_purchase_order_no": "PO-10042",
      "expected_date": "2026-09-10",
      "lines": null,
      "order_date": "2026-09-10",
      "sales_order_no": 10,
      "ship_date": "2026-09-10",
      "shipping_address": {
        "city": "Montreal",
        "line1": "123 Example Street",
        "line2": "Suite 200",
        "postal_code": "H4S 2C1",
        "state": "QC"
      },
      "status": "OPEN",
      "subtotal": 12.5,
      "tax1": false,
      "tax1_rate": 12.5,
      "tax2": false,
      "tax2_rate": 12.5,
      "tracking_number": "string",
      "updated_at": "2026-09-10T14:30:00Z"
    }
  ],
  "pagination": {
    "limit": 50,
    "offset": 0,
    "total": 1,
    "has_more": false
  },
  "order": "id:asc"
}

Retrieve a sales order

get/sales-orders/{sales_order_id}sales:read

Path parameters

  • sales_order_idintegerrequired

    The order's id.

    • > 0
Returns
200 One SalesOrder object in data.
Errors
400 401 403 404 429 500 503
GET /sales-orders/{sales_order_id}
curl "https://public-api.nutrasoft.ca/v1/sales-orders/123" \
  -H "Authorization: Bearer $NUTRASOFT_API_KEY"
Response200
{
  "data": {
    "id": 123,
    "billing_address": {
      "city": "Montreal",
      "line1": "123 Example Street",
      "line2": "Suite 200",
      "postal_code": "H4S 2C1",
      "state": "QC"
    },
    "company": "Example Foods Inc.",
    "created_at": "2026-09-10T14:30:00Z",
    "customer_id": 123,
    "customer_purchase_order_no": "PO-10042",
    "expected_date": "2026-09-10",
    "lines": [
      {
        "id": 123,
        "cancelled_qty_base": 12.5,
        "discount_rate": 12.5,
        "notes": "string",
        "order_qty": 12.5,
        "order_qty_base": 12.5,
        "price": 12.5,
        "product_code": "SAMPLE-01",
        "product_id": 123,
        "product_name": "Sample name",
        "shipped_qty_base": 12.5,
        "tax1": false,
        "tax2": false,
        "uom_type": "INVENTORY_UNIT"
      }
    ],
    "order_date": "2026-09-10",
    "sales_order_no": 10,
    "ship_date": "2026-09-10",
    "shipping_address": {
      "city": "Montreal",
      "line1": "123 Example Street",
      "line2": "Suite 200",
      "postal_code": "H4S 2C1",
      "state": "QC"
    },
    "status": "OPEN",
    "subtotal": 12.5,
    "tax1": false,
    "tax1_rate": 12.5,
    "tax2": false,
    "tax2_rate": 12.5,
    "tracking_number": "string",
    "updated_at": "2026-09-10T14:30:00Z"
  }
}

Create a sales order

post/sales-orderssales:write

Creates an OPEN order with its lines. Each order_qty is in its line's uom_type unit and is stored in base units, and the subtotal is computed from the lines. Not idempotent: a retry creates a second order.

Request body

  • customer_idintegerrequired

    A customer in your account.

    • > 0
  • linesarray of objectsrequired

    From 1 to 200 lines.

    • 1 to 200 items
    Show 9 fields of lines
    • order_qtynumberrequired

      Quantity ordered, in uom_type units.

      • > 0
    • product_idintegerrequired

      A product in your account.

      • > 0
    • discount_ratenumbernullable

      Percent off this line, 0 to 100.

      • >= 0
      • <= 100
    • idintegernullable

      On PATCH, the id of an existing line to keep and update. Omit it to add a line.

      • > 0
    • notesstringnullable
      • max 2000 chars
    • pricenumbernullable

      Per uom_type unit, stored as sent. No price list is applied.

      • >= 0
    • tax1boolean

      Whether tax 1 applies to this line.

      • default false
    • tax2boolean

      Whether tax 2 applies to this line.

      • default false
    • uom_typestring

      The unit order_qty and price are in: BASE_UOM is the base unit, INVENTORY_UNIT holds uom_qty * uom_base_conversion base units and PACKAGING_SIZE holds uom_base_conversion, per the product.

      • default BASE_UOM
      • one ofINVENTORY_UNITPACKAGING_SIZEBASE_UOM
  • billing_addressobjectnullable

    Omit it to use the customer's current address.

    Show 5 fields of billing_address
    • citystringnullable
      • max 100 chars
    • line1stringnullable
      • max 100 chars
    • line2stringnullable
      • max 100 chars
    • postal_codestringnullable

      Postal or ZIP code.

      • max 20 chars
    • statestringnullable

      Province or state. Free text.

      • max 100 chars
  • customer_purchase_order_nostringnullable

    The customer's own purchase order reference. Free text.

    • max 100 chars
  • expected_datestringnullable
    • date YYYY-MM-DD
  • order_datestringnullable
    • date YYYY-MM-DD
  • shipping_addressobjectnullable

    Omit it to use the billing address of this order.

    Show 5 fields of shipping_address
    • citystringnullable
      • max 100 chars
    • line1stringnullable
      • max 100 chars
    • line2stringnullable
      • max 100 chars
    • postal_codestringnullable

      Postal or ZIP code.

      • max 20 chars
    • statestringnullable

      Province or state. Free text.

      • max 100 chars
  • tracking_numberstringnullable
    • max 100 chars
Returns
201 One SalesOrder object in data.
Errors
400 401 403 409 429 500 503
POST /sales-orders
curl -X POST "https://public-api.nutrasoft.ca/v1/sales-orders" \
  -H "Authorization: Bearer $NUTRASOFT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "customer_id": 123,
  "lines": [
    {
      "order_qty": 12.5,
      "product_id": 123
    }
  ]
}'
Response201
{
  "data": {
    "id": 123,
    "billing_address": {
      "city": "Montreal",
      "line1": "123 Example Street",
      "line2": "Suite 200",
      "postal_code": "H4S 2C1",
      "state": "QC"
    },
    "company": "Example Foods Inc.",
    "created_at": "2026-09-10T14:30:00Z",
    "customer_id": 123,
    "customer_purchase_order_no": "PO-10042",
    "expected_date": "2026-09-10",
    "lines": [
      {
        "id": 123,
        "cancelled_qty_base": 12.5,
        "discount_rate": 12.5,
        "notes": "string",
        "order_qty": 12.5,
        "order_qty_base": 12.5,
        "price": 12.5,
        "product_code": "SAMPLE-01",
        "product_id": 123,
        "product_name": "Sample name",
        "shipped_qty_base": 12.5,
        "tax1": false,
        "tax2": false,
        "uom_type": "INVENTORY_UNIT"
      }
    ],
    "order_date": "2026-09-10",
    "sales_order_no": 10,
    "ship_date": "2026-09-10",
    "shipping_address": {
      "city": "Montreal",
      "line1": "123 Example Street",
      "line2": "Suite 200",
      "postal_code": "H4S 2C1",
      "state": "QC"
    },
    "status": "OPEN",
    "subtotal": 12.5,
    "tax1": false,
    "tax1_rate": 12.5,
    "tax2": false,
    "tax2_rate": 12.5,
    "tracking_number": "string",
    "updated_at": "2026-09-10T14:30:00Z"
  }
}

Update a sales order

patch/sales-orders/{sales_order_id}sales:write

Omitted fields are left unchanged. Sending lines replaces the order's lines and recomputes its subtotal.

Refused with 409 for an order that is not OPEN and for one placed and paid through the storefront.

Path parameters

  • sales_order_idintegerrequired

    The order's id.

    • > 0

Request body

  • billing_addressobjectnullable
    Show 5 fields of billing_address
    • citystringnullable
      • max 100 chars
    • line1stringnullable
      • max 100 chars
    • line2stringnullable
      • max 100 chars
    • postal_codestringnullable

      Postal or ZIP code.

      • max 20 chars
    • statestringnullable

      Province or state. Free text.

      • max 100 chars
  • customer_idintegernullable
    • > 0
  • customer_purchase_order_nostringnullable
    • max 100 chars
  • expected_datestringnullable
    • date YYYY-MM-DD
  • linesarray of objectsnullable

    The complete set of lines, from 1 to 200. A line sent with its id is updated, a line without one is added, and a line left out is deleted. The subtotal is recomputed. Round trips need cost:read, or the prices you send back are empty.

    • 1 to 200 items
    Show 9 fields of lines
    • order_qtynumberrequired

      Quantity ordered, in uom_type units.

      • > 0
    • product_idintegerrequired

      A product in your account.

      • > 0
    • discount_ratenumbernullable

      Percent off this line, 0 to 100.

      • >= 0
      • <= 100
    • idintegernullable

      On PATCH, the id of an existing line to keep and update. Omit it to add a line.

      • > 0
    • notesstringnullable
      • max 2000 chars
    • pricenumbernullable

      Per uom_type unit, stored as sent. No price list is applied.

      • >= 0
    • tax1boolean

      Whether tax 1 applies to this line.

      • default false
    • tax2boolean

      Whether tax 2 applies to this line.

      • default false
    • uom_typestring

      The unit order_qty and price are in: BASE_UOM is the base unit, INVENTORY_UNIT holds uom_qty * uom_base_conversion base units and PACKAGING_SIZE holds uom_base_conversion, per the product.

      • default BASE_UOM
      • one ofINVENTORY_UNITPACKAGING_SIZEBASE_UOM
  • order_datestringnullable
    • date YYYY-MM-DD
  • shipping_addressobjectnullable
    Show 5 fields of shipping_address
    • citystringnullable
      • max 100 chars
    • line1stringnullable
      • max 100 chars
    • line2stringnullable
      • max 100 chars
    • postal_codestringnullable

      Postal or ZIP code.

      • max 20 chars
    • statestringnullable

      Province or state. Free text.

      • max 100 chars
  • tracking_numberstringnullable
    • max 100 chars
Returns
200 One SalesOrder object in data.
Errors
400 401 403 404 409 429 500 503
PATCH /sales-orders/{sales_order_id}
curl -X PATCH "https://public-api.nutrasoft.ca/v1/sales-orders/123" \
  -H "Authorization: Bearer $NUTRASOFT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "customer_id": 123
}'
Response200
{
  "data": {
    "id": 123,
    "billing_address": {
      "city": "Montreal",
      "line1": "123 Example Street",
      "line2": "Suite 200",
      "postal_code": "H4S 2C1",
      "state": "QC"
    },
    "company": "Example Foods Inc.",
    "created_at": "2026-09-10T14:30:00Z",
    "customer_id": 123,
    "customer_purchase_order_no": "PO-10042",
    "expected_date": "2026-09-10",
    "lines": [
      {
        "id": 123,
        "cancelled_qty_base": 12.5,
        "discount_rate": 12.5,
        "notes": "string",
        "order_qty": 12.5,
        "order_qty_base": 12.5,
        "price": 12.5,
        "product_code": "SAMPLE-01",
        "product_id": 123,
        "product_name": "Sample name",
        "shipped_qty_base": 12.5,
        "tax1": false,
        "tax2": false,
        "uom_type": "INVENTORY_UNIT"
      }
    ],
    "order_date": "2026-09-10",
    "sales_order_no": 10,
    "ship_date": "2026-09-10",
    "shipping_address": {
      "city": "Montreal",
      "line1": "123 Example Street",
      "line2": "Suite 200",
      "postal_code": "H4S 2C1",
      "state": "QC"
    },
    "status": "OPEN",
    "subtotal": 12.5,
    "tax1": false,
    "tax1_rate": 12.5,
    "tax2": false,
    "tax2_rate": 12.5,
    "tracking_number": "string",
    "updated_at": "2026-09-10T14:30:00Z"
  }
}

Cancel a sales order

post/sales-orders/{sales_order_id}/cancelsales:write

Cancels the order and writes off every unshipped quantity. An order that already shipped something becomes CLOSE rather than CANCELLED, so read status on the response.

Only OPEN, BACK_ORDER, PREPARING and SHIPPED orders can be cancelled; anything else is a 409. An order paid through the storefront is also a 409: cancel it in NutraSoft, where the payment can be refunded.

Path parameters

  • sales_order_idintegerrequired

    The order's id.

    • > 0
Returns
200 One SalesOrder object in data.
Errors
400 401 403 404 409 429 500 503
POST /sales-orders/{sales_order_id}/cancel
curl -X POST "https://public-api.nutrasoft.ca/v1/sales-orders/123/cancel" \
  -H "Authorization: Bearer $NUTRASOFT_API_KEY"
Response200
{
  "data": {
    "id": 123,
    "billing_address": {
      "city": "Montreal",
      "line1": "123 Example Street",
      "line2": "Suite 200",
      "postal_code": "H4S 2C1",
      "state": "QC"
    },
    "company": "Example Foods Inc.",
    "created_at": "2026-09-10T14:30:00Z",
    "customer_id": 123,
    "customer_purchase_order_no": "PO-10042",
    "expected_date": "2026-09-10",
    "lines": [
      {
        "id": 123,
        "cancelled_qty_base": 12.5,
        "discount_rate": 12.5,
        "notes": "string",
        "order_qty": 12.5,
        "order_qty_base": 12.5,
        "price": 12.5,
        "product_code": "SAMPLE-01",
        "product_id": 123,
        "product_name": "Sample name",
        "shipped_qty_base": 12.5,
        "tax1": false,
        "tax2": false,
        "uom_type": "INVENTORY_UNIT"
      }
    ],
    "order_date": "2026-09-10",
    "sales_order_no": 10,
    "ship_date": "2026-09-10",
    "shipping_address": {
      "city": "Montreal",
      "line1": "123 Example Street",
      "line2": "Suite 200",
      "postal_code": "H4S 2C1",
      "state": "QC"
    },
    "status": "OPEN",
    "subtotal": 12.5,
    "tax1": false,
    "tax1_rate": 12.5,
    "tax2": false,
    "tax2_rate": 12.5,
    "tracking_number": "string",
    "updated_at": "2026-09-10T14:30:00Z"
  }
}