Recipe & Menu Engineering Import API Guide

Introduction

The Recipe & Menu Engineering (RME) Import API lets you create or update a wide range of ingredient and supplier details in Fourth.

Quick Facts

Integration type HTTP REST with JSON and XML
Authentication Basic authentication
Availability All customers using our Fourth Inventory for Restaurants solution
Testing Test environment available
More information See the Import API Reference

Get access

To get started with this API, you will need:

  • A Recipe & Menu Engineering Import API account to access this API
  • The root URL for requests to the test and live environments

Your mutual Fourth customer must request credentials on your behalf. Please ensure they do this as soon as possible. The Fourth Professional Services team member managing the integration can provide the above information and help you with any integration questions you may have.

Note: Access to each POST and DELETE operation is provided only on request. If you wish to use an additional POST or DELETE operations in the future, please ask your customer to request this on your behalf. Existing and new GET operations are available without restriction to integrated partners.

Updates

You can find any updates on the Release Notes page for this API.

Uniquely identifying each ingredient

Inside Fourth, ingredients are linked with suppliers. When an ingredient is initially entered into Fourth via a POST /ingredients request, the ingredient must include these details:

  • SupplierName — Name of the supplier
  • SupplierCode — A unique identifier for the ingredient, as provided by the supplier

Fourth assigns each new ingredient with a StarChefKey. This is a unique identifier that should be used when updating ingredient details using the other endpoints. Along with the SupplierName and SupplierCode, this identifier is returned in relevant ingredient-related GET requests.

When creating or updating ingredient records, these rules apply:

  • If the request includes a StarChefKey, then we use this to identify the ingredient. If the ingredient isn’t found, then we generate an error.
    The values for SupplierName and SupplierCode are not used for matching the ingredient. Instead:
    • If these have values, we update the record with the new values.
    • If the values are null, then we keep the existing values, as these fields must always have a value.
  • If the request does not include a StarChefKey, then we use the SupplierName and SupplierCode to check whether there is a matching ingredient record. If no record is found, we create a new record.

Category types

The Fourth Inventory for Restaurants solution has a hierarchy of user-defined categories. The top level category is category type, followed by main category and sub categories:

  1. Category Type
  2. Main Category
  3. SubCategory
  4. SubCategory
  5. SubCategory

Category types can be either “smart” or “system”. Smart categories align with categories in Fourth Inventory. Items can have multiple system categories, but typically have only one smart category. 

Ingredient Price Bands

Recipe & Menu Engineering supports price bands for ingredients. This enables our customers to have product-by-product or across-the-board price uplifts as necessary to support their different regions and restaurants.

In the API, we provide these endpoints for price bands:

Support for Natasha's Law

The Food Information (Amendment) (England) Regulations 2019, also known as Natasha’s Law, requires food businesses to label all food that is ‘pre-packaged for direct sale’ with the complete ingredient and allergen details.

To support this legislation, each ingredient and recipe in Fourth has fields to hold full sub-ingredient data. This data can come from two sources: manually keyed in by our customers, or via our APIs from a partner or supplier.

As well, you can specify consumer-friendly names for each ingredient and recipe. See Adding consumer-friendly naming below for more information.

Note: our RME Export API also has endpoints related to Natasha’s Law, which are used for auditing purposes.

Managing the ingredient list for an ingredient

The ingredient list field in Fourth is designed to hold the sub-ingredients and allergens for an ingredient.

Ingredient lists are specifically designed to provide the text required for labels and displays. They do not replace any requirements you have to supply nutrient and intolerance data for an ingredient via the POST ingredientnutrient and POST ingredientintolerance endpoints.

Screenshot showing the ingredient Tomato Ketchup, with the Ingredient List tab open. Four ingredients are in the list: “Tomatoes, Water, CELERY salt, Sugar”.

For example, the ingredient pasta sauce would have an ingredient list of: Tomatoes, basil, butter (Cow’s MILK, salt), onion, salt, pepper. Unless otherwise advised by your customer, send the allergens in uppercase, as the label design in Fourth specifies: "For allergens, see ingredients in UPPERCASE".

Ingredient lists are owned by parent ingredients, as the ingredients and allergens should be identical between parent and alternate ingredients. The lists also include a Ready for use field. This enables both partners (via the API) and customers to confirm that an ingredient list is accurate and ready for use on automatically-generated recipe labels.

Ingredient lists can hold far more data (beyond an order of magnitude) than any possible ingredient or recipe would contain, so treat these fields as having no maximum character limit.

The Recipe & Menu Engineering Import API provides these endpoints for managing ingredient lists for ingredients:

  • POST /ingredientlist — This enables partners to add and update the full ingredient list (sub-ingredients and allergens) for an ingredient. This request replaces all values currently in the ingredient list. Therefore, you must include ALL sub-ingredients and allergens in the ingredient in any request.
  • GET /ingredientlist — this retrieves the text in the ingredient list field.

Note that these endpoints are useable only when the customer has the full ingredient list functionality enabled.

Example POST request

See the API Reference for full details about this endpoint.

[
   {
      "SupplierName": "Grocer",
      "SupplierCode": "1357",
      "StarchefKey": "0014674",
      "FullIngredientList": " Water, MUSTARD Flour, Spirit Vinegar, Sea Salt, MUSTARD Husk, Pimento, Turmeric",
      "LabelDescription": "Dijon Mustard",
      "ReadyForUse": "YES"
   }
]

Example GET request

This example shows a parent ingredient, Bulgarian Beef Sausages with two alternate ingredients. Note that the value of ParentGuid and AlternateGuid is the same for the parent ingredient.

See the API Reference for full details about this endpoint.

[
   {
      "IngredientName": "Bulgarian Beef Sausages",
      "StarchefKey": "14889",
      "ParentGuid": "ad0e454a-cbf5-420e-9c36-8dd7e1fbc0cc",
      "AlternateGuid": "ad0e454a-cbf5-420e-9c36-8dd7e1fbc0cc",
      "FullIngredientList": "Beef, Oats (GLUTEN), Salt, Pepper, Nitrates E420",
      "LabelDescription": "Rich Beef Sausages",
      "ReadyForUse": "YES"
   },
   {
      "IngredientName": "Flashy Sausages Dog",
      "StarchefKey": "14891",
      "ParentGuid": "ad0e454a-cbf5-420e-9c36-8dd7e1fbc0cc",
      "AlternateGuid": "35a6d7a6-3e78-4d63-9b93-9073be0e0847",
      "FullIngredientList": "Beef, Oats (GLUTEN), Salt, Pepper, Nitrates E420",
      "LabelDescription": "Rich Beef Sausages",
      "ReadyForUse": "YES"
   },
   {
      "IngredientName": "Posh Sausages",
      "StarchefKey": "15861",
      "ParentGuid": "ad0e454a-cbf5-420e-9c36-8dd7e1fbc0cc",
      "AlternateGuid": "981f85d4-93e2-43ed-9b83-34f638d2f1ec",
      "FullIngredientList": "Beef, Oats (GLUTEN), Salt, Pepper, Nitrates E420",
      "LabelDescription": "Rich Beef Sausages",
      "ReadyForUse": "YES"
   }
]

Getting the ingredient lists for recipes

The GET /recipeingredientlist endpoint enables you to retrieve the full ingredient list for a recipe.  However, with recipes, there are two variations of ingredient list. For each recipe, the customer can select which list is preferred for creating labels and reports.

The variations are:

  • Manual — this list is keyed in by the customer. It does not auto-update in any way.
  • Automatically generated — this list is generated by Fourth. It combines the ingredient list for each ingredient in the recipe into one list. The lists for each ingredient are included in parenthesis, with the ingredients listed in weight order, in descending order by the amount within the recipe.

The automatically generated list updates when:

  •  An ingredient's ingredient list is changed.
  •  An ingredient is added or removed from a recipe.
  •  A conversion is added or removed.
  •  A recipe is part of another recipe, and the preferred field (auto-generated or manual) for the sub-recipe changes.
  •  The consumer-friendly name or main name fields for an ingredient or recipe change.

Automatically generated lists require all the ingredients in them to have ingredient lists that are "Ready for use". If an ingredient's ingredient list is not set as ready for use, then an error message is shown in the recipe's ingredient list. 

Screenshot showing the Ingredient Lists tab within Fourth. There are two fields for the two list types, each showing the ingredients for an Avocado and Crab salad. The allergens of ingredients are capitalized. “Use Automatic in report” is selected.

Ingredient lists can hold far more data (beyond an order of magnitude) than any possible ingredient or recipe would contain, so treat these fields as having no maximum character limit.

You can retrieve these lists using the GET /recipeingredientlist endpoint. The request body includes a PreferredFieldInTheReport value to ensure that you use the preferred list. During development, you should discuss with your customer what your system should do if the preferred field is empty.

Note that this endpoint returns data only when the customer has the full ingredient list functionality enabled.

Example GET request

See the API Reference for full details about this endpoint.

[
   {
      "RecipeName": "Avocado and Crayfish Salad",
      "StarchefKey": "14675",
      "RecipeGuid": "986601f8-1add-410f-aa80-b6e9e910a2f4",
      "ManualFullIngredientList": "Crayfish Tails (CRUSTACEAN), Avocado, Curly Endive, Little Gem Lettuce, Radicchio, Balsamic Vinegar and Mustard Dressing (Olive Oil, Balsamic Vinegar, Dijon Mustard (Water, MUSTARD Flour, Spirit Vinegar, Sea Salt, MUSTARD Husk, Pimento, Turmeric))",
      "ManualLastModifiedDate": "Feb 1 2021 2:23PM",
      "AutoFullIngredientList": "Crayfish Tails (CRUSTACEAN), Avocado, Lettuce Curly Endive, Lettuce, Little Gem, Lettuce Radicchio - Per Kg, Balsamic Vinegar and Mustard Dressing (Olive Oil, Balsamic Vinegar, Dijon Mustard (Water, MUSTARD Flour, Spirit Vinegar, Sea Salt, MUSTARD Husk, Pimento, Turmeric))",
      "AutoLastModifiedDate": "Feb 1 2021 2:14PM",
      "PreferredFieldInTheReport": "Auto"
   }
]

Adding consumer-friendly naming for ingredients and recipes

To further support creating labels suitable for consumers, each ingredient and recipe has an optional consumer-friendly name that you can supply.

For individual ingredients, specify this name in the LabelDescription field of POST ingredientList request.

Example POST ingredientList request body

[
   {
      "SupplierName": "Grocer",
      "SupplierCode": "1357",
      "StarchefKey": "0014674",
      "FullIngredientList": " Water, MUSTARD Flour, Spirit Vinegar, Sea Salt, MUSTARD Husk, Pimento, Turmeric",
      "LabelDescription": "Dijon Mustard"
   }
]

See the API Reference for full details about this endpoint.

If provided, the label description is used instead of the ingredient name in recipe ingredient lists (when auto-calculated). For example, the following image shows an ingredient with the ingredient name Flour White Soft. It has a label description of Flour. When a label is printed for a relevant recipe, the ingredient is described as Flour (WHEATflour). This is the combination of the label description with the ingredient list for the ingredient.

Screenshot of an ingredient's details, with the ingredient name and label description outlined in red. Below this is a recipe label, showing that the label description of the recipe is used on this label.

If there is no label description for an ingredient, then the ingredient name is used. You can retrieve the LabelDescription values for ingredients via the GET ingredientList endpoint.

For recipes, you can supply a consumer-friendly name via the POST recipenames endpoint. This endpoint allows you to update the naming for a recipe. The RecipeMenuDescription field is used on labels by default. If this does not exist, then the RecipeName is used.

Example POST recipenames request body

See the API Reference for full details about this endpoint.

[
   {
      "RecipeStarChefKey": "0030702",
      "RecipeName": "Brown Cake",
      "RecipeShortName": "Cake",
      "RecipeMenuDescription": "Brownie",
      "RecipeDescription": "Cake with cocoa and milk",
      "RecipeInternalCode": "1123",
      "RecipeExternalCode": "2345"
   }
]

As with all POST endpoints for this API, your request should include the full payload; any fields left blank are set to null.

Alternatively, if you need to retrieve recipe names, use the GET recipenames endpoint.

Example GET recipenames response body

See the API Reference for full details about this endpoint.

[
  {
    "RecipeGuid": "6BD28622-E5FE-452B-A627-E2C65584DAC2",
    "RecipeStarChefKey": "0030702",
    "RecipeName": "Brown Cake",
    "RecipeShortName": "Cake",
    "RecipeMenuDescription": "Brownie",
    "RecipeDescription": "Cake with cocoa and milk",
    "RecipeInternalCode": "1123",
    "RecipeExternalCode": "2345"
  }
]

Where to find more information about Natasha's Law

For more information about Natasha's Law:

Unit of measure (UoM) values and codes

There a several requests where you will need to set values for a UoM or unit code. The following require a long name as their value:

  • SupplyQuantityUnit
  • UnitSizeUom
  • AlternativeUnit1Uom
  • AlternativeUnit2Uom

The UnitCode parameter must use the abbreviated name.

Lastly, there are two optional parameters SupplierOrderUom or InvoiceUom that take only these values:

  • EA — each
  • CS — case
  • KGM — kilogram

The next table has the possible long name and abbreviated name values.

Long name Abbreviated name
(UnitCode only)
Type Equates to
bakers dozen bdz    
BARREL BRL Volume 5376 Fl oz (US)

bottle

btl

   

bunch

bnch

   
Bushel BU Volume 1191.57 Fl oz (US)

centilitre

cl

   

clove

clv

   

cup (UK)

cup (UK)

   

cup (US)

cup (US)

   
dozen dz    

each

ea

   

floz (UK)

floz (UK)

   

floz (US)

floz (US)

   

gallon (UK)

gal (UK)

   

gallon (US)

gal (US)

   

gill (UK)

gill (UK)

   

gill (US)

gill (US)

   

gram

g

   
KEG (D) 1/2 KEG (D) 1/2 Volume 1984 Floz (US)
KEG (D) 1/4 KEG (D) 1/4 Volume 992  Floz (US)
KEG (D) 1/6 KEG (D) 1/6 Volume 661 Floz (US)
KEG (I) 1/2 KEG (I) 1/2 Volume 1690.70 Fl oz (US)
KEG (I) 1/3 KEG (I) 1/3 Volume 1014.42 Fl oz (US)
KEG (I) 1/4 KEG (I) 1/4 Volume 845.35 Fl oz (US)

kilogram

kg

   

litre

l

   

loaf

loaf

   

milligram

mg

   

millilitre

ml

   

ounce

oz

   
PACK PK Each 1 Each
Pan 1/3 4" Deep Pan 1/3 x 4" Volume 4.5 Quarts (US)
PAN 1/6 6" Deep Pan 1/6 x 6" Volume 2.5 Quarts (US)

piece

piece

   

pint (UK)

pt (UK)

   

pint (US)

pt (US)

   

pound

lb

   

quart (UK)

qt (UK)

   

quart (US)

qt (US)

   
Quart, Dry (US) QT, Dry (US) Volume 37.2364 Fl oz (US)

serving(s)

serving

   
SHEET SHT Each 1 Each

single

single

   

slice

slice

   

stone

stone

   

tbsp (UK)

tbsp (UK)

   

tbsp (US)

tbsp (US)

   

tin

tin

   
TRAY TRAY Each 1 Each

tsp (UK)

tsp (UK)

   

tsp (US)

tsp (US)

   

Descriptor values

These descriptors use the same set of values:

  • SupplyQuantityDescriptor
  • UnitSizeUomDescriptor
  • AlternativeUnit1Descriptor
  • AlternativeUnit2Descriptor

The possible values are:

Bag

Bottle

Box

Bucket

Bunch

Carton

Case

Can

Container

Each

Jar

Keg

Pack

Portion

Punnet

Roll

Sheet

Sleeve

Tin

Tub

Resources

For the list of endpoints and methods, see the Import API Reference. Fourth will provide you with the base path for requests.

Request header

For all requests, you must provide your authentication details using Basic authentication in the header.

POST /ingredients HTTP/1.1
Host: instance.example.com
Accept: text/json
Authorization: Basic VXNlcm5hbWU6cGFzc3dvcmQ=
Field Description
Authorization

Your Recipe & Menu Engineering Imports ID and password, separated by a colon, and then base64 encoded. Your ID and password are case-sensitive. 

Accept The data format you are using for the request. Options are: application/json, text/json, application/xml, text/xml.

Request body

For full details about what is required in the request body, see the reference and the examples below.

Response to requests

Successful requests

Successful POST requests receive an HTTP 202 Accepted response with an empty response body.

Unsuccessful requests

Unsuccessful requests receive an HTTP 400-599 response, with an error message in the response body. See the error messages for each of these requests: 

Checking whether a request was processed

For successfully submitted POST requests, Fourth returns a status in the synchronous response body. For example:

{
  "Status": "Processed;Aug 10 2020 8:32AM",
  "BatchId": "2345"
}

The two possible states are Processed (with a timestamp) and Not processed.

It's not possible for every request to be processed before the synchronous response. Not processed means that the request was successfully received, but is still queued for processing. To check the processing status later, you can use the /batches endpoint:

[ROOT]/api/ingredientandaccessimport/batches

By default, the 10 most recently received requests are reported on, however you can filter the response using query parameters.

Example response:

[
  {
    "Status": "Not processed",
    "BatchId": "1243"
  },
  {
    "Status": "Processed;Aug 08 2020 3:45PM",
    "BatchId": "1255"
  },
  {
    "Status": "Processed;Aug 08 2020 10:05PM",
    "BatchId": "1289"
  },
  {
    "Status": "Not processed",
    "BatchId": "2108"
  },
  {
    "Status": "Processed;Aug 09 2020 10:12AM",
    "BatchId": "2111"
 }
]

If a request has not been processed after an hour, please raise a case with Fourth support via your mutual customer.

Making suppliers requests

Before you can start adding ingredients, you need to make sure the ingredient supplier exists in Fourth. You can do this using the suppliers resource. 

This example request adds a new supplier. The accountNumber is your unique reference for the supplier. The SupplierCurrencyCode is in standard ISO 4217 codes. 

POST /suppliers  HTTP/1.1
Host: instance.example.com
Content-Type: application/json
Authorization: Basic VXNlcm5hbWU6cGFzc3dvcmQ=

[
{
   "SupplierId": "",
   "AccountNumber": "ACME12346",
   "SupplierName": "Chris's produce", 
   "AlternateSupplierName": "CHRISPRO",
   "CountryGuid": "example",
   "SupplierCurrencyCode": "GBP"
}
]

Note that CountryGuid is optional as it is not required for most use cases. The value is a Fourth ID for the country.

Making ingredient requests

Use the ingredient resource to add or update an ingredient. You need to include the ingredient sets to which the ingredient belongs, and the ingredient's supplier (and both the sets and suppliers must already exist in Fourth). 

Customers can choose to review and accept or reject ingredient changes submitted by via this endpoint. Please confirm with your customer whether they plan to do this, and the workflow to follow between you.

Simple example

POST /ingredient  HTTP/1.1
Host: instance.example.com
Content-Type: application/xml
Authorization: Basic VXNlcm5hbWU6cGFzc3dvcmQ=

<ArrayOfIngredient>
   <Ingredient>
      <IngredientName>Ribs</IngredientName>
      <SupplierName>Butcher</SupplierName>
      <SupplierCode>SupplierCode1</SupplierCode>
      <SupplyQuantity>6.0000</SupplyQuantity>
      <SupplyQuantityNumber>2.0000</SupplyQuantityNumber>
      <SupplyQuantityUnit>kilogram</SupplyQuantityUnit>
      <IngredientType>Food</IngredientType>
      <CostPrice>20.0000</CostPrice>
      <InternalCode>2008</InternalCode>
      <IngredientSets>
         <Set>Master Ingredients</Set>
      </IngredientSets>
   </Ingredient>
</ArrayOfIngredient>

Sending supply and unit sizes

The Supply quantity fields in the request provide the pack and quantity details of the supplied product. This example shows a carton of 12 tonic waters that comes in 150 ml cans. Note that SupplyQuantity and SupplyQuantityNumber are interchangeable from Fourth's perspective; however, your customer will likely have a pattern that they always use (e.g. SupplyQuantity for the number of items). 

   ...
   "IngredientName": "SugarBush Tonic",
   "SupplyQuantity": "12",
   "SupplyQuantityNumber": "150",
   "SupplyQuantityUnit": "millilitre",
   "SupplyQuantityDescriptor": "Carton",
   ...

The Unit fields are the details used in Fourth Inventory for stocktake purposes. For example, the same product might have the following unit fields:

   ...
   "UnitSizeNumber": "15",  
   "UnitSizeUom": "centilitre",  
   "UnitSizeUomDescriptor": "Can",
   ...

The Supply and Unit fields MUST must logically match. This means that if an ingredient's UnitSizeUom is:

  • A weight, the SupplyQuantityUnit must also be a weight.
  • A volume, the SupplyQuantityUnit must also be a volume.
  • Other, the SupplyQuantityUnit must be the same value; e.g. each, slice or bottle.

If they do not match, you will not be able to update the ingredient.

Catch weight ingredients

Catch weight ingredients are those that have varying weight and invoice cost each time; for example, freshly caught fish.

For catch weight ingredients, the UoMs of the Invoice and Unit must match. For example:

   ...
   "UnitSizeUom": "KG",
   "InvoiceUom": "KGM",
   ...

If they do not match, you will not be able to update the ingredient.

Note that the only valid UoMs for catch weight products are KG (KGM) or LB.

Settings that restrict access to updating UoMs

There are two global settings in Fourth that can stop you from updating UoM values via the API. These are:

  • Supply Quantity read-only for Live Ingredients — when enabled, you cannot update these supply fields for an ingredient: SupplyQuantityNumber, SupplyQuantity, and SupplyQuantityUnit.
  • Unit Size read-only for Live Ingredients —  when enabled, you cannot update the values for these fields: UnitSizeNumber, and UnitSizeUom.

To enable or disable this functionality, customers must contact the Fourth team.

Alternate ingredients

You can use this resource to add alternate ingredients. Alternate ingredients are always linked to a parent ingredient, so in the request you will need to specify the parent ingredient.  

Alternate ingredients can come from the same or different suppliers from the parent ingredient. When an alternate ingredient is created, its pack size (supply quantity) can be defined using the parent ingredient base Unit of Measure (UoM) or any of the parent ingredient conversion UoMs.

For more information, see Understanding alternate and parent ingredients in the Export API Guide.

Example with alternate ingredients data

</ArrayOfIngredient>
   <Ingredient>
      <IngredientName>ApiAlternateAutomation Ingredient 021</IngredientName>
      <SupplierName>Dairy</SupplierName>
      <SupplierCode>B391</SupplierCode>
      <SupplyQuantity>12.0000</SupplyQuantity>
      <SupplyQuantityUnit>gram</SupplyQuantityUnit>
      <CostPrice>12.5000</CostPrice>
      <IngredientType>Food</IngredientType>
      <InternalCode>1007</InternalCode>
      <IngredientSets>
         <Set>Test 1</Set>
         <Set>Test 2</Set>
         <Set>Test 3</Set>
      </IngredientSets>
      <SupplyQuantityNumber>1.0000</SupplyQuantityNumber>
      <ParentSupplierName>Dairy</ParentSupplierName>       
      <ParentSupplierCode>B600</ParentSupplierCode>
      <RankOrder>2</RankOrder>
      <ParentStarChefKey>0036858</ParentStarChefKey>
   </Ingredient> 
</ArrayOfIngredient>

AlternativeUnit values

These elements are used with Fourth Inventory: 

  • AlternativeUnit1Quantity, AlternativeUnit1Uom, AlternativeUnit1Descriptor
  • AlternativeUnit2Quantity, AlternativeUnit2Uom, AlternativeUnit2Descriptor

They create an alternative stock count unit in the Inventory system for the ingredient. If you need to use these values please contact your Fourth Implementation Consultant. 

Example with all stock compatibility values

<ArrayOfIngredient>
   <Ingredient>
      <IngredientName>Ribs</IngredientName>
      <SupplierName>Butcher</SupplierName>
      <SupplierCode>SupplierCode1</SupplierCode>
      <SupplyQuantity>6.0000</SupplyQuantity>
      <SupplyQuantityUnit>kilogram</SupplyQuantityUnit>
      <IngredientType>Food</IngredientType>
      <CostPrice>20.0000</CostPrice>
      <InternalCode>2008</InternalCode>
      <IngredientSets>
         <Set>Test 1</Set>
         <Set>Test 2</Set>
         <Set></Set>
      </IngredientSets>
      <SupplyQuantityNumber>2.0000</SupplyQuantityNumber>
      <DistributorName>Dairy</DistributorName>
      <DistributorCode>Dairy001</DistributorCode>
      <ExternalCode>EXTCODE01</ExternalCode>
      <SupplyQuantityDescriptor>case</SupplyQuantityDescriptor>
      <UnitSizeNumber>10</UnitSizeNumber>
      <UnitSizeUom>ounce</UnitSizeUom>
      <UnitSizeUomDescriptor>Case</UnitSizeUomDescriptor>
      <CostModel>Highest</CostModel>
      <IsAdjustmentItem>True</IsAdjustmentItem>
      <PreventUsageInRecipes>False</PreventUsageInRecipes>
      <TransferRequisitionStatus>False</TransferRequisitionStatus>
      <ExcludeFromGP>False</ExcludeFromGP>
      <ZeroStockCount>True</ZeroStockCount>
      <ItemVatable>Yes</ItemVatable>
      <FirstDelivery>2017-06-28</FirstDelivery>
      <BinNumber>12134</BinNumber>
      <MaxOrderQuantity>50</MaxOrderQuantity>
      <MinOrderQuantity>5</MinOrderQuantity>
      <AlternativeUnit1Quantity>5</AlternativeUnit1Quantity>
      <AlternativeUnit1Uom>centilitre</AlternativeUnit1Uom>
      <AlternativeUnit1Descriptor>Bottle</AlternativeUnit1Descriptor>
      <AlternativeUnit2Quantity>1000</AlternativeUnit2Quantity>
      <AlternativeUnit2Uom>milligram</AlternativeUnit2Uom>
      <AlternativeUnit2Descriptor>Box</AlternativeUnit2Descriptor>
     <SupplierOrderUom>CS</SupplierOrderUom>
     <InvoiceUom>CS</InvoiceUom>
     <InvoicePrice>7.55</InvoicePrice>
   </Ingredient>
</ArrayOfIngredient>

Error messages for ingredients

Error Message Description

Ingredient Name is mandatory and must be less than 150 characters.

Ingredient name missing or too long.

Supplier Name does not exist in StarChef or Value is missing.

Supplier Name value not provided or does not exist in StarChef.

Supplier Code is mandatory and must be less than 50 characters.

Supplier Code value missing or too long.

Supply Quantity Number is mandatory and must be valid decimal value.

Supply Quantity Number value missing or incorrect format.

Supply Quantity Quantity is mandatory and must be valid decimal value.

Supply Quantity Quantity value missing or incorrect format.

Cost Price is mandatory and must be valid decimal value.

Cost Price value missing or invalid format.

Ingredient Set(s) does not exist in StarChef or Value is missing.

Ingredient set value not provided or does not exist in StarChef.

Multiple Records exist with same Supplier Name and Supplier Code combination.

Trying to import the same ingredient (defined by the combination of Supplier Name and Supplier Code) more than once or ingredient already exists in StarChef.

Multiple Records exist with same Distributor Name and Distributor code combination.

Trying to import the same ingredient (defined by the combination of Distributor Name and Distributor Code) more than once or ingredient already exists in StarChef.

Ingredient Type could be only food or non-food.

Trying to import an ingredient with type different than food or non-food.

External Code must be less than 50 characters.

External code contains more than 50 characters.

Supply Quantity descriptor does not exist in StarChef or Value is missing.

Supplier Quantity Descriptor value doesn't exists in StarChef.

Unit Size number must be valid decimal value.

Unit Size number value is not a decimal value.

Unit Size UoM does not exist in StarChef or Value is missing

Unit Size UoM value doesn't exist in the StarChef UoM table. See the Unit of measure (UoM) values and codes table for valid values. 

Unit Size UoM descriptor does not exist in StarChef or Value is missing.

Unit Size UoM Descriptor value doesn't exists in StarChef. See the Descriptor values table for valid values. 

Cost model does not exist in StarChef or Value is missing.

Cost Model value doesn't exist in StarChef.

Flag Adjustment Item value is not Boolean.

Is Adjustment Item value is not entered as True or False.

Flag Prevent Usage in Recipes value is not Boolean.

Prevent Usage in Recipes value is not entered as True or False.

Transfer Requisition Status value is not Boolean.

Transfer Requisition Status value is not entered as True or False.

Exclude from GP value is not Boolean.

Exclude From GP value is not entered as True or False.

Zero Stock Count value is not Boolean.

Zero Stock Count value is not entered as True or False.

Item Vatable does not exist in StarChef or Value is missing.

Item Vatable value is not entered as Yes, No or - .

First delivery must be valid date value.

Date into Warehouse value is not entered in the correct format yyyy-mm-dd.

Max order quantity must be valid decimal value.

Maximum Order Quantity value is not entered as a decimal value.

Min order quantity must be valid decimal value.

Minimum Order Quantity value is not entered as a decimal value.

Alternative Unit1 quantity must be valid decimal value.

Alternative Unit1 quantity value is not entered as a decimal value.

Alternative Unit1 UoM does not exist in StarChef or Value is missing.

Alternative Unit1 UoM value doesn't exist in the StarChef UoM table.

Alternative Unit1 descriptor does not exist in StarChef or Value is missing.

Alternative Unit1 descriptor value doesn't exist in StarChef.

Alternative Unit2 quantity must be valid decimal value.

Alternative Unit2 quantity value is not entered as a decimal value.

Alternative Unit2 UoM does not exist in StarChef or Value is missing.

Alternative Unit2 UoM value doesn't exist in the StarChef UoM table.

Alternative Unit2 descriptor does not exist in StarChef or Value is missing.

Alternative Unit2 descriptor value doesn't exist in the StarChef descriptor table.

Supplier Order UoM does not exist in StarChef or Value is missing.

Supplier Order UoM value is not one of the valid values: CS, EA, KGM.

Invoice UoM does not exist in StarChef or Value is missing.

Invoice UoM value is not one of the valid values: CS, EA, KGM.

Invoice Price must be valid decimal value

Invoice Price value is not entered as a decimal value.

Parent Supplier Name does not exist in StarChef or Value is missing.

Parent Supplier Name value is not provided or does not exist in StarChef.

Parent Supplier Name and Parent Supplier Code combination is not full

Either Parent Supplier Name value is not provided or does not exist in StarChef or the Supplier Code value is not provided.

Parent Supplier StarChef Key does not exist or Value is missing.

StarChef Key value is not provided or is not valid.

Parent Supplier Name must be less than 150 characters.

Parent Supplier Name value should not exceed 150 characters.

Parent Supplier Code must be less than 50 characters.

Parent Supplier Code value should not exceed 50 characters.

Rank Order is not valid number.

Rank Order should be a valid number.

Multiple Records exist with the same rank order.

Two or more alternate ingredients that are associated with the same parent ingredient cannot be imported with the same rank order.

Supplied Unit name is not part of the family.

Unit of measure of the alternate ingredient must correspond to the parent unit of measure.

Making ingredientnutrient requests

Use ingredientnutrient to add nutrition details for an ingredient.

If you need to remove a nutrient from an ingredient's information, send in the nutrient with no value (or null) for NutrientValue.  

In this example, the request adds two nutrients (Energy_KJ and Cal_Carb_Pct), and removes one (Caffeine) from the ingredient CHRI332

POST /ingredientnutrient  HTTP/1.1
Host: instance.example.com
Content-Type: application/xml
Authorization: Basic VXNlcm5hbWU6cGFzc3dvcmQ=

<ArrayOfIngredientNutrient>
   <IngredientNutrient>
      <SupplierName>Chris's produce</SupplierName>
      <SupplierCode>CHRI332</SupplierCode>
      <NutrientName>Energy_KJ</NutrientName>   
      <NutrientValue>10.235</NutrientValue>
   </IngredientNutrient>
   <IngredientNutrient>
      <SupplierName>Chris's produce</SupplierName>
      <SupplierCode>CHRI332</SupplierCode>
      <NutrientName>Cal_Carb_Pct</NutrientName>   
      <NutrientValue>6.115</NutrientValue>
   </IngredientNutrient>
   <IngredientNutrient>
      <SupplierName>Chris's produce</SupplierName>
      <SupplierCode>CHRI332</SupplierCode>
      <NutrientName>Caffeine</NutrientName>   
      <NutrientValue></NutrientValue>
   </IngredientNutrient>
</ArrayOfIngredientNutrient>

Nutrient values table

NutrientName Display Description on Starchef Screen

Cal_Carb_Pct

% Calories from Carbohydrate

Cal_Fat_Pct

% Calories from Fat

Cal_MUFA_Pct

% Calories from Monounsaturated Fatty Acid (MUFA)

Cal_PUFA_Pct

% Calories from Polyunsaturated Fatty Acid (PUFA)

Cal_Prot_Pct

% Calories from Protein

Cal_SatFat_Pct

% Calories from Saturated Fat (SFA)

Alpha_Tocopherol

Alpha Tocopherol (mg)

Biotin

Biotin (μg)

Caffeine

Caffeine (mg)

Calcium

Calcium (mg)

Cal_Details

Calorie Breakdown

Cal_Fat

Calories from Fat

Cal_SatFat

Calories from Saturated Fat

Carb

Carbohydrate

Carotene

Carotene (μg)

Carotene_alpha

Carotene, alpha (μg)

Carotene_beta

Carotene, beta (μg)

Chloride

Chloride (mg)

Fat_Chol_mg

Cholesterol (mg)

Choline

Choline (mg)

Chromium

Chromium (μg)

Copper

Copper (mg)

Cryptoxanthins

Cryptoxanthins (μg)

Energy_kCal

Energy (kcal)

Energy_KJ

Energy (kJ)

Fat_sol

Fat soluble vitamins

Fibre_AOAC

Fibre (AOAC)

Fibre_NSP

Fibre (NSP)

Fluoride

Fluoride (mg)

Folate

Folate, food (μg)

Folic_Acid

Folic Acid (Folate) (μg)

Fructose

Fructose

Glucose

Glucose

Iodine

Iodine (μg)

Iron

Iron (mg)

Lactose

Lactose

Lutein_zeaxanthin

Lutein + zeaxanthin (μg)

Lycopene

Lycopene (μg)

Magnesium

Magnesium (mg)

Maltose

Maltose

Manganese

Manganese (mg)

Mineral

Minerals

Molybdenum

Molybdenum (μg)

Fat_Mono

mono-unsaturates

Niacin

Niacin (mg)

NMES

NMES

Pantothenic_Acid

Pantothenic acid (mg)

Phosphorus

Phosphorus (mg)

Fat_Poly

poly-unsaturates

Potassium

Potassium (mg)

Protein

Protein

Retinol

Retinol (μg)

Riboflavin

Riboflavin (mg)

Fat_Sat

saturates

Selenium

Selenium (μg)

Sodium

Sodium (mg)

Carb_Starch

starch

Sucrose

Sucrose

Thiamin

Thiamin (mg)

Fat

Total Fat

Carb_Sugars

total sugars

Vitamin_A_μg

Vitamin A (μg)

Vitamin_A

Vitamin A (IU)

Vitamin_A_RE

Vitamin A (RE)

Vitamin_B12

Vitamin B12 (μg)

Vitamin_B6

Vitamin B6 (mg)

Vitamin_C

Vitamin C (mg)

Vitamin_D

Vitamin D (μg)

Vitamin_D_IU

Vitamin D (IU)

Vitamin_E

Vitamin E (mg)

Vitamin_K1

Vitamin K1 (μg)

Water

Water

Water_sol

Water soluble vitamins

Zinc

Zinc (mg)

Error messages for ingredientnutrient 

Error Message Description
Supplier Name does not exist in StarChef or Value is missing. Supplier Name value is missing or does not exist in StarChef.
Supplier Code is mandatory and must be less than 50 characters. Supplier Code value missing or too long.
No ingredient exists for this Supplier Name and Supplier Code combination. Such ingredient does not exist.
Invalid nutrient name. Incorrect nutrient name. 
Invalid nutrient value. Nutrient value is not in the correct format.
Duplicate nutrient_name. Trying to update the same nutrient value twice.

Making ingredientintolerance requests

Use ingredientintolerance to add intolerance details for an ingredient.

If you need to remove an intolerance from an ingredient's information, send in the intolerance with IntoleranceValue set to null.  

Please note that customers can choose to manually review and approve any intolerance values updated via the API. This does not have any impact on the behavior of the API itself.

In this example, the request adds two intolerances and removes one from the ingredient CHRI201

POST /ingredientintolerance  HTTP/1.1
Host: instance.example.com
Content-Type: application/xml
Authorization: Basic VXNlcm5hbWU6cGFzc3dvcmQ=

<ArrayOfIngredientIntolerance>
   <IngredientIntolerance>
      <SupplierName>Chris's produce</SupplierName>
      <SupplierCode>CHRI201</SupplierCode>
      <IntoleranceCode>AddSalt</IntoleranceCode> 
      <IntoleranceValue>Yes</IntoleranceValue>
   </IngredientIntolerance>
   <IngredientIntolerance>
      <SupplierName>Chris's produce</SupplierName>
      <SupplierCode>CHRI201</SupplierCode>
      <IntoleranceCode>Nuts</IntoleranceCode> 
      <IntoleranceValue>May</IntoleranceValue>
   </IngredientIntolerance>
   <IngredientIntolerance>
      <SupplierName>Chris's produce</SupplierName>
      <SupplierCode>CHRI201</SupplierCode>
      <IntoleranceCode>AddSalt</IntoleranceCode> 
      <IntoleranceValue>null</IntoleranceValue>
   </IngredientIntolerance>
</ArrayOfIngredientIntolerance>

Intolerance values table

IntoleranceCode - API Import Display Description on StarChef Screen

Glutamates

Contains Added Glutamates

AddSalt

Contains Added Salt

AddedTransFats

Contains Added Trans Fats

OtherAdditives

Contains Additives

Alcohol

Contains Alcohol or Alcohol Based Products

AnimalFat

Contains Animal Fat (excluding milk fat)

AnimalProd

Contains Animal Products (excluding rennet free milk products)

ArtCol

Contains Artificial Colours

ArtFlav

Contains Artificial Flavours

Preserv

Contains Artificial Preservatives

ArtSweet

Contains Artificial Sweeteners

Azo

Contains Azo Dyes

Benz

Contains Benzoates (if greater than 1mg/kg or l)

BHA_BHT

Contains BHA/BHT (if greater than 1mg/kg or l)

Celery

Contains Celery / Celeriac Products

Wheat

Contains Cereals that Contain Gluten

Coconut

Contains Coconut

Crustaceans

Contains Crustaceans

E110_E102_E122_E124_E104_E129

Contains E110/E102/E122/E124/E104/E129

E211_Sodium_Benzoate

Contains E211 Sodium Benzoate

Egg

Contains Eggs / Egg Derivatives

Fish

Contains Fish or Fish Products

FlavEnhan

Contains Flavour Enhancers

GM

Contains G.M. Material / Ingredients

Garlic_Onions

Contains Garlic / Onion Products

Gluten

Contains Gluten or Gluten Products

HydrogenatedVegOils

Contains Hydrogenated Vegetable Oils >1%

Irradiated

Contains Irradiated Food

Lactose

Contains Lactose

Lupin

Contains Lupin Flour / Lupin Products

Maize

Contains Maize or Maize Derivatives

Milk

Contains Milk or Milk Products

ModifiedStarch

Contains Modified Starch

Molluscs

Contains Molluscs

MSG

Contains MSG

Mushrooms

Contains Mushrooms or Mushroom Products

Mustard

Contains Mustard or Mustard Products

NatFlav

Contains Natural Flavourings

Nuts

Contains Nuts or Nut Trace

NatCol

Contains Only Natural Colours

Seeds

Contains Seeds / Seed Oil

Sesame

Contains Sesame Seed or Sesame Seed Products

ShellFish

Contains Shellfish

Soya

Contains Soya

Sulph_Diox

Contains Sulphur Dioxide/Sulphites

Organic

Organically Produced

Coeliacs

Suitable for Coeliacs

Halaal

Suitable for Halaal Diet

Kosher

Suitable for Kosher Diet

LactoseIntol

Suitable for Lactose Intolerants

Vegan

Suitable for Vegans

Veg

Suitable for Vegetarians

Barley

Barley

Chestnuts

Chestnuts

Sulphites

Contains Sulphites

Sulph

Contains Sulphur Dioxide (if greater than 10mg/kg)

CottonSeed

Cotton seed

Kamut

Kamut (Wheat)

Oats

Oats

OtherNuts

Other

OtherSeeds

Other

Peanuts

Peanuts

PineNuts

Pine Nuts

PoppySeed

Poppy Seed

Rye

Rye

SeedOils

Seed Oils

Spelt

Spelt (Wheat)

SunflowerSeed

Sunflower Seed

TreeNuts

Tree Nuts

CerealsWheat

Wheat

Almonds

Almonds

BrazilNuts

Brazil Nuts

CashewNuts

Cashew Nuts

Hazelnuts

Hazelnuts

Macadamias

Macadamia or Queensland Nuts

PecanNuts

Pecan Nuts

Pistachios

Pistachios

Walnuts

Walnuts

Error messages for ingredientintolerance

Error Message Description
Supplier Name does not exist in StarChef or Value is missing. Supplier Name value is missing or does not exist in StarChef.
Supplier Code is mandatory and must be less than 50 characters. Supplier Code value missing or too long.
No ingredient exists for this Supplier Name and Supplier Code combination. Such ingredient does not exist.
Intolerance value is invalid. Intolerance value must be yes / no / may / null.
Intolerance Code does not exist in Starchef or Value is missing Intolerance code missing or incorrect. See the intolerance values table for possible values.

Making ingredientcategory requests

The ingredientcategory resource lets you add categories to an ingredient. 

Our Fourth Inventory for Restaurants solution has a hierarchy of user-defined categories. You can include the top three levels in this request, which are:

  1. Category Type
  2. Main Category
  3. SubCategory 

Before you can add an ingredient to ingredient categories, the categories must already exist in Fourth. You can use the Recipe & Menu Engineering Export API to retrieve a list of existing categories. 

An ingredient may have more than one category applied to it. In which case, one of the categories must become the default category for the ingredient. 

 <ArrayOfIngredientCategory>
   <IngredientCategory>
       <SupplierName>Chris's produce</SupplierName>
       <SupplierCode>CHRI103</SupplierCode>
       <CategoryTypeName>Cost Center</CategoryTypeName>
       <MainCategoryName>Food</MainCategoryName>
       <SubCategoryName>Vegetables</SubCategoryName>
       <IsDefault>yes</IsDefault>
   </IngredientCategory>
</ArrayOfIngredientCategory>

Error messages for ingredientcategory

Error Message Description

Supplier Name does not exist in StarChef or Value is missing.

Supplier Name value not provided or does not exist in StarChef.

Supplier Code is mandatory and must be less than 50 characters.

Supplier Code value is missing or too long.

Category type does not exist in Starchef or Value is missing.

Missing Category Type value or Category Type does not exist in StarChef.

Required Ingredient Category Type not found.

Mandatory Category Type not provided for the ingredient.

Invalid category tree structure provided.

All provided categories exist but structure is incorrect.

is_default value is invalid

Incorrect is_default value.

Invalid category for alternate ingredients

Category provided is applicable only for parent ingredients.

Categories cannot be set for alternate ingredients inherited from parent ingredients

Alternates with "Inherit Parent Values" cannot have category value updated.

Making ingredientconversion requests

This request adds or updates conversion information for an ingredient.

Conversions let you take the unit of measure for purchasing (the "supply quantity") and provide a more recipe-friendly unit of measure elsewhere in Fourth. 

In the screenshot:

  • quantity is the left column (values 1, 1, and 1)
  • number is the middle (values: 800, 1 and 12) 

Screenshot showing example conversions in the Fourth user interface

To remove a conversion for a unit of measure, leave the quantity and number values empty. You can only delete conversions that are not in use. 

For a list of unit of measures for UnitCode, see the Unit of measure (UoM) values and codes table

The following example shows the same ingredient having two new conversions added (for piece and cup (UK)), and one removed (for btl). 

POST /ingredientconversion  HTTP/1.1
Host: instance.example.com
Content-Type: application/xml
Authorization: Basic VXNlcm5hbWU6cGFzc3dvcmQ=

<ArrayOfIngredientConversion>
   <IngredientConversion>
      <SupplierName>Chris's produce</SupplierName>
      <SupplierCode>CHRIS201</SupplierCode>
      <UnitCode>piece</UnitCode>
      <Quantity>8</Quantity>
      <Number>1</Number>
   </IngredientConversion>
   <IngredientConversion>
      <SupplierName>Chris's produce</SupplierName>
      <SupplierCode>CHRIS201</SupplierCode>
      <UnitCode>cup (UK)</UnitCode>
      <Quantity>4</Quantity>
      <Number>1.5</Number>
   </IngredientConversion>
   <IngredientConversion>
      <SupplierName>Chris's produce</SupplierName>
      <SupplierCode>CHRIS201</SupplierCode>
      <UnitCode>btl</UnitCode>
      <Quantity></Quantity>
      <Number></Number>
   </IngredientConversion>
</ArrayOfIngredientConversion>

Error messages for ingredientconversion 

Error Message Description

Invalid product.

The combination of Supplier Name value and Supplier Code value does not exist in StarChef.

Supplier Name does not exist in StarChef or Value is missing.

Supplier Name value not provided or does not exist in StarChef.

Supplier Code is mandatory and must be less than 50 characters.

Supplier Code value missing or too long.

Invalid UoM name

UoM UnitCode missing or incorrect. See the Unit of measure (UoM) values and codes table for a list of possible values.

Invalid UoM quantity value.

UoM Quantity value incorrect.

Missing UoM quantity value.

UoM Quantity value is missing.

Invalid UoM number value.

UoM Number value is incorrect.

Missing UoM number value.

UoM Number value is missing.

Duplicate UoM Conversion.

UoM conversion for this particular UoM already exists.

Duplicate UoM Weight. Only one Weight UoM per ingredient is allowed.

Only one Weight UoM per ingredient is allowed.

Duplicate UoM Volume. Only one Volume UoM per ingredient is allowed.

Only one Volume UoM per ingredient is allowed.

Unable to delete non-existent UoM Conversion.

Trying to delete UoM conversion that does not exist.

Unable to delete UoM Conversion. It is used in recipe/menu/alternates.

Trying to delete UoM conversion which is used in another item, remove the usage first.

Making ingredientshelflife requests

Use the ingredientshelflife resource to view and manage the shelf life of ingredients:

  • POST /ingredientshelflife
  • GET /ingredientshelflife

You will need to talk to your customer about their Fourth settings when integrating with this resource. Customers can tailor the six shelf life fields in Fourth for their own use (normally done during the Fourth implementation stage). Therefore, the names that customers use for the fields may not match the ones in the API request. For example, ShelfLifeTwo may be named “Maximum shelf life from freezer” in the UI. Most customers only use a few of the shelf life fields.

As well, each customer can have a global setting for the minimum and maximum accepted shelf life for items. When Fourth receives a POST /ingredientshelflife request, we check that the values sent are within the customer’s limits. If one or more of the values is outside a limit, Fourth returns an error message in the format:

The value should be between [min - max] value.

The POST /ingredientshelflife endpoint lets you add or update shelf life values. Unlike most fields in the POST requests for this API, you can choose to update ONLY the shelf life fields that are relevant. Any fields you don’t include in the request retain their current value.

You cannot send through a null value. However, 0 is an accepted value — you should discuss with your customer what this value would mean for them.

Example POST /ingredientshelflife request body

This example shows all the possible shelf life fields.

[
   {
      "ShelfLife": "12", 
      "ShelfLifeTwo": "2",
      "ShelfLifeThree": "0",
      "ShelfLifeFour": "0",
      "MinShelfLifeIntoUnit": "0",
      "MinShelfLifeDays": "0",
      "SupplierName": "Dairy",
      "SupplierCode": "B365",
      "StarChefKey": "0030702"
   }
]

The GET /ingredientShelfLife returns the shelf life values for an ingredient. This can include empty strings, as most customers do not use all the shelf life fields.

You can filter these requests by ingredient productId, guid, and groupGuid.

Example GET /ingredientShelfLife response body

[
   {
      "ShelfLife": "7",
      "ShelfLifeTwo": "3",
      "ShelfLifeThree": "",
      "ShelfLifeFour": "",
      "MinShelfLifeIntoUnit": "",
      "MinShelfLifeDays": "",
      "SupplierName": "The Farm",
      "SupplierCode": "C132",
      "StarChefKey": "0031291"
   }
]

For more information about these endpoints, see the API Reference:

Troubleshooting

I received a response that said "Not processed" — what should I do?

It's not possible for Fourth to process every request before the synchronous response is sent back. This means that valid requests may receive a status of Not processed. When this happens, you can use the /batches endpoint to check later whether a requests was processed.

Most requests are processed within a few minutes. However, make sure there is a reasonable delay before checking the processing; for example one hour allows for plenty of time. If the request status is still Not processed then you can either:

  • Retry the request
  • Raise a case via your mutual customer

How do I tell whether there was an issue with my request after processing?

If there is an issue with processing a requests, then an exception report is created. When Fourth provides your API credentials, we will also ensure to ask for an email address to send exception reports so that you are aware of any request failures.