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].
API-ingested sales onlyBoth the
sales.*andsale.*event families only fire 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 trigger these events. This matches the existing read-path scope described in the analytics guide.
Overview
Flipdish exposes two families of sale-related webhook events. Both are scoped to API-ingested sales; they differ in what they carry and what they're designed for.
| Family | Events | Payload | 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 | Generally available |
sale.* (new) | sale.created.v1, sale.updated.v1, sale.status.updated.v1 | Full sale payload inline | Closed beta |
The sales.* events (legacy, generally available)
sales.* events (legacy, generally available)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 /salesManagement/orgs/{orgId}/salesChannels/{salesChannelId}/sales/{saleId} — to fetch the line items, charges, discounts, and payments.
Use these events when you need broad availability today, or when you already have a read-path built against the Sales Management API.
The sale.* events (new, closed beta)
sale.* events (new, closed beta)The sale.* family was designed to eliminate the follow-up API call: the full sale object is embedded in the event payload itself.
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.
{
"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 | API-ingested sales only |
| 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 | Generally available | Closed beta |
When to use which family
Use sales.* if you're building against the Sales Management API read path already, or need to go live before the sale.* beta opens.
Use sale.* if you want a simpler handler that processes the full sale from the event payload without a round-trip, or if you need sale.updated.v1 to track mid-lifecycle changes.
The sales.* events will be deprecated when sale.* reaches general availability. They will remain available until all subscribers have migrated, but new integrations should prefer sale.*.
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
