Search

Are you looking for test card numbers?

Would you like to contact support?

Point-of-sale icon

Make Pay-at-table payments

How to use terminal initiated payment flows like Pay at table or Pay at curbside.

Using our Standalone solution?

Our Standalone solution doesn't support Pay at table.

Depending on how you interact with your customers, you may need to initiate payments from a terminal instead of a cash register. This lets you accept payments from your customers at a table, hotel room, or curbside.

The terminal initiated payment flow offers:

  • Equal and unequal split payments.
  • Support for all payment methods that you added to your account, as well as cash.
  • Easy combination with tipping options.
    Customers can enter a tip amount on the terminal with every split payment. If you let your staff enter a reference number when they start the payment from the terminal, you can then log the tip with that staff member to avoid adjusting tips later.

How it works

To begin with, you need to set up the feature. See Step 1: Configure Pay at table. After you've done that, the flow is as follows:

  1. On the terminal, your staff selects a button to start Pay at table, and enters their reference number.
  2. The terminal sends an event notification to the cash register. The notification informs the cash register that the terminal is waiting to receive a payment request for the reference number.
  3. If the reference number is not enough to decide which payment request to send, you send an InputRequest to the terminal, to ask your staff for more details. For example, ask for a table number, a choice from a list of bills, or a ride number. See Step 2: Collect input from your staff.
  4. Your staff provides the requested input on the terminal.
  5. You send a PrintRequest to print the bill using the terminal. This is optional. It depends on your business needs whether to do this and when.
  6. You send a PaymentRequest from the cash register to the terminal. See Step 3: Make a payment.
  7. The terminal shows the amount due, Split check, and options to:
    • Split the bill Equally. The terminal will ask for the number of splits.
    • Split the bill Unequally. The terminal will ask for the amount of the first split. This is also the option to choose if there's a single customer paying the entire bill.
  8. Then the terminal shows the split amount and options to:
    • Pay in Cash. Your staff receives the cash and selects a button on the terminal display to confirm.
    • Pay by Card. Your staff hands the terminal to the customer so that they can pay their split and respond to the tipping options on the terminal (if configured).
  9. After the split payment is Approved and Sent, the terminal prints a receipt.
  10. You process the split payment response, to keep track of the amount that's been paid. See Step 4: Receive payment result.
  11. If there is a remaining amount due, the terminal shows Next split and options to:
    • Pay later. This option is useful when there's a group of customers that are paying their share of the bill at different times. When your staff selects this button, the terminal shows Cancelled. When someone else from the group is ready to pay, your staff needs to start Pay at table again.
    • Pay remainder. You send another PaymentRequest for the next split payment (see Step 3 and Step 4).
      With equal splits, the terminal calculates the amount of the next split payment based on the number of splits. With unequal splits, the terminal shows the remaining amount and your staff enters the amount of the next split payment.

This continues until the full amount has been paid.

On the terminal, you can:
Press to go back a step in the flow. This is possible until the moment Cash or Card is selected.
Press to cancel the flow at any point.

Before you begin

Before you make any Pay-at-table transactions, make sure that you have:

  • Read and understood our Terminal API fundamentals.
  • Built an integration that can make a payment.
  • Set up event notifications. This is necessary to let the terminal send a notification to the cash register. The notification informs the cash register that the terminal is waiting to receive a payment request.

Also make sure that you are using payment terminals with an integrated printer and a WiFi connection, for example:

  • V400c
  • V400m. This model can automatically switch to a cellular 3G/4G connection if the WiFi connection drops.

Step 1: Configure Pay at table

In this step, you:

  • Enable the feature that lets the terminal send a SaleWakeUp event notification to the cash register. This notification alerts the cash register to the fact that the terminal is waiting to receive a payment request.
  • Write the text of the button that your staff selects on the terminal display to start Pay at table. Selecting the button triggers the SaleWakeUp event notification.
  • (Optional) Write the text to ask your staff to enter their reference number. The SaleWakeUp event notification will include the reference number your staff enters. You can use this for example to retrieve the associated bill, or to log sales and tips per staff member.
  • Add logic to your cash register so that it is able to handle the SaleWakeUp event notification.

After you have completed this step, you don't need to do it again.

To enable Pay at table and define the text shown on the terminal display:

  1. In your Customer Area, go to Point of Sale > Terminals and select your terminal.
  2. On the terminal page, select the Terminal API tab.
  3. Under Event Notification Buttons set the following values:

    Field Description
    Enable notification button Select Yes
    Notification category Select Sale wake up
    Title Enter the text to show on the button that starts the flow from the terminal. For example, Pay@tTable
    Details Enter the text to ask for a reference number.

    The reference number can consist of a maximum of 10 digits.

    If you leave this field empty, the terminal sends the SaleWakeUp event notification immediately when the button is selected.

  4. Select Save.

The terminal is now able to send SaleWakeUp event notifications to the cash register. These notifications include:

  • EventToNotify: SaleWakeUp
  • EventDetails: The reference number that your staff entered.

When the cash register receives these event notifications, it needs to handle them. Make sure your cash register is able to:

  1. Process the reference number received in the EventDetails field of the event notification.
  2. Retrieve the sale transactions (the bills) associated with the terminal or the reference number, and decide what to do next. For example:

    • If there is only one open bill, send a PaymentRequest. Or send a PrintRequest to let the terminal print the bill, followed by a PaymentRequest.
    • If there are more open bills, send an InputRequest to ask your staff for more details.

Step 2: Collect input from your staff

When you receive a SaleWakeUp event notification from the terminal, you need to find the bill that's associated with the terminal or with the reference number included in the notification, and send a payment request. However, there may be several open bills to choose from. In that case, do the following:

  1. Make an InputRequest (or a series of input requests) to ask your staff to enter more information on the terminal.
    For example: First ask for the table number with a text input request. Then send a menu input request to show a list of bills associated with the table number and ask your staff to select one.
  2. Process the responses to your input requests so that your cash register is able to retrieve the correct bill to send a payment request for.

Step 3: Make a payment

Technically Pay-at-table is a split payments flow. You make several subsequent payment requests for the same sale until the full amount has been paid. If a single customer pays the entire bill, you'd treat that as an unequal split for the full amount and you require only one split payment request to get the full amount paid.

In this split payments flow, you:

  • Set the split payments flag to true in each payment request.
  • Specify a unique sale transaction ID in the first payment request, and repeat that same ID in all subsequent split payments for the same sale.
  • Make sure your cash register keeps track of the amount that's been paid already.

After you have received a SaleWakeUp event notification from the terminal and collected information to determine for which bill the terminal wants to receive a payment request, proceed as follows:

  1. From your cash register, make a POST request to a Terminal API endpoint, specifying:

    • MessageHeader: This follows the standard MessageHeader structure, explained in Terminal API fundamentals, which includes:

      • ProtocolVersion: 3.0
      • MessageClass: Service
      • MessageCategory: Payment.
      • MessageType: Request
      • SaleID: Your unique ID for the cash register.
      • ServiceID: Your unique ID for this transaction attempt, consisting of 1-10 alphanumeric characters. This value needs to be unique within the last 48 hours.
      • POIID: Unique ID of the terminal.¬†This indicates which terminal the payment will be routed to.

    • PaymentRequest.SaleData: This SaleData object will be echoed in the response. It contains:

      • SaleTransactionID.TransactionID: Your unique reference for the sale (for example, the bill for table 5). All split payments belonging to the same sale (the same bill) must use this same sale TransactionID.
      • SaleTransactionID.TimeStamp: Date and time of the payment request, in UTC format.
      • Other fields as needed.
        For example, you can use tenderOption=AskGratuity in the SaleToAcquirerData to trigger the terminal to show the tipping options you configured.
        Or you can use the SaleToAcquirerData and TokenRequestedType for shopper recognition.

    • PaymentRequest.PaymentTransaction: This part of the request body indicates how much remains to be paid and how much has been paid already:

      • AmountsReq.Currency: The currency of the transaction.
      • AmountsReq.RequestedAmount: The amount that remains to be paid. For the first split payment, this is the full sale amount. For a subsequent split payment, this is the sale amount minus the PaidAmount.
      • PaidAmount: The amount that's already been paid. For the first split payment, this is zero. For a subsequent split payment, this is the sum of the amounts paid in previous split payments for the same sale.

    • PaymentRequest.PaymentData: This part of the request body is where you set the split payment flag:
      • PaymentType: Normal
      • SplitPaymentFlag: true

    For more information on the Terminal API request structure, refer to the Terminal API fundamentals.

    {
      "SaleToPOIRequest": {
        "MessageHeader": {
          "ProtocolVersion":"3.0",
          "MessageClass":"Service",
          "MessageCategory":"Payment",
          "MessageType":"Request",
          "SaleID":"POSSystemID12345",
          "ServiceID":"0207111104",
          "POIID":"V400cPlus-301506502"
        },
        "PaymentRequest": {
          "SaleData": {
            "SaleTransactionID": {
              "TransactionID": "9820s",
              "TimeStamp": "2019-11-12T12:58:23.000Z"
            }
          },
          "PaymentTransaction": {
            "AmountsReq": {
              "Currency": "USD",
              "RequestedAmount": 89.65,
              "PaidAmount": 0
            }
          },
          "PaymentData": {
            "PaymentType": "Normal",
            "SplitPaymentFlag": true
          }
        }
      }    
    }

    The payment request is routed to the terminal. This shows options to split Equally or Unequally, as described in How it works.
    When the payment is processed, you receive the payment result.

    If only a partial amount has been paid, the terminal shows options to Pay later or Pay remainder.
    If Pay remainder is selected, the terminal automatically calculates the next split in case of equal splits, or asks for the next amount in case of unequal splits.
    You would then make the next split payment request as shown in the next example.

    {
      "SaleToPOIRequest": {
        "MessageHeader": {...},
        "PaymentRequest": {
          "SaleData": {
            "SaleTransactionID": {
              "TransactionID": "9820s",
              "TimeStamp": "2019-11-12T13:44:20.000Z"
            }
          },
          "PaymentTransaction": {
            "AmountsReq": {
              "Currency": "USD",
              "RequestedAmount": 69.65,
              "PaidAmount": 20
            }
          },
          "PaymentData": {
            "PaymentType": "Normal",
            "SplitPaymentFlag": true
          }
        }
      }    
    }

Step 4: Receive payment result

When a split payment is processed, you receive the result.

  • If the payment is successful, the PaymentResponse body in the Terminal API response contains:

    • SaleData: This part of the PaymentResponse echoes the SaleData object from the PaymentRequest. It includes the TransactionID of the sale (the bill) that this split payment belongs to.
    • PaymentResult: This part of the PaymentResponse shows the payment method and the amount paid:

      • OnlineFlag: true for a card or wallet payment, or false for a cash payment.
      • PaymentInstrumentData.PaymentInstrumentType: Cash or Card
      • AmountsResp.AuthorizedAmount: The amount that's been paid with this transaction. Your cash register should keep track of this, and add it to the PaidAmount in a subsequent split payment for the same sale.
      • PaymentType: Normal

    • Response: This part of the PaymentResponse shows whether more split payments are needed to pay off the bill:

      • Result: Success indicates the full RequestedAmount has been paid. Partial indicates there's still an amount due, so more split payments are needed.
      • AdditionalResponse: A base64 string. When decoded, this is a JSON object with additional transaction data. For a cash payment, this field isn't included.
    {
      "SaleToPOIResponse": {
        "MessageHeader": {...},                         // Echoed from request
        "PaymentResponse": {
          "POIData": {...},
          "SaleData": {                                 // Echoed from request
            "SaleTransactionID": {                      // Echoed from request
              "TimeStamp": "2019-11-12T12:58:23.000Z",  // Echoed from request
              "TransactionID": "9820s"                  // Echoed from request
            }
          },
          "PaymentResult": {
            "OnlineFlag": true,
            "PaymentAcquirerData": {...},
            "PaymentInstrumentData": {
              "CardData": {...}
              },
              "PaymentInstrumentType": "Card"
            },
            "AmountsResp": {
              "AuthorizedAmount": 20,
              "Currency": "USD"
            },
            "PaymentType": "Normal"
          },
          "Response": {
            "Result": "Partial",
            "AdditionalResponse": "tid=01506502&AID=A0000000041010&transactionType=GOODS_SERVICES&backendGiftcardIndicator=false&posadditionalamounts.originalAmountValue=2000&..."
          }
        }
      }
    }
    {
      "SaleToPOIResponse": {
        "MessageHeader": {...},                         // Echoed from request
        "PaymentResponse": {
          "POIData": {...},
          "SaleData": {                                 // Echoed from request
            "SaleTransactionID": {                      // Echoed from request
              "TimeStamp": "2019-11-12T13:44:20.000Z",  // Echoed from request
              "TransactionID": "9820s"                  // Echoed from request
            }
          },
          "PaymentResult": {
            "OnlineFlag": false,
            "PaymentAcquirerData": {...},
            "PaymentInstrumentData": {
              "PaymentInstrumentType": "Cash"
            },
            "AmountsResp": {
              "AuthorizedAmount": 69.65,
              "Currency": "USD"
            },
            "PaymentType": "Normal"
          },
          "Response": {
            "Result": "Success"
          }
        }
      }
    }
  • If Pay later is selected on the payment terminal when it receives a request for a subsequent split payment, the terminal shows Cancelled. You receive a payment result containing:

    • PaymentResponse.Response.Result: Failure
    • PaymentResponse.Response.ErrorCondition: PaymentRestriction. This indicates that the Pay-at-table flow was interrupted. It's not the preceding split payment that failed.

  • If the payment failed, the terminal shows Declined and you receive a payment result containing:

    • PaymentResponse.Response.Result: Failure
    • PaymentResponse.Response.ErrorCondition: Indicates why the payment failed. For example, Refused indicates the card issuer refused the transaction, and Cancel indicates the transaction was cancelled on the terminal. Refer to our refusal reasons documentation.

Keeping your staff informed

The terminal will show the usual progress messages while a payment is processed. However, any errors occurring at other moments in the Pay-at-table flow are received at the cash register. Because your staff is not near the cash register, they won't know what happened and what they need to do. To help them, you can make a DisplayRequest to send a message from the cash register to the terminal.

Related steps