Skip to content

Webhooks

Webhooks allow applications to receive, via HTTP requests, information about when something happens in GoTab in realtime. Examples include receiving a webhook event when a product has been updated, a new order is submitted, or the fiscal day has ended at a location.

Webhook endpoints, headers, and events can be configured on the integrations dashboard.

All webhook URLs will be POSTed to with a Content-Type header value of application/json and a JSON formatted payload object with the following properties:

KeyTypeOptionalDescription
typestringNoThe event type. Examples include PRODUCT_UPDATED, ORDER_PLACED, and ITEM_ADDED.
targetUuidstringYesA UUID provided only if the type of event targets a particular resource. For ORDER_PLACED this would be an orderUuid.
targetIdstringYesAn ID provided for events where the target does not have a UUID. For CATEGORY_UPDATED this would be a categoryId.
locationUuidstringYesThe UUID of the location the event occurred at.
locationNamestringYesThe name of the location the event occurred at.
locationIdstringYesThe ID of the location the event occurred at.
createdAtstringNoAn ISO 8601 timestamp for the exact time the event was created.
dataobjectNoThe data for the event. The shape of the data varies based on the event being sent.

The payload’s data, targetUuid, and targetId properties will vary depending on the event type.

In addition to any custom headers configured on the dashboard, the POST request will contain the following headers:

KeyDescription
X-GoTab-Event-TypeThe event type as a header.
X-GoTab-Event-Target-UUIDThe event targetUuid as a header.
X-GoTab-Event-Target-IDThe event targetId as a header.
X-GoTab-Application-IDThe unique identifier of the application configured to receive the webhook event. This value will match the value shown on the integration dashboard page.
X-GoTab-SignatureIf the webhook is configured with a secret then this value will be the SHA-256 HMAC of the request body encoded using the provided secret.

The User-Agent for all webhook requests will start with GoTab-WebhookAgent.

If a secret is configured on your webhook, the X-GoTab-Signature header will contain a hex-encoded SHA-256 HMAC of the raw JSON request body, signed with your secret. To verify the signature:

  1. Read the raw request body as a string (before JSON parsing).
  2. Compute HMAC-SHA256(body, secret) and hex-encode the result.
  3. Compare it to the X-GoTab-Signature header value.
POST /webhook/endpoint HTTP/2
Host: localhost:5000
User-Agent: GoTab-WebhookAgent/1.0
Content-Type: application/json
X-GoTab-Event-Type: ORDER_PLACED
X-GoTab-Event-Target-UUID: ord_xxxxxxxxx
X-GoTab-Event-Target-ID: 12345
X-GoTab-Application-ID: int_xxxxxxx
X-GoTab-Signature: [SHA-256 HMAC HEX]
{
"type": "ORDER_PLACED",
"targetUuid": "ord_xxxxxxxxx",
"targetId": "12345",
"locationUuid": "loc_xxxxxxxxx",
"locationName": "Main Street Location",
"locationId": "67890",
"createdAt": "2023-01-01T00:00:00.000Z",
"data": { ... }
}

Fired whenever an item is successfully added to an order.

type: ITEM_ADDED
targetUuid: itemUuid

KeyTypeDescription
orderIdstringThe ID of the order the item was added to.
productIdstringThe ID of the product added.
namestringThe name of the item.
productNamestringThe name of the product.
categoryNamestringThe category the item belongs to.
quantitynumberThe quantity added.
pricenumberThe price of the item.
tagsstring[]Tags associated with the item.
tabIdstringThe ID of the tab the item was added to.
tabUuidstringThe UUID of the tab the item was added to.

Fired whenever an item is removed from an order.

type: ITEM_REMOVED
targetUuid: itemUuid

KeyTypeDescription
orderIdstringThe ID of the order the item was removed from.
namestringThe name of the item.
productNamestringThe name of the product.
quantitynumberThe quantity removed.
pricenumberThe price of the item.
tagsstring[]Tags associated with the item.
tabIdstringThe ID of the tab the item was removed from.
tabUuidstringThe UUID of the tab the item was removed from.

Fired whenever a tab is opened at a location.

type: OPEN_TAB
targetUuid: tabUuid

KeyTypeDescription
namestringThe name of the tab.
spotNamestringThe name of the spot where the tab was opened.
totalnumberThe current tab total.
openedFromstringThe context in which the tab was opened. Known values: SERVICE_MENU, SERVER_TAB.

Fired whenever a tab is closed at a location.

type: CLOSE_TAB
targetUuid: tabUuid

Data: None


Fired whenever an order has been placed at a location.

type: ORDER_PLACED
targetUuid: orderUuid

KeyTypeDescription
createdstringISO 8601 timestamp of when the order was created.
orderNamestringThe name/label of the order.
scheduledbooleanWhether the order is scheduled for a future time.
zoneNamestringThe name of the zone where the order was placed.
spotNamestringThe name of the spot where the order was placed.
zoneTagsstring[]Tags associated with the zone.
zoneGroupNamestringThe name of the zone group.
totalnumberThe order total, including taxes and fees.
tabUuidstringThe UUID of the tab this order belongs to.
itemNamesstring[]A full list of item names from the order.
itemTagsstring[]A full list of item tags the order contains.
categoryNamesstring[]A full list of category names represented in the order.

Fired whenever a guest successfully verifies their identity at a location (e.g. after a phone verification flow).

type: GUEST_VERIFIED
targetUuid: customerUuid

KeyTypeDescription
oldCustomerIdstringThe previous customer ID if the guest was merged with an existing record.
isFirstTimebooleanWhether this is the first time the guest has verified at this location.

Fired whenever a guest subscribes to a location (e.g. opts into marketing communications).

type: GUEST_SUBSCRIBED
targetUuid: customerUuid

KeyTypeDescription
handlestringThe handle (e.g. phone number or email) the guest subscribed with.

Fired whenever a guest unsubscribes from a location.

type: GUEST_UNSUBSCRIBED
targetUuid: customerUuid

KeyTypeDescription
handlestringThe handle (e.g. phone number or email) the guest unsubscribed with.

Fired whenever a menu at a location is updated.

type: MENU_UPDATED
targetUuid: menuUuid

Data: None


Fired whenever a product at a location is updated.

type: PRODUCT_UPDATED
targetUuid: productUuid

Data: None


Fired whenever a category at a location is updated or when a product within that category is updated. The cause property describes the chain of events that triggered this event.

type: CATEGORY_UPDATED
targetUuid: null — categories do not have a UUID. Use targetId instead.
targetId: categoryId

KeyTypeDescription
causeobjectThe update that triggered this category event. If a product change caused it, this will be { "type": "PRODUCT_UPDATED" }.

Fired whenever a location’s settings or details are updated.

type: LOCATION_UPDATED
targetUuid: locationUuid

Data: None


Fired whenever a QR code is scanned at a location. This event is throttled to once per 5 minutes per customer per target to avoid duplicate events from repeated scans.

type: QR_SCANNED
targetId: spotId (or the ID of whichever resource the QR code points to)

KeyTypeDescription
typestringThe type of resource the QR code targets. Currently always SPOT.
targetNamestringThe name of the resource the QR code points to.
entryPointstringThe entry point context in which the QR code was scanned.

Event TypetargetUuidtargetIdHas Data
ITEM_ADDEDitemUuidYes
ITEM_REMOVEDitemUuidYes
OPEN_TABtabUuidNo
CLOSE_TABtabUuidNo
ORDER_PLACEDorderUuidYes
GUEST_VERIFIEDcustomerUuidYes
GUEST_SUBSCRIBEDcustomerUuidYes
GUEST_UNSUBSCRIBEDcustomerUuidYes
MENU_UPDATEDmenuUuidNo
PRODUCT_UPDATEDproductUuidNo
CATEGORY_UPDATEDnullcategoryIdYes
LOCATION_UPDATEDlocationUuidNo
QR_SCANNEDspotIdYes

GoTab retries webhook deliveries when your endpoint returns a non-2xx response or times out. Retries use exponential backoff over approximately 24 hours before the event is considered permanently failed.

To avoid missed events:

  • Return a 2xx response as quickly as possible — do heavy processing asynchronously (queue the payload, respond immediately)
  • Your endpoint has a 10-second timeout — responses that take longer are treated as failures
  • Design your handler to be idempotent — the same event may be delivered more than once

Use a tunneling tool to expose a local server and register it as your webhook endpoint in the Integration Dashboard.

ngrok:

Terminal window
ngrok http 3000
# Gives you: https://abc123.ngrok.io → forward to localhost:3000

cloudflared:

Terminal window
cloudflared tunnel --url http://localhost:3000

Register the public URL as your webhook endpoint, then trigger events by interacting with your sandbox location. Verify the X-GoTab-Signature header in your handler:

import crypto from 'crypto';
function verifySignature(rawBody, secret, signatureHeader) {
const expected = crypto
.createHmac('sha256', secret)
.update(rawBody)
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(expected),
Buffer.from(signatureHeader)
);
}