POS v1

POS v1

This API is Live and ready to use in production.

TableCheck has specialized integrations with Oracle MICROS (Simphony), Shiji Infrasys (HERO), Agilisys (InfoGenesis), and many more. Please contact your TableCheck Sales Representative to check if your desired integration already exists.

For further inquiries and assistance, please contact api@Tablecheck.com.

The POS API is used to connect Point-of-Sale systems to the TableCheck platform.

Target Audience

The POS API is recommended for use exclusively by POS vendors. It cannot be used by restaurant booking sites, etc.

Endpoint

The POS API allows the implementer to modify data.

https://api.tablecheck.com/api/pos/v1/...

Interactive API console

https://api.tablecheck.com/api/pos/v1/docs

Refer to Using the API Console for help.

Data Model

This section describes TableCheck’s object relational structure exposed by the API.

The POS API provides multi-tenant access: with a single API key you can manage data across multiple end-user accounts and even multiple POS systems. End-user tenancy is controlled with the following objects:

  • A “Franchise” is a merchant account, typically a restaurant group company or a hotel property.

  • A “Shop” is a restaurant venue. One Franchise has many Shops.

Depending on the end-user’s POS setup, a Franchise or Shop will correspond to the POS client account, and a Shop will correspond to one or more POS revenue centers.

A Shop has a one-to-many relationship with each of the following objects:

  • A “Table” corresponds to any physical location for seating, including tables, counter stools, and private rooms. In order for mapping logic to work, it is important that the table names within the POS exactly match the names used in TableCheck.

  • A “Reservation” corresponds to the POS party or table status. A Reservation will be assigned to one or more Tables. Note that multiple Reservations may be assigned to the same Table, so long as their seating times are not overlapping.

  • A “PosJournal” corresponds to the POS guest check. A Reservation may have multiple PosJournals, e.g. in the case that checks are split within the party. As described in the logic section below, there are cases where creating a PosJournal object (i.e. “opening a check”) will automatically create an associated Reservation object.

Lastly, a PosJournal has three sub-object types, each being a one-to-many relationship:

  • A “PosOrder” corresponds to a single food/beverage order line-item, for example: “3 x Chicken Salad @ $10.99”. The PosOrder includes the menu item name as a text field, as well as the quantity and unit price.

  • A “PosDiscount” corresponds to a discount such as a coupon or voucher which is subtracted from the check subtotal.

  • A “PosPayment” corresponds a money payment to settle the check, and includes information about the payment method such as cash or credit card.

API Setup

Please perform the following process for each new Shop which would like which is setup in the system.

  1. Request access to the Shops to enable POS integration by contacting api@tablecheck.com

  2. Verify you can access the Shop via the API

  3. Confirm the table names are matched between TableCheck and the POS system

Setup: Requesting Access to a Shop

In the future we plan to automate the Shop access request process.

Please request access to specific Shops (restaurants) by contacting api@tablecheck.com. Please include:

  • The Shop name

  • Your reference ID code to use for the Shop (will appear as Shop.ref in our API)

  • The Shop parent company (to help match)

  • The Shop address (to help match)

Setup: Browsing the Accessible Shop List

🔗 API Console

The /shops endpoint will return all restaurants for which you have been granted access.

GET /shops

Setup: Confirming Table Names

🔗 API Console

The POS API uses table names to automatically match Checks to existing Reservations. We recommend POS vendors to implement an automatic check process which is run periodically to ensure both systems remain in-sync.

The /shops/{shop_id}/tables endpoint returns all tables associated with the shop.

GET /shops/{shop_id}/tables

We recommend to pass time param to get all tables available for specific time.

Warning: POS API integration will NOT work properly if table names do not match between TableCheck and your POS system.

Live API Workflow

Overview

  1. When a user opens or modifies a guest check, transmit it to TableCheck's “PosJournal” API

  2. TableCheck will match the PosJournal to a Reservation (or create a new Reservation)

  3. When Reservations change in TableCheck, either via API or via user actions, TableCheck will notify the POS System of the change.

  4. According to the change, the POS system should retrieve the Reservation object and update the Table Status within the POS accordingly.

Transmitting Guest Checks (PosJournals)

🔗 API Console

You may fetch info for a single shop by either the id or slug.

GET /shops/{shop_id}/pos_journals

Create PosJournal

🔗 API Console

You can create PosJournal using the following URL:

POST /shops/{shop_id}/pos_journals

Special params:

Name

Comment

Name

Comment

receipt_num

Required field and represent Check ID

reservation_ref

TableCheck Reservation ID

reservation_status

Reservation ‘status’ that should be updated on associated Reservation record. See status mapping below

table_names

Table names could be fetched from https://api.tablecheck.com/api/pos/v1/docs#/table_names/listTables

num_people

receipt_num

order_at

table_names

Params that will be used for Reservation creation if reservation not found.

pos_orders

pos_discounts

pos_payments

Arrays of PosJournal associated records.

 

Update PosJournal

🔗 API Console

Update URL:

PUT /shops/{shop_id}/pos_journals/{pos_journal_id}

We allow to update all the same params as listed for :create PosJournal action except receipt_num param since it considered as unchangeable.

Linking Reservations and Setting Reservation Status

In the aforementioned PUT /shops/{shop_id}/pos_journals/{pos_journal_id} API endpoint, you may use the PosJournal.reservation_status parameter to automate Reservation status actions. In each case a Reservation will attempted to be linked as follows:

  1. If a Reservation was already created by or linked to the PosJournal as a result of a previous action (as per below), use that Reservation.

  2. If either of the PosJournal.reservation_id or reservation_ref parameters are set, attempt to use those to lookup the Reservation by its id or ref

  3. Attempt to automatch the reservation according to the paxtable_names, and opened_at parameters.

  4. Create a new Reservation

reservation_status Value

Reservation Action

Reservation.status

reservation_status Value

Reservation Action

Reservation.status

occupied

Guest has been seated at a table.

:seated

bill_printed

Bill has been printed

:check_req

paid

The bill has been paid by the guest.

:paid

cleaning

The guest has left the table,

:paid

vacant

The table is cleaned and ready for the next guest.

:paid

Setting Rich Data on PosJournals

While it is possible to implement the API by only setting basic fields such as opened_attotal_amt, etc., we recommend to transmit as many of the available fields as possible, including:

  • PosOrders - Includes menu item and order price details.

  • PosDiscounts - Promotional discount codes applied to the sales amount.

  • PosPayments - Payment method (credit card, cashless, etc.) and card brand / issuer. 

Restaurant end users can see data in TableCheck Manager and use it to generate detailed reports and analytics. Refer to the API Console for further details.

Receiving Reservation Sync Events

Please refer to the Sync API for instructions on how receive SyncEvent messages which indicate that a Reservation has changed on the TableCheck side as per the below example.

Note that you will receive all SyncEvents for all Shops to a single API callback URL. (If you require handling SyncEvents on a per-Shop basis, please refer to the polling instructions in the Sync API.)

// SyncEvent object { "id": "ae5355ca1fd337ed5d6893e2", "event_type": "created" "syncable_type": "reservation", "syncable_id": "ca1fd893e2Zae5355337ed5d6", // The reservation ID "syncable_ref": "your_id_here" // PosJournal.reservation_ref, if set }

Fetching a Reservation based on a Webhook Event

🔗 API Console

When you receive the SyncEvent, you may fetch the Reservation (including any associated PosJournals) using the following endpoint:

GET /shops/{shop_id}/reservations/{syncable_id or syncable_ref}

Pre-loading Reservations

🔗 API Console

Certain POS systems may wish to pre-load Reservations and open PosJournals in advance. This may be done using the Reservations list endpoint follows:

// Load all reservations starting between Nov 26, 2018 19:00 and 20:00 UTC GET /shops/{shop_id}/reservations?start_at_min=2018-11-26T19:00:00Z&start_at_max=2018-11-26T20:00:00Z

Update Reservations

🔗 API Console

Certain Reservation could be updated without updating PosJournal

PUT /shops/{shop_id}/reservations/{syncable_id or syncable_ref}

Table Status API

🔗 API Console

For certain POS systems and mobile ordering use cases, it may be easier to work with tables (i.e. identified by table name) rather than reservations. To do this, use the table_status endpoint.

Updating Status at a Table

The following example will find the reservation at table “A1” an change its status to seated:

PUT /shops/{shop_id}/table_status/update Body: { table_name: "A1", status: "seated", allow_create_reservation: true } Response: { table_status: { table_id: "5071d35765a26aa79f465e70", table_name: "A1", reservation_id: "65e70356071daa79f4765a25", reservation_start_at: "2024-01-01T17:00:00.000+09:00", reservation_end_at: "2024-01-01T19:00:00.000+09:00", status: "seated" } }

Updating Status by Reservation ID

After an initially fetching or updating table status as per the above example, you should store the reservation_id returned and used it for subsequent updates. This will guarantee you are updating the same diner’s reservation status, even if the current time exceeds their reservation period, or they move to a different table.

PUT /shops/{shop_id}/table_status/update Body: { reservation_id: "65e70356071daa79f4765a25", status: "paid" } Response: { table_status: { table_id: "5071d35765a26aa79f465e70", table_name: "A1", reservation_id: "65e70356071daa79f4765a25", reservation_start_at: "2024-01-01T17:00:00.000+09:00", reservation_end_at: "2024-01-01T19:00:00.000+09:00", status: "paid" } }

Clearing a Table

To clear a reservation from a table at the current time, set the status value to "vacant". This will cause the end time of the reservation to shift to be before the current time. Note that in this case, the API will return status "vacant" because there is no longer a reservation at the current time, however, the reservation object itself will have status "turned_over".

PUT /shops/{shop_id}/table_status/update Body: { reservation_id: "65e70356071daa79f4765a25", status: "vacant" } Response: { table_status: { table_id: "5071d35765a26aa79f465e70", table_name: "A1", reservation_id: "65e70356071daa79f4765a25", reservation_start_at: "2024-01-01T17:00:00.000+09:00", reservation_end_at: "2024-01-01T18:30:00.000+09:00", // changed status: "vacant" } }

Refer to the API documentation for further details.

TODO

  • Voiding Orders

  • Discounts (surcharges?) coupon code, etc.?