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). |
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:
|
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". |
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 |
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:
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:
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. 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:
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:
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:
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:
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:
Type: String |
20 |
TenderTypeCode |
Code. For example:
Use the values in your POS system for these fields. Type: String |
21 |
TenderTypeDesc |
Type of payment, including delivery aggregators. For example:
Use the values in your POS system for these fields. Type: String |
22 |
DeductionCode |
Deduction code. For example:
Use the values in your POS system for these fields. Type: String |
23 |
DeductionDesc |
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. 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:
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. 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:
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:
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:
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:
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 |
Second level of categorization from the POS system. For example:
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:
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:
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:
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:
Type: String |
58 |
TransactionStartEnd |
Flag that indicates whether this is the first or last record for a transaction (check). The values are:
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.