Files
ordinaceprojekt/Medevio/medevio_api_notes.md
T
Vladimir Buzalka c1a5909f65 notebookvb
2026-06-02 06:37:25 +02:00

19 KiB

MEDEVIO API -- Working Notes

General Architecture

  • Frontend: React + Material-UI (MUI) + Apollo GraphQL
  • Backend: GraphQL API -> https://api.medevio.cz/graphql
  • Authentication: cookies/tokens stored in medevio_storage.json (Playwright session)
  • Frontend base: https://my.medevio.cz/mudr-buzalkova/klinika/...
  • Session handling: token refreshed through AccessToken_AuthSelf calls

Authentication and Session

Reuse session cookies from Playwright:

state = json.load(open("medevio_storage.json"))
cookies = {c["name"]: c["value"] for c in state["cookies"] if "medevio" in c["domain"]}

Use these cookies in every requests.post(GRAPHQL_URL, headers, cookies, data=...) call.


HTTP Setup (Python)

GRAPHQL_URL = "https://api.medevio.cz/graphql"
headers = {
    "content-type": "application/json",
    "origin": "https://my.medevio.cz",
    "referer": "https://my.medevio.cz/",
}
response = requests.post(GRAPHQL_URL, headers=headers, cookies=cookies, data=json.dumps(payload))

Key IDs

Entity ID
Clinic 25f24970-dae3-4f80-9337-d3616e53fb10
Clinic slug mudr-buzalkova
Calendar MUDr. Buzalkova (manzelka) 144c4e12-347c-49ca-9ec0-8ca965a4470d
Calendar Vlado b6555c7e-4e95-4657-b441-87c2c9a7b2ca
AIS entity (Medicus) ef1549a5-d266-4f52-9a4d-7275e79ac82e

Complete GraphQL Operations Catalog

Session & Auth

Operation Purpose
AccessToken_AuthSelf Verify or refresh session
Operation Variables Response
Search clinicSlug, locale, query clinic, results (patients + requests)

Patient Card (modal)

Operation Variables Response
ClinicPatientDetailModal_GetData clinicSlug, patientId, patientUuid, locale, challengesStatus clinic, calendars, patient (full detail), challenges, patientRequestsResponse, treatmentPlanPatients, premiumPlans, insuranceCards, pinnedRequests, canBeRemoved
ClinicPatientRequestHistory_FilterPatientRequestsForClinic clinicSlug, locale, patientId, patientRequestFilter, pageInfo {first, offset} filterResponse, clinic, queues, calendars, userECRFs, substates, tags
ClinicPatientDetailModal_FindMergeSuggestions clinicSlug, patientUuid mergeSuggestions

Patient object structure (from GetData)

patient {
  id, name, surname, identificationNumber (rodne cislo bez lomitka),
  sex (Male/Female), dob (YYYY-MM-DD), email, phone,
  kind (Human), type (Human), status (ACTIVE),
  isInClinic, isInOrganizationOnly, hasMobileApp,
  anamnesisShared, anamnesisStatusForClinic { updatedAt },
  insuranceCompanyObject { id, code, name, shortName },
  tags [], familyMembers [], clinics [],
  note, organizationNotes [],
  city, street, houseNumber,
  user { id, name, surname, email, phone, registrationCompletedTime },
  createdAt, editableByDoctor, userRelationship, premiumPlanPatient
}

Patient Edit

Operation Variables Response
EditPatientModal_GetClinic clinicSlug clinic
ClinicEditPatient_GetPatientForClinic clinicSlug, patientId, includePatient patient, clinic
ClinicEditPatient_ListInsuranceCompanies country insuranceCompanies [] (id, code, name)
UseSupportedCountryCodes_Codes (none) codes (phone country codes)

Patient List (Kartoteka)

Operation Variables Response
LegacyClinicPatientListPage_ListClinicPatients clinicSlug, criteria {premiumPlanId, tagId}, pageInfo {first: 50, offset} count, patients, clinic

Fungující dotaz pro stránkovaný seznam pacientů (sync)

Pozor: listClinicPatients nefunguje pro hromadný export. Fungující query je listPatients:

query SyncListPatients($clinicSlug: String!, $pageInfo: PageInfo!, $filter: ListPatientFilter!) {
  patientsList: listPatients(clinicSlug: $clinicSlug, filter: $filter, pageInfo: $pageInfo) {
    count
    patients {
      id
      identificationNumber
      name
      surname
      sex
      phone
      status2
      isInClinic
      locale
      insuranceCompanyObject { id shortName }
      user { id phone name surname }
    }
  }
}

Variables:

{
  "clinicSlug": "mudr-buzalkova",
  "filter": {},
  "pageInfo": { "first": 50, "offset": 0 }
}

Stránkování: offset se zvyšuje po 50, count v odpovědi = celkový počet pacientů.

Dotaz pro detail jednoho pacienta

query GetPatientDetail($clinicSlug: String!, $patientId: String!) {
  patient: getPatientForClinic(clinicSlug: $clinicSlug, patientId: $patientId) {
    id
    name
    surname
    identificationNumber
    sex
    dob
    email
    phone
    status
    isInClinic
    hasMobileApp
    anamnesisShared
    note
    city
    street
    houseNumber
    createdAt
    insuranceCompanyObject {
      code
      name
    }
    user {
      id
      email
      phone
    }
  }
}

Variables:

{
  "clinicSlug": "mudr-buzalkova",
  "patientId": "<UUID>"
}

Sync pacientů do MySQL

Dvoustupňový proces:

  1. listPatients stránkovaně stáhne seznam všech patient IDs (po 50)
  2. Pro každého pacienta se zavolá getPatientForClinic pro detail
  3. UPSERT do medevio.medevio_pacient (23 sloupců)

Skript: Medevio/80 Pacienti/sync_patients_to_mysql.py Výsledek: 1963 pacientů synchronizováno (květen 2026).

Má pacient Medevio účet?user_id IS NOT NULL (žádný redundantní boolean sloupec)

  • 1 230 pacientů má účet (63 %), 733 nemá (37 %) — stav květen 2026

Známé problémy

  • hasMobileApp je nefunkční na úrovni pacienta — ověřeno na více endpointech:

    • getPatientForClinic → vždy false
    • ClinicPatientDetailModal_GetDatapatient.hasMobileApp vždy false
    • listPatients → pole vůbec neexistuje v GraphQL schema
  • Správná hodnota hasMobileApp je na objektu request, nikoli pacienta:

    • ClinicRequestDetail_GetPatientRequest2request.hasMobileApp vrací správně
    • request.extendedPatient.hasMobileApp je stále vždy false
    • UI komponenta PatientRequest.MessageSend čte hodnotu z request.hasMobileApp a rozhoduje:
      • true → zobrazí "Odeslat do aplikace"
      • false + telefon existuje → zobrazí "Odeslat přes SMS"
      • false + žádný telefon → tlačítko se nezobrazí vůbec
  • Praktické získání hasMobileApp pro pacienty:

    • Stáhnout všechny požadavky přes ClinicLegacyRequestList_ListPatientRequestsForClinic (aktivní i vyřízené)
    • Pro každého pacienta vzít nejnovější hasMobileApp z jeho požadavků
    • Nevýhoda: pacienti bez jediného požadavku budou NULL; hodnota odráží stav k době posledního požadavku

Requests (Pozadavky)

Operation Variables Response
ClinicLegacyRequestList_ListPatientRequestsForClinic clinicSlug, locale, pageInfo {first: 30, offset}, queueAssignment, queueId, state (ACTIVE/DONE) requests, clinic
ClinicRequestList2 clinicSlug, queueId, queueAssignment, state (ACTIVE/DONE), pageInfo {first, offset}, locale requestsResponse { count, patientRequests [] }

ClinicRequestList2 volá listPatientRequestsForClinic2 — novější endpoint, vrací count a plně stránkovaný seznam. Struktura položky:

patientRequest { id, displayTitle, createdAt, updatedAt, doneAt, removedAt,
  extendedPatient { name, surname, identificationNumber },
  lastMessage { createdAt } }

Skript: Medevio/10ReadPozadavky/PRAVIDELNE_0_READ_ALL_ACTIVE_POZADAVKY.py

Request list item structure

request {
  id, createdAt, dueDate, displayTitle, doneAt, removedAt,
  priority, evaluationResult, clinicId,
  extendedPatient { id, identificationNumber, kind, name, surname,
    note, owner, key, premiumPlanPatient, status, tags [] },
  queue { id, name }, substate, pinType,
  ecrf { id, name, iconMaskColor { name } },
  flags [], hasMobileApp
}

Request Detail

Operation Variables Response
ClinicRequestDetail_GetPatientRequest2 clinicSlug, isDoctor, requestId, locale request (full detail)
UseMessages_ListMessages requestId, updatedSince messages
Communication_GetClinicFooter clinicSlug footer
ClinicRequestNotes_Get patientRequestId notes []
ClinicRequestNotes_Update noteInput { id, content } { id }
ClinicRequestNotes_Create noteInput { requestId, content } { id }
ClinicRequestDetail_GetMessages clinicSlug, requestId zprávy (alternativní endpoint)

Interní poznámky k požadavku (klinické notes)

# Čtení
query ClinicRequestNotes_Get($patientRequestId: String!) {
  notes: getClinicPatientRequestNotes(requestId: $patientRequestId) {
    id content createdAt updatedAt createdBy { id name surname }
  }
}

# Aktualizace existující
mutation ClinicRequestNotes_Update($noteInput: UpdateClinicPatientRequestNoteInput!) {
  updateClinicPatientRequestNote(noteInput: $noteInput) { id }
}

# Vytvoření nové
mutation ClinicRequestNotes_Create($noteInput: CreateClinicPatientRequestNoteInput!) {
  createClinicPatientRequestNote(noteInput: $noteInput) { id }
}

K jednomu požadavku existuje typicky jedna interní poznámka. Pokud neexistuje → Create, pokud existuje → Update. Skript: Medevio/30 ManipulacePoznámek/101 JednoducheDoplneniInterniPoznamky.py

Alternativní endpoint pro zprávy konverzace

query ClinicRequestDetail_GetMessages($clinicSlug: String!, $requestId: ID!) {
  clinicRequestDetail_GetPatientRequestMessages(clinicSlug: $clinicSlug, requestId: $requestId) {
    id text createdAt
    sender { id name }
    extendedPatient { name surname identificationNumber }
  }
}

Skript: Medevio/10ReadPozadavky/10 UpdateMessageswithJmeno.py

Request detail structure

request {
  id, doneAt, doneBy { id, name, surname },
  removedAt, queue, isInClinic,
  clinic { id, paymentEnabled, hasInvoicingEnabled, slug, features },
  clinicMedicalRecord, clinicMedicalRecordVisibleToPatient,
  extendedPatient { ... (same as patient) },
  ecrf, ecrfFilledData, eventType (PATIENT_REQUEST),
  flags [], invoice, userNote, paymentData,
  recording, reservations [], evaluationResult, tags [],
  createdAt, createdBy, customTitle, createdByDoctor,
  displayTitle, referringClinic, pinType,
  dueDate, substate, hasMobileApp,
  priceWhenCreated, currencyWhenCreated
}

Calendar (Kalendar)

Operation Variables Response
ClinicCalendar_ListClinicReservations calendarIds [], clinicCountry, clinicSlug, locale, since (ISO), until (ISO), showTimeSlots, schedulePatientId, emptyCalendarIds holidays, reservations, vacations
ClinicCalendar_GetWindows calendarIds [], clinicSlug, locale, since, until calendarWindows (ordinacni hodiny)
Agenda_ListAll calendarIds [], clinicSlug, locale, since, until reservations (jednorazove) + recurringReservations (opakujici)

Agenda_ListAll volá dva endpointy zároveň:

  • listClinicReservations → jednorazové rezervace (pacienti + poznámky lékaře)
  • listClinicRecurringReservations → opakující se rezervace; vrací recurringReservation { id calendarId color note rrule { frequency interval dtstart tzid byweekday bymonthday byweekno } } a instances { start end note color }

Fungující skript: Medevio/agenda_dne.py — funkce list_agendu(start, end, calendar)

Vytvoření poznámky lékaře v kalendáři

mutation CreateReservation_MakeReservationByDoctor(
  $clinicSlug: String!, $color: ECRFIconColor, $note: String!, $timeSlotInput: TimeSlotInput!
) {
  reservation: makeReservationByDoctor(
    clinicSlug: $clinicSlug color: $color note: $note timeSlotInput: $timeSlotInput
  ) { id __typename }
}

Variables: clinicSlug, color (např. "CHARCOAL"), note (text), timeSlotInput { calendarId, start (UTC ISO), end (UTC ISO) } Vrací: reservation.id — UUID nové rezervace. Skript: Medevio/zapis_poznamky.py — funkce zapis_poznamku(calendar, den, cas, trvani_min, poznamka, color)

Smazání / zrušení rezervace

# Jednorazová:
mutation UpdateReservation_CancelReservationByDoctor(
  $clinicSlug: String!, $reservationId: UUID!
) {
  reservation: cancelReservationByDoctor(clinicSlug: $clinicSlug, reservationId: $reservationId) { id __typename }
}

# Opakující se:
mutation UpdateReservation_CancelRecurringReservationByDoctor($input: RemoveRecurringReservationInput!) {
  success: removeDateFromRecurringReservation(input: $input)
}

Pro opakující se: input { clinicSlug, recurringReservationId, date (UTC ISO), updateType: "Single"|"ThisAndFuture"|"All" } Skript: Medevio/smaz_poznamku.py — funkce smaz_jednorazovou(reservation_id), smaz_opakujici(recurring_id, date, update_type)

Reservation structure

reservation {
  id, calendarId,
  clinic { id, slug, aisEntity { id, slug } },
  color, done, canceledAt,
  end (ISO), note,
  request {
    displayTitle, id,
    ecrf { id, name, iconMaskColor { name } },
    extendedPatient { dob, email, id, identificationNumber,
      kind, name, surname, note, phone, sex, status, tags [],
      insuranceCompanyObject { code, name } }
  }
}

Patient Status Change (Zmena stavu)

Operation Variables Response
ClinicPatientEditStatusModal_UpdateClinicPatientStatus clinicSlug, patientId (UUID), status updated (boolean)

Dostupné stavy (ClinicPatientStatus)

UI název API hodnota
Aktivní ACTIVE
Odmítnutý DECLINED
Vyřazený REMOVED
Čekající PENDING

Mutation

mutation ClinicPatientEditStatusModal_UpdateClinicPatientStatus($clinicSlug: String!, $patientId: String!, $status: ClinicPatientStatus!) {
  updated: updateClinicPatientStatus(
    clinicSlug: $clinicSlug
    patientId: $patientId
    status: $status
  )
}

Odpověď: { "data": { "updated": true } }

Skript pro hromadnou změnu: Medevio/80 Pacienti/bulk_set_removed.py


References (Referovani)

Operation Variables Response
ClinicReferences_GetClinic clinicSlug clinic, substates
ClinicReferences_ListReferencesSentByClinic clinicSlug, locale, pageInfo {first: 51, offset} references

Treatment Plans (Lecebne plany)

Operation Variables Response
PlanPatientsPage_GetClinic clinicSlug clinic
PlanPatientsPage_ListPlanPatients clinicSlug, pageInfo {first: 51, offset} planPatients

Settings (Nastaveni)

Operation Purpose
ClinicSettingsSubNavigation_GetClinic Navigation state for settings
ClinicRequestSettings_GetClinic Request settings
UserEcrfListing_GetClinicECRFMenu List request types (ECRF forms)
ClinicEcrfSet_ListECRFSets List request type groups
ClinicOpeningHoursEdit_GetClinicOpeningHours2 Opening hours settings
ClinicPaymentsSettings_GetClinic Payment settings
StripeVerificationContext_GetClinicCompanyInfo Stripe payment verification
SettingsPage General settings
InviteSettings Invite settings
InviteSettings_GetInviteContent Invite content/templates
ImportAisSettings_GetClinic AIS integration settings
ImportAisSettings_GetAises Available AIS systems
ClinicUserGrid_Columns User grid columns (queues, calendars)
ClinicUserGrid_Rows User list for clinic

Clinic Info

Operation Purpose
ClinicNavigation_GetClinic Basic clinic info
ClinicAgenda_GetCalendarsForClinic List calendars within clinic

Playwright Selectors

Purpose Selector
Agenda rows div[data-testid='reservation-row']
Row ID data-id
Agenda fields div[data-field='Time'], div[data-field='Patient'], div[data-field='Reason']

URL Patterns

Page URL
Search /mudr-buzalkova/klinika/hledat/?q={query}
Patient card /mudr-buzalkova/klinika/hledat/?q={query}&pacient={uuid}
Request detail /mudr-buzalkova/klinika/hledat/?q={query}&pozadavek={uuid}
Requests (active) /mudr-buzalkova/klinika/pozadavky/
Requests (done) /mudr-buzalkova/klinika/pozadavky?vyrizene=1
Calendar /mudr-buzalkova/klinika/kalendar/?kalendar={calendarId}&pohled=pracovni-tyden
Patient list /mudr-buzalkova/klinika/kartoteka/
References /mudr-buzalkova/klinika/reference
Treatment plans /mudr-buzalkova/klinika/lecebne-plany/pacienti
Settings - requests /mudr-buzalkova/klinika/nastaveni/pozadavky
Settings - groups /mudr-buzalkova/klinika/nastaveni/skupiny-pozadavku
Settings - invites /mudr-buzalkova/klinika/nastaveni/pozvanky
Settings - integrations /mudr-buzalkova/klinika/nastaveni/propojky
Settings - hours /mudr-buzalkova/klinika/nastaveni/ordinacni-doba
Settings - payments /mudr-buzalkova/klinika/nastaveni/platby
Users /mudr-buzalkova/klinika/uzivatele/

Insurance Companies (CZ)

Code Name
0 Ministerstvo zdravotnictvi CR
111 VZP
201 VoZP
205 CPZP
207 OZP
209 ZPS
211 ZPMV
213 RBP
999 Jina

Clinic Features (enabled)

RESERVATION_REMINDERS, PUSH_NOTIFICATIONS, INVITES, ON_DEMAND_SLOT_GENERATOR, REQUEST_TYPES_ACCESS_RULES, CAN_REFER_PATIENTS, TREATMENT_PLANS_V2, MEDICAL_RECORDS, CAMPAIGNS, PATIENT_SEGMENTATION, ADVANCED_CALENDAR_FUNCTIONS, PATIENT_CLINIC_STATUS, STANDARD_TARIFF_FUNCTIONS, CLINIC_CLOSED_WARNINGS, ADVANCED_SWITCHBOARD, REQUEST_AUTOMATIONS, REQUEST_PINNING, AI_SWITCHBOARD_PROMO, PATIENT_REQUEST_SUBSTATES


Security / Maintenance Notes

  • GraphQL introspection disabled.
  • Refresh session cookies periodically.
  • Keep data GDPR-compliant.

Future Tasks

  • Automate cookie renewal.
  • Build helper functions:
    • get_reservations(date) using ClinicCalendar_ListClinicReservations
    • get_reservation_detail(reservation_id)
    • get_patient(patient_id) using ClinicPatientDetailModal_GetData
    • list_patients(offset) using LegacyClinicPatientListPage_ListClinicPatients
    • search_patients(query) using Search
    • get_requests(state, offset) using ClinicLegacyRequestList_ListPatientRequestsForClinic
    • get_request_detail(request_id) using ClinicRequestDetail_GetPatientRequest2
  • Map vaccine keywords.
  • Export to Excel/MySQL for vaccine order planning.