Autentisering
Alla API-anrop använder en API-nyckel som bearer-token. Skapa en i appen under Developer → API keys. Nycklar är antingen skrivskyddade eller läs/skriv.
curl https://savrsoft.com/api/v1/events \ -H "Authorization: Bearer savr_live_your_key_here"
Bas-URL: https://savrsoft.com/api/v1 · Alla svar är i JSON. Fel returneras som { "error": "…" } med en 4xx/5xx-statuskod.
Statuskoder
| Kod | När du får den |
|---|---|
200 | Lyckad läsning. |
201 | Skapad utan problem. Innehållet är { "id": 42 } — hämta posten om du behöver resten av informationen. |
400 | Ett obligatoriskt fält saknas, t.ex. { "error": "name is required" }, eller så gick det inte att läsa en pagineringscursor. |
401 | Ingen API-nyckel, en felaktig sådan, eller en nyckel som har återkallats. |
403 | En skrivskyddad nyckel användes för en skrivåtgärd. Skapa en läs-/skrivnyckel under Utvecklare → API-nycklar. |
404 | Posten finns inte, eller tillhör en annan organisation — de två fallen är medvetet omöjliga att skilja åt. Returneras också för en okänd sökväg eller metod. |
Denna API:s omfattning
API:et är endast läsning och skapande. Det finns inga DELETE, PUT eller PATCH
-slutpunkter — en förfrågan som använder en sådan returnerar 404 Unknown endpoint, precis som för alla okända sökvägar. Radering och
redigering görs i appen, så en integration kan inte förstöra en cateringfirmas poster. Om du behöver skrivåtkomst utöver att skapa,
berätta för oss vad du bygger.
Sidnumrering
Varje listslutpunkt är sidnumrerad. Skicka med limit (standard 100, max 500) och
följ next_cursor tills has_more är false:
{
"data": [ ... ],
"has_more": true,
"next_cursor": "eyJuYW1lIjoiQWNtZSIsImlkIjo0Mn0"
}
Skicka tillbaka markören direkt för att få nästa sida. Behandla den som ogenomskinlig — kodningen kan komma att ändras:
curl "https://savrsoft.com/api/v1/clients?limit=100&cursor=eyJuYW1lIjoiQWNtZSIsImlkIjo0Mn0" \ -H "Authorization: Bearer savr_live_your_key_here"
Sidnumrering är förankrad till den senaste raden du tog emot, inte till en offset, så rader som skapas eller raderas medan du bläddrar kommer inte att göra att du hoppar över eller upprepar en post. En markör förblir giltig på obestämd tid.
| Parameter | Beteende |
|---|---|
limit | 1–500. Om värdet saknas, är noll, negativt eller icke-numeriskt används 100 som standard; allt över 500 begränsas till 500. |
cursor | next_cursor från föregående sida. Utelämna den för den första sidan. En markör som inte kan läsas — skadad, eller från en annan endpoint — returnerar 400 Invalid cursor istället för att tyst börja om från början. |
Ordning: /events och /invoices nyast först; /recipes och
/clients efter namn, där oavgjort avgörs av id så att sidnumreringen förblir stabil när namn upprepas.
Endpoints
/v1/meDin organisation (id, namn, valuta).
/v1/eventsLista evenemang, nyast först. Paginerad — se Sidnumrering ovan.
/v1/events/{id}Ett event med tillhörande rätter.
/v1/events · kräver läs-/skrivbehörighetSkapa ett event. Body:
{ "name": "Acme holiday party", "event_date": "2026-12-18",
"guests": 120, "price_per_head": 55, "event_type": "corporate" }
/v1/recipes · GET/v1/recipes/{id}Lista recept (med allergener & kostflaggor), eller hämta ett recept med ingredienser. Listan är paginerad och sorterad efter namn.
/v1/clients · POST/v1/clientsLista kunder (paginerad, efter namn) eller skapa en ny. Body för att skapa: { "name": "...", "email": "...", "phone": "...", "company": "..." }
/v1/invoices · GET/v1/invoices/{id}Lista fakturor med beräknade totalsummor, nyaste först, eller hämta en faktura med radposter. Listan är paginerad.
Webhooks
Registrera en endpoint under Developer → Webhooks. Vi skickar en POST med en JSON-payload när events inträffar:
{
"id": "evt_abc123",
"type": "event.inquiry",
"created_at": "2026-07-17T18:20:00.000Z",
"data": { "id": 42, "name": "Corporate lunch — Dana Ruiz", ... }
}
Eventtyper
| Typ | Utlöses när |
|---|---|
event.created | Ett event skapas |
event.inquiry | En ny cateringförfrågan kommer in online |
invoice.sent | En faktura markeras som skickad |
invoice.paid | En faktura markeras som betald |
proposal.approved | En kund godkänner ett förslag |
client.created | En kund skapas |
Verifiera signaturer
Varje leverans innehåller en x-savrsoft-signature header: HMAC-SHA256 av den råa förfrågningskroppen, signerad med din webhook-signeringsnyckel. Beräkna samma värde och jämför:
// 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();
