Przejdź do treści

Wizyty zewnętrzne — przebieg integracji

Ścieżki są względne wobec /partner/v1/pets. Uwierzytelnienie jak w pozostałych modułach: x-client-id, x-api-key, x-user-id.

Zakres tego modułu

Wizyta zewnętrzna to wizyta u weterynarza spoza platformy, wprowadzana przez właściciela zwierzaka. Może nieść załączniki, zabiegi i leki.

Ten moduł obsługuje też badania, szczepienia, odrobaczanie i profilaktykę przeciwpasożytniczą — planuje się je jako zabieg przy wizycie. Pielęgnacja (kąpiel, pazury, uszy) ma osobną ścieżkę, opisaną w dokumentacji pielęgnacji.

Dwa zastosowania wizyty

To najważniejsza rzecz do zrozumienia w tym module. Wizyta służy do dwóch różnych celów, rozróżnianych polem treatAsWrapper:

treatAsWrapper Znaczenie
false prawdziwa wizyta — odbyła się u weterynarza, ma nazwę, placówkę, zalecenia, załączniki
true opakowanie — wizyta istnieje wyłącznie po to, by nieść zaplanowany zabieg

Drugi wariant jest techniczny. Gdy użytkownik chce zaplanować szczepienie, nie odbywa się żadna wizyta — ale model przechowuje zabiegi wyłącznie przy wizytach, więc tworzy się pustą wizytę-opakowanie i podpina do niej zabieg.

W interfejsie warto opakowania traktować inaczej niż prawdziwe wizyty: pokazywać je jako zaplanowany zabieg, a nie jako odbytą wizytę.

Scenariusz A — zapis odbytej wizyty

POST /{petId}/external-appointments
{ "date": "2026-09-04",
  "treatAsWrapper": false,
  "name": "Kontrola po zabiegu",
  "clinic": "Przychodnia Na Hożej",
  "hour": "14:30",
  "recommendations": "Kontrola za 2 tygodnie",
  "files": ["private/health_record_book/…/wynik.pdf"] }

Wymagane są tylko date i treatAsWrapper. Reszta jest opcjonalna.

Załączniki

files to pełna lista ścieżek do zachowania:

  • ścieżka pominięta na liście → załącznik zostaje usunięty
  • pominięcie całego pola files → załączniki pozostają bez zmian

Pliki wgrywa się wcześniej ścieżką plików, z purpose: "health_record". Są prywatne, więc do wyświetlenia potrzebny jest podpisany adres z POST /files/download-url. Pojedynczy załącznik można też usunąć wprost:

DELETE /{petId}/external-appointments/{externalAppointmentId}/files/{fileId}

fileId to trzeci identyfikator w obiegu i nie jest tym, który zwraca potwierdzenie wgrania. Plik ma bowiem: path w magazynie, id rekordu pliku (POST /files/confirm) oraz id wiersza załącznika przy wizycie. Usuwanie przyjmuje wyłącznie ten trzeci, widoczny jako Files[].id w odpowiedzi GET .../external-appointments/{id}. Podanie identyfikatora z potwierdzenia kończy się 400 "Validation failed (uuid is expected)".

Scenariusz B — zaplanowanie badania lub szczepienia

Dwa kroki: opakowanie, potem zabieg.

1) GET  /{petId}/external-appointments/available-treatments
   → katalog badań, szczepień, odrobaczania i profilaktyki dla gatunku

2) POST /{petId}/external-appointments
   { "date": "2026-11-20", "treatAsWrapper": true }
   → { "appointment": { "id": "…" } }

3) POST /{petId}/external-appointments/{externalAppointmentId}/cyclic-treatments
   { "cyclicTreatmentId": "…", "date": "2026-11-20",
     "reminderInterval": "YEARLY", "comment": "…" }

cyclicTreatmentId pochodzi z katalogu i jest wymagany. lastTimeTreatmentDate jest tutaj opcjonalne — przy pierwszym szczepieniu po prostu się go nie podaje.

Powtórzenie zabiegu

Przy planowaniu kolejnego wystąpienia można w tym samym żądaniu zamknąć poprzednie:

POST /{petId}/external-appointments
{ "date": "2027-11-20", "treatAsWrapper": true,
  "pastExternalAppointmentId": "<id poprzedniego opakowania>" }

Poprzednia wizyta zostaje oznaczona jako wykonana.

Odczyt

GET /{petId}/external-appointments/{externalAppointmentId}

Zwraca wizytę wraz z zagnieżdżonymi PetMedicines, ExternalAppointmentCyclicTreatment i Files. Zabiegów i leków nie trzeba dowoływać osobno — przychodzą razem z wizytą, z nazwami w języku żądania.

Godzina wraca jako tekst

hour w odpowiedziach jest łańcuchem "HH:MM", złożonym z godziny i minuty, albo null, gdy czas nie jest ustawiony. Pole minute występuje obok i pozostaje liczbą. Przy wysyłaniu podaje się "14:30".

Edycja i usunięcie

PATCH  /{petId}/external-appointments/{externalAppointmentId}
DELETE /{petId}/external-appointments/{externalAppointmentId}

Edycja jest częściowa — wystarczy przesłać to, co się zmienia, także samo name albo samo files. date i treatAsWrapper są wymagane wyłącznie przy tworzeniu.

Jeden wyjątek: hour jest zawsze nadpisywane, więc pominięcie go czyści godzinę. Jeśli wizyta ma godzinę i ma ją zachować, trzeba ją odesłać.

Zabiegi przy wizycie

POST   /{petId}/external-appointments/{externalAppointmentId}/cyclic-treatments
PATCH  /{petId}/external-appointments/{externalAppointmentId}/cyclic-treatments/{eaCyclicTreatmentId}
DELETE /{petId}/external-appointments/{externalAppointmentId}/cyclic-treatments/{eaCyclicTreatmentId}

Zabieg zawsze należy do wizyty — nie istnieje samodzielnie. Usunięcie wizyty usuwa także jej zabiegi.

Identyfikator zabiegu przy wizycie

Edycja i usunięcie biorą eaCyclicTreatmentId — identyfikator wiersza zabiegu przy tej wizycie, czyli ExternalAppointmentCyclicTreatment[].id z odczytu wizyty.

Skrót ea to „external appointment": to identyfikator powiązania zabiegu z wizytą, a nie pozycji katalogowej. Nie jest to cyclicTreatmentId — ten ostatni wskazuje pozycję w katalogu i przekazuje się go wyłącznie przy tworzeniu zabiegu, w ciele żądania. Użycie katalogowego w ścieżce kończy się 404.

Ciało żądania przy zabiegu

Pole POST PATCH Uwagi
cyclicTreatmentId wymagane nieobecne przy edycji zabieg wskazuje ścieżka
date wymagane opcjonalne pominięte przy edycji zachowuje termin
lastTimeTreatmentDate opcjonalne wymagane wartość albo jawne null; pominięte zostałoby skasowane
hour, comment, reminderInterval opcjonalne opcjonalne

Oba wywołania zwracają utworzony lub zmieniony wiersz zabiegu, razem z jego id — tym samym, którego wymaga edycja i usunięcie. Nie trzeba więc dowoływać wizyty tylko po to, żeby poznać identyfikator.

Oś czasu

Zabieg zaplanowany przy wizycie pojawia się na osi czasu jako wpis typu ExternalAppointment, z polem entity_category ustawionym na rodzaj zabiegu (VACCINATION, TREATMENT, DEWORMING, TICK_PREVENTION, FLEA_PREVENTION).

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

Stan wykonania czyta się z pola completed wizyty. Pole completed na samym zabiegu jest zawsze false — model śledzi wykonanie na poziomie wizyty.

Najczęstsze przyczyny błędów

Objaw Przyczyna
403 przy dowolnej operacji Zwierzak nie należy do użytkownika z x-user-id
404 mimo poprawnego identyfikatora wizyty Wizyta należy do innego zwierzaka niż podany w ścieżce
404 przy edycji lub usunięciu zabiegu Użyto cyclicTreatmentId z katalogu zamiast eaCyclicTreatmentId z wizyty
400 „uuid is expected" przy usuwaniu załącznika Użyto id z potwierdzenia wgrania zamiast Files[].id z wizyty
Odrzucone utworzenie wizyty Brak date albo treatAsWrapper — oba są wymagane
Godzina zniknęła po edycji hour pominięte w PATCH; jest zawsze nadpisywane
Załącznik zniknął po edycji files wysłane bez jego ścieżki; to pełna lista do zachowania
hour nie parsuje się jako liczba W odpowiedziach to tekst "HH:MM"
W katalogu nie ma pielęgnacji Pielęgnacja ma własny katalog i własną ścieżkę planowania

Przykładowa sekwencja — zaplanowanie szczepienia

GET  /partner/v1/pets/{petId}/external-appointments/available-treatments
POST /partner/v1/pets/{petId}/external-appointments
     { "date": "2026-11-20", "treatAsWrapper": true }        → { appointment: { id } }
POST /partner/v1/pets/{petId}/external-appointments/{externalAppointmentId}/cyclic-treatments
     { "cyclicTreatmentId": "…", "date": "2026-11-20" }

później, po wykonaniu:
PATCH /partner/v1/pets/{petId}/external-appointments/{externalAppointmentId}
     { "date": "2026-11-20", "treatAsWrapper": true, "hour": "…" }