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.
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:
For example:
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:
|
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:
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:
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:
|
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:
|
20. TenderTypeCode
Type: String Code. For example:
Use the values in your POS system for these fields. |
21. TenderTypeDesc
Type: String Type of payment, including delivery aggregators. For example:
Use the values in your POS system for these fields. |
22. DeductionCode
Type: String Deduction code. For example:
Use the values in your POS system for these fields. |
23. DeductionDesc
Type: String Deduction description. For example:
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:
|
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. 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:
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:
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:
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:
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:
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:
|
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:
|
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:
|
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:
|
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:
|
58. TransactionStartEnd
Type: String Flag that indicates whether this is the first or last record for a transaction (check). The values are:
|
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.
- How to Discount a sales item of modifier
- How to Add a discount to a bill
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).
- How to Add mains away data
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.
- How to Add food and drinks (including modifiers)
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.
- How to Add food and drinks (sales items)
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.
- How to Start a tab
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.
- How to Add payment details
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.
- How to Void an item before any prep
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.
- How to Void an item after prep
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.
- How to Void an item after prep
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.