POS Gateway Reference

Introduction

This page provides a reference for the POS Gateway. You should also read the POS Gateway guide, as this explains how to accurately send in your POS data using the gateway.

Updates

You can find any updates on the Release Notes page for the POS Gateway.

If you're an existing partner, please sign up for release note notifications. New partners are automatically provided notifications.

Testing

We provide a sand-box environment for testing data submission. If you would like to test our API, please contact Fourth for a test account.

When you are ready to go live, we need the related Fourth customer to provide written authorization. After this, we issue a set of secure login credentials, and you can begin submitting live POS data.

The Transaction Dataset file

The Transaction Dataset file is a denormalized export of POS transactions from the POS provider's database (or data warehouse). The POS provider (or customer) should send a file daily to Fourth, with incremental data.

Format and escaping

The file must be a .CSV file that is comma delimited, and with double-quote around each field; for example: "field1", "field2". If you need to include double-quotes in your descriptive fields, then you must escape each one with an additional double-quote; for example:

  • INCORRECT: "10" pizza" — this will fail data validation
  • CORRECT: "10"" pizza"  — this will successfully pass data validation
  • INCORRECT: "The "Great" Beer Company" — this will fail data validation
  • CORRECT: "The ""Great"" Beer Company" — this will successfully pass data validation

Encoding

Encode the file according to the UTF-8 standard, without BOM.

File size limit

Below the daily limit of 30 MB (of unzipped data). If you need to load files larger than this (generally to load in historical data) please contact us.

You can send the file either zipped or unzipped.

Cell character limit

No more than 255 characters for each field.

Files for multiple locations

Preferably, the database should send a single daily file that contains the transactional data for all locations for a customer. However, providers can also send a separate file for each location, if necessary.

Data duplication

Fourth expects only incremental POS data in each new file. Sending unnecessary data (that is, data Fourth has already received that does not include updates or new records) must be keep to a minimum to reduce the resources needed and time taken to process.

However, it may be permissible to send rolling dates, of 3 days maximum. This is dependent on your data volume and scenario. You must check with Fourth first before doing this.

Transaction types

You MUST set a transaction type code for each record, otherwise the record is deemed invalid.  Some transaction types require you to send data in every field, while others only require a sub-set of fields.

Table 1: transaction types

Transaction type code Description
DISC_ITEM Represents a discount applied to one specific item. It provides additional information about the discount such as discount name and id.
MAINS_AWAY This represents an instruction to the kitchen that the customer has finished their starters and the kitchen should start preparing the main course (or the next course).
MODIFIER_ITEM Modifier Item i.e. "no cheese". It is useful to separate small modifications to a main menu item so that we can add that layer of analysis to our Business Intelligence (BI) dashboards. Howeer, as modifiers are usually small additions or deductions, they may be ignored for labor forecasting computation.
PRINT_CHECK This represents when the server prints the check (used in conjunction with TENDER or TAB_CLOSE to see how long the customer waited to pay the check).
SALES_ITEM Represents the sale of a menu item. This transaction type carries critical information including but not limited to adjusted tax for the actual price paid, the list price of the item (price on the menu) and the price paid that will include any discount at the item or check level.
SERVICE_CHARGE

Represents any service charges posted on the check, as well as any tips (if these are recorded on the POS).

Your TENDER transaction types can include the service charge in "tenderAmount". If you plan on doing this, then you:

  • MUST always provide a SERVICE_CHARGE transaction for any service charges.
  • When integrating, let us know if your tender includes the service charge, so that we can configure our system to provide the meal-only tender value to our customers.
TAB_CLOSE

Represents the time the check is closed. This also shows the sales totals for the check.

For "TAB_OPEN" & "TAB_CLOSED": Where multiple records are recorded against a single check code, use the field "TransactionStartEnd" to indicate first and last record for the check. These values to use are:

  • "1" — first record
  • "2" — last record
TAB_OPEN Represents the time the check is opened.
TENDER

Represents the amount paid on the check, which should be split out by tender type. For example: "CASH", "UBEREATS", "VISA".

The "tenderAmount" can include or exclude the service charge. If the TENDER:

  • Includes the service charge paid, then you MUST include a SERVICE_CHARGE transaction showing the value of the service charge.
  • Doesn't include service charge paid, then it is optional to include SERVICE_CHARGE transactions.

When integrating, let us know if your tender includes the service charge, so that we can configure our system to provide the meal-only tender value to our customers.

VOID_ERROR

Item voided before any type of preparation.

An example of this is an error corrected will the server is still adding an order into the till. This is swiftly corrected without any impact either to the stock or labor.

VOID_ITEM

Item that was voided after some labor occurred, but where the item goes back to stock.

An example is an unopened bottled beer that is returned because the customer changed their mind. This impacts the labor because someone needs to serve the beer, but does not impact the stock count.

VOID_WASTE
VOID_WASTE2
VOID_WASTE3
VOID_WASTE4
VOID_WASTE5
VOID_WASTE6
VOID_WASTE7
VOID_WASTE8
VOID_WASTE9
VOID_WASTE10

Item that was voided after preparation, where the item reduces the stock available. An example is a cocktail that has been prepared but is returned because the customer did not like it. This void category impacts both the stock (raw ingredients used) and the labor (as someone had to prepare the cocktail).

There are eleven VOID_WASTE variants. This allows our mutual customer to differentiate between what caused a VOID_WASTE transaction. For example, they could be used to indicate:

  • VOID_WASTE2 — food or beverages voided because there was a mistake during ordering.
  • VOID_WASTE3 — food or beverages voided because the diner did not like the taste.
  • VOID_WASTE4 — food voided due to contamination from the kitchen (e.g. meat on a vegetarian pizza).
  • VOID_WASTE5 — staff meals
  • etc...

Please work with our mutual customer and the Fourth CSM team to decide the meaning of each VOID_WASTE variant.

The variants are all exported to Fourth Inventory. In the rest of the Fourth platform, such as Fourth Analytics, the variants are aggregated into VOID_WASTE.

You must include a description in the "DeductionDesc" column for each VOID_WASTE variant. This is shown onscreen to Fourth Inventory users.

VOID_WASTE11

Item that was voided after preparation, where the item reduces the stock available.

VOID_WASTE11 is reserved for voiding items that are not associated with a specific check. For example, this could be breadrolls that were burnt during baking.

This field is exported to Fourth Inventory as is. In the rest of the Fourth platform, such as Fourth Analytics, VOID_WASTE11 is aggregated into VOID_WASTE.

You must include a description in the "DeductionDesc" column for each VOID_WASTE variant. This is shown onscreen to Fourth Inventory users.

Types of data fields

The fields in the .csv file are one of:

  • Decimal — number up to 4 decimal points. For example: "123.45"
  • Integer — number with no decimal point. For example: "12345"
  • String —text string up to 255 characters. For example: "AbC123"
  • Date — date in the format: YYYY-MM-DD. For example: "2019-01-30"
  • Time — use the local timezone, rather than UTC. The format is HH:MM:SS; for example: "23:07:57"
    For each transaction, send the time that the transaction occurred, rather than the time that the tab was closed. This provides the customer with better analytics.

All fields must be enclosed with double quotes; for example, "Margherita".

When to use negative and positive values

All decimal and integer fields must be positive. The exception to this is the void transactions types (VOID_ITEM, VOID_ERROR, VOID_WASTE, VOID_WASTE2 to VOID_WASTE11). For void transactions, These fields MUST have a negative value:

  • "qty"
  • "listprice" (and "listpriceconv")
  • "tax" (and "taxconv")
  • "pricepaid" (and "pricepaidconv")
  • "costpricetheo" (and "costpricetheoconv")

For example, the value of "qty" is "-1" for a single voided item.

For all other transaction types, including DISC_ITEM, the number fields MUST be positive!

Fields

The first row in the transaction dataset MUST be the field names listed below. The names are case insensitive.

The dataset must include all the fields. If there is no data for a field, then insert a default value, rather than leave the field empty. The default values are:

  • For decimal or integer fields enter zero value, i.e. "0"
  • For all other fields enter a blank string value, i.e.  ""

This file shows the fields in the correct order and whether a value is required for each transaction type.

Please note, this file is NOT a direct example of a dataset, as it shows the transaction type in the first column. As well, because it has been saved as an .xls file, it does not include double quotes around all fields.

Table 2: Field descriptions

# Column Description
1

TransactionId

A unique ID for this record.

For new records, this value must always be unique, and not repeat across days or locations. Do not reuse this ID ever, unless you intend on updating a record.

To update an existing record, submit the updated data using the ID of the existing record.

Many POS Gateway users dynamically create IDs using data from the transaction. This might include a number of data points joined together, such as:

  • sitelocation_ timestamp_ transactiontypecode_ checkcode_ recordactivitycode

For example:

  • 1234_130500_SALES_ITEM_28581_2_34

If you dynamically create IDs in this way, then you must continue to use the same format in perpetuity (forever). This is to stop issues with updating historic sales records after a change to the ID format. In particular, if you change the date or timestamp in the ID when resubmitting records, then this will create a new record, rather than update an existing record.

Alternatively, store the TransactionId with your transaction record for use when updating an existing record.

Note that many of our POS partners include their own incremental count in the transaction ID. We'd prefer partners to include an incremental count if possible; and we recommended it if you will allow customers to void items outside of a transaction, in case a user sends through multiple voids for the same item at the same time (causing a duplicate transactionID).

Type: String, up to 50 characters in length. Special characters must be escaped.

2 UnitId

Customer or POS stock location code. Leave this field empty ("") unless otherwise advised by Fourth.

Type: String

3 SiteLocationCode

The code for the store, cafe, restaurant or other physical location. The values need to be set in advance of sending us data. There are two ways to achieve this:

  • Fourth can provide you with the existing codes for locations, which you then add or map to the POS system. These codes are discoverable as Fourth accounting codes in our Workforce Management solution.
  • Your business can provide a list of your own codes with the names of the locations. We then create a mapping to our codes. However, you will need to ensure that you provide us with the new code when a new location is added.

Type: String

4

TradingDate

The fiscal date of the transaction.

This may be different from the actual date of the transaction, particularly for premises that close late in the evening. For example, if a restaurant is open on Fridays from 4pm until 2am, all transactions for that period should use Friday's date as the trading date.

Must use the format: YYYY-MM-DD.

Type: Date

5

Time

Must use the format: HH:MM:SS. Send this in the local time, rather than the time in UTC.

For each transaction, send the time that the transaction occurred, rather than the time that the tab was closed. This will help provide the customer with better analytics.

Type: Time

6

TimeFact

A numeric time reference. Leave empty (""), as Fourth populates this field.

7

TerminalCode

The ID of the POS (or till) on which the transaction occurred.

Leave this field empty ("") if you cannot supply this information.

Type: String

8

TerminalDesc

Description of the POS (or till), if applicable.

Leave this field empty ("") if you cannot supply this information.

Type: String

9

RecordActivityCode

Incremental record number for each transaction or check record. The record number should usually reset for each check.

Type: Integer

10

ReceiptCode

Number or code shown on printed receipt. This can differ from the check code.

Leave this field empty ("") if you do not have separate receipt codes.

Type: String

11

CheckCode

The check or transaction reference that identifies the check for the table. Ideally this would be unique.

Type: String

12

TableCode

Tab or table reference. For example: 

  • "17"
  • "table 4"

Leave this field empty ("") if customer sales are not assigned to tables.

Type: String

13

RevenueCentreCode

Revenue center code or reference.

Use the values in your POS system for these fields.

Type: String

14

RevenueCentreDesc

Description for the revenue center; for example:

  • "restaurant"
  • "bar"

Use the values in your POS system for these fields.

Type: String

15

TransactionTypeCode

Used to categorize the type of record. See Transaction types for a table of values.

Type: String

16

SalesItemId

A Fourth ID. Leave empty (""), as Fourth populates this field.

17

SalesItemPLU

The item's PLU code. You must:

  • Always supply a value for this field (for the relevant transactions types)
  • Use the codes from Fourth Inventory for Hotels if your customer is using this solution

Type: String

18

SalesItemGUID

Alternative product reference field. This is normally your POS system's reference.

Leave empty ("") if you do not have a separate POS GUID for the sales item.

Type: String

19

SalesItemDesc

Product description, for example:

  • "cheeseburger"

Type: String

20

TenderTypeCode

Code. For example:

  • "12"

Use the values in your POS system for these fields.

Type: String

21

TenderTypeDesc

Type of payment, including delivery aggregators. For example:

  • "VISA"
  • "CASH"
  • "PAYPAL"
  • "DELIVEROO"

  • "UBEREATS"

Use the values in your POS system for these fields.

Type: String

22

DeductionCode

Deduction code. For example:

  • "1234"

Use the values in your POS system for these fields.

Type: String

23

DeductionDesc

Deduction description. For example:

  • "25% off check"
  • "staff meal"

Ensure that you include this field for all relevant transaction types, as it is the user-friendly description shown onscreen to users. For example, VOID_WASTE transactions must include this description so that users can understand what type of wastage occurred.

Type: String

24

Covers

Use this field in TAB_CLOSE to record the number of covers (diners).

For all other transaction types, you can use the value "0".

Type: Integer

25

Qty

Quantiy of the sales and modifier items either sold, discounted or otherwise modified.

For VOID_ITEM, VOID_ERROR, VOID_WASTE2 — VOID_WASTE11, and VOID_WASTE transactions, this must be a negative value; for example: "-1".

Type: Decimal

26

Currency

Local currency symbol. For example:

  • "GBP"
  • "USD"
  • "EUR"

Type: String

27

ListPrice

For TAB_CLOSE only, this can be either the total price of the items before discount, or the price paid.

For all other transaction types, this is the item's price as advertised in the menu, before any deductions or discounts on the check or item. Do not multiply this by "Qty".

UK: Use the item's price inclusive of VAT.

US: Use the item's price exclusive of tax.

For VOID_ITEM, VOID_ERROR, VOID_WASTE2 — VOID_WASTE11, and VOID_WASTE transactions, this must be a negative value; for example: "-9.50".

Type: Decimal

28

Tax

Amount of tax applied to the item, in local currency. To enter the correct amount:

  • Ensure that the tax is calcuated from the "PricePaid", not the "ListPrice".
  • Calculate the amount of tax after the price is multipled by "Qty".

For VOID_ITEM, VOID_ERROR, VOID_WASTE2 — VOID_WASTE11, and VOID_WASTE transactions, this must be a negative value; for example: "-1.46".

Type: Decimal

29

PricePaid

Price the item was sold at, inclusive of tax and including any deductions (e.g. promotions, discounts or refunds). This should be in the local currency.

If the record is for multiple items, then this price must be the combined price for all items. That is, the price must be multiplied by the quantity ("Qty") of items sold in this transaction.

For VOID_ITEM, VOID_ERROR, VOID_WASTE2 — VOID_WASTE11, and VOID_WASTE transactions, this must be a negative value; for example: "-9.50".

Type: Decimal

30

Deduction

Amount of deduction applied to the item, in local currency. This number should always be positive.

If the record is for multiple items, then this value must be the combined deduction for all items.

Type: Decimal

31

TenderAmount

Amount tendered, in local currency.

For TAB_CLOSE, this should be the full tendered amount (excluding service charge). This means it will be the same value as for "PricePaid".

Type: Decimal

32

CostPriceTheo

The theoretical cost of the item sold, in local currency. Leave empty ("") unless otherwise directed by Fourth or the mutual customer.

For VOID_ITEM, VOID_ERROR, VOID_WASTE2 — VOID_WASTE11, and VOID_WASTE transactions, this must be a negative value; for example: "-4.50".

Type: Decimal

33

ListPriceConv

Use the same value as "ListPrice" unless otherwise advised by Fourth.

For VOID_ITEM, VOID_ERROR, VOID_WASTE2 — VOID_WASTE11, and VOID_WASTE transactions, this must be a negative value; for example: "-9.50".

Type: Decimal

34

TaxConv

Use the same value as "Tax" unless otherwise advised by Fourth.

For VOID_ITEM, VOID_ERROR, VOID_WASTE2 — VOID_WASTE11, and VOID_WASTE transactions, this must be a negative value; for example: "-1.46".

Type: Decimal

35

PricePaidConv

Use the same value as "PricePaid" unless otherwise advised by Fourth.

For VOID_ITEM, VOID_ERROR, VOID_WASTE2 — VOID_WASTE11, and VOID_WASTE transactions, this must be a negative value; for example: "-9.50".

Type: Decimal

36

DeductionConv

Use the same value as "Deduction" unless otherwise advised by Fourth.

Type: Decimal

37

TenderAmountConv

Use the same value as "TenderAmount" unless otherwise advised by Fourth.

Type: Decimal

38

CostPriceTheoConv

Leave empty ("") unless otherwise directed by Fourth or the mutual customer. If using, enter the same value as "CostPriceTheo", unless otherwise advised by Fourth.

For VOID_ITEM, VOID_ERROR, VOID_WASTE2 — VOID_WASTE11, and VOID_WASTE transactions, this must be a negative value; for example: "-4.50".

Type: Decimal

39

OrderTypeDesc

The order type, for example:

  • "Eat in"
  • "Takeaway"

Use the values in your POS system for these fields.

Type: String

40

MenuBand

Menu price band; also known as 'menu level' and 'price band'. For example:

  • "low"
  • "1"

This is used when you have the same product that is sold at different prices at different times, for example happy hour.

Leave empty ("") if you are not using it.

Type: String

41

MajorGroupDesc

For each sales item, your POS system can send product category data. You can include up to three levels of hierarchy:

  1. "MajorGroupDesc" — the primary level of categorization, e.g. "Beverages" 
  2. "FamilyGroupDesc" — the second level of categorization, e.g. "Wine"
  3. "SubGroupDesc" — the last level of categorization, e.g. "White Wine"

If your customer is using Fourth Inventory for Hotels (Adaco), each value must be prefixed with a two-digit number between 01-99. The numbers should be unique. For example:

  • "01-Food"
  • "02-Beverages"
  • "03-Retail"

If you are sending only one level of hierarchy, send these values in the field "MajorGroupDesc".

If you are sending two levels of hierarchy, send these values in the fields "MajorGroupDesc" and "FamilyGroupDesc".

Type: String

42

FamilyGroupDesc

Second level of categorization from the POS system. For example:

  • "Starters"
  • "Mains"
  • "Drinks" 

Type: String

43

SubGroupDesc

Third level of categorization from the POS system. This is the level just above the sales item.

Type: String

44

TabOwner

Operator ID of the person who entered the record.

Type: String

45

TabOwnerDesc

The name of operator who entered the record. Separate their firstname and surname with a space. For example:

  • "Maria Rossi"

Type: String

46

OriginalTabOwner

Operator ID of the person who opened the tab.

Type: String

47

OriginalTabOwnerDesc

The name of operator who opened the tab. Separate their firstname and surname with a space.

Type: String

48

OldTableCode

RESERVED FOR FUTURE USE. Leave empty ("").

Old tab ID. For use when items are transferred from one tab to another.

Type: String

49

PrevTransactionCode

RESERVED FOR FUTURE USE. Leave empty ("").

Old check code. For use when items are transferred from one check to another.

Type: String

50

AuthorisedBy

RESERVED FOR FUTURE USE. Leave empty ("").

Person who authorized a discount, if applicable.

Type: String

51

TextField

RESERVED FOR FUTURE USE. Leave empty ("").

Free text field, with a limit of 250 characters.

Type: String

52

GuestDesc

RESERVED FOR FUTURE USE. Leave empty ("").

The booking party name.

Type: String

53

GuestCode

RESERVED FOR FUTURE USE. Leave empty ("").

Reserved for possible uses such as SUV codes or hotel room numbers.

Type: String

54

TimeSentToPrep

RESERVED FOR FUTURE USE. Leave empty ("").

A number ('timefact') that shows when orders are sent to the kitchen. This is the number or seconds since midnight; for example, 7:30PM would be:

  • "70200"

Type: Integer

55

BumpTime

RESERVED FOR FUTURE USE. Leave empty ("").

A number ('timefact') that shows when items were sent or taken to the customer. This is the number or seconds since midnight; for example, 7:47PM would be:

  • "71220"

Type: Integer

56

UniversalTimeSlotId

Time slots in 15 minute increments. Leave empty (""), as Fourth populates this field.

57

TimeSlotDesc

RESERVED FOR FUTURE USE. Leave empty ("").

Customer-defined time slot. For example:

  • "12:00-12:59"
  • "Lunchtime"

Type: String

58

TransactionStartEnd

Flag that indicates whether this is the first or last record for a transaction (check). The values are:

  • "1" — first record
  • "2" — last record

Type: String

59

IsDeleted

Use zero ("0") unless otherwise advised by Fourth.

Type: Decimal

60

CustomField1

Leave empty ("") unless otherwise advised by Fourth.

Type: String

61

CustomField2

Leave empty ("") unless otherwise advised by Fourth.

Type: String

62

CustomField3

Leave empty ("") unless otherwise advised by Fourth.

Type: String

63

CustomFact1

Leave empty ("") unless otherwise advised by Fourth.

Type: String

64

CustomFact2

Leave empty ("") unless otherwise advised by Fourth.

Type: String

65

DateFact

Numeric trading-date reference. Leave empty (""), as Fourth populates this field.

How Fourth uses the data

Once your POS data is delivered to the POS Gateway, Fourth creates individual exports that are forwarded to the different parts of the Fourth Platform that use POS data. These are:

  • Labor Productivity, for use in demand forecasts.
  • Inventory, for recording the movement of inventory.
  • Analytics, for use in business intelligence reports.

Each Fourth module uses POS sales data in different ways, and so the exports are tailored to each module. For example, Inventory needs a daily aggregate, while Labor Productivity needs 15 minute intervals, and will also map the POS sales categories to its own. However, the same value for total daily net sales is used throughout the Fourth Platform.

How the daily net sales is computed

Fourth determines the daily net sum by taking the "PricePaid" minus "Tax", for the following transaction types:

  • SALES_ITEM
  • MODIFIER_ITEM
  • VOID_ITEM
  • VOID_ERROR
  • VOID_WASTE

This is why it is important that in your dataset:

  • The "PricePaid" already includes any discounts applied to the item (or check).
  • That the "Tax" value is for the "PricePaid" and not the "ListPrice".

Quantity metrics sent to Fourth modules

The individual exports forwarded to the Fourth modules will have quantity values that may vary from one another. This is because each module requires different metrics. For example, the export for demand forecasting must include the total number of items prepared and, depending on the Fourth customer's configuration, may include or exclude voided item quantities. Meanwhile, the Inventory export must include voided items (VOID_WASTE) so as to have accurate data about the items used.

Demand forecasting export

To create this export, Fourth extracts the quantity of times prepared and the net sales associated, by:

  • Location
  • Item
  • Category
  • 15 minute time slot

The data is mapped to the three main categories defined in the POS system (e.g. the values of the "Majorgroupdesc" field). This export relies on the sub-category values (major, family and sub) matching the values that already exist and are maintained by Fourth and the client. If you need to introduce a new group, then you must notify Fourth, so that we can adjust the mapping. Otherwise, any new category or group is ignored from the total net sales calculation and from labor forecasting.

As well, the labor forecast only uses mains menu items to predict the number of staff needed. The forecast ignores modifiers to mains (for example, added cheese) as this doesn't represent additional work. It also does not count mains that became VOID_ITEM and VOID_ERROR items, as no work was done.

Normally, the categorization settings for a sales item are maintained by Fourth in collaboration with the client. This includes settings such as whether a transaction type (e.g. VOID_ITEM) is applicable for an item. If, for any reason, the categorization is changed at the POS end, you must notify Fourth so that we can update the configuration.

Inventory export

The Inventory export compiles the following data for every location, date and PLU:

  • Quantity of items sold
  • Total net sales
  • Total tax
  • Net price paid
  • Total gross sales
  • Sales type (based on the transaction type)

Analytics export

The Analytics export contains the raw POS sales data, which is used to create business intelligence reports.