savrsoft

Documentazione API

Una semplice API REST per leggere e scrivere i tuoi dati di catering, oltre a webhook firmati per eventi in tempo reale. Crea una chiave in Developer nell'app.

Autenticazione

Tutte le richieste API utilizzano una chiave API come bearer token. Creane una nell'app in Developer → API keys. Le chiavi sono di sola lettura oppure di lettura/scrittura.

curl https://savrsoft.com/api/v1/events \
  -H "Authorization: Bearer savr_live_your_key_here"

URL di base: https://savrsoft.com/api/v1 · Tutte le risposte sono in formato JSON. Gli errori restituiscono { "error": "…" } con uno status 4xx/5xx.

Codici di stato

CodiceQuando lo ricevi
200Lettura riuscita.
201Creazione riuscita. Il corpo è { "id": 42 } — recupera il record se ti serve il resto delle informazioni.
400Manca un campo obbligatorio, ad es. { "error": "name is required" }, oppure non è stato possibile leggere un cursore di paginazione.
401Nessuna chiave API, una non valida o una che è stata revocata.
403È stata usata una chiave in sola lettura per una scrittura. Crea una chiave di lettura/scrittura in Developer → API keys.
404Il record non esiste, oppure appartiene a un'altra organizzazione — le due situazioni sono deliberatamente indistinguibili. Restituito anche per un percorso o metodo non riconosciuto.

Ambito di questa API

L'API consente solo lettura e creazione. Non ci sono endpoint DELETE, PUT o PATCH — una richiesta che ne usa uno restituisce 404 Unknown endpoint, come qualsiasi percorso non riconosciuto. L'eliminazione e la modifica avvengono nell'app, quindi un'integrazione non può distruggere i dati di un caterer. Se ti serve un accesso in scrittura oltre alla creazione, dicci cosa stai realizzando.

Paginazione

Ogni endpoint di tipo elenco è paginato. Passa limit (predefinito 100, massimo 500) e segui next_cursor finché has_more è false:

{
  "data": [ ... ],
  "has_more": true,
  "next_cursor": "eyJuYW1lIjoiQWNtZSIsImlkIjo0Mn0"
}

Passa il cursore così com'è per ottenere la pagina successiva. Trattalo come opaco — la codifica potrebbe cambiare:

curl "https://savrsoft.com/api/v1/clients?limit=100&cursor=eyJuYW1lIjoiQWNtZSIsImlkIjo0Mn0" \
  -H "Authorization: Bearer savr_live_your_key_here"

La paginazione è ancorata all'ultima riga ricevuta, non a un offset, quindi le righe create o eliminate durante la navigazione non causeranno il salto o la ripetizione di un record. Un cursore rimane valido indefinitamente.

ParametroComportamento
limit1–500. Se assente, zero, negativo o non numerico, il valore predefinito è 100; qualsiasi valore superiore a 500 viene limitato a 500.
cursornext_cursor dalla pagina precedente. Ometterlo per la prima pagina. Un cursore che non può essere letto — corrotto o proveniente da un endpoint diverso — restituisce 400 Invalid cursor invece di ricominciare silenziosamente dall'inizio.

Ordinamento: /events e /invoices dal più recente; /recipes e /clients per nome, con parità risolta per id in modo che la paginazione rimanga stabile quando i nomi si ripetono.

Endpoint

GET/v1/me

La tua organizzazione (id, nome, valuta).

GET/v1/events

Elenca gli eventi, dal più recente. Paginato — vedi Paginazione sopra.

GET/v1/events/{id}

Un evento con i suoi piatti.

POST/v1/events · richiede read/write

Crea un evento. Corpo:

{ "name": "Acme holiday party", "event_date": "2026-12-18",
  "guests": 120, "price_per_head": 55, "event_type": "corporate" }
GET/v1/recipes · GET/v1/recipes/{id}

Elenca le ricette (con allergeni & indicazioni dietetiche), oppure una singola ricetta con gli ingredienti. L'elenco è paginato e ordinato per nome.

GET/v1/clients · POST/v1/clients

Elenca i clienti (paginati, per nome) oppure ne crea uno. Corpo per la creazione: { "name": "...", "email": "...", "phone": "...", "company": "..." }

GET/v1/invoices · GET/v1/invoices/{id}

Elenca le fatture con i totali calcolati, dalla più recente, oppure una singola fattura con le voci di dettaglio. L'elenco è paginato.

Webhook

Registra un endpoint in Developer → Webhooks. Inviamo una richiesta POST con un payload JSON quando si verificano gli eventi:

{
  "id": "evt_abc123",
  "type": "event.inquiry",
  "created_at": "2026-07-17T18:20:00.000Z",
  "data": { "id": 42, "name": "Corporate lunch — Dana Ruiz", ... }
}

Tipi di evento

TipoSi attiva quando
event.createdViene creato un evento
event.inquiryArriva una nuova richiesta di catering online
invoice.sentUna fattura viene contrassegnata come inviata
invoice.paidUna fattura viene contrassegnata come pagata
proposal.approvedUn cliente approva una proposta
client.createdViene creato un cliente

Verifica delle firme

Ogni consegna include un header x-savrsoft-signature : l'HMAC-SHA256 del corpo grezzo della richiesta, firmato con la tua chiave segreta del webhook. Calcola lo stesso valore e confrontalo:

// Node.js
const crypto = require('crypto');
const sig = crypto.createHmac('sha256', SIGNING_SECRET)
  .update(rawBody).digest('hex');
if (sig !== req.headers['x-savrsoft-signature']) reject();
Privacy · Sicurezza · Termini · Domande? savrsoft.com · Crea integrazioni per il catering in pochi minuti.