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

The Product object

  • idinteger
  • activeboolean
  • allergensarray of objectsnullable

    On GET /products/{product_id} only; null on the list.

    Show 5 fields of allergens
    • allergen_idinteger
    • codestringnullable
    • is_major_allergenboolean
    • namestringnullable
    • sourcestring

      declared: recorded directly against this product.

  • costnumbernullable

    Cost per inventory unit. Requires cost:read; null means redacted, not zero. Separate from operations_cost.

  • created_atstringnullable
    • UTC timestamp
  • descriptionstringnullable
  • is_deletedboolean
  • kindstring

    Derived from product_type. Says which of material and recipe is populated.

    • one ofmaterialrecipe
  • materialobjectnullable

    Populated only when kind is material.

    Show 4 fields of material
    • banned_country_idsarray of integer
    • food_idintegernullable

      The nutrition source. Fetch with GET /foods/{food_id}.

    • substitute_product_idsarray of integer
    • supplier_idsarray of integer
  • namestringnullable
Show 11 more attributes
  • operations_costnumbernullable

    Operations cost per inventory unit. Requires cost:read.

  • product_codestringnullable
  • product_typestring
    • one ofRAW_MATERIALPACKAGINGMISCELLANEOUSRECIPESUB_RECIPEFINISHED_GOOD
  • recipeobjectnullable

    Populated only when kind is recipe.

    Show 6 fields of recipe
    • byproduct_product_idsarray of integer
    • ingredients_enstringnullable

      The generated ingredient declaration.

    • ingredients_frstringnullable
    • portion_in_gramsnumbernullable
    • qc_checkpoint_idsarray of integer
    • recipe_grams_yieldnumbernullable
  • shelf_lifeintegernullable
  • tag_idsarray of integernullable

    On GET /products/{product_id} only; null on the list.

  • unit_of_measure_idintegernullable
  • uom_base_conversionnumbernullable

    Second conversion factor. See uom_qty.

  • uom_base_idintegernullable
  • uom_qtynumbernullable

    First conversion factor. One inventory unit is uom_qty * uom_base_conversion base units.

  • updated_atstringnullable
    • UTC timestamp

Product families

Fields each product family carries
FieldMaterialRecipe
product_typeRAW_MATERIAL, PACKAGING, MISCELLANEOUSRECIPE, SUB_RECIPE, FINISHED_GOOD
kindmaterialrecipe
material.banned_country_idsYesNo, material is null
material.food_idThe nutrition source. Fetch with GET /foods/{food_id}.YesNo, material is null
material.substitute_product_idsYesNo, material is null
material.supplier_idsYesNo, material is null
recipe.byproduct_product_idsNo, recipe is nullYes
recipe.ingredients_enThe generated ingredient declaration.No, recipe is nullYes
recipe.ingredients_frNo, recipe is nullYes
recipe.portion_in_gramsNo, recipe is nullYes
recipe.qc_checkpoint_idsNo, recipe is nullYes
recipe.recipe_grams_yieldNo, recipe is nullYes
Allergensallergens[].allergen_idYesYes
Tagstag_idsYesYes
Units of measureunit_of_measure_idYesYes
Product lotslinked by product_idYesYes

Operations

List products

get/productscatalog:read

One table, two families: every row carries kind, material or recipe. allergens, tag_ids, material and recipe are null here: retrieve a product for them.

Query parameters

  • namestringnullable

    Partial match.

  • product_codestringnullable

    Partial match.

  • product_typesarray of stringnullable

    Repeat the parameter to match any of several types.

    • one ofRAW_MATERIALPACKAGINGMISCELLANEOUSRECIPESUB_RECIPEFINISHED_GOOD
  • searchstringnullable

    Free-text match.

  • sortstringnullable

    Comma-separated field:direction pairs, e.g. id:desc. Sortable: created_at, id, name, product_code, product_type, 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 Product objects in data, with pagination.
Errors
400 401 403 429 500 503
GET /products
curl "https://public-api.nutrasoft.ca/v1/products?limit=50" \
  -H "Authorization: Bearer $NUTRASOFT_API_KEY"
Response200
{
  "data": [
    {
      "id": 123,
      "active": true,
      "allergens": null,
      "cost": 12.5,
      "created_at": "2026-09-10T14:30:00Z",
      "description": "string",
      "is_deleted": false,
      "kind": "material",
      "material": {
        "banned_country_ids": [
          123
        ],
        "food_id": 123,
        "substitute_product_ids": [
          123
        ],
        "supplier_ids": [
          123
        ]
      },
      "name": "Sample name",
      "operations_cost": 12.5,
      "product_code": "SAMPLE-01",
      "product_type": "RAW_MATERIAL",
      "recipe": null,
      "shelf_life": 10,
      "tag_ids": null,
      "unit_of_measure_id": 123,
      "uom_base_conversion": 12.5,
      "uom_base_id": 123,
      "uom_qty": 12.5,
      "updated_at": "2026-09-10T14:30:00Z"
    }
  ],
  "pagination": {
    "limit": 50,
    "offset": 0,
    "total": 1,
    "has_more": false
  },
  "order": "id:asc"
}

Retrieve a product

get/products/{product_id}catalog:read

Exactly one of material and recipe is populated, as kind says. The bill of materials is not published in v1.

Path parameters

  • product_idintegerrequired

    The product's id.

    • > 0
Returns
200 One Product object in data.
Errors
400 401 403 404 429 500 503
GET /products/{product_id}
curl "https://public-api.nutrasoft.ca/v1/products/123" \
  -H "Authorization: Bearer $NUTRASOFT_API_KEY"
Response200
{
  "data": {
    "id": 123,
    "active": true,
    "allergens": [
      {
        "allergen_id": 123,
        "code": "SAMPLE-01",
        "is_major_allergen": false,
        "name": "Sample name",
        "source": "string"
      }
    ],
    "cost": 12.5,
    "created_at": "2026-09-10T14:30:00Z",
    "description": "string",
    "is_deleted": false,
    "kind": "material",
    "material": {
      "banned_country_ids": [
        123
      ],
      "food_id": 123,
      "substitute_product_ids": [
        123
      ],
      "supplier_ids": [
        123
      ]
    },
    "name": "Sample name",
    "operations_cost": 12.5,
    "product_code": "SAMPLE-01",
    "product_type": "RAW_MATERIAL",
    "recipe": null,
    "shelf_life": 10,
    "tag_ids": [
      123
    ],
    "unit_of_measure_id": 123,
    "uom_base_conversion": 12.5,
    "uom_base_id": 123,
    "uom_qty": 12.5,
    "updated_at": "2026-09-10T14:30:00Z"
  }
}