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

Purchase orders

Orders to your suppliers, in purchase units. Idempotent with Idempotency-Key.

purchasing:readpurchasing:writehttps://public-api.nutrasoft.ca/v1

The Purchase order object

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

    The supplier name as it stood on this order.

  • created_atstringnullable
    • UTC timestamp
  • expected_datestringnullable
    • date YYYY-MM-DD
  • linesarray of objectsnullable

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

    Show 12 fields of lines
    • idinteger
    • costnumbernullable

      Per purchase unit. Requires cost:read.

    • discount_ratenumbernullable

      Percent off this line. Requires cost:read.

    • expiration_datestringnullable
      • UTC timestamp
    • lead_timeintegernullable

      In days.

    • notesstringnullable
    • product_codestringnullable
    • product_idintegernullable
    • product_namestringnullable
    • quantitynumbernullable

      Ordered, in the purchase unit.

    • quantity_basenumbernullable

      Ordered, in the product's base unit.

    • supplier_partnostringnullable

      The supplier's part number.

  • order_datestringnullable
    • date YYYY-MM-DD
  • purchase_order_nointegernullable

    Unique within your account.

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

    Note CLOSED, where a sales order status uses CLOSE.

    • one ofOPENSENTCONFIRMEDCLOSEDBACK_ORDERCANCELLEDRECEIVED
  • subtotalnumbernullable

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

  • supplier_idintegernullable
  • supplier_referencestringnullable

    The supplier's own reference for this order.

  • 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.

  • updated_atstringnullable
    • UTC timestamp

Operations

List purchase orders

get/purchase-orderspurchasing:read

Intent to buy: a purchase order never moves stock. Use search or the named filters, not both. Money fields require cost:read.

Query parameters

  • supplier_idintegernullable
    • > 0
  • statusarray of stringnullable

    Repeat the parameter to match any of several statuses.

    • one ofOPENSENTCONFIRMEDCLOSEDBACK_ORDERCANCELLEDRECEIVED
  • 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, purchase_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 PurchaseOrder objects in data, with pagination.
Errors
400 401 403 429 500 503
GET /purchase-orders
curl "https://public-api.nutrasoft.ca/v1/purchase-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",
      "expected_date": "2026-09-10",
      "lines": null,
      "order_date": "2026-09-10",
      "purchase_order_no": 10,
      "received_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,
      "supplier_id": 123,
      "supplier_reference": "INV-58213",
      "tax1": false,
      "tax1_rate": 12.5,
      "tax2": false,
      "tax2_rate": 12.5,
      "updated_at": "2026-09-10T14:30:00Z"
    }
  ],
  "pagination": {
    "limit": 50,
    "offset": 0,
    "total": 1,
    "has_more": false
  },
  "order": "id:asc"
}

Retrieve a purchase order

get/purchase-orders/{purchase_order_id}purchasing:read

Path parameters

  • purchase_order_idintegerrequired

    The order's id.

    • > 0
Returns
200 One PurchaseOrder object in data.
Errors
400 401 403 404 429 500 503
GET /purchase-orders/{purchase_order_id}
curl "https://public-api.nutrasoft.ca/v1/purchase-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",
    "expected_date": "2026-09-10",
    "lines": [
      {
        "id": 123,
        "cost": 12.5,
        "discount_rate": 12.5,
        "expiration_date": "2026-09-10T14:30:00Z",
        "lead_time": 10,
        "notes": "string",
        "product_code": "SAMPLE-01",
        "product_id": 123,
        "product_name": "Sample name",
        "quantity": 12.5,
        "quantity_base": 12.5,
        "supplier_partno": "string"
      }
    ],
    "order_date": "2026-09-10",
    "purchase_order_no": 10,
    "received_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,
    "supplier_id": 123,
    "supplier_reference": "INV-58213",
    "tax1": false,
    "tax1_rate": 12.5,
    "tax2": false,
    "tax2_rate": 12.5,
    "updated_at": "2026-09-10T14:30:00Z"
  }
}

Create a purchase order

post/purchase-orderspurchasing:write· idempotent with Idempotency-Key

Raises an OPEN order: no stock moves and no cost changes. The vendor block and ship-to are copied from the supplier, and the subtotal is computed from the lines.

Idempotent on Idempotency-Key: a retry with the same key returns the order the first call created, with status 200. Reusing a key with a different body is a 409.

Refused with 409 when your account blocks unapproved suppliers and this one is suspended or rejected.

Headers

  • Idempotency-Keystringnullable

    Your own unique string for this order, up to 200 characters. Reusing it returns the order it created the first time.

    • max 200 chars

Request body

  • linesarray of objectsrequired

    From 1 to 200 lines.

    • 1 to 200 items
    Show 8 fields of lines
    • product_idintegerrequired

      A product in your account.

      • > 0
    • quantitynumberrequired

      In the product's purchase unit.

      • > 0
    • costnumbernullable

      Per purchase unit.

      • >= 0
    • discount_ratenumbernullable

      Percent off this line, 0 to 100.

      • >= 0
      • <= 100
    • expiration_datestringnullable
      • date YYYY-MM-DD
    • lead_timeintegernullable

      In days.

      • >= 0
    • notesstringnullable
      • max 2000 chars
    • supplier_partnostringnullable

      The supplier's part number.

      • max 100 chars
  • supplier_idintegerrequired
    • > 0
  • expected_datestringnullable
    • date YYYY-MM-DD
  • notesstringnullable
    • max 2000 chars
  • order_datestringnullable
    • date YYYY-MM-DD
  • supplier_referencestringnullable

    The supplier's own reference for this order.

    • max 255 chars
Returns
201 One PurchaseOrder object in data.
Errors
400 401 403 409 429 500 503
POST /purchase-orders
curl -X POST "https://public-api.nutrasoft.ca/v1/purchase-orders" \
  -H "Authorization: Bearer $NUTRASOFT_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: 3f1c6a52-8d0e-4b7a-9c2f-5e8d1b4a7c90" \
  -d '{
  "lines": [
    {
      "product_id": 123,
      "quantity": 12.5
    }
  ],
  "supplier_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",
    "expected_date": "2026-09-10",
    "lines": [
      {
        "id": 123,
        "cost": 12.5,
        "discount_rate": 12.5,
        "expiration_date": "2026-09-10T14:30:00Z",
        "lead_time": 10,
        "notes": "string",
        "product_code": "SAMPLE-01",
        "product_id": 123,
        "product_name": "Sample name",
        "quantity": 12.5,
        "quantity_base": 12.5,
        "supplier_partno": "string"
      }
    ],
    "order_date": "2026-09-10",
    "purchase_order_no": 10,
    "received_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,
    "supplier_id": 123,
    "supplier_reference": "INV-58213",
    "tax1": false,
    "tax1_rate": 12.5,
    "tax2": false,
    "tax2_rate": 12.5,
    "updated_at": "2026-09-10T14:30:00Z"
  }
}

Update a purchase order

patch/purchase-orders/{purchase_order_id}purchasing:write

Only OPEN and SENT orders are editable; anything else is a 409. Omitted fields are left unchanged.

Sending lines replaces every line and recomputes the subtotal. Changing supplier_id copies the vendor block and ship-to from the new supplier. Not idempotent.

Path parameters

  • purchase_order_idintegerrequired

    The order's id.

    • > 0

Request body

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

    The complete set of lines, from 1 to 200. They replace every line on the order.

    • 1 to 200 items
    Show 8 fields of lines
    • product_idintegerrequired

      A product in your account.

      • > 0
    • quantitynumberrequired

      In the product's purchase unit.

      • > 0
    • costnumbernullable

      Per purchase unit.

      • >= 0
    • discount_ratenumbernullable

      Percent off this line, 0 to 100.

      • >= 0
      • <= 100
    • expiration_datestringnullable
      • date YYYY-MM-DD
    • lead_timeintegernullable

      In days.

      • >= 0
    • notesstringnullable
      • max 2000 chars
    • supplier_partnostringnullable

      The supplier's part number.

      • max 100 chars
  • notesstringnullable
    • max 2000 chars
  • order_datestringnullable
    • date YYYY-MM-DD
  • supplier_idintegernullable
    • > 0
  • supplier_referencestringnullable
    • max 255 chars
Returns
200 One PurchaseOrder object in data.
Errors
400 401 403 404 409 429 500 503
PATCH /purchase-orders/{purchase_order_id}
curl -X PATCH "https://public-api.nutrasoft.ca/v1/purchase-orders/123" \
  -H "Authorization: Bearer $NUTRASOFT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "expected_date": "2026-09-10"
}'
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",
    "expected_date": "2026-09-10",
    "lines": [
      {
        "id": 123,
        "cost": 12.5,
        "discount_rate": 12.5,
        "expiration_date": "2026-09-10T14:30:00Z",
        "lead_time": 10,
        "notes": "string",
        "product_code": "SAMPLE-01",
        "product_id": 123,
        "product_name": "Sample name",
        "quantity": 12.5,
        "quantity_base": 12.5,
        "supplier_partno": "string"
      }
    ],
    "order_date": "2026-09-10",
    "purchase_order_no": 10,
    "received_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,
    "supplier_id": 123,
    "supplier_reference": "INV-58213",
    "tax1": false,
    "tax1_rate": 12.5,
    "tax2": false,
    "tax2_rate": 12.5,
    "updated_at": "2026-09-10T14:30:00Z"
  }
}

Change a purchase order's status

post/purchase-orders/{purchase_order_id}/statuspurchasing:write

OPEN may move to SENT, CONFIRMED or CANCELLED; SENT to CONFIRMED or CANCELLED; CONFIRMED to CANCELLED; RECEIVED and BACK_ORDER to CLOSED. Any other move is a 409, and a closed order is final.

Path parameters

  • purchase_order_idintegerrequired

    The order's id.

    • > 0

Request body

  • statusstringrequired

    RECEIVED and BACK_ORDER are written by receiving in NutraSoft and cannot be set here.

    • one ofSENTCONFIRMEDCANCELLEDCLOSED
Returns
200 One PurchaseOrder object in data.
Errors
400 401 403 404 409 429 500 503
POST /purchase-orders/{purchase_order_id}/status
curl -X POST "https://public-api.nutrasoft.ca/v1/purchase-orders/123/status" \
  -H "Authorization: Bearer $NUTRASOFT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "status": "SENT"
}'
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",
    "expected_date": "2026-09-10",
    "lines": [
      {
        "id": 123,
        "cost": 12.5,
        "discount_rate": 12.5,
        "expiration_date": "2026-09-10T14:30:00Z",
        "lead_time": 10,
        "notes": "string",
        "product_code": "SAMPLE-01",
        "product_id": 123,
        "product_name": "Sample name",
        "quantity": 12.5,
        "quantity_base": 12.5,
        "supplier_partno": "string"
      }
    ],
    "order_date": "2026-09-10",
    "purchase_order_no": 10,
    "received_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,
    "supplier_id": 123,
    "supplier_reference": "INV-58213",
    "tax1": false,
    "tax1_rate": 12.5,
    "tax2": false,
    "tax2_rate": 12.5,
    "updated_at": "2026-09-10T14:30:00Z"
  }
}