Menodi API
Koppla Menodi till era egna system. Hämta samtal, bokningar och kontakter, boka tider och få besked direkt när något händer.
Ladda ner hela dokumentationen: Markdown (.md) Text (.txt) OpenAPI (.json)
Vill ni hellre att vi bygger kopplingen åt er? Läs om anpassade flöden.
Kom igång
API:t är avstängt tills ni aktiverar det. Ägaren eller en behörig användare gör det i appen, under Integrationer → API, och skapar sedan nycklar där. En nyckel ger åtkomst till samtal, transkript, inspelningar, bokningar och kontakter, som kan innehålla känsliga personuppgifter. Ni ansvarar för vart uppgifterna skickas.
Skicka nyckeln som en Bearer-token. Ett bra första anrop är /me:
curl https://menodi.se/api/v1beta/me \
-H "Authorization: Bearer mnd_live_..."
const res = await fetch('https://menodi.se/api/v1beta/calls?limit=10', {
headers: { Authorization: `Bearer ${process.env.MENODI_API_KEY}` },
});
const { data, next_cursor } = await res.json();
Skydda nyckeln. Den ger åtkomst till kunduppgifter, transkript och inspelningar. Använd den bara från er server, aldrig i en webbsida eller app. Läcker den återkallar ni den i appen och skapar en ny. Den som tar emot uppgifter via API:t ansvarar för att hantera dem enligt GDPR.
Så fungerar API:t
- Bas-URL:
https://menodi.se/api/v1beta - Versioner:
v1betakan ändras med förvarning. Närv1släpps är den stabil: nya fält kan tillkomma, så ignorera fält ni inte känner igen. Brytande ändringar kommer i en ny version. - Tider är UTC i ISO 8601. Lediga tider anges också med klockslag i svensk tid.
- Sidindelning: listor svarar med
dataochnext_cursor. Skicka värdet somcursorför nästa sida.nullbetyder att det inte finns fler. - Stegvis synk: skicka
updated_aftertill/bookingseller/contactsför att bara hämta det som ändrats. - Gränser: 120 anrop per minut per nyckel och 30 nya bokningar per minut. Över gränsen svarar API:t 429 med headern
Retry-After. - Okända värden: fält med fasta värden, som
outcome, kan svaraother. Hantera det utan att stanna. - Testsamtal ingår aldrig.
- Felsökning: varje svar har headern
X-Request-Id. Ange den när ni kontaktar oss.
Boka via API:t
Hämta lediga tider, och skicka sedan en av dem till POST /bookings. Samma regler gäller som på företagets bokningssida. Headern Idempotency-Key krävs: skickar ni samma nyckel igen, till exempel efter ett nätverksfel, får ni samma svar utan att bokningen skapas två gånger.
curl -X POST https://menodi.se/api/v1beta/bookings \
-H "Authorization: Bearer mnd_live_..." \
-H "Idempotency-Key: 3f8a1c52-7e0b-4a7e-9b1d-2c6d5e4f3a10" \
-H "Content-Type: application/json" \
-d '{
"start": "2026-12-01T09:00:00Z",
"service_id": "...",
"customer": { "name": "Kim Andersson", "phone": "+46701234567" },
"notify_customer": true
}'
- En tid som inte går att boka ger
409 slot_unavailable, med orsaken idetails.reason:closed,notice,advanceellerbusy. - Tjänster med manuell bekräftelse ger status
pendingtills företaget har bekräftat. - Bekräftelse-SMS följer företagets inställning. Skicka
"notify_customer": falseför att stänga av det för en bokning. - Företag som bokar i ett journalsystem får
409 pms_managedpå lediga tider och bokningar. Läsning fungerar som vanligt. - Två samtidiga anrop mot samma tid kan i sällsynta fall båda gå igenom. Kontrollera svaret om ni bokar i stora volymer.
- Ombokning görs genom att avboka och skapa en ny bokning.
Webhooks
Lägg till en https-adress under Integrationer → API och välj händelser. Menodi skickar en POST när något händer. Med knappen Skicka testhändelse får ni en webhook.ping att testa mot.
| Händelse | När |
|---|---|
call.completed | Ett samtal är klart och sparat. Transkriptet hämtas med GET /calls/{id}. |
booking.created | En bokning skapades, oavsett kanal. |
booking.updated | Tid, status, tjänst, personal, kunduppgifter eller anteckning ändrades. |
booking.cancelled | En bokning avbokades. |
booking.deleted | En bokning raderades. Bara id skickas. |
{
"id": "e2f1c7a4-...",
"type": "booking.created",
"created_at": "2026-11-05T10:15:00.000Z",
"api_version": "v1beta",
"data": { "id": "...", "start": "2026-12-01T09:00:00.000Z", "status": "confirmed" }
}
- Svara med 2xx inom 10 sekunder. Allt annat, även en omdirigering, räknas som misslyckat.
- Omförsök sker efter 1 minut, 5 minuter, 30 minuter, 2 timmar, 12 timmar och 24 timmar.
- Samma händelse kan komma mer än en gång, och i annan ordning. Använd
idför att bara hantera den en gång. Innehållet visar läget vid leveransen, inte när händelsen inträffade.
Kontrollera signaturen
Headern Menodi-Signature har formen t=<tidsstämpel>,v1=<signatur>. Signaturen är HMAC-SHA256 av tidsstämpel.råtext med signeringshemligheten, som visas när adressen läggs till. Kontrollera den mot den råa texten, innan den tolkas som JSON.
import { createHmac, timingSafeEqual } from 'node:crypto';
function isFromMenodi(rawBody, header, secret) {
const parts = Object.fromEntries(header.split(',').map((p) => p.split('=')));
// Avvisa gamla händelser, så att en uppfångad begäran inte kan spelas upp igen.
if (Math.abs(Date.now() / 1000 - Number(parts.t)) > 300) return false;
const expected = createHmac('sha256', secret).update(`${parts.t}.${rawBody}`).digest('hex');
const given = Buffer.from(parts.v1 ?? '', 'utf8');
const wanted = Buffer.from(expected, 'utf8');
return given.length === wanted.length && timingSafeEqual(given, wanted);
}
Referens
Hämtas direkt från OpenAPI-beskrivningen, som också går att läsa in i verktyg som Postman.
Laddar referensen…
Felkoder
Fel svarar med { "error": { "code", "message", "request_id", "details" } }. Bygg logik på code, som inte byter betydelse. message är text som kan ändras.