API di FlavosoFondamentiPaginazione e filtri

Paginazione e filtri

Gli elenchi arrivano a pagine con un cursore. Con i filtri, updated_since e acknowledged recuperi in modo affidabile solo ciò che è nuovo.

Elenchi

Ogni elenco ha la stessa forma: object: "list", gli elementi in data, più has_more e next_cursor. limit sceglie da 1 a 100 elementi per pagina, il valore predefinito è 25. Per GET /events il cursore si chiama after e il valore predefinito è 50.

Se ce ne sono altri, la risposta riporta has_more: true. Allora rimandi next_cursor come cursor, finché has_more è falso. Il cursore è opaco: va restituito, non costruito da te né salvato.

Il cursore non porta con sé i filtri. Invia gli stessi filtri a ogni pagina, altrimenti scorri un elenco diverso.
# First page: the filters go along on every page
curl "https://api.flavoso.com/v1/orders?created_since=2026-10-03T22:00:00Z&created_until=2026-10-04T22:00:00Z&limit=100" \
  -H "Authorization: Bearer $ACCESS_TOKEN"

# has_more is true: pass next_cursor back, with the SAME filters
curl "https://api.flavoso.com/v1/orders?created_since=2026-10-03T22:00:00Z&created_until=2026-10-04T22:00:00Z&limit=100&cursor=NEXT_CURSOR" \
  -H "Authorization: Bearer $ACCESS_TOKEN"

Filtri

Separa con virgole più valori dello stesso filtro: status=pending,confirmed.

ElencoFiltriOrdinamento
GET /ordersstatus, type, paid, acknowledged, updated_since, created_since, created_until, external_idPrima quelli modificati più di recente; con updated_since in ordine crescente di updated_at.
GET /reservationsstatus, updated_since, starts_from, starts_untilPrima quelle modificate più di recente; con starts_from o starts_until in ordine crescente di starts_at.
GET /menu/productscategory_id (un identificativo o none), available, external_id, updated_sinceSempre in ordine crescente di updated_at.
GET /menu/categories, GET /menu/option-groups, GET /menu/optionsexternal_id, updated_sinceSempre in ordine crescente di updated_at.
GET /eventsafter (anche latest), types (anche menu.*)In ordine crescente, il più vecchio per primo.

Un filtro che l'elenco non supporta dà 400 invalid_request con param. acknowledged si riferisce alla tua app: acknowledged=false restituisce gli ordini che la tua app non ha ancora preso in carico, senza limiti di tempo (vedi sotto). Un'altra app vede il proprio stato.

Pattern: tutto dall'ultima esecuzione

Senza webhook la strada è updated_since. Memorizza l'updated_at dell'ultimo ordine elaborato e interroga regolarmente con quello; è in UTC e va bene così com'è (un timestamp senza fuso orario dà 400). Con updated_since gli elementi arrivano in ordine crescente, la modifica più vecchia per prima. Lo stesso vale per le prenotazioni e gli elenchi del menu, GET /menu/options compreso.

Usa un minuto di sovrapposizione (updated_since un minuto prima dell'ultimo valore) e riconosci i duplicati da id e updated_at. Altrimenti due modifiche nello stesso secondo possono sfuggire tra due interrogazioni.
// Everything that changed since the last run, oldest change first. listAll() as above.
const OVERLAP_MS = 60_000;

export async function pollOrders(accessToken, state) {
  const since = new Date(Date.parse(state.since) - OVERLAP_MS).toISOString();
  for await (const order of listAll(accessToken, "/orders", { updated_since: since })) {
    if (state.seen[order.id] === order.updated_at) continue; // handled in the overlap already
    await handleOrder(order); // your code; must tolerate seeing an order again
    state.seen[order.id] = order.updated_at;
    if (order.updated_at > state.since) state.since = order.updated_at;
  }
  // Forget what lies before the overlap, then persist the state for the next run
  for (const [id, at] of Object.entries(state.seen)) {
    if (Date.parse(at) < Date.parse(state.since) - OVERLAP_MS) delete state.seen[id];
  }
  await saveState(state);
}

La cosa più sicura è usare entrambi: il webhook è veloce, l'interrogazione regolare recupera ciò che è andato perso. Ancora più semplice, GET /events restituisce tutto in ordine.

Pattern: solo ciò che non è ancora stato preso in carico

Per una cassa la domanda raramente è «cosa è cambiato», ma «cosa non ho ancora registrato». È proprio ciò che restituisce GET /orders?acknowledged=false. Dopo la registrazione segnali l'ordine come preso in carico con POST /orders/{id}/acknowledge, con il tuo numero di scontrino come external_id; da quel momento esce dall'elenco.

acknowledged=false non ha limiti di tempo: l'elenco contiene ogni ordine che la tua app non ha mai preso in carico, anche quelli precedenti al collegamento, completati e annullati. Limitalo quindi sempre con created_since, per esempio con il created_at del collegamento da GET /me.

Questo pattern tollera i crash: ciò che non è stato preso in carico ritorna all'esecuzione successiva. Per questo la tua registrazione deve essere idempotente per ogni ordine. Prendi in carico ogni ordine che hai gestito, anche uno annullato che non registri: altrimenti resta nell'elenco e ritorna a ogni esecuzione.

# The orders your app has not taken over yet, since the connection was made
# (created_at from GET /me). Without created_since the list has no time limit.
curl "https://api.flavoso.com/v1/orders?acknowledged=false&created_since=2026-10-04T17:40:00.000Z&limit=50" \
  -H "Authorization: Bearer $ACCESS_TOKEN"

# Booked into your system as receipt R-2026-000123: acknowledge it
curl -X POST https://api.flavoso.com/v1/orders/ORDER_ID/acknowledge \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: ack-ORDER_ID" \
  -d '{"external_id": "R-2026-000123"}'

# Not booked, for example because it was cancelled already: acknowledge it all the same,
# otherwise it stays in the list
curl -X POST https://api.flavoso.com/v1/orders/OTHER_ORDER_ID/acknowledge \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "Idempotency-Key: ack-OTHER_ORDER_ID"

Periodi

created_since e created_until limitano gli ordini in base a quando sono arrivati, per esempio per un'esportazione giornaliera; starts_from e starts_until limitano le prenotazioni in base al loro inizio, per esempio per il libro prenotazioni di una serata. Entrambi sono timestamp in UTC: il giorno del locale inizia alla mezzanotte del suo fuso orario, quindi a Berlino d'estate alle 22:00:00Z del giorno prima. L'inizio è incluso, la fine no: created_since e starts_from includono l'istante, created_until e starts_until lo escludono. Così un giorno si collega al successivo senza buchi.

Cosa non compare mai in un elenco

  • Ordini online non pagati. Un ordine con pagamento online esiste per l'API solo quando il pagamento è confermato, esattamente come nella dashboard.
  • Prenotazioni eliminate. La loro eliminazione è segnalata da un reservation.updated finale.

Qualcosa non è chiaro? Scrivi a support@flavoso.com indicando l'identificativo di X-Request-Id. Così troviamo la tua richiesta nel registro.