Przejdź do treści

Oś czasu — przebieg integracji

Ścieżka: GET /partner/v1/timeline/{petId}. Uwierzytelnienie jak w pozostałych modułach: x-client-id, x-api-key, x-user-id.

Czym jest oś czasu

Oś czasu to jedna wspólna lista wszystkich zdarzeń medycznych zwierzaka — wizyt, prediagnoz, szczepień, zabiegów pielęgnacyjnych i przypomnień o lekach. Nie tworzy się jej wpisów wprost: powstają samoczynnie, gdy dodaje się dane w pozostałych modułach.

To jedyny endpoint, który pokazuje te zdarzenia razem, w porządku chronologicznym. Służy do zbudowania widoku kalendarza albo historii zwierzaka.

Zapytanie

GET /partner/v1/timeline/{petId}?period=FUTURE&take=10
GET /partner/v1/timeline/{petId}?period=PAST&categories=VACCINATION,PetMedicines
GET /partner/v1/timeline/{petId}?period=PAST&cursor=<nextCursor>
Parametr Domyślnie Znaczenie
period FUTURE FUTURE — od dzisiaj wzwyż, rosnąco; PAST — sprzed dzisiaj, malejąco
take 10 rozmiar strony, maksymalnie 100
cursor nextCursor z poprzedniej odpowiedzi
categories wszystkie filtr, wartości po przecinku

Granicą między PAST a FUTURE jest bieżąca chwila, a nie początek dnia. Ma to praktyczny skutek: większość wpisów ma datę bez godziny, czyli północ, więc dzisiejsze zdarzenia trafiają do PAST — już po pierwszej sekundzie doby. Widok „dzisiaj" należy budować z period=PAST i odfiltrować po dacie po swojej stronie.

Nie ma trybu zwracającego przeszłość i przyszłość naraz — widok łączony powstaje z dwóch wywołań.

Stronicowanie

{ "timeline": [  ], "nextCursor": "3f2b…" }

nextCursor równy null oznacza ostatnią stronę. Kursor wskazuje pierwszy wpis kolejnej strony, więc nie trzeba niczego pomijać ani odcinać — kolejne strony się nie zazębiają. Kursor nieznany systemowi zwraca pustą listę, a nie błąd.

Uwaga: strona może zawierać mniej pozycji niż take, mimo że nextCursor nie jest pusty. Wpisy, których źródłowy rekord został w międzyczasie usunięty, są odrzucane po pobraniu strony. Nie należy więc traktować timeline.length < take jako końca listy — końcem jest wyłącznie nextCursor: null.

Filtrowanie

categories przyjmuje wartości pola entity_category:

Wartość Czego dotyczy
MedVisit wizyta u weterynarza w naszej sieci
Prediagnosis wypełniona prediagnoza
ExternalAppointment wizyta zewnętrzna bez zabiegu
PetMedicines przypomnienie o lekach
VACCINATION szczepienie
TREATMENT badanie
DEWORMING odrobaczanie
TICK_PREVENTION profilaktyka przeciwkleszczowa
FLEA_PREVENTION profilaktyka przeciwpchelna
CARE pielęgnacja

Nieznana wartość kończy się 400 — celowo, bo w przeciwnym razie literówka dawałaby pustą oś czasu nie do odróżnienia od braku zdarzeń.

Odpowiedź: lista niejednorodna

To najważniejsza rzecz w tym module. Każdy wpis ma wspólny zestaw pól, a do tego pola zależne od rodzaju rekordu. Rodzaj rozpoznaje się po record_type:

{ "id": "…", "record_type": "ExternalAppointment", "entity_category": "VACCINATION",
  "date": "2026-11-20T00:00:00.000Z", "related_record": "…", "pet_id": "…",
  "metadata": {}, "created_at": "…", "updated_at": "…",
  "name": "Szczepienie przeciw wściekliźnie", "comment": null,
  "completed": false, "hour": 14, "minute": 30, "petMedicines": [] }
Pole wspólne Znaczenie
record_type dyskryminator — po nim wybiera się sposób renderowania
entity_category dokładniejszy rodzaj, ten sam, po którym się filtruje
date data zdarzenia, nadpisana datą rekordu źródłowego
related_record identyfikator rekordu w module źródłowym
pet_id zwierzak

date jest istotne: wpis osi czasu ma własną datę utworzenia, ale w odpowiedzi zastępuje ją data zdarzenia z rekordu źródłowego. Zawsze więc pokazuje termin, a nie moment dodania.

Tego identyfikatora używa się, żeby przejść z osi czasu do szczegółów:

record_type related_record wskazuje Dokąd z nim iść
MedVisit wizytę w naszej sieci GET /med-visit/user-visit/{visitId}/{petId}
Prediagnosis prediagnozę GET /prediagnosis/results/{prediagnosisId}
CyclicTreatment przypomnienie o pielęgnacji GET /pets/cyclic-treatment-reminders/{reminderId}
ExternalAppointment wizytę zewnętrzną GET /pets/{petId}/external-appointments/{externalAppointmentId}
ExternalAppointmentCyclicTreatment zabieg przy wizycie wizytę pobiera się razem z zabiegami
PetMedicines grupę przypomnień o lekach (notificationGroupId) PUT /pets/{petId}/pet-medicines/reminder/{notificationGroupId}/completed

Przy pielęgnacji i lekach related_record nie jest identyfikatorem zabiegu ani leku — to identyfikator przypomnienia. To najczęstsza pomyłka w tym module.

Warianty wpisu

MedVisit

{ "record_type": "MedVisit", "is_closed": true, "name": "Zapalenie ucha zewnętrznego" }

name to nazwa rozpoznanej choroby w języku żądania, is_closed mówi, czy weterynarz zamknął wizytę.

Prediagnosis

{ "record_type": "Prediagnosis", "name": "Pilna konsultacja", "color": "#E5442F",
  "img": "https://…" }

name, color i img opisują triaż — wynik prediagnozy. Kolor i ikona są gotowe do wyświetlenia bez własnego mapowania.

CyclicTreatment — pielęgnacja

{ "record_type": "CyclicTreatment", "entity_category": "CARE",
  "name": "Obcinanie pazurów", "comment": "Tylko przednie łapy", "icon": "SCISSORS",
  "petCyclictreatmentId": "…", "petCyclictreatmentNotificationId": "…",
  "completed": false }

Dwa identyfikatory obok siebie i oba są potrzebne:

  • petCyclictreatmentId — zaplanowana czynność; nim się edytuje, oznacza wykonanie i usuwa (/pets/{petId}/cyclic-treatments/{treatmentId})
  • petCyclictreatmentNotificationId — to konkretne przypomnienie

Zwróć uwagę na pisownię: petCyclictreatmentId, małe t w „treatment". To część istniejącego kontraktu, nie zmieniamy jej.

name bierze nazwę z katalogu, a gdy czynność jest spoza katalogu — nazwę własną.

ExternalAppointment — wizyta zewnętrzna

Ten wariant ma dwie postacie, zależnie od entity_category:

Zwykła wizyta (entity_category: "ExternalAppointment"):

{ "name": "Kontrola po zabiegu", "comment": "Kontrola za 2 tygodnie",
  "completed": true, "hour": 14, "minute": 30 }

Wizyta niosąca zabieg (entity_category: VACCINATION, TREATMENT, DEWORMING, TICK_PREVENTION, FLEA_PREVENTION, CARE):

{ "name": "Szczepienie przeciw wściekliźnie", "comment": "…", "completed": false,
  "hour": 14, "minute": 30,
  "petMedicines": [ { "id": "…", "name": "Metacam" } ] }

Tu name to nazwa zabiegu, nie wizyty, comment to komentarz zabiegu (a gdy go brak — zalecenia z wizyty), a petMedicines wymienia aktywne leki podpięte pod wizytę. Pole petMedicines występuje tylko w tej postaci.

Stan wykonania czyta się z completed wizyty — to na niej model śledzi wykonanie.

ExternalAppointmentCyclicTreatment

{ "record_type": "ExternalAppointmentCyclicTreatment", "entity_category": "VACCINATION",
  "name": "Szczepienie przeciw wściekliźnie", "comment": null,
  "completed": false, "hour": null, "minute": null }

Osobny wpis dla zabiegu powstaje wyłącznie przy prawdziwej wizycie, nie przy wizycie-opakowaniu — dzięki temu zaplanowany zabieg nie dubluje się na osi czasu.

Uwaga: completed na tym wpisie jest zawsze false — nic go nie zapisuje. Wykonanie zabiegu czyta się z wpisu wizyty.

PetMedicines — przypomnienie o lekach

{ "record_type": "PetMedicines", "completed": false,
  "medicineNotifications": [
    { "id": "…", "name": "Metacam", "dose": "1 tabletka", "hour": 8, "minute": 0 } ] }

Jeden wpis grupuje wszystkie leki zwierzaka na dany dzień, a nie jeden lek. id w środku to identyfikator leku (petMedicineId), przydatny do edycji.

Trzy rzeczy warte uwagi:

  • completed dotyczy całej grupy i oznacza się je przez related_record (PUT /pets/{petId}/pet-medicines/reminder/{notificationGroupId}/completed)
  • leki dezaktywowane są pomijane, a lek usunięty ze słownika wraca jako "MedicineDeleted"
  • przypomnienia powstają raz na dobę; szczegóły w dokumentacji leków

Godziny w tym module

W przeciwieństwie do pozostałych modułów hour i minute na osi czasu są liczbami, nie tekstem — 14 i 30 zamiast "14:30". null oznacza brak ustawionej godziny. Formatowanie jest po stronie partnera.

Najczęstsze przyczyny błędów

Objaw Przyczyna
403 Zwierzak nie należy do użytkownika z x-user-id
400 przy filtrowaniu Nieznana wartość w categories
400 przy period Dozwolone są wyłącznie PAST i FUTURE
Pusta oś czasu mimo zdarzeń Domyślne FUTURE pokazuje tylko przyszłość — przeszłość wymaga period=PAST
Dzisiejszego zdarzenia nie ma w FUTURE Granicą jest bieżąca chwila, a wpisy bez godziny mają datę na północ — szukaj w PAST
Strona krótsza niż take Wpisy bez rekordu źródłowego są odrzucane; koniec listy to nextCursor: null
404 przy pobieraniu szczegółów Użyto related_record jako identyfikatora zabiegu lub leku — przy pielęgnacji i lekach to identyfikator przypomnienia
hour nie parsuje się jako tekst Na osi czasu godzina jest liczbą
Brak petMedicines we wpisie wizyty Pole występuje tylko przy wizycie niosącej zabieg

Przykładowa sekwencja

GET /partner/v1/timeline/{petId}?period=FUTURE&take=20        → nadchodzące
GET /partner/v1/timeline/{petId}?period=FUTURE&take=20&cursor=…

widok historii:
GET /partner/v1/timeline/{petId}?period=PAST&take=20

tylko szczepienia i badania:
GET /partner/v1/timeline/{petId}?period=PAST&categories=VACCINATION,TREATMENT