POS Gateway Guide

Introduction

This page explains how to send in your POS data using the Fourth POS Gateway. Read this in conjunction with the POS Gateway reference, which holds full descriptions for each field and transaction type.

Updates

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

What is the POS Gateway?

The POS Gateway is our standardized and streamline way to deliver POS data to Fourth systems. It acts as a single point-of-entry to all Fourth systems that use POS data. This data in turn drives labor forecasts, inventory movement and business intelligence reporting in Fourth.

Learn how Fourth uses POS data

If you are a POS provider, you must integrate with this gateway, rather than creating a custom integration with Fourth. Doing so makes sure that you only need to integrate once with us, regardless of the Fourth solution you need to communicate with now or in the future.

Get started

To integrate with the POS Gateway, follow these steps:

  1. Contact Fourth, so that we can provide account details and support your business. Your mutual customer can introduce you to their Fourth contact to do this.
  2. Develop your CSV export, using this page and the POS Gateway reference.
  3. Test your integration with our sandbox — we'll also validate your file using our own tools.
  4. Get the customer to provide written sign-off.
  5. Go live!

Downloads

Before reading further, please download these files:

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

How is POS data delivered?

You send your POS data as a CSV file to the POS Gateway, normally once a day per customer location. We call this file the Transaction Dataset. You can send the file using either:

  • POS Transaction API
    The POS Transaction API is our preferred data delivery method. It is a RESTful API that supports HTTPS connections. See the POS Transaction API reference for details.
  • SFTP
    For each customer, you have a separate SFTP folder that only has data from your POS systems. This ensures privacy and security for both the Fourth customers and your business.

 

What's inside the Transaction Dataset csv file?

The Transaction Dataset maps your data to a set of transaction types and data fields that the POS Gateway can consume.

You must send us the data as a CSV file that uses double quotes and commas. Empty fields MUST be double quoted. 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",...

Transaction types

Each row of the dataset has a transaction type. This is the action that has occured during the dining experience. The types are:

  • TAB_OPEN and TAB_CLOSE open and close the check.
  • SALES_ITEM and MODIFIER_ITEM are the food and drink orders.
  • DISC_ITEM is used for any discounts applied.
  • VOID_ERROR, VOID_ITEM, VOID_WASTE, and VOID_WASTE2 to VOID_WASTE11 are for voiding any items as required.
  • MAINS_AWAY and PRINT_CHECK enable you to timestamp these events.
  • SERVICE_CHARGE and TENDER take tip and payment information. 

The transaction types are set in the 15th column of the transaction dataset: "TransactionTypeCode". You MUST set a transaction type for each record, otherwise the record is ignored!

For example, during an average dining experience, these transactions would happen:

Action Transaction type
Customer is ready to order. TAB_OPEN
Customer orders starter. SALES_ITEM
Customer orders main meal. SALES_ITEM
Customer orders drink. SALES_ITEM
Customer asks for their main meal to not include tomato. MODIFIER_ITEM
Server sees that the customer has finished their starter. MAINS_AWAY
Server prints the bill to pass to the customer. PRINT_CHECK
Service charge is recorded. SERVICE_CHARGE
Customer pays the bill. TENDER
Check is closed. TAB_CLOSE

Read the full description of transaction types

Fields

The fields (columns in the csv file) hold the data you are sending for each transaction type. Some fields are mandatory for all transaction types, such as:

  • "transactionid" is a unique ID for the record.
  • "recordactivitycode" is an incremental number of each transaction for a check.
  • "time" identifies when the transaction occurred.

Other fields are relevant only to a specific transaction type, such as:

  • "tendertypecode" and "tendertypedesc" are used only for TENDER transactions.
  • "transactionstartend" is used only for TAB_OPEN and TAB_CLOSE transactions.

You must include ALL columns in the dataset, in the correct order. Each field must include one of:

  • Data; e.g. "pizza funghi" or "12.50"
  • An empty string; e.g. ""
  • Zero; e.g. "0"

Note that we have a number of fields that are reserved for future use. You just need to include an empty string "" or "0" for these as shown in the mandatory and optional fields download.

Read the full descriptions for each field

How should I format the dataset file?

You must send us the data as a csv file that uses double quotes and commas. Empty strings must be enclosed in double quotes. For example, the value for "unitid" is always an empty string:

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

As well, you must:

  • Encode it using UTF-8 standard, without BOM
  • Send it as either zipped or unzipped
  • Ensure the filesize is below 30 MB
  • Ensure fields are below 255 characters

See the formatting, encoding and other rules that apply to the dataset

How do I update records?

You can update records for a past date by sending in a new .csv file. The POS Gateway processes the file and:

  • Updates any existing transactions
  • Adds any new transactions

To update a transaction, you MUST use exactly the same unique "TransactionId" as was previously sent in. If you send in a file that has new transactionIds for a date (with existing records), then the POS Gateway treats these as new transaction records for that date. Therefore, we highly recommend that you do not ever change the format of your transaction IDs if you generate these on-the-fly.

You can submit updates to data for up to 2 years in the past. If you need to submit bulk sales data for further back than this, then please contact us.

How do I delete records?

If for some reason you sent in transactions that now need to be deleted, then there are two options:

  • Resubmit the transactions (with the same "TransactionId") and set the price columns to "0". If this is not possible, then;
  • Get your customer to raise a support case to resubmit transactions for the dates in question. Ensure that you give the customer the .csv files for the dates that need changing. Your .csv files must contain ALL the transaction sales data for the dates that need resubmitting. Our support team will delete the data from those dates, and then submit the new data for processing.

Examples


Start a tab

The TAB_OPEN transaction type opens a tab.

There’s no sales data recorded for this transaction type. Instead, it primarily records the:

  • "time": This is the time the check is first opened; for example, "19:30:31".
    It’s vital for our customers that the start and end times are recorded accurately.

  • "RecordActivityCode": As it’s the first record for a transaction, this is "1".

  • "TransactionStartEnd": This is always "1".

For mandatory fields around sales, price and tax, just enter "0" or "" as shown in the example.

01: Example simple open & close tab

Close a tab

The TAB_CLOSE transaction type closes a tab. It also records the:

  • "PricePaid", "TenderAmount", and "Tax": these are the totals for the check excluding service charge.

  • "ListPrice": For TAB_CLOSE only, this can be either the total list price of the items before discount, or the price paid.

  • "Time": This is the time the check is closed. It’s vital for our customers that the start and end times are recorded accurately.

  • "RecordActivityCode": This must be the last record for the check.

  • "Covers": e.g. for 4 people, this would be "4".

  • "Qty": The number of items on the bill. We recommend using the number of charged and stock-related items; however, you can deviate from this if necessary. 

  • "TransactionStartEnd": This is always "2".

01: Example simple open & close tab

Add food and drinks

All food and drinks sales are covered by the SALES_ITEM and MODIFIER_ITEM transaction types. These transaction types require the price per item, any discount applied, and the tax on the price paid (not the list price tax).

As you’d expect, these transaction types require you to send through a lot of data about each sales item. This includes the categorization for the item. Normally, the categorizations for sales items are maintained by Fourth in collaboration with the customer. If, for any reason, the categorizations are changed at the POS end, you must notify Fourth so that we can update the configuration. The categorization fields are:

  • "MajorGroupDesc", for example "Food"

  • "FamilyGroupDesc", for example "Mains"

  • "SubGroupDesc", for example "Burgers"

Note: For customers using Fourth Inventory for Hotels (Adaco), these must include a two-digit code at the start; e.g. "12-Burgers".

An additional field, "SalesItemDesc", holds the description for the item, such as "water" or "Lentil goats cheese salad". A common cause of issues — particularly for places serving pizza! — is including a double quote in the description. This causes the data load to fail so we ask partners to avoid using them. However, if you must include double-quotes in your descriptive fields, then you must escape each one with an additional double-quote:

...,"10"" pizza",... 

More double-quote examples

Calculating price and tax value

For each sales or modifier item, there a number of fields for including pricing and tax. These are:

  • "ListPrice": The original price per item before any discounts; in the UK this includes VAT.

  • "Qty": The number of items purchased

  • "PricePaid": The price paid for ALL items after any discounts are applied, including VAT.

  • "Tax": The VAT included in the "PricePaid".

For example, a check that includes two identical pizzas with no discount would look similar to:

TransactionTypeCode SalesItemDesc Qty ListPrice Tax PricePaid
SALES_ITEM Pizza Vegetarian 2 10.00 3.33 20.00

Charged and free modifiers

For charged modifiers, include the "ListPrice", "PricePaid" and "Tax" for the modifier separately from the related SALES_ITEM. For example:

TransactionTypeCode SalesItemDesc Qty ListPrice Tax PricePaid
SALES_ITEM Pizza Vegetarian 2 10.00 3.33 20.00
MODIFIER_ITEM Olives 1 1.00 .17 1.00

For free modifiers, use "0" for the "ListPrice", "PricePaid" and "Tax".  All modifiers should also have their own "salesitemPLU", regardless of whether they are charged or free.

The following example shows one person dining with charged and free modifiers.

02: Example simple with modifiers

Discount a sales item or modifier

The preferred way to discount an item is to use the transaction type DISC_ITEM.

Important fields for deductions are:

  • "SalesItemPLU" and "SalesItemDesc" identify the item the deduction applies to. You should also include the categorization for the item ("MajorGroupDesc", "FamilyGroupDesc" and "SubGroupDesc").
  • "DeductionCode" and "DeductionDesc" identify the type of deduction.
  • "Qty" is the number of discounts (of the same type) used by the diners.
  • "Deduction" is the value of the deduction, for example "5" for 5 pounds off of the item. This is a positive value. It is also the cumulative total of the discount; that is, the value of the deduction x "Qty".  For example:
TransactionTypeCode DeductionCode DeductionDesc Qty Deduction
DISC_ITEM 300 £2 off pizza 2 4
DISC_ITEM 301 £1 off pasta 1 1

The original food or drink item must include the deduction in the "PricePaid" column. For example:

TransactionTypeCode SalesItemDesc Qty ListPrice PricePaid Deduction
SALES_ITEM Pasta Vegetarian 1 10.00 6.50 0
DISC_ITEM Pasta Vegetarian 1 0 0 3.50

03: Example with discounted items

Add a discount to part or all of the bill

Where possible, a discount should always be recorded against the sales item that it applied to. However, there are of course situations where a discount is applied across part or all of an entire bill.

To record a discount that goes against the entire bill, rather than one a specific item, then you MUST have values for these fields:

  • "TransactionTypeCode": Must be "DISC_ITEM"
  • "DeductionCode": For example, "410".
  • "DeductionDesc": For example, "20% off food items".
  • "Qty: Number of this type of deduction.
  • "Deduction": The full amount deducted from the check.
  • "OrderTypeDesc": For example, "EAT IN".

You do not need values for:

  • "SalesItemPLU"
  • "SalesItemGUID"
  • "SalesItemDesc"
  • "MenuBand"
  • "MajorGroupDesc"
  • "FamilyGroupDesc"
  • "SubGroupDesc"

For the individual sales items and modifiers, you MUST remove the percentage discount amount from their "PricePaid". The TAB_CLOSE must show the total paid after the discount is applied. For example:

TransactionTypeCode SalesItemDesc DeductionDesc Qty ListPrice PricePaid Deduction
SALES_ITEM Pasta Vegetarian   1 10.00 8.00 0
SALES_ITEM Latte   1 3.50 2.80 0
DISC_ITEM Discount 20% off Tuesdays 1 0 0 2.70
TAB_CLOSE     2 13.50 10.80 0

04: Example with discount applied to across the check

Calculate UK tax

The tax field is used for the actual tax paid by the diner after any discounts. For example (where the VAT for all items is set at 20%):

TransactionTypeCode SalesItemDesc Qty ListPrice Tax PricePaid Deduction
SALES_ITEM Fanta 1 2.50 0.42 2.50 0
SALES_ITEM Cola 2 2.50 0.83 5.00 0
SALES_ITEM Pasta ham 1 10.00 1.67 10.00 0
SALES_ITEM Pizza Vegetarian 1 10.00 1.08 6.50 0
DISC_ITEM Pizza Vegetarian 1 0 0 0 3.50
TAB_CLOSE   5 27.50 4.00 24.00  

Void an item before any prep

Use the VOID_ERROR transaction type to void items where no prep has occurred; for example, when a diner changes their order before the kitchen has started on the meal.

The values for voided items must be negative. For example, if a server adds two colas to a check and then realises it should only be one, the values would be:

TransactionTypeCode SalesItemDesc Qty ListPrice Tax PricePaid
SALES_ITEM Cola 2 2.50 0.83 5.00
VOID_ERROR Cola -1 -2.50 -0.41 -2.50

Modifiers (MODIFIER_ITEM) are voided in the same way as sales items (SALES_ITEM).

Voids SHOULD if possible include a description and code for the void. These values are visible to customers in Fourth and help them make decisions about their services. Use the deduction fields for these:

  • "DeductionCode": for example, "500".
  • "DeductionDesc": for example, "void before service"

However, do not set a value for "Deduction". This should remain "0".

05: Example voids

Void an item after prep

Use these transaction types to void items where prep has occurred.

  • VOID_ITEM — voids an item where prep occured but the item can go back into stock; e.g. an unopened bottle of beer the diner no longer wants.
  • VOID_WASTE, VOID_WASTE2 to VOID_WASTE10  — voids an item where it cannot be resold. Each customer self-determines what they wish VOID_WASTE2 to VOID_WASTE10 to refer to.

Learn more VOID_WASTE categorization

The values for voided items must be negative. For example:

TransactionTypeCode SalesItemDesc Qty ListPrice Tax PricePaid
SALES_ITEM Pizza 1 10.00 1.67 10.00
VOID_WASTE Pizza -1 -10.00 -1.67 -10.00

Modifiers (MODIFIER_ITEM) are voided in the same way as sales items (SALES_ITEM).

Voids SHOULD if possible include a description and code for the void. These values are visible to customers in Fourth and help them make decisions about their services. Use the deduction fields for these:

  • deductioncode: for example, "600".
  • deductiondesc: for example, "Customer rejected" or "Ingredient contamination".

However, do not set a value for deduction. This should remain "0".

05: Example voids

Void an item not assigned to a specific check

Sometimes the restaurant may need to void items that were not assigned to a specific check. For example:

  • A bottle of spirits accidentally knocked over
  • Bread rolls accidentally burnt in the oven

You can void these items outside of a tab using VOID_WASTE11. When doing so, set the RecordActivityCode to "1", provide the quantity of wastage, and the sales value of the voided items in PricePaid.

TransactionTypeCode RecordActivityCode SalesItemDesc Qty ListPrice Tax PricePaid
VOID_WASTE11 1 Bread Roll -12 0 0 -18.00
VOID_WASTE11 1 House white bottle -1 0 0 -22.00

06 Example voids outside tab

Add a tip or service charge

Service charges are recorded using the SERVICE_CHARGE transaction type. This allows our mutual customers to review tips and charges via Fourth Analytics.

The charge is listed in "TenderAmount". Provide only the paid amount for the service charge, not the requested amount. If no service charge was collected, use "0".

Do NOT include the service charge in the TAB_CLOSE totals. For example, in the following, the diners receive a check for £27.50. However, the PricePaid and TenderAmount for TAB_CLOSE is £25.00.

TransactionTypeCode SalesItemDesc Qty ListPrice Tax PricePaid TenderAmount
SALES_ITEM Pizza 2 10.00 3.34 20.00  
SALES_ITEM Fanta 2 2.50 0.83 5.00  
SERVICE_CHARGE           2.50
TAB_CLOSE   4 25.00 3.34 25.00 25.00

07: Example with service charge

Add mains away and bill printing data

If possible, include MAINS_AWAY and PRINT_CHECK transactions in your dataset to help your customer better understand their diners' behaviour.

Use the MAINS_AWAY transaction type to timestamp when the kitchen is instructed to begin prepping the next course of a meal. Use the PRINT_CHECK transaction type to timestamp when the server prints the check (used in conjunction with TENDER or TAB_CLOSE to see how long the customer waited to pay the bill).

For Fourth and the customer, the primary piece of information we need for each of these events is the "Time". Aside from the fields that are mandatory for all transaction types — such "TransactionId" — there are no additional fields you need to enter.

08: Example with Mains Away and Print Check

Add payment details

Use the TENDER transaction type to add payment details.

You only need to specify the received payment without service charge. Use these fields to do so:

  • "TenderTypeCode"
  • "TenderTypeDesc"
  • "TenderAmount"

For example, the full amount these diners paid is £45.00, but both the TENDER and TAB_CLOSE values exclude the service charge.

TransactionTypeCode PricePaid TenderTypeCode TenderTypeDesc TenderAmount
SERVICE_CHARGE       5.00
TENDER   1 CASH 20.00
TENDER   2 VISA 20.00
TAB_CLOSE 40.00      

09: Example tenders

Include dine-and-dash or other missed payment events

The value for "PricePaid" should always show the received payment. This means that If for some reason the diners do not pay all or part of the check, this value will be lower than expected. For example, if the diners leave without paying at all:

TransactionTypeCode Qty ListPrice Tax PricePaid
SALES_ITEM 2 10.00 0 0
SALES_ITEM 2 2.50 0 0
TAB_CLOSE 4 25.00 0 0