Sale webhook events (beta)
The new sale. event family delivers full sale payloads inline. Understand what's available, how they differ from the legacy sales. events, and how to get access.
Closed betaThe
sale.*event family is currently in closed beta. The event schemas are published and stable, but webhook delivery is gated. To subscribe, email [email protected].
sales.*is being deprecated soonThe
sales.*family is slated for deprecation in the near term assale.*matures. Do not build new integrations againstsales.*— existing subscribers should plan their migration tosale.*now rather than waiting for a formal deprecation notice.
API-ingested sales only (sales.*)The
sales.*event family only fires for sales created through the Sales Management API (POST /salesManagement/orgs/{orgId}/sales). Sales recorded natively on the Flipdish POS, kiosk, web app, or third-party marketplaces (UberEats, JustEats, etc.) do not currently triggersales.*events. This matches the existing read-path scope described in the analytics guide.The
sale.*family fires for all channels — see below.
Overview
Flipdish exposes two families of sale-related webhook events. They differ in channel scope, payload shape, and availability.
| Family | Events | Payload | Scope | Status |
|---|---|---|---|---|
sales.* (legacy) | sales.created.v1, sales.cancelled.v1, sales.pos.status.updated.v1, sales.delivery.status.updated.v1 | Identifiers only — orgId, propertyId, salesChannelId, saleId | API-ingested sales only | Deprecating soon |
sale.* (new) | sale.created.v1, sale.updated.v1, sale.status.updated.v1 | Full sale payload inline | All channels (POS, kiosk, web, marketplace, API) | Closed beta |
The sales.* events (legacy, deprecating soon)
sales.* events (legacy, deprecating soon)These events fire for every sale lifecycle transition and carry just enough context to identify the sale and look it up:
| Event | When it fires | Key fields beyond IDs |
|---|---|---|
sales.created.v1 | A new sale is recorded | — |
sales.cancelled.v1 | A sale is voided | cancellationReason, cancellationNotes, cancelledBy |
sales.pos.status.updated.v1 | POS / kitchen state change | status (SALE_PREPARED_BY_KITCHEN, SALE_PICKUP_TIME_CHANGED, SALE_DELIVERY_TIME_CHANGED, SALE_CANCELLED) |
sales.delivery.status.updated.v1 | Delivery state change | status (SALE_DISPATCHED, SALE_ON_THE_WAY, SALE_DELIVERED) |
Because the payload carries identifiers only, your handler must call the Sales Management API — GET /sales/orgs/{orgId}/sales/{saleId} (org-wide, no salesChannelId needed) — to fetch the line items, charges, discounts, and payments.
These events remain available for existing subscribers, but new integrations should not rely on them — they are being deprecated soon in favor of sale.*. If you need broad availability today ahead of sale.* general availability, request beta access below rather than building against sales.*.
The sale.* events (new, closed beta)
sale.* events (new, closed beta)The sale.* family is emitted when any order is ingested by Flipdish — regardless of channel (POS, kiosk, web, marketplace, or API). The full sale object is embedded in the event payload itself, so no follow-up GET is required.
Events
sale.created.v1
sale.created.v1Fires when a sale is first recorded. The detail.properties.sale field carries the complete PublicSale object at the moment of creation: items, modifiers, charges, discounts, payments, customer, delivery/dine-in details, and menu reference. See Sale object schema for a field-by-field breakdown of every nested object (customer, delivery, dineIn, items, charges, discounts, payments).
{
"source": "rms",
"detail-type": "sale.created.v1",
"detail": {
"properties": {
"orgId": "org123",
"brandId": "br123",
"propertyId": "p123",
"salesChannelId": "sc123",
"salesChannelType": "UberEats",
"saleId": "3N356",
"externalId": "sale-external-123",
"sale": {
"salesChannelId": "sc123",
"source": "App",
"dispatchType": "Delivery",
"menuId": "123e4567-e89b-12d3-a456-426614174000",
"menuRevisionId": "123",
"items": [ ... ],
"charges": [ ... ],
"discounts": [ ... ],
"payments": [ ... ]
}
},
"metadata": { ... }
}
}sale.updated.v1
sale.updated.v1Fires when a sale's content changes materially — items added or removed, charges or discounts modified. The embedded sale reflects the post-update state. There is no equivalent event in the sales.* family: previously you had to poll or reconcile to detect updates.
sale.status.updated.v1
sale.status.updated.v1A unified status event that covers both POS kitchen states and delivery states in a single discriminated union. It replaces the two separate sales.pos.status.updated.v1 and sales.delivery.status.updated.v1 events.
Status values: SALE_CANCELLED, SALE_PREPARED_BY_KITCHEN, SALE_DISPATCHED, SALE_ON_THE_WAY, SALE_DELIVERED.
Key differences at a glance
sales.* (legacy) | sale.* (new) | |
|---|---|---|
| Scope | API-ingested sales only | All channels (POS, kiosk, web, marketplace, API) |
| Payload | Identifiers only | Full PublicSale object inline |
| Follow-up API call needed | Yes, to hydrate items/charges/payments | No |
| Sale update event | None | sale.updated.v1 |
| Status events | Two separate events | One unified sale.status.updated.v1 |
Includes brandId | No | Yes |
| Availability | Deprecating soon | Closed beta |
When to use which family
Use sale.* for all new work — it's the family that will remain supported. It gives you a simpler handler that processes the full sale from the event payload without a round-trip, plus sale.updated.v1 to track mid-lifecycle changes.
Avoid building new integrations against sales.*. It's kept around only for existing subscribers while they migrate; use it for early sandbox testing (see below) if sale.* beta access isn't available to you yet, but don't take a production dependency on it.
The sales.* events are being deprecated soon as sale.* matures. They will remain available for a migration window, but do not wait for a formal deprecation notice to start moving to sale.*.
Migration mapping
Instead of (sales.*, legacy) | Use (sale.*, new) |
|---|---|
sales.created.v1 | sale.created.v1 |
sales.pos.status.updated.v1 + sales.delivery.status.updated.v1 | sale.status.updated.v1 (single unified status event covering both) |
sales.cancelled.v1 | sale.status.updated.v1 with status SALE_CANCELLED — there's no separate cancelled event in the new family |
| (no equivalent) | sale.updated.v1 — new: tracks mid-lifecycle changes to items, charges, and discounts |
Getting access to sale.* events
sale.* eventsThe sale.* events are in closed beta. Webhook delivery is gated and not available through the self-serve Portal subscription UI.
To subscribe:
- Build and test against your sandbox org using the
sales.*events, which are freely available. - Email [email protected] with your
orgId, the events you want (sale.created.v1,sale.updated.v1,sale.status.updated.v1), and a brief description of your use case. - The integrations team will provision access and confirm your subscription endpoint.
Related
- Subscribe to Flipdish Events (v3) — delivery contract and signature verification
- Build a POS sales analytics integration — end-to-end guide using the
sales.*events and Sales Management API - Sales Management API reference — read sales by date range or by ID
Updated 10 days ago

