Mediflo
REST API

REST API

Przegląd zewnętrznego API Mediflo — adres bazowy, wersjonowanie, koperty odpowiedzi i rodziny endpointów.

Zewnętrzne API Mediflo daje Twojemu systemowi dostęp do tego, co robi Portal: konfiguracji botów głosowych, sesji rozmów, zadań, historii połączeń, próśb o kontakt, webhooków i zgłoszeń do wsparcia. Wszystko przez jeden klucz API z listą zakresów.

Adres bazowy

https://app.mediflo.ai/api/external/v1

Kontrakt maszynowy: openapi.json (OpenAPI 3.1, generowany z tych samych schematów Zod, którymi walidują się trasy) oraz llms.txt — zwięzły indeks dla agenta AI konsumującego API.

Wersjonowanie

v1 jest stabilne. Wersja siedzi w ścieżce, więc niekompatybilna zmiana dostanie nową ścieżkę, a nie po cichu zmieni tę. Historia zmian: Changelog.

Pola dodajemy bez zapowiedzi — parsuj odpowiedzi tolerancyjnie i ignoruj nieznane klucze.

Koperty odpowiedzi

KształtKiedy
{ "data": { … } }Pojedynczy obiekt
{ "data": [ … ], "pagination": { … } }Lista — patrz Paginacja
{ "error": { "code", "message", "details?" } }Każdy błąd — patrz Błędy

Znaczniki czasu to zawsze łańcuchy ISO 8601 w UTC.

Rozgałęziaj się na `code`, nie na `message`

message jest tłumaczony na język wywołującego i może się zmienić bez zapowiedzi. Stabilny jest wyłącznie code.

Współbieżność

Zapisy, które mogłyby się nadpisać, wymagają wartości, którą przeczytałeś:

  • konfiguracja bota — expectedUpdatedAt,
  • przepływy rozmowy — expectedVersion.

Niezgodność to 409 z aktualną wartością w odpowiedzi. Przeczytaj ponownie, scal, ponów.

Rodziny endpointów

Pełna referencja każdej operacji — parametry, schematy, kody odpowiedzi — jest generowana z openapi.json i znajdziesz ją w sekcji Referencja w menu po lewej.

Rodziny sprzed OpenAPI

Zadania, użytkownicy, tagi, połączenia i prośby o kontakt są starsze niż generowany kontrakt i nie ma ich w openapi.json. Działają bez zmian; poniżej pełny opis ich powierzchni.

Zadania

OperacjaZakres
GET /taskstasks.read
GET /tasks/{taskId}tasks.read
POST /taskstasks.write
PATCH /tasks/{taskId}tasks.write
DELETE /tasks/{taskId}tasks.write

Parametry GET /tasks: page, limit, status (TODO, IN_PROGRESS, DONE, CANCELLED), priority (LOW, MEDIUM, HIGH, URGENT), assignedToUserId, search, orderBy (createdAt, updatedAt, dueDate, priority, title; domyślnie createdAt), orderDir (asc, desc; domyślnie desc).

Ciało POST /tasks: title (wymagane, do 500 znaków), description, priority (domyślnie MEDIUM), dueDate (ISO 8601), assignedToUserId, tagIds. Odpowiedź 201. PATCH przyjmuje te same pola poza assignedToUserId — przypisania są zarządzane osobno; description i dueDate przyjmują null, żeby wyczyścić wartość, a tagIds zastępuje całą listę tagów.

companyId (UUID firmy z CRM) wiąże zadanie z firmą — tylko w organizacjach z modułem firm (B2B). Pozostałe organizacje dostają 404 TENANT_MODULE_UNAVAILABLE, a nieznana lub usunięta firma daje 422 VALIDATION_ERROR. W PATCH wartość null usuwa powiązanie. Odpowiedzi zawierają pole company ({ id, name } albo null).

curl -s "https://app.mediflo.ai/api/external/v1/tasks?status=TODO&priority=HIGH&limit=20" \
  -H "Authorization: Bearer mflo_live_..."
{
  "data": [
    {
      "id": "550e8400-e29b-41d4-a716-446655440000",
      "title": "Oddzwonić w sprawie zgłoszenia",
      "status": "TODO",
      "priority": "HIGH",
      "origin": "SYSTEM",
      "dueDate": "2026-09-10T14:00:00.000Z",
      "assignedToUser": { "id": "123e4567-e89b-12d3-a456-426614174000", "firstName": "Jan", "lastName": "Kowalski" },
      "telephonyCall": { "id": "c9f3a6b8-1234-5678-9abc-def012345678", "fromNumber": "+48123456789", "direction": "inbound" },
      "patient": { "id": "a1b2c3d4-5678-90ab-cdef-123456789012", "firstName": "Maria", "lastName": "Nowak" },
      "contact": null,
      "tags": [{ "id": "tag-uuid-1", "name": "Pilne", "color": "#FF0000" }],
      "createdAt": "2026-09-06T10:30:00.000Z",
      "updatedAt": "2026-09-06T10:30:00.000Z"
    }
  ],
  "pagination": { "page": 1, "limit": 20, "total": 234, "totalPages": 12 }
}

Dwie rzeczy, które zaskakują:

  • Usunięte zadanie zwraca 404 TASK_NOT_FOUND. Usuwanie jest miękkie, ale dla tego API zadanie po prostu znika — GET, PATCH i DELETE odpowiadają tak samo. deletedAt w udanej odpowiedzi jest więc zawsze null.
  • Uzasadnienie modelu nigdy nie wychodzi na zewnątrz. Dla zadań origin: "SYSTEM" powstałych z analizy rozmowy rozumowanie modelu opiera się na transkrypcji i zostaje w Mediflo. Widzisz systemSource — zgrubną etykietę producenta — i tyle. Ani tutaj, ani w webhookach, ani w eksportach.

Użytkownicy i tagi

GET /users (zakres users.read) — parametry page, limit, isActive, search; zwraca id, email, firstName, lastName, fullName, imageUrl, isActive, createdAt, lastSeenAt i rolę.

GET /tags (zakres tags.read) — parametry search, includeDeleted; zwraca id, name, color, description, createdAt i twórcę. Zapis użytkowników i tagów nie istnieje w v1 — rób to w Portalu.

Połączenia

GET /calls (zakres calls.read) — historia połączeń telefonicznych, tylko do odczytu. Parametry: page, limit, phoneNumber (E.164, dopasowuje fromNumber albo toNumber), dateFrom, dateTo. Wyniki od najnowszych po startedAt.

curl -s "https://app.mediflo.ai/api/external/v1/calls?phoneNumber=%2B48123456789&limit=20" \
  -H "Authorization: Bearer mflo_live_..."
{
  "data": [
    {
      "id": "c9f3a6b8-1234-5678-9abc-def012345678",
      "direction": "inbound",
      "status": "COMPLETED",
      "fromNumber": "+48123456789",
      "toNumber": "+48221234567",
      "startedAt": "2026-09-01T09:15:00.000Z",
      "answeredAt": "2026-09-01T09:15:06.000Z",
      "endedAt": "2026-09-01T09:18:31.000Z",
      "duration": 205,
      "totalDuration": 211,
      "summary": "Rozmówca przełożył termin.",
      "voicemailDetected": false,
      "topic": { "id": "topic-uuid", "name": "Zmiana terminu" },
      "agentUser": { "id": "user-uuid", "fullName": "Anna Wiśniewska" }
    }
  ],
  "pagination": { "page": 1, "limit": 20, "total": 87, "totalPages": 5 }
}

duration to czas rozmowy w sekundach liczony od answeredAt (null dla nieodebranych), totalDuration obejmuje dzwonienie, a summary jest generowane przez AI i bywa null, dopóki analiza nie ruszy.

Prośby o kontakt

GET /contact-requests (zakres contact-requests.read) — parametry page, limit, status (PENDING, IN_PROGRESS, HANDLED, EXPIRED, CANCELLED).

POST /contact-requests (zakres contact-requests.write) — phoneNumber albo email jest wymagane, do tego obowiązkowe source (do 100 znaków, np. website, crm) oraz opcjonalnie callerName, sourceIdentifier, reason, priority, expiresAt, metadata, telephonyCallId, dispatcherDispatchId. Zwraca 201 z tym samym kształtem co lista (attempts puste).

Zwracany zestaw pól jest kompletnym kontraktem — pola spoza niego celowo nie wychodzą na zewnątrz.

Dwa własne błędy: CONTACT_REQUEST_INVALID_CALL_REFERENCE i CONTACT_REQUEST_INVALID_DISPATCH_REFERENCE, oba 400, gdy wskazane telephonyCallId / dispatcherDispatchId nie istnieje w Twoim workspace.

Zgodność z Thulium

Zakres thulium.initialize-call obsługuje endpoint inicjujący połączenia wychodzące zgodny z API Thulium — istnieje wyłącznie po to, żeby integracje napisane pod Thulium działały bez przepisywania.

Audyt

Każde uwierzytelnione żądanie do /api/external/v1/* trafia do dziennika audytu Twojego workspace: użyty klucz API, metoda HTTP, endpoint (z identyfikatorami zwiniętymi do :id), wynik oraz identyfikator zasobu, który powstał lub się zmienił. Dotyczy to też żądań, które odrzuciliśmy — brak zakresu, przekroczony limit, operacja, która padła po autoryzacji.

Żądania, które padają zanim klucz rozwiąże się do workspace (klucz błędny, nieznany, wygasły albo unieważniony), nie dają się przypisać do tenanta, więc nie ma ich w Twoim dzienniku — lądują w logach operacyjnych Mediflo.

Ciała żądań i odpowiedzi nigdy nie są przechowywane.

Na tej stronie