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'd like to receive release notes, please fill in this form.

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.

Go live

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.

Downloads

Before reading further, please download these files:

  • Example Transaction Dataset csv file
  • Mandatory and optional fields by transaction type (Excel spreadsheet)
    Please note, the second 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.

Having these to hand will help as you read through this guide.

Standards for the Transaction Dataset

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

Screenshot of the example CSV file we provide.

First row

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

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

For example, this shows the first five columns with some rows of data:

"transactionid","unitid","sitelocationcode","tradingdate","time",...
"example1234","","1234","2020-09-28","13:57:00",...
"example9876","","1234","2017-09-28","13:57:00",...

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 must send the file unzipped.

Required fields

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

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.

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 values

The void transactions types (VOID_ITEM, VOID_ERROR, VOID_WASTE, VOID_WASTE2 to VOID_WASTE11) 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!

Field descriptions

1. TransactionId

 

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

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

2. UnitId

 

Type: String

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

3. SiteLocationCode

 

Type: String

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.

4. TradingDate

 

Type: Date, must use the format: YYYY-MM-DD.

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.

5. Time

 

Type: Time, must use the format: HH:MM:SS.

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.

Send this in the local time, rather than the time in UTC.

6. TimeFact

 

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

7. TerminalCode

 

Type: String

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

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

8. TerminalDesc

 

Type: String

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

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

9. RecordActivityCode

 

Type: Integer

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

10. ReceiptCode

 

Type: String

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.

11. CheckCode

 

Type: String

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

12. TableCode

 

Type: String

Tab or table reference. For example: 

  • "17"
  • "table 4"

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

13. RevenueCentreCode

 

Type: String

Revenue center code or reference.

Use the values in your POS system for these fields.

14. RevenueCentreDesc

 

Type: String

Description for the revenue center; for example:

  • "restaurant"
  • "bar"

Use the values in your POS system for these fields.

15. TransactionTypeCode

 

Type: String

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

16. SalesItemId

 

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

17. SalesItemPLU

 

Type: String

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

18. SalesItemGUID

 

Type: String

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.

19. SalesItemDesc

 

Type: String

Product description, for example:

  • "cheeseburger"

20. TenderTypeCode

 

Type: String

Code. For example:

  • "12"

Use the values in your POS system for these fields.

21. TenderTypeDesc

 

Type: String

Type of payment, including delivery aggregators. For example:

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

  • "UBEREATS"

Use the values in your POS system for these fields.

22. DeductionCode

 

Type: String

Deduction code. For example:

  • "1234"

Use the values in your POS system for these fields.

23. DeductionDesc

 

Type: String

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.

24. Covers

 

Type: Integer

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

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

25. Qty

 

Type: Decimal

Quantity 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".

26. Currency

 

Type: String

Local currency symbol. For example:

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

27. ListPrice

 

Type: Decimal

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

28. Tax

 

Type: Decimal

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

29. PricePaid

 

Type: Decimal

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

30. Deduction

 

Type: Decimal

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.

31. TenderAmount

 

Type: Decimal

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

32. CostPriceTheo

 

Type: Decimal

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

33. ListPriceConv

 

Type: Decimal

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

34. TaxConv

 

Type: Decimal

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

35. PricePaidConv

 

Type: Decimal

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

36. DeductionConv

 

Type: Decimal

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

37. TenderAmountConv

 

Type: Decimal

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

38. CostPriceTheoConv

 

Type: Decimal

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

39. OrderTypeDesc

 

Type: String

The order type, for example:

  • "Eat in"
  • "Takeaway"

Use the values in your POS system for these fields.

40. MenuBand

 

Type: String

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.

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

 

Type: String

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

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

43. SubGroupDesc

 

Type: String

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

44. TabOwner

 

Type: String

Operator ID of the person who entered the record.

45. TabOwnerDesc

 

Type: String

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

  • "Maria Rossi"

46. OriginalTabOwner

 

Type: String

Operator ID of the person who opened the tab.

47. OriginalTabOwnerDesc

 

Type: String

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

48. OldTableCode

 

Type: String

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

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

49. PrevTransactionCode

 

Type: String

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

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

50. AuthorisedBy

 

Type: String

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

Person who authorized a discount, if applicable.

51. TextField

 

Type: String

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

Free text field, with a limit of 250 characters.

52. GuestDesc

 

Type: String

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

The booking party name.

53. GuestCode

 

Type: String

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

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

54. TimeSentToPrep

 

Type: Integer

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"

55. BumpTime

 

Type: Integer

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"

56. UniversalTimeSlotId

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

57. TimeSlotDesc

 

Type: String

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

Customer-defined time slot. For example:

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

58. TransactionStartEnd

 

Type: String

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

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

59. IsDeleted

 

Type: Decimal

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

60. CustomField1

 

Type: String

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

61. CustomField2

 

Type: String

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

62. CustomField3

 

Type: String

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

63. CustomFact1

 

Type: String

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

64. CustomFact2

 

Type: String

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

65. DateFact

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

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.

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. However, 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).

How to Add bill printing data

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.

How to Add a tip or service charge

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

How to Close a tab

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

How to Void an item not assigned to a specific check

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.