Menodi/Docs
Docs API & utvecklare
Beta

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: v1beta kan ändras med förvarning. När v1 slä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 data och next_cursor. Skicka värdet som cursor för nästa sida. null betyder att det inte finns fler.
  • Stegvis synk: skicka updated_after till /bookings eller /contacts fö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 svara other. 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 i details.reason: closed, notice, advance eller busy.
  • Tjänster med manuell bekräftelse ger status pending tills företaget har bekräftat.
  • Bekräftelse-SMS följer företagets inställning. Skicka "notify_customer": false för att stänga av det för en bokning.
  • Företag som bokar i ett journalsystem får 409 pms_managed på 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ändelseNär
call.completedEtt samtal är klart och sparat. Transkriptet hämtas med GET /calls/{id}.
booking.createdEn bokning skapades, oavsett kanal.
booking.updatedTid, status, tjänst, personal, kunduppgifter eller anteckning ändrades.
booking.cancelledEn bokning avbokades.
booking.deletedEn 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 id fö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.