Flavoso APIWebhooks and eventsFetching events
Fetching events
GET /events returns the same events as webhooks, for you to fetch: for POS systems without a public address and for catching up after an outage.
When to fetch instead of receive
- POS without a public address: a program in the restaurant behind a router cannot receive webhooks. It fetches the events.
- Catching up: after an outage, a switched-off webhook or a bug in your processing.
- Reconciling: as a second path next to the webhook that makes sure nothing is missing.
Events are created for every active connection, even if your app has no webhook at all.
Fetching
GET /events returns the restaurant's events your connection may see, plus the app.* events of this connection, in ascending order, the oldest first, up to 30 days back. app.disconnected never arrives here: the connection's tokens end with the disconnection. You recognise a disconnection by a 401 and then invalid_grant on the refresh.
| Parameter | Meaning |
|---|---|
after | An event id (evt_…): only what came after it. Without after, it starts at the oldest kept event of the last 30 days, including events from before the connection. latest: no events, only the position after the newest one, to start a new connection. An id that this restaurant does not have (any more), for example because it is older than 30 days, continues with the oldest kept event and sets gap: true. |
types | Types separated by commas, with * for a whole group: order.created,menu.*. |
limit | 1 to 100, default 50. |
The response is a list with data, has_more, next_after and gap. next_after is the value for after to continue from there; it is always set, even when there were no events. gap: true means your after was no longer kept: events may have been missed, so resynchronise with GET /orders?updated_since=… and the other lists you use.
{
"object": "list",
"data": [
{
"id": "evt_2bf5a9b06b75442a9244e884a1acfc57",
"object": "event",
"type": "reservation.updated",
"created_at": "2026-10-04T17:45:10.410Z",
"api_version": "2026-10-08",
"livemode": true,
"tenant_id": "7d0e5b8a-3c41-4f2e-9a6b-1e2d3c4b5a69",
"connection_id": "4b3f7c1e-9a2d-4e8b-b5f6-0c1d2e3f4a5b",
"data": {
"object": {
"object": "reservation",
"id": "9c8b7a6d-5e4f-4a3b-9c2d-1e0f9a8b7c6d",
"code": "R7K2Q9",
"status": "confirmed",
"starts_at": "2026-10-10T17:30:00.000Z",
"duration_minutes": 120,
"party_size": 4,
"table_ids": [
"2b3c4d5e-6f7a-4b8c-9d0e-1f2a3b4c5d6e"
],
"source": "staff",
"guest_name": "Alex Example",
"note": "Window seat if possible",
"created_at": "2026-10-04T12:00:00.000Z",
"updated_at": "2026-10-04T12:00:00.000Z"
},
"previous_status": "pending",
"changed": [
"status"
]
}
}
],
"has_more": false,
"next_after": "evt_2bf5a9b06b75442a9244e884a1acfc57",
"gap": false
}The polling loop
- 1
Where you are
Read the
aftervalue you stored for this connection. For a new connection uselatest: withoutafteryou would get the last 30 days, including events from before the connection. - 2
Fetch and process
Fetch events and process each one. The processing detects duplicates by
id. - 3
Move on
Only once the whole page is processed, store
next_afterdurably, per connection. - 4
Continue or wait
If
has_moreis true, fetch the next page right away. Otherwise wait a few seconds.
# A new connection starts now: no events, only next_after. Store it for this connection.
# (Without after you would get the last 30 days, also events from before the connection.)
curl "https://api.flavoso.com/v1/events?after=latest" \
-H "Authorization: Bearer $ACCESS_TOKEN"
# Then always from where you stopped: after = next_after of the previous page.
# "gap": true means that after was no longer kept: resync with GET /orders.
curl "https://api.flavoso.com/v1/events?types=order.*,menu.*,store.*,app.*&limit=100&after=evt_2bf5a9b06b75442a9244e884a1acfc57" \
-H "Authorization: Bearer $ACCESS_TOKEN"Polling every 5 to 30 seconds fits easily into the rate limit of 120 requests per minute per connection.
A single event
GET /events/{id} returns one event, for example to look up an id from the webhook log.
curl https://api.flavoso.com/v1/events/evt_2bf5a9b06b75442a9244e884a1acfc57 \
-H "Authorization: Bearer $ACCESS_TOKEN"The same envelope
A fetched event is the same envelope as in the webhook: the same id, the same fields, the same data, frozen on the first read or send. If you use both, you detect duplicates by id. The signature only exists for webhooks; when fetching, the token proves who is asking.
Retention
Events are kept for 30 days. For anything older, catch up through the lists, for example GET /orders with updated_since. An after older than that is not an error: the response continues with the oldest kept event and says gap: true.
Still unclear? Write to support@flavoso.com and include the id from X-Request-Id. It lets us find your request in the log.