---
updatedAt: 2026-06-10T08:44:49.000Z
agentTools:
  projectIndex: https://developers.spoton.com/central-api/llms.txt
---

# Delivery of an API event.

## Verifying signatures

1. Base64-decode the `signature_key` returned on subscription creation (standard alphabet, no `=` padding) to get the raw key bytes.
2. Compute HMAC-SHA256 over the raw request body bytes exactly as received. Do not re-serialize the JSON.
3. Hex-encode the result in lowercase (64 characters). Do not Base64-encode it.
4. Compare it with the `X-Spoton-Webhook-Signature` header using a constant-time comparison.

**Java (17+)**

```java
byte[] key = Base64.getDecoder().decode(signatureKey);
Mac mac = Mac.getInstance("HmacSHA256");
mac.init(new SecretKeySpec(key, "HmacSHA256"));
String expected = HexFormat.of().formatHex(mac.doFinal(rawBody));
boolean valid = MessageDigest.isEqual(
    expected.getBytes(StandardCharsets.US_ASCII),
    signatureHeader.getBytes(StandardCharsets.US_ASCII));
```

**Node.js**

```javascript
const crypto = require('crypto');
const key = Buffer.from(signatureKey, 'base64');
const expected = crypto.createHmac('sha256', key).update(rawBody).digest('hex');
const valid = expected.length === signatureHeader.length &&
  crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(signatureHeader));
```

**Python**

```python
import base64, hashlib, hmac
# The key has no padding, and b64decode requires it.
key = base64.b64decode(signature_key + '=' * (-len(signature_key) % 4))
expected = hmac.new(key, raw_body, hashlib.sha256).hexdigest()
valid = hmac.compare_digest(expected, signature_header)
```

# OpenAPI definition

````json
{
  "openapi": "3.0.0",
  "info": {
    "title": "Webhook Event v1",
    "description": "The Webhook Event provides standardised way of informing third party integrations about events to orders and menu updates for relevant locations.",
    "version": "1.0.0",
    "contact": {
      "name": "SpotOn"
    }
  },
  "paths": {
    "/": {
      "post": {
        "summary": "Delivery of an API event.",
        "description": "## Verifying signatures\n\n1. Base64-decode the `signature_key` returned on subscription creation (standard alphabet, no `=` padding) to get the raw key bytes.\n2. Compute HMAC-SHA256 over the raw request body bytes exactly as received. Do not re-serialize the JSON.\n3. Hex-encode the result in lowercase (64 characters). Do not Base64-encode it.\n4. Compare it with the `X-Spoton-Webhook-Signature` header using a constant-time comparison.\n\n**Java (17+)**\n\n```java\nbyte[] key = Base64.getDecoder().decode(signatureKey);\nMac mac = Mac.getInstance(\"HmacSHA256\");\nmac.init(new SecretKeySpec(key, \"HmacSHA256\"));\nString expected = HexFormat.of().formatHex(mac.doFinal(rawBody));\nboolean valid = MessageDigest.isEqual(\n    expected.getBytes(StandardCharsets.US_ASCII),\n    signatureHeader.getBytes(StandardCharsets.US_ASCII));\n```\n\n**Node.js**\n\n```javascript\nconst crypto = require('crypto');\nconst key = Buffer.from(signatureKey, 'base64');\nconst expected = crypto.createHmac('sha256', key).update(rawBody).digest('hex');\nconst valid = expected.length === signatureHeader.length &&\n  crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(signatureHeader));\n```\n\n**Python**\n\n```python\nimport base64, hashlib, hmac\n# The key has no padding, and b64decode requires it.\nkey = base64.b64decode(signature_key + '=' * (-len(signature_key) % 4))\nexpected = hmac.new(key, raw_body, hashlib.sha256).hexdigest()\nvalid = hmac.compare_digest(expected, signature_header)\n```",
        "operationId": "WebhookEvent_Delivery",
        "responses": {
          "200": {
            "description": "A successful response.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {}
                }
              }
            }
          },
          "201": {
            "description": "Created.",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "400": {
            "description": "Bad request. Delivery will not be retried.",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "500": {
            "description": "There was an error processing the request. Delivery will be retried.",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          }
        },
        "parameters": [
          {
            "name": "x-spoton-webhook-signature",
            "description": "HMAC-SHA256 signature of the raw request body, encoded as lowercase hexadecimal (64 characters). It is not Base64-encoded.",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "x-spoton-webhook-signature-version",
            "description": "Payload signature version. Currently only `v1` is supported.\nThe v1 signature standard is an HMAC-SHA256 of the raw request body in its entirety, output as lowercase hex. The secret is the `signature_key` generated when the subscription is created. SpotOn shares the key Base64-encoded (standard alphabet, without `=` padding), so decode it to raw bytes before use.",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/v1Event"
              }
            }
          },
          "description": "Webhook Event",
          "required": true
        }
      }
    }
  },
  "components": {
    "schemas": {
      "EventDetails": {
        "type": "object",
        "properties": {
          "menu": {
            "title": "Event details for menu related events",
            "allOf": [
              {
                "$ref": "#/components/schemas/v1Menu"
              }
            ]
          },
          "item": {
            "title": "Event details for item related events",
            "allOf": [
              {
                "$ref": "#/components/schemas/v1Item"
              }
            ]
          },
          "modifier": {
            "title": "Event details for modifier related events",
            "allOf": [
              {
                "$ref": "#/components/schemas/v1Modifier"
              }
            ]
          },
          "order": {
            "title": "Event details for order related events",
            "allOf": [
              {
                "$ref": "#/components/schemas/v1Order"
              }
            ]
          },
          "locationConnection": {
            "title": "Event details for location connection related events",
            "allOf": [
              {
                "$ref": "#/components/schemas/v1LocationConnection"
              }
            ]
          },
          "laborTimePunch": {
            "title": "Event details for labor time punch related events",
            "allOf": [
              {
                "$ref": "#/components/schemas/v1LaborTimePunch"
              }
            ]
          },
          "fohReservationTicket": {
            "title": "Event details for front-of-house reservation ticket events",
            "allOf": [
              {
                "$ref": "#/components/schemas/v1FOHReservationTicket"
              }
            ]
          },
          "onboarding": {
            "title": "Event details for embedded onboarding events",
            "allOf": [
              {
                "$ref": "#/components/schemas/v1Onboarding"
              }
            ]
          }
        },
        "description": "Event details",
        "title": "Details"
      },
      "FOHReservationTicketCheckTotal": {
        "type": "object",
        "properties": {
          "items_total_cents": {
            "type": "string",
            "format": "int64",
            "example": 5400,
            "description": "Sum of all item prices in cents",
            "title": "Sum of all item prices in cents"
          },
          "tax_cents": {
            "type": "string",
            "format": "int64",
            "example": 486,
            "description": "Total tax in cents",
            "title": "Total tax in cents"
          },
          "tip_cents": {
            "type": "string",
            "format": "int64",
            "example": 1080,
            "description": "Total tip in cents",
            "title": "Total tip in cents"
          },
          "paid_amount_cents": {
            "type": "string",
            "format": "int64",
            "example": 6966,
            "description": "Total amount paid in cents",
            "title": "Total amount paid in cents"
          },
          "other_charges_cents": {
            "type": "string",
            "format": "int64",
            "example": 0,
            "description": "Other charges in cents",
            "title": "Other charges in cents"
          },
          "menu_items_count": {
            "type": "integer",
            "format": "int32",
            "example": 3,
            "description": "Total count of menu items on the ticket",
            "title": "Total count of menu items on the ticket"
          },
          "due_cents": {
            "type": "string",
            "format": "int64",
            "example": 0,
            "description": "Amount still due in cents",
            "title": "Amount still due in cents"
          },
          "discount_cents": {
            "type": "string",
            "format": "int64",
            "example": 0,
            "description": "Total discount in cents",
            "title": "Total discount in cents"
          },
          "service_charges_cents": {
            "type": "string",
            "format": "int64",
            "example": 0,
            "description": "Total service charges in cents",
            "title": "Total service charges in cents"
          },
          "sub_total_cents": {
            "type": "string",
            "format": "int64",
            "example": 5400,
            "description": "Subtotal in cents (items + other charges - discount)",
            "title": "Subtotal in cents"
          },
          "total_cents": {
            "type": "string",
            "format": "int64",
            "example": 5886,
            "description": "Grand total in cents (subtotal + service charges + tax)",
            "title": "Grand total in cents"
          }
        },
        "description": "Check total amounts. All monetary values are in cents.",
        "title": "CheckTotal",
        "required": [
          "items_total_cents",
          "tax_cents",
          "sub_total_cents",
          "total_cents"
        ]
      },
      "FOHReservationTicketEmployee": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "example": "emp-001",
            "description": "SpotOn Employee ID",
            "title": "SpotOn Employee ID"
          },
          "first_name": {
            "type": "string",
            "example": "Jane",
            "description": "Employee first name",
            "title": "Employee first name"
          },
          "last_name": {
            "type": "string",
            "example": "Smith",
            "description": "Employee last name",
            "title": "Employee last name"
          }
        },
        "description": "Employee (server) assigned to the ticket",
        "title": "Employee",
        "required": [
          "id",
          "first_name",
          "last_name"
        ]
      },
      "FOHReservationTicketMenuCategory": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "example": "cat-101",
            "description": "Menu category ID",
            "title": "Menu category ID"
          },
          "name": {
            "type": "string",
            "example": "Entrees",
            "description": "Menu category name",
            "title": "Menu category name"
          },
          "level": {
            "type": "integer",
            "format": "int32",
            "example": 0,
            "description": "Menu category depth level in the hierarchy (0 = top level)",
            "title": "Menu category depth level in the hierarchy"
          }
        },
        "description": "Menu item category",
        "title": "MenuCategory",
        "required": [
          "id",
          "name"
        ]
      },
      "FOHReservationTicketMenuItem": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "example": "prod-456",
            "description": "Menu item ID",
            "title": "Menu item ID"
          },
          "name": {
            "type": "string",
            "example": "Margherita Pizza",
            "description": "Menu item name",
            "title": "Menu item name"
          },
          "price_cents": {
            "type": "string",
            "format": "int64",
            "example": 1800,
            "description": "Unit price in cents",
            "title": "Unit price in cents"
          },
          "open": {
            "type": "boolean",
            "example": false,
            "description": "Whether this is an open (custom-priced) item",
            "title": "Whether this is an open (custom-priced) item"
          },
          "course": {
            "type": "integer",
            "format": "int32",
            "example": 1,
            "description": "Course number",
            "title": "Course number"
          },
          "categories": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/FOHReservationTicketMenuCategory"
            },
            "description": "Category hierarchy for the menu item",
            "title": "Category hierarchy for the menu item"
          }
        },
        "description": "Menu item definition within an order item",
        "title": "MenuItem",
        "required": [
          "id",
          "name",
          "price_cents"
        ]
      },
      "FOHReservationTicketMenuItemModifier": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "example": "mod-789",
            "description": "Modifier ID",
            "title": "Modifier ID"
          },
          "name": {
            "type": "string",
            "example": "Extra Cheese",
            "description": "Modifier name",
            "title": "Modifier name"
          },
          "price_cents": {
            "type": "string",
            "format": "uint64",
            "example": 150,
            "description": "Modifier price in cents",
            "title": "Modifier price in cents"
          },
          "quantity": {
            "type": "integer",
            "format": "int64",
            "example": 1,
            "description": "Modifier quantity",
            "title": "Modifier quantity"
          }
        },
        "description": "Modifier applied to an order item",
        "title": "MenuItemModifier"
      },
      "FOHReservationTicketOrderItem": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "example": "item-001",
            "description": "Order item ID",
            "title": "Order item ID"
          },
          "name": {
            "type": "string",
            "example": "Margherita Pizza",
            "description": "Display name of the item",
            "title": "Display name of the item"
          },
          "price_cents": {
            "type": "string",
            "format": "uint64",
            "example": 1800,
            "description": "Total price in cents (unit price * quantity + modifiers)",
            "title": "Total price in cents"
          },
          "quantity": {
            "type": "integer",
            "format": "int64",
            "example": 1,
            "description": "Quantity ordered",
            "title": "Quantity ordered"
          },
          "sent_at": {
            "type": "string",
            "format": "date-time",
            "example": "2025-03-27T18:05:00Z",
            "description": "Timestamp when the item was sent to the kitchen",
            "title": "Timestamp when the item was sent to the kitchen"
          },
          "status": {
            "example": "ORDER_ITEM_STATUS_SENT",
            "description": "Item status",
            "title": "Item status",
            "allOf": [
              {
                "$ref": "#/components/schemas/FOHReservationTicketOrderItemStatus"
              }
            ]
          },
          "menu_item": {
            "description": "Menu item definition",
            "title": "Menu item definition",
            "allOf": [
              {
                "$ref": "#/components/schemas/FOHReservationTicketMenuItem"
              }
            ]
          },
          "modifiers": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/FOHReservationTicketMenuItemModifier"
            },
            "description": "Modifiers applied to the item",
            "title": "Modifiers applied to the item"
          },
          "server_note": {
            "type": "string",
            "example": "No onions",
            "description": "Server note or comment on the item",
            "title": "Server note or comment on the item"
          }
        },
        "description": "An item on the ticket",
        "title": "OrderItem",
        "required": [
          "id",
          "name",
          "price_cents",
          "quantity",
          "status",
          "menu_item"
        ]
      },
      "FOHReservationTicketOrderItemStatus": {
        "type": "string",
        "enum": [
          "ORDER_ITEM_STATUS_HELD",
          "ORDER_ITEM_STATUS_SENT"
        ],
        "description": " - ORDER_ITEM_STATUS_HELD: Item is held and has not been sent to the kitchen.\n - ORDER_ITEM_STATUS_SENT: Item has been sent to the kitchen."
      },
      "FOHReservationTicketOrderType": {
        "type": "string",
        "enum": [
          "ORDER_TYPE_ORDER_IN",
          "ORDER_TYPE_TAKE_OUT",
          "ORDER_TYPE_DELIVERY"
        ],
        "description": " - ORDER_TYPE_ORDER_IN: Dine-in order.\n - ORDER_TYPE_TAKE_OUT: Take-out order.\n - ORDER_TYPE_DELIVERY: Delivery order."
      },
      "FOHReservationTicketPaymentInfo": {
        "type": "object",
        "properties": {
          "amount_cents": {
            "type": "string",
            "format": "int64",
            "example": 5886,
            "description": "Payment amount in cents",
            "title": "Payment amount in cents"
          },
          "tip_cents": {
            "type": "string",
            "format": "int64",
            "example": 1080,
            "description": "Tip amount in cents",
            "title": "Tip amount in cents"
          },
          "type": {
            "example": "PAYMENT_TYPE_CREDIT_CARD",
            "description": "Payment type",
            "title": "Payment type",
            "allOf": [
              {
                "$ref": "#/components/schemas/FOHReservationTicketPaymentType"
              }
            ]
          },
          "currency": {
            "type": "string",
            "example": "USD",
            "description": "ISO 4217 currency code",
            "title": "ISO 4217 currency code"
          },
          "paid_at": {
            "type": "string",
            "format": "date-time",
            "example": "2025-03-27T19:30:00Z",
            "description": "Timestamp when the payment was made",
            "title": "Timestamp when the payment was made"
          }
        },
        "description": "Payment applied to the ticket",
        "title": "PaymentInfo",
        "required": [
          "amount_cents",
          "type",
          "currency"
        ]
      },
      "FOHReservationTicketPaymentType": {
        "type": "string",
        "enum": [
          "PAYMENT_TYPE_CASH",
          "PAYMENT_TYPE_CREDIT_CARD",
          "PAYMENT_TYPE_GIFT_CARD",
          "PAYMENT_TYPE_OTHER"
        ],
        "description": " - PAYMENT_TYPE_CASH: Cash payment.\n - PAYMENT_TYPE_CREDIT_CARD: Credit card payment.\n - PAYMENT_TYPE_GIFT_CARD: Gift card payment.\n - PAYMENT_TYPE_OTHER: Other payment type."
      },
      "FOHReservationTicketSeatStatus": {
        "type": "string",
        "enum": [
          "SEAT_STATUS_SEATED",
          "SEAT_STATUS_FIRST_COURSE",
          "SEAT_STATUS_ENTREE",
          "SEAT_STATUS_DESSERT",
          "SEAT_STATUS_COMPLETE"
        ],
        "description": " - SEAT_STATUS_SEATED: Party has been seated.\n - SEAT_STATUS_FIRST_COURSE: First course has been served.\n - SEAT_STATUS_ENTREE: Entree has been served.\n - SEAT_STATUS_DESSERT: Dessert has been served.\n - SEAT_STATUS_COMPLETE: Meal is complete."
      },
      "FOHReservationTicketTable": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "example": "table-12",
            "description": "Table ID",
            "title": "Table ID"
          },
          "name": {
            "type": "string",
            "example": "Table 12",
            "description": "Table name",
            "title": "Table name"
          },
          "seats": {
            "type": "integer",
            "format": "int32",
            "example": 4,
            "description": "Number of seats at the table",
            "title": "Number of seats at the table"
          }
        },
        "description": "Table assigned to the ticket",
        "title": "Table",
        "required": [
          "id",
          "name"
        ]
      },
      "LaborTimePunchBreakRecord": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "example": "break-123456",
            "description": "Id of the break record",
            "title": "Id of the break record"
          },
          "start": {
            "type": "string",
            "format": "date-time",
            "example": "2021-01-01T12:00:00Z",
            "description": "Break start timestamp",
            "title": "Break start timestamp"
          },
          "end": {
            "type": "string",
            "format": "date-time",
            "example": "2021-01-01T12:30:00Z",
            "description": "Break end timestamp",
            "title": "Break end timestamp"
          },
          "type": {
            "example": "BREAK_TYPE_UNPAID",
            "description": "Type of break",
            "title": "Type of break",
            "allOf": [
              {
                "$ref": "#/components/schemas/LaborTimePunchBreakType"
              }
            ]
          }
        },
        "description": "Break record detail",
        "title": "BreakRecord",
        "required": [
          "id",
          "start",
          "type"
        ]
      },
      "LaborTimePunchBreakType": {
        "type": "string",
        "enum": [
          "BREAK_TYPE_UNPAID",
          "BREAK_TYPE_PAID"
        ],
        "title": "- BREAK_TYPE_UNPAID: Unpaid break\n - BREAK_TYPE_PAID: Paid break"
      },
      "LaborTimePunchBreaks": {
        "type": "object",
        "properties": {
          "break_records": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/LaborTimePunchBreakRecord"
            },
            "description": "List of break records taken during the time punch",
            "title": "List of break records taken during the time punch"
          }
        },
        "description": "Breaks container with reserved field for future status information (e.g., overflow handling)",
        "title": "Breaks"
      },
      "LaborTimePunchTimePunchDetail": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "example": "6266",
            "description": "Id of the time punch record",
            "title": "Id of the time punch record"
          },
          "job_id": {
            "type": "string",
            "example": "3257",
            "description": "Job ID associated with the time punch",
            "title": "Job ID associated with the time punch"
          },
          "employee_id": {
            "type": "string",
            "example": "426ba544-97ef-44db-bda0-ba053b3896a5",
            "description": "Employee ID (UUID)",
            "title": "Employee ID (UUID)"
          },
          "wage": {
            "type": "integer",
            "format": "int64",
            "example": 1101,
            "description": "Wage amount in cents",
            "title": "Wage amount in cents"
          },
          "status": {
            "example": "STATUS_OPEN",
            "description": "Status of the time punch",
            "title": "Status of the time punch",
            "allOf": [
              {
                "$ref": "#/components/schemas/v1LaborTimePunchStatus"
              }
            ]
          },
          "clock_in": {
            "type": "string",
            "format": "date-time",
            "example": "2025-05-05T14:32:00Z",
            "description": "Clock in timestamp",
            "title": "Clock in timestamp"
          },
          "clock_out": {
            "type": "string",
            "format": "date-time",
            "example": "2025-05-05T14:37:00Z",
            "description": "Clock out timestamp",
            "title": "Clock out timestamp"
          },
          "breaks": {
            "description": "Breaks taken during the time punch",
            "title": "Breaks taken during the time punch",
            "allOf": [
              {
                "$ref": "#/components/schemas/LaborTimePunchBreaks"
              }
            ]
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "example": "2025-06-11T14:44:58.074098Z",
            "description": "Creation timestamp",
            "title": "Creation timestamp"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time",
            "example": "2025-06-11T14:44:58.074098Z",
            "description": "Last update timestamp",
            "title": "Last update timestamp"
          },
          "declared_cash_tips_in_cents": {
            "type": "integer",
            "format": "int64",
            "example": 500,
            "description": "Declared cash tips amount in cents. Will be a non-negative value.",
            "title": "Declared cash tips amount in cents"
          },
          "deleted_at": {
            "type": "string",
            "format": "date-time",
            "example": "2025-06-11T14:50:00.000000Z",
            "description": "Deletion timestamp (only populated for delete events)",
            "title": "Deletion timestamp"
          }
        },
        "description": "Time punch detail",
        "title": "TimePunchDetail",
        "required": [
          "id",
          "job_id",
          "employee_id",
          "wage",
          "status",
          "clock_in",
          "created_at",
          "updated_at"
        ]
      },
      "OnboardingChangedDetails": {
        "type": "object",
        "properties": {
          "application_id": {
            "type": "string",
            "example": "8f1135e7-b46f-4d93-a5eb-4dbe8569e4d1",
            "description": "ID of the Partner Application",
            "title": "ID of the Partner Application"
          },
          "spoton_id": {
            "type": "string",
            "example": "BL-FFFF-4444-DDDD",
            "description": "SpotOn business location ID",
            "title": "SpotOn business location ID"
          },
          "changed_at": {
            "type": "string",
            "format": "date-time",
            "example": "2026-07-28T10:00:00Z",
            "description": "Timestamp when the merchant changed a post-activation setting",
            "title": "Timestamp when the merchant changed a post-activation setting"
          },
          "resource_url": {
            "type": "string",
            "example": "https://api.spoton.com/onboarding/v1/locations/BL-FFFF-4444-DDDD/settings",
            "description": "URL to retrieve a merchant's onboarding settings",
            "title": "URL to retrieve a merchant's onboarding settings"
          }
        },
        "description": "Payload for the onboarding.changed event",
        "title": "ChangedDetails",
        "required": [
          "application_id",
          "spoton_id",
          "changed_at"
        ]
      },
      "OnboardingOnboardingDetails": {
        "type": "object",
        "properties": {
          "application_id": {
            "type": "string",
            "example": "8f1135e7-b46f-4d93-a5eb-4dbe8569e4d1",
            "description": "ID of the Partner Application",
            "title": "ID of the Partner Application"
          },
          "completed_at": {
            "type": "string",
            "format": "date-time",
            "example": "2026-07-03T14:22:00Z",
            "description": "Timestamp when the merchant completed the wizard",
            "title": "Timestamp when the merchant completed the wizard"
          },
          "completed_step_indices": {
            "type": "array",
            "items": {
              "type": "integer",
              "format": "int32"
            },
            "description": "Zero-based indices of steps completed by the merchant",
            "title": "Zero-based indices of completed steps"
          },
          "resource_url": {
            "type": "string",
            "example": "https://api.spoton.com/onboarding/v1/locations/BL-FFFF-4444-DDDD/submissions",
            "description": "Authenticated pull URL for full submission values (requires onboarding:submissions:read scope)",
            "title": "Pull URL for full submission values"
          },
          "config_id": {
            "type": "string",
            "example": "01234567-89ab-cdef-0123-456789abcdef",
            "description": "ID of the onboarding template configuration in effect when the merchant completed onboarding",
            "title": "UUID of the template config version in effect at completion"
          }
        },
        "description": "Payload for the onboarding.completed event",
        "title": "OnboardingDetails",
        "required": [
          "application_id",
          "completed_at"
        ]
      },
      "OnboardingResetDetails": {
        "type": "object",
        "properties": {
          "application_id": {
            "type": "string",
            "example": "8f1135e7-b46f-4d93-a5eb-4dbe8569e4d1",
            "description": "ID of the Partner Application",
            "title": "ID of the Partner Application"
          },
          "reset_at": {
            "type": "string",
            "format": "date-time",
            "example": "2026-07-28T10:00:00Z",
            "description": "Timestamp when the merchant reset the integration",
            "title": "Timestamp when the merchant reset the integration"
          }
        },
        "description": "Payload for the onboarding.reset event",
        "title": "ResetDetails",
        "required": [
          "application_id",
          "reset_at"
        ]
      },
      "v1Event": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "example": "e4bc6225-353b-47da-9202-593b77babff6",
            "description": "Unique id of the event",
            "title": "Unique id of the event"
          },
          "timestamp": {
            "type": "string",
            "format": "date-time",
            "example": "2021-01-01T00:00:00Z",
            "description": "Timestamp of the event",
            "title": "Timestamp of the event"
          },
          "category": {
            "example": "EVENT_CATEGORY_ITEM",
            "description": "Category of the event",
            "title": "Category of the event",
            "allOf": [
              {
                "$ref": "#/components/schemas/v1EventEventCategory"
              }
            ]
          },
          "location_id": {
            "type": "string",
            "example": "BL-ABCD-EFGH-HIJK",
            "description": "Location ID",
            "title": "Location ID"
          },
          "organization_id": {
            "type": "string",
            "example": "BO-ABCD-EFGH-HIJK",
            "description": "Organization ID that owns the location. This field is only available for onboarding events.",
            "title": "Organization ID"
          },
          "details": {
            "description": "Details of the event (one of the following depending on `category`).",
            "title": "Details of the event",
            "allOf": [
              {
                "$ref": "#/components/schemas/EventDetails"
              }
            ]
          }
        },
        "description": "Webhook Event",
        "title": "Event",
        "required": [
          "id",
          "timestamp",
          "category",
          "location_id",
          "details"
        ]
      },
      "v1EventEventCategory": {
        "type": "string",
        "enum": [
          "EVENT_CATEGORY_MENU",
          "EVENT_CATEGORY_ITEM",
          "EVENT_CATEGORY_MODIFIER",
          "EVENT_CATEGORY_ORDER",
          "EVENT_CATEGORY_LOCATION_CONNECTION",
          "EVENT_CATEGORY_LABOR_TIME_PUNCH",
          "EVENT_CATEGORY_FOH",
          "EVENT_CATEGORY_ONBOARDING"
        ],
        "description": "- EVENT_CATEGORY_MENU: Event category for menu related events\n - EVENT_CATEGORY_ITEM: Event category for items related events\n - EVENT_CATEGORY_MODIFIER: Event category for modifier related events\n - EVENT_CATEGORY_ORDER: Event category for order related events\n - EVENT_CATEGORY_LOCATION_CONNECTION: Event category for location connection related events\n - EVENT_CATEGORY_LABOR_TIME_PUNCH: Event category for labor time punch related events\n - EVENT_CATEGORY_FOH: Event category for front-of-house related events\n - EVENT_CATEGORY_ONBOARDING: Event category for embedded onboarding related events",
        "title": "EventCategory is the category of the event"
      },
      "v1FOHReservationTicket": {
        "type": "object",
        "properties": {
          "ticket_id": {
            "type": "string",
            "example": "12345",
            "description": "Unique reservation ticket identifier",
            "title": "Unique reservation ticket identifier"
          },
          "ticket_number": {
            "type": "string",
            "example": "1042",
            "description": "POS ticket number",
            "title": "POS ticket number"
          },
          "opened_at": {
            "type": "string",
            "format": "date-time",
            "example": "2025-03-27T18:00:00Z",
            "description": "Timestamp when the ticket was opened",
            "title": "Timestamp when the ticket was opened"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time",
            "example": "2025-03-27T18:30:00Z",
            "description": "Timestamp of the last ticket update",
            "title": "Timestamp of the last ticket update"
          },
          "closed_at": {
            "type": "string",
            "format": "date-time",
            "example": "2025-03-27T19:30:00Z",
            "description": "Timestamp when the ticket was closed",
            "title": "Timestamp when the ticket was closed"
          },
          "party_size": {
            "type": "integer",
            "format": "int64",
            "example": 4,
            "description": "Number of guests in the party",
            "title": "Number of guests in the party"
          },
          "order_type": {
            "example": "ORDER_TYPE_ORDER_IN",
            "description": "Type of order",
            "title": "Type of order",
            "allOf": [
              {
                "$ref": "#/components/schemas/FOHReservationTicketOrderType"
              }
            ]
          },
          "order_items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/FOHReservationTicketOrderItem"
            },
            "description": "Items on the ticket",
            "title": "Items on the ticket"
          },
          "check_total": {
            "description": "Check total amounts",
            "title": "Check total amounts",
            "allOf": [
              {
                "$ref": "#/components/schemas/FOHReservationTicketCheckTotal"
              }
            ]
          },
          "payments": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/FOHReservationTicketPaymentInfo"
            },
            "description": "Payments applied to the ticket",
            "title": "Payments applied to the ticket"
          },
          "tables": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/FOHReservationTicketTable"
            },
            "description": "Tables assigned to the ticket",
            "title": "Tables assigned to the ticket"
          },
          "employee": {
            "description": "Employee (server) assigned to the ticket",
            "title": "Employee (server) assigned to the ticket",
            "allOf": [
              {
                "$ref": "#/components/schemas/FOHReservationTicketEmployee"
              }
            ]
          },
          "external_reservation_id": {
            "type": "string",
            "example": "partner-res-abc-123",
            "description": "External reservation ID from the partner system",
            "title": "External reservation ID from the partner system"
          },
          "seat_status": {
            "example": "SEAT_STATUS_SEATED",
            "description": "Current seat status of the party",
            "title": "Current seat status of the party",
            "allOf": [
              {
                "$ref": "#/components/schemas/FOHReservationTicketSeatStatus"
              }
            ]
          }
        },
        "description": "Front-of-house reservation ticket event details. Contains POS ticket data associated with a partner reservation.",
        "title": "FOHReservationTicket",
        "required": [
          "ticket_id",
          "ticket_number",
          "opened_at",
          "party_size",
          "order_type",
          "check_total",
          "employee",
          "external_reservation_id"
        ]
      },
      "v1Item": {
        "type": "object",
        "properties": {
          "type": {
            "example": "EVENT_TYPE_CREATED",
            "description": "Type of the event",
            "title": "Field of type EventType",
            "allOf": [
              {
                "$ref": "#/components/schemas/v1ItemEventType"
              }
            ]
          },
          "details": {
            "description": "Details of the resource",
            "title": "Details of the resource",
            "allOf": [
              {
                "$ref": "#/components/schemas/v1ItemResourceDetail"
              }
            ]
          },
          "menu_id": {
            "type": "string",
            "example": "123456",
            "description": "ID of the menu",
            "title": "ID of the menu"
          }
        },
        "description": "Order item details",
        "title": "Item",
        "required": [
          "type",
          "details"
        ]
      },
      "v1ItemEventType": {
        "type": "string",
        "enum": [
          "EVENT_TYPE_CREATED",
          "EVENT_TYPE_UPDATED",
          "EVENT_TYPE_DELETED",
          "EVENT_TYPE_AVAILABILITY_UPDATED"
        ],
        "title": "- EVENT_TYPE_CREATED: Event type for created event\n - EVENT_TYPE_UPDATED: Event type for updated event\n - EVENT_TYPE_DELETED: Event type for deleted event\n - EVENT_TYPE_AVAILABILITY_UPDATED: Event type for availability updated event"
      },
      "v1ItemResourceDetail": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "example": "123456",
            "description": "Id of the resource",
            "title": "Id of the resource"
          },
          "uri": {
            "type": "string",
            "example": "https://api.spoton.com/v1/menu/123456",
            "description": "Uri of the resource",
            "title": "Uri of the resource"
          },
          "is_available": {
            "type": "boolean",
            "description": "Indicates the current availability of the menu item.",
            "title": "Is resource active"
          }
        },
        "description": "Resource detail",
        "title": "ResourceDetail",
        "required": [
          "id",
          "uri"
        ]
      },
      "v1LaborTimePunch": {
        "type": "object",
        "properties": {
          "type": {
            "example": "EVENT_TYPE_CREATED",
            "description": "Type of the event",
            "title": "Field of type EventType",
            "allOf": [
              {
                "$ref": "#/components/schemas/v1LaborTimePunchEventType"
              }
            ]
          },
          "details": {
            "description": "Details of the time punch",
            "title": "Details of the time punch",
            "allOf": [
              {
                "$ref": "#/components/schemas/LaborTimePunchTimePunchDetail"
              }
            ]
          }
        },
        "description": "Labor time punch event details",
        "title": "LaborTimePunch",
        "required": [
          "type",
          "details"
        ]
      },
      "v1LaborTimePunchEventType": {
        "type": "string",
        "enum": [
          "EVENT_TYPE_CREATED",
          "EVENT_TYPE_UPDATED",
          "EVENT_TYPE_DELETED"
        ],
        "title": "- EVENT_TYPE_CREATED: Event type for created event\n - EVENT_TYPE_UPDATED: Event type for updated event\n - EVENT_TYPE_DELETED: Event type for deleted event"
      },
      "v1LaborTimePunchStatus": {
        "type": "string",
        "enum": [
          "STATUS_OPEN",
          "STATUS_CLOSED"
        ],
        "title": "- STATUS_OPEN: Time punch is open\n - STATUS_CLOSED: Time punch is closed"
      },
      "v1LocationConnection": {
        "type": "object",
        "properties": {
          "type": {
            "example": "EVENT_TYPE_LOCATION_CONNECTION_ACTIVE",
            "description": "Type of the event",
            "title": "Field of type EventType",
            "allOf": [
              {
                "$ref": "#/components/schemas/v1LocationConnectionEventType"
              }
            ]
          },
          "details": {
            "description": "Details of the resource",
            "title": "Details of the resource",
            "allOf": [
              {
                "$ref": "#/components/schemas/v1LocationConnectionResourceDetail"
              }
            ]
          }
        },
        "description": "Location connection event details",
        "title": "LocationConnection",
        "required": [
          "type",
          "details"
        ]
      },
      "v1LocationConnectionEventType": {
        "type": "string",
        "enum": [
          "EVENT_TYPE_LOCATION_CONNECTION_ACTIVE",
          "EVENT_TYPE_LOCATION_CONNECTION_AUTHORIZED",
          "EVENT_TYPE_LOCATION_CONNECTION_INACTIVE",
          "EVENT_TYPE_LOCATION_CONNECTION_INITIATED",
          "EVENT_TYPE_LOCATION_CONNECTION_DELETED"
        ],
        "description": " - EVENT_TYPE_LOCATION_CONNECTION_ACTIVE: Location Connection Active indicates that the partner-merchant connection is active and ready to use.\n - EVENT_TYPE_LOCATION_CONNECTION_AUTHORIZED: Location Connection Authorized indicates that the partner-merchant connection is authorized, but partner-merchant connection is not ready or not known.\n - EVENT_TYPE_LOCATION_CONNECTION_INACTIVE: Location Connection Inactive indicates that the partner-merchant connection is inactive and access is revoked.\n - EVENT_TYPE_LOCATION_CONNECTION_INITIATED: Location Connection Initiated indicates that the partner-merchant connection is initiated and waiting for approval and partner onboarding.\n - EVENT_TYPE_LOCATION_CONNECTION_DELETED: Location Connection Deleted indicates that the partner-merchant connection is deleted."
      },
      "v1LocationConnectionResourceDetail": {
        "type": "object",
        "properties": {
          "application_id": {
            "type": "string",
            "example": "8f1135e7-b46f-4d93-a5eb-4dbe8569e4d1",
            "description": "Id of the Partner Application",
            "title": "Id of the Partner Application"
          }
        },
        "description": "Resource detail",
        "title": "ResourceDetail",
        "required": [
          "application_id"
        ]
      },
      "v1Menu": {
        "type": "object",
        "properties": {
          "type": {
            "example": "EVENT_TYPE_CREATED",
            "description": "Type of the event",
            "title": "Field of type EventType",
            "allOf": [
              {
                "$ref": "#/components/schemas/v1MenuEventType"
              }
            ]
          },
          "details": {
            "description": "Details of the resource",
            "title": "Details of the resource",
            "allOf": [
              {
                "$ref": "#/components/schemas/v1MenuResourceDetail"
              }
            ]
          },
          "menu_id": {
            "type": "string",
            "example": "123456",
            "description": "ID of the menu",
            "title": "ID of the menu"
          }
        },
        "description": "Menu event details",
        "title": "Menu",
        "required": [
          "type",
          "details"
        ]
      },
      "v1MenuEventType": {
        "type": "string",
        "enum": [
          "EVENT_TYPE_CREATED",
          "EVENT_TYPE_UPDATED",
          "EVENT_TYPE_DELETED",
          "EVENT_TYPE_ACTIVATED",
          "EVENT_TYPE_DEACTIVATED"
        ],
        "title": "- EVENT_TYPE_CREATED: Event type for created event\n - EVENT_TYPE_UPDATED: Event type for updated event\n - EVENT_TYPE_DELETED: Event type for deleted event\n - EVENT_TYPE_ACTIVATED: Event type for activated event\n - EVENT_TYPE_DEACTIVATED: Event type for deactivated event"
      },
      "v1MenuResourceDetail": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "example": "123456",
            "description": "Id of the resource",
            "title": "Id of the resource"
          },
          "uri": {
            "type": "string",
            "example": "https://api.spoton.com/v1/menu/123456",
            "description": "Uri of the resource",
            "title": "Uri of the resource"
          }
        },
        "description": "Resource detail",
        "title": "ResourceDetail",
        "required": [
          "id",
          "uri"
        ]
      },
      "v1Modifier": {
        "type": "object",
        "properties": {
          "type": {
            "example": "EVENT_TYPE_UPDATED",
            "description": "Type of the event",
            "title": "Field of type EventType",
            "allOf": [
              {
                "$ref": "#/components/schemas/v1ModifierEventType"
              }
            ]
          },
          "details": {
            "description": "Details of the resource",
            "title": "Details of the resource",
            "allOf": [
              {
                "$ref": "#/components/schemas/v1ModifierResourceDetail"
              }
            ]
          },
          "menu_id": {
            "type": "string",
            "example": "123456",
            "description": "ID of the menu",
            "title": "ID of the menu"
          }
        },
        "description": "Modifier details",
        "title": "Modifier",
        "required": [
          "type",
          "details"
        ]
      },
      "v1ModifierEventType": {
        "type": "string",
        "enum": [
          "EVENT_TYPE_UPDATED",
          "EVENT_TYPE_AVAILABILITY_UPDATED"
        ],
        "title": "- EVENT_TYPE_UPDATED: Event type for updated event\n - EVENT_TYPE_AVAILABILITY_UPDATED: Event type for availability updated event"
      },
      "v1ModifierResourceDetail": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "example": "123456",
            "description": "Id of the resource",
            "title": "Id of the resource"
          },
          "uri": {
            "type": "string",
            "example": "https://api.spoton.com/v1/menu/123456",
            "description": "Uri of the resource",
            "title": "Uri of the resource"
          },
          "is_available": {
            "type": "boolean",
            "description": "Indicates the current availability of the menu item modifier.",
            "title": "Is resource active"
          }
        },
        "description": "Resource detail",
        "title": "ResourceDetail",
        "required": [
          "id",
          "uri"
        ]
      },
      "v1Onboarding": {
        "type": "object",
        "properties": {
          "type": {
            "example": "EVENT_TYPE_COMPLETED",
            "description": "Type of the onboarding event",
            "title": "Type of the onboarding event",
            "allOf": [
              {
                "$ref": "#/components/schemas/v1OnboardingEventType"
              }
            ]
          },
          "details": {
            "description": "Details of the onboarding.completed event — set only when type = EVENT_TYPE_COMPLETED",
            "title": "Completion details — only set when type = EVENT_TYPE_COMPLETED",
            "allOf": [
              {
                "$ref": "#/components/schemas/OnboardingOnboardingDetails"
              }
            ]
          },
          "reset_details": {
            "description": "Details of the onboarding.reset event — set only when type = EVENT_TYPE_RESET",
            "title": "Reset details — only set when type = EVENT_TYPE_RESET",
            "allOf": [
              {
                "$ref": "#/components/schemas/OnboardingResetDetails"
              }
            ]
          },
          "changed_details": {
            "description": "Details of the onboarding.changed event — set only when type = EVENT_TYPE_CHANGED",
            "title": "Changed details — only set when type = EVENT_TYPE_CHANGED",
            "allOf": [
              {
                "$ref": "#/components/schemas/OnboardingChangedDetails"
              }
            ]
          }
        },
        "description": "Embedded onboarding event details",
        "title": "Onboarding",
        "required": [
          "type"
        ]
      },
      "v1OnboardingEventType": {
        "type": "string",
        "enum": [
          "EVENT_TYPE_COMPLETED",
          "EVENT_TYPE_RESET",
          "EVENT_TYPE_CHANGED"
        ],
        "description": " - EVENT_TYPE_COMPLETED: Merchant completed onboarding.\n - EVENT_TYPE_RESET: Merchant reset the integration.\n - EVENT_TYPE_CHANGED: Merchant changed a post-activation setting."
      },
      "v1Order": {
        "type": "object",
        "properties": {
          "type": {
            "example": "EVENT_TYPE_CANCELED",
            "description": "Type of the event",
            "title": "Field of type EventType",
            "allOf": [
              {
                "$ref": "#/components/schemas/v1OrderEventType"
              }
            ]
          },
          "details": {
            "description": "Details of the resource",
            "title": "Details of the resource",
            "allOf": [
              {
                "$ref": "#/components/schemas/v1OrderResourceDetail"
              }
            ]
          }
        },
        "description": "Order event details",
        "title": "Order",
        "required": [
          "type",
          "details"
        ]
      },
      "v1OrderEventType": {
        "type": "string",
        "enum": [
          "EVENT_TYPE_CANCELED",
          "EVENT_TYPE_ORDER_FULFILLMENT_UPDATE"
        ],
        "title": "- EVENT_TYPE_CANCELED: Event type for canceled event\n - EVENT_TYPE_ORDER_FULFILLMENT_UPDATE: Event type for fulfillment update event"
      },
      "v1OrderResourceDetail": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "example": "123456",
            "description": "Id of the resource",
            "title": "Id of the resource"
          },
          "external_id": {
            "type": "string",
            "example": "external-123456",
            "description": "External id of the resource",
            "title": "External id of the resource"
          },
          "uri": {
            "type": "string",
            "example": "https://api.spoton.com/orders/v1/locations/5689/orders/123456",
            "description": "Uri of the resource",
            "title": "Uri of the resource"
          }
        },
        "description": "Resource detail",
        "title": "ResourceDetail",
        "required": [
          "id"
        ]
      }
    }
  }
}
````