savrsoft

Documentation de l'API

Une API REST simple pour lire et écrire vos données de traiteur, avec des webhooks signés pour les événements en temps réel. Créez une clé dans Développeur dans l'application.

Authentification

Toutes les requêtes API utilisent une clé API comme jeton porteur. Créez-en une dans l'application sous Développeur → Clés API. Les clés sont soit lecture seule soit lecture/écriture.

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

URL de base : https://savrsoft.com/api/v1 · Toutes les réponses sont au format JSON. Les erreurs renvoient { "error": "…" } avec un statut 4xx/5xx.

Codes de statut

CodeQuand vous l'obtenez
200Lecture réussie.
201Création réussie. Le corps est { "id": 42 } — récupérez l'enregistrement si vous avez besoin du reste.
400Un champ requis est manquant, par ex. { "error": "name is required" }, ou un curseur de pagination n'a pas pu être lu.
401Pas de clé API, une clé mal formée, ou une clé qui a été révoquée.
403Une clé en lecture seule a été utilisée pour une écriture. Créez une clé lecture/écriture sous Développeur → Clés API.
404L'enregistrement n'existe pas, ou appartient à une autre organisation — les deux cas sont délibérément indissociables. Ce code est également renvoyé pour un chemin ou une méthode non reconnus.

Portée de cette API

L'API est en lecture et création uniquement. Il n'y a pas de points de terminaison DELETE, PUT ou PATCH — une requête utilisant l'un d'eux renvoie 404 Unknown endpoint, comme pour tout chemin non reconnu. La suppression et la modification se font dans l'application, donc une intégration ne peut pas détruire les enregistrements d'un traiteur. Si vous avez besoin d'un accès en écriture au-delà de la création, dites-nous ce que vous construisez.

Pagination

Chaque point de terminaison de liste est paginé. Passez limit (par défaut 100, maximum 500) et suivez next_cursor jusqu'à ce que has_more soit false:

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

Renvoyez le curseur tel quel pour obtenir la page suivante. Traitez-le comme opaque — l'encodage peut changer :

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

La pagination est ancrée à la dernière ligne reçue, et non à un décalage, si bien que les lignes créées ou supprimées pendant la navigation ne vous feront pas sauter ou répéter un enregistrement. Un curseur reste valide indéfiniment.

ParamètreComportement
limit1–500. Absent, zéro, négatif ou non numérique revient par défaut à 100 ; toute valeur supérieure à 500 est plafonnée à 500.
cursornext_cursor de la page précédente. Omettez-le pour la première page. Un curseur illisible — corrompu, ou provenant d'un autre endpoint — renvoie 400 Invalid cursor plutôt que de repartir silencieusement du début.

Tri : /events et /invoices du plus récent au plus ancien ; /recipes et /clients par nom, les égalités étant départagées par id afin que la pagination reste stable en cas de noms identiques.

Endpoints

GET/v1/me

Votre organisation (id, nom, devise).

GET/v1/events

Liste des événements, du plus récent au plus ancien. Paginé — voir Pagination ci-dessus.

GET/v1/events/{id}

Un événement avec ses plats.

POST/v1/events · nécessite lecture/écriture

Créer un événement. Corps :

{ "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}

Liste des recettes (avec allergènes & régimes alimentaires), ou une recette avec ses ingrédients. La liste est paginée et triée par nom.

GET/v1/clients · POST/v1/clients

Liste des clients (paginée, par nom) ou création d'un client. Corps de création : { "name": "...", "email": "...", "phone": "...", "company": "..." }

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

Liste des factures avec totaux calculés, les plus récentes en premier, ou une facture avec ses lignes de détail. La liste est paginée.

Webhooks

Enregistrez un endpoint sous Developer → Webhooks. Nous envoyons en POST une charge JSON lorsque des événements se produisent :

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

Types d'événements

TypeSe déclenche quand
event.createdUn événement est créé
event.inquiryUne nouvelle demande de traiteur en ligne arrive
invoice.sentUne facture est marquée comme envoyée
invoice.paidUne facture est marquée comme payée
proposal.approvedUn client approuve une proposition
client.createdUn client est créé

Vérification des signatures

Chaque envoi inclut un en-tête x-savrsoft-signature : le HMAC-SHA256 du corps brut de la requête, signé avec votre clé secrète de webhook. Calculez le vôtre et comparez :

// 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();
Confidentialité · Sécurité · Conditions · Des questions ? savrsoft.com · Créez des intégrations traiteur en quelques minutes.