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:
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¶
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": "…" }