Przejdź do treści

Konwencje techniczne

Konwencje API są zbieżne z założeniami REST API – Założenia v1.0 (pharmind XF). Poniżej zastosowanie tych założeń w API.ERP — tak, jak jest wdrożone; elementy oznaczone „do doprecyzowania” nie mają jeszcze ustalonej postaci.


1. Założenia ogólne

  • Kontrakt jest anglojęzyczny. Ścieżki, nazwy pól, wartości kodowane, opisy (description) i komunikaty błędów są po angielsku.
  • Wyjątkiem są dane i nazwy czytelne w słownikach (display, np. active → „Aktywny") — te opisują treść dziedzinową i pozostają po polsku.
  • Ten przewodnik jest po polsku; język dokumentacji nie jest językiem kontraktu.

2. Adresy bazowe (Base URL)

Element Opis (do uzupełnienia)
Wzorzec URL Np. https://<środowisko>.<domena>/api — do doprecyzowania
Środowiska Produkcja, test, dev — do uzupełnienia
Uwagi Punkt wejścia API, ewentualne prefixy — do doprecyzowania

3. Nazewnictwo endpointów

3.1 Ogólne zasady

  • Nazwy zasobów: proste, czytelne, odzwierciedlające reprezentowane dane.
  • Rzeczowniki w liczbie mnogiej: /parties, /purchase-requisitions, /posting-instructions.
  • Liczba pojedyncza tylko dla zasobów jednoelementowych: /metadata.

3.2 Konwencje zapisu

  • Kebab-case w ścieżkach: /product-definitions, /purchase-orders, /inventory-documents.
  • Brak czasowników w endpointach — operacje reprezentują metody HTTP.
  • Operacje na kolekcji (pełna lista tras: Kontrakty API):
  • GET /v1/<resource> — wyszukiwanie; zasób wskazuje parametr identifier=system|value
  • POST /v1/<resource> — utworzenie; treść niesie identifier[].system (przestrzeń wymagana, value opcjonalne)
  • PATCH /v1/<resource>?identifier=system|value — aktualizacja
  • Brak tras z {id} oraz brak operacji PUT i DELETE.

3.3 Operacje niestandardowe

  • Prefiks $ na kolekcji: GET /v1/fixed-asset-documents/$document-content?identifier=…&format=…. Karta wdrożenia wymienia operację w rest[].resource[].operation[] z adresem definicji https://api-erp.kamsoft.pl/ns/OperationDefinition/<name> (karta wdrożenia).

3.4 Hierarchia zasobów

  • Brak zagnieżdżeń w ścieżkach — powiązania wyraża się filtrami: /v1/journal-entries?postingInstruction=…, /v1/party-roles?party=….

3.5 Parametry zapytań

  • camelCase: lastModified, issueDateFrom, issueDateTo, employeeId, productGroupId.
  • Wartości kodowane i identyfikatory jako para system|value (np. identifier, owner, type, status); atrybuty jako code|value.
  • Parametry jednoznaczne.

3.6 Bezpieczeństwo

  • Nie umieszczać wrażliwych danych w ścieżkach endpointów.

4. Wersjonowanie API

  • Wersja w ścieżce: /v1/parties, /v1/purchase-orders.
  • Numeracja wersji: liczby całkowite (1, 2, 3…).
  • Zasady zmian (breaking vs non-breaking, deprecation) — do uzupełnienia.

5. Autentykacja

  • Model: Do uzupełnienia: np. OAuth 2.0, API key — wybór i uzasadnienie.
  • Przepływ: Np. client credentials, resource owner — do doprecyzowania.
  • Nagłówek: Authorization: Bearer <token> (lub inny schemat po doprecyzowaniu).
  • Rejestracja aplikacji: Gdzie i w jakiej formie — do doprecyzowania.

6. Nagłówki HTTP

Nagłówek Wartość / uwagi
Authorization Bearer <token>
Content-Type application/json (request: POST/PATCH)
Accept application/json (response)
Własne nagłówki Prefiks ks-; małe litery, wyrazy oddzielone myślnikami (np. ks-report-execution-id w trybie raportowym). Spójnie w całym API.
Inne Idempotency key, request-id — do doprecyzowania

6.1 Zakres żądania: klient i instalacja

Wywołanie nie niesie identyfikacji klienta. Instancja API.ERP pracuje zawsze dla jednego klienta i to ona go wyznacza.

W instalacji klienta może pracować kilka systemów źródłowych. Odczyt ma trzy tory — rozstrzyga je para zawężeń profile i identifier:

Co podaje integrator w odczycie Kto odpowiada
parametr profile tylko pierwszy w kolejności system honorujący ten profil; pozostałe nie są odpytywane
parametr identifier=system\|value (przestrzeń OID) wyłącznie instalacja wskazana tą przestrzenią; gdy nie prowadzi tego zasobu albo profilu — 404
ani profile, ani identifier wszystkie instalacje rozumiejące ten zasób; odpowiedź jest złączeniem ich wyników

Zapis (POST, PATCH) rozstrzyga się inaczej: dziedzinę wyznacza profil (meta.profile albo profil rozpoznany po treści), a przestrzeń identyfikatora — gdy podana — wskazuje instalację przyjmującą zapis (musi należeć do miejsca prawdy profilu, w przeciwnym razie 404); bez przestrzeni zapis idzie do pierwszego systemu w kolejności.

Kolejność systemów jest parametrem wdrożenia od opiekuna integracji KAMSOFT i nie wynika z żadnego endpointu — nie niesie jej ani GET /v1/metadata, ani GET /v1/naming-systems.

Przestrzenie identyfikatorów w odpowiedzi należą do instalacji, która żądanie obsłużyła. Szerzej: Identyfikacja i parametry wdrożenia.


7. Metoda PATCH (aktualizacja)

  • Przestrzeń identyfikatora jest opcjonalna w POST (identifier[].system; value nadaje system prowadzący): podana wskazuje instalację, pominięta — rozstrzyga profil (rejestracja zasobu). W PATCH parametr identifier=system|value wskazuje zasób do zmiany, więc jest konieczny.
  • Jeden endpoint PATCH na zasób, na kolekcji: PATCH /v1/parties?identifier=system|value&owner=https://gov.pl/nip|<NIP>, PATCH /v1/fixed-asset-documents?identifier=…, PATCH /v1/document-references.
  • Cel wskazuje parametr identifier=system|value (przestrzeń wewnętrzna instalacji); dla DocumentReference cel wynika z identifier[] w treści.
  • Body: pełny zasób w postaci kanonicznej (ten sam model co w POST); nie tablica operacji.
  • Content-Type: application/json. Odpowiedź: 200 OK z zasobem po stronie systemu prowadzącego.
  • Zasoby z PATCH: Party, FixedAssetDocument, DocumentReference (zmiana statusu dokumentu magazynowego) — Kontrakty API.

8. Paginacja i filtrowanie

  • Mechanizm: count (liczba elementów strony, domyślnie 20) i offset (liczba pominiętych elementów, domyślnie 0): GET /v1/parties?count=50&offset=100.
  • Odpowiedź kolekcji: koperta { "items": [ … ], "nextToken": null }; nextToken jest zarezerwowany na kursor i obecnie zawsze null — kolejną stronę pobiera się zwiększając offset.
  • Brak wyników: 200 OK z items: [].
  • Filtrowanie: parametry zapytań w camelCase (p. 3.5); sortowanie nie jest parametryzowane.

8.1 Filtr podany jest stosowany albo odrzucany

  • Zbiór parametrów wyszukiwania zasobu w danej instalacji wymienia karta wdrożenia (rest[].resource[].searchParam[], karta). Każdy parametr z karty jest obsługiwany — nie ma parametrów przyjmowanych bez efektu.
  • Filtr kodowany (category, type, status i pokrewne) ma postać system|value. Wartość jest rozpoznawana po każdym słowniku, który karta deklaruje dla tego zasobu i parametru, a nie po jednym wybranym.
  • system spoza tych słowników kończy się 400 z nazwą parametru w detail. Filtr nigdy nie jest po cichu pomijany.
  • Kod nieznany w rozpoznanej przestrzeni to sytuacja danych, nie błąd żądania: 200 OK z items: [].
  • Gdy filtr został podany, odpowiedź zawiera wyłącznie zasoby, które go spełniają — niezależnie od tego, która instalacja żądanie obsłużyła.

Zasób może mieć dla jednego parametru więcej niż jeden słownik; obie przestrzenie są wtedy poprawne:

GET /v1/product-definitions?category=https%3A%2F%2Fapi-erp.kamsoft.pl%2Fvs%2Fwarehouse%2Fproduct-definition-category%7Cmedications
GET /v1/product-definitions?category=https%3A%2F%2Fapi-erp.kamsoft.pl%2Fvs%2Fretail%2Fproduct-definition-category%7Ccatalog

Trzecia przestrzeń w tym samym parametrze (np. słownik innego zasobu) kończy się 400, a nie pełną listą.


9. Obsługa błędów (Problem Details)

  • Błędy sygnalizujemy odpowiednimi statusami HTTP.
  • Format błędów: RFC 9457 Problem Details (application/problem+json).
  • Pola w odpowiedzi błędu:
  • status (numer HTTP)
  • typehttps://httpstatuses.com/{status}
  • title — stały tytuł per status: Invalid request (400), Resource not found (404), Request cannot be processed (422), Operation not implemented (501), Source system unavailable (503)
  • detail (szczegóły; dla błędów, których treść zostaje w logu — tekst odsyłający do traceId)
  • instance (ścieżka żądania)
  • traceId (identyfikator śladu do zgłoszenia problemu)
  • Zalecenie dla klientów: sprawdzać status HTTP i parsować body błędu; logować traceId do wsparcia.

10. Statusy HTTP

  • Sukces: 200 OK (odczyt oraz zapis POST/PATCH — odpowiedź niesie zasób), 202 Accepted (POST /v1/reports).
  • Błędy klienta: 400 Bad Request (zły format parametru, wartość filtra kodowanego z przestrzeni spoza słowników zadeklarowanych dla zasobu, zapis bez rozpoznanego profilu, nieznany profile), 401 Unauthorized, 403 Forbidden (brak roli API.<Zasób>.Read/.Write), 404 Not Found (przestrzeń identyfikatora wskazuje instalację nieobsługującą profilu, nieznany raport), 422 Unprocessable Entity (profil nieobsługiwany w instalacji, zasób tylko do odczytu, odrzucenie przez system prowadzący).
  • Serwer: 500 Internal Server Error, 501 Not Implemented, 503 Service Unavailable (system prowadzący nie odpowiada).

10.1 Operacje asynchroniczne

  • 202 Accepted stosujemy dla operacji przyjętych do przetwarzania, których wynik nie jest jeszcze gotowy w momencie odpowiedzi.
  • W odpowiedzi warto zwracać identyfikator zlecenia oraz link do statusu lub artefaktu, np. id, status, statusUrl, resultUrl.
  • Dla zleceń raportów i eksportów klient przekazuje publiczny klucz RSA, a serwer odsyła jednorazowy dataKey po jego zaszyfrowaniu.
  • Artefakty raportów są szyfrowane hybrydowo PGP; dla csv używamy AES-256, dla parquet stosujemy flow PME.
  • Opcjonalna kompresja zstd może zostać wykonana przed szyfrowaniem, jeśli dany typ raportu to wspiera.

11. Modele Request i Response

  • Format: JSON. Request: Content-Type: application/json; response: application/json.
  • Nazwy pól w JSON: camelCase (spójnie w całym API).
  • POST/PATCH: body — zasób kanoniczny z resourceType, meta.profile — listą adresów kanonicznych profili, np. ["https://api-erp.kamsoft.pl/ns/StructureDefinition/Contractor"] (albo cechami rozpoznającymi profil), identifier[].system (przestrzeń wymagana; value przy rejestracji opcjonalne — nadaje je system prowadzący) i polami wymaganymi przez profil (sekcja 7).
  • Nie umieszczać w body danych wrażliwych, które powinny być w nagłówkach lub chronione inaczej.
  • Definicje pól, typów i wymagalności — w schematach profili; niniejsze konwencje określają kształt (camelCase, koperta kolekcji, Problem Details).
  • Wyjątek praktyczny dla zleceń raportów: publiczny klucz RSA klienta jest przekazywany w request, aby serwer mógł zwrócić zaszyfrowany dataKey w odpowiedzi 202 Accepted.

11a. DomainResource — Model bazowy dla wszystkich zasobów biznesowych (wzorowanie na FHIR)

Wszystkie zasoby biznesowe w API.ERP (DocumentReference, Invoice, InventoryDocument, Party, Employment, PostingInstruction itp.) dziedziczą z abstrakcyjnego modelu DomainResource (wzorowany na FHIR DomainResource). Zapewnia to spójność, rozszerzalność i compliance ze standardem Kamsoft.FAIR (Fast Adaptive Interoperable Resources): zasoby są Findable (identyfikatory), Accessible (CRUD endpoints), Interoperable (Reference + słowniki kodowe), Reusable (DomainResource inheritance) we wszystkich domenach.

11a.1 Struktura DomainResource

Każdy zasób biznesowy zawiera:

Pole Typ Opis Wymagane
id string Unikatowy identyfikator zasobu w API (zazwyczaj nadawany przez serwer) Tak (na GET)
meta object Metadane zasobu: lastModified (datetime), version, profile (lista adresów kanonicznych profili), itd. Opcjonalnie
identifier Identifier[] Tablica identyfikatorów z różnych systemów (wewnętrzny id, numer z ERP, itp.) — patrz sekcja 12.1 Opcjonalnie
status CodeableConcept Status zasobu (np. active, inactive, draft, finalized) — semantyka zależy od typu zasobu Opcjonalnie
type CodeableConcept Typ zasobu (np. rodzaj dokumentu, rodzaj Party, rodzaj produktu) — semantyka zależy od modelu Opcjonalnie

11a.2 Dziedziczenie i specjalizacja

  • Konkretne zasoby (DocumentReference, Invoice, Employment itp.) rozszerzają DomainResource, dodając pola specyficzne dla danej domeny.
  • Przykład: Invoice extends DomainResource, dodając pola specyficzne: issueDate, saleDate, dueDate, seller, buyer, totalNet, totalVat, totalGross, lines[], ksefAcquisitionDate.
  • Przykład: InventoryDocument extends DomainResource, dodając: movementType, fromLocation, toLocation, product[], quantity[].
  • W JSON Schema: wykorzystujemy allOf z referencją do DomainResource.schema.json + pola dodatkowe.

Przykład w OpenAPI/JSON Schema:

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "title": "Invoice",
  "allOf": [
    { "$ref": "#/components/schemas/DomainResource" },
    {
      "type": "object",
      "properties": {
        "issueDate": { "type": "string", "format": "date" },
        "seller": { "$ref": "#/components/schemas/Reference" },
        "buyer": { "$ref": "#/components/schemas/Reference" },
        "totalNet": { "$ref": "#/components/schemas/Money" },
        "totalVat": { "$ref": "#/components/schemas/Money" },
        "totalGross": { "$ref": "#/components/schemas/Money" },
        "lines": { 
          "type": "array", 
          "items": { "$ref": "#/components/schemas/InvoicePosition" } 
        }
      }
    }
  ]
}

11a.3 Korzyści z DomainResource

  • Spójność: Wszystkie zasoby mają wspólne pola rdzeniowe (id, meta, identifier, attribute, status, type).
  • Rozszerzalność: Rozszerzanie modelu realizujemy przez attribute[] oraz profile zasobów.
  • FAIR compliance:
  • Findable: identifier[] wspiera wiele systemów identyfikacji
  • Accessible: zasoby dostępne przez jednolite endpointy kolekcji (GET, a dla wybranych POST/PATCH)
  • Interoperable: Reference[] wspiera linki pomiędzy zasobami
  • Reusable: struktura spójna dla wszystkich domen
  • FHIR kompatybilność: Ułatwia interoperacyjność z systemami zdrowotnymi (jeśli potrzebna).

11a.4 Reference (Odniesienia między zasobami)

Pola typu Reference (np. seller, buyer, partOf) zawierają:

Pole Typ Opis
identifier Identifier Podstawa logiczna referencji — identyfikator biznesowy celu (system + value); zgodnie z Reference
type string (opcjonalnie) Typ zasobu docelowego (np. Party) — wraz z identifier tworzy referencję logiczną
reference string (opcjonalnie) Ścieżka zasobu (np. Party/123 lub pełny URL) — opcjonalny dodatek techniczny, nie zastępuje identifier
display string (opcjonalnie) Tekst czytelny dla człowieka (cached copy)

Konwencja identifier-first: znaczenie biznesowe referencji niesie para type + identifier; rozstrzyganie odbywa się przez wyszukiwanie GET /v1/<kolekcja>?identifier=system|value (sekcja 12.4). Pełna definicja i reguły rozstrzygania: Reference.

Patrz sekcja 12 — Reference jest też dostępnym typem w Identifier.assigner i innych polach.


12. Rozszerzalna identyfikacja: Identifier i Coding (wzorowane na FHIR)

Wszystkie modele (zasoby) w API mogą — a w wielu przypadkach powinny — zawierać rozszerzalną identyfikację inspirowaną FHIR: Identifier (identyfikatory z różnych systemów) oraz Coding (kody z systemów terminologicznych). Umożliwia to wielozakresową identyfikację i klasyfikację bez sztywnego schematu na poziomie API.

12.1 Identifier (identyfikator)

Pozwala opisać jeden lub wiele identyfikatorów zasobu (np. wewnętrzny ID, numer dokumentu z ERP, identyfikator z systemu zewnętrznego). Pola w camelCase:

Pole Typ Opis
use string (opcjonalnie) Kontekst użycia: usual, official, temp, secondary — do doprecyzowania wartości
type CodeableConcept (opcjonalnie) Cel identyfikatora, gdy przestrzeń nie jest znana — wyłącznie kody FHIR identifier-type (v2-0203, np. TAX); rodzaj identyfikatora niesie system
system string (URI) Przestrzeń nazw identyfikatora — niesie jego rodzaj: rejestr publiczny (np. https://gov.pl/nip) albo przestrzeń wewnętrzna instalacji urn:oid:1.2.616.1.113769.4.<instalacja>.<klucz> z NamingSystem (GET /v1/naming-systems)
value string Wartość identyfikatora
period obiekt (opcjonalnie) Okres ważności: start, end (np. ISO 8601)
assigner Reference (opcjonalnie) Kto lub jaki system przypisał identyfikator

Zasób może mieć tablicę identifier[] (np. identifier: [{ system, value }, ...]). Minimalny użyteczny zestaw: system + value.

12.2 Coding (kod z systemu terminologicznego)

Pozwala przypisać zasobowi kody z zewnętrznych lub wewnętrznych słowników (np. typ dokumentu, status, jednostka miary). Pola w camelCase:

Pole Typ Opis
system string (URI) System kodów (np. https://api-erp.kamsoft.pl/vs/warehouse/document-type)
version string (opcjonalnie) Wersja systemu kodów
code string Symbol kodu
display string (opcjonalnie) Tekst czytelny dla człowieka
userSelected boolean (opcjonalnie) Czy użytkownik wybrał ten kod z listy

Zasób może mieć pola typu Coding (pojedynczy kod) lub CodeableConcept: obiekt z tablicą coding i opcjonalnym text (tekst swobodny). Przykład: type: { coding: [{ system: "https://api-erp.kamsoft.pl/vs/finance/document-type", code: "invoice", display: "Invoice" }], text: "Faktura" }.

12.3 Zastosowanie w modelach

  • Identifier: np. PurchaseOrder.identifier[], Party.identifier[] — wiele identyfikatorów (wewnętrzny id instalacji, NIP, REGON, numer w systemie księgowym).
  • Coding / CodeableConcept: status, type, category, unit — wszędzie, gdzie potrzebna jest klasyfikacja z możliwością rozszerzenia o nowe systemy kodów.

Szczegóły per zasób (które pola są wymagane, dopuszczalne kody) — schematy profili i słowniki.

12.4 Wyszukiwanie po identyfikatorze biznesowym (query parameter ?identifier=)

Identifier to parametr filtrujący, przekazywany jako jedna para system|wartość.

Kolekcyjne GET endpoints z parametrem identifier (np. GET /v1/parties, GET /v1/invoices, GET /v1/product-definitions; pełna lista w Kontraktach API) wspierają wyszukiwanie po identyfikatorze biznesowym.

Format

?identifier=system|value
  • system — URI przestrzeni nazw identyfikatora (np. https://gov.pl/nip, urn:oid:1.2.616.1.113769.4.<instalacja>.65)
  • | (pipe) — separator między systemem a wartością
  • Przecinek w wartości parametru jest niedozwolony (400): jedno wywołanie = jeden identyfikator. Kilka identyfikatorów sprawdza się kolejnymi wywołaniami.

Przykłady

  1. Wyszukanie Party (kontrahenta) po NIP (Numerze Identyfikacji Podatkowej)

    GET /v1/parties?identifier=https://gov.pl/nip|9542685559
    
    Zwraca zasoby Party z identyfikatorem w systemie https://gov.pl/nip o wartości 9542685559.

  2. Wyszukanie Party po identyfikatorze wewnętrznym instalacji (system OID)

    GET /v1/parties?identifier=urn:oid:2.999.2|123
    
    Część przed | to system (tu: przestrzeń wewnętrzna zapisana jako OID — w przykładach placeholder z łuku 2.999, zob. konwencje przykładów), część po | to wartość identyfikatora w tym systemie. Przestrzeń wewnętrzna kieruje zapytanie do jednej instalacji; przestrzeń spoza miejsca prawdy zasobu kończy się 404 (deployment.md §2).

  3. Wyszukanie Invoice (faktury) z filtrem statusu

    GET /v1/invoices?category=https://api-erp.kamsoft.pl/vs/warehouse/invoice-category|invoice&identifier=https://ksef.podatki.gov.pl|ABC123&status=https://api-erp.kamsoft.pl/vs/warehouse/invoice-status|<kod>
    
    Szuka Invoice o podanym numerze KSeF I statusie (AND między filtrami).

Logika wyszukiwania

  • Inne filtry (?status=, ?type=, ?category= itp.) łączą się z identifier: logika AND — zwracane zasoby spełniają zarówno warunek identyfikatora, jak i inne filtry. Każdy podany filtr jest stosowany albo odrzucany statusem 400 (sekcja 8.1).
  • Brak wyniku: Gdy identyfikator nie pasuje do żadnego zasobu, API zwraca 200 OK z pustą listą (items: []), nie 404 — zasób jest wtedy nieodnaleziony (sytuacja danych, nie błąd składni żądania); zob. Reference — rozstrzyganie referencji.

Właściciel (owner)

Firmę (podmiot prowadzący dane) wskazuje parametr owner=system|value, zwykle NIP: owner=https://gov.pl/nip|1234567890. Jest wymagany przy POST /v1/parties i PATCH /v1/parties oraz przyjmowany jako filtr w większości odczytów. Parametru company nie ma.

Implementacja

  • Parametr identifier ma postać system|value; separator | w URL koduje się jako %7C.
  • Backend porównuje system i value z tablicą resource.identifier[] po stronie systemu prowadzącego.

13. Idempotency

  • Cel: Uniknięcie duplikatów przy retry (np. tworzenie zamówienia, faktury).
  • Mechanizm: Nagłówek idempotency key / pole w body / zewnętrzny identyfikator — do doprecyzowania.
  • Zasady: Retry z tym samym kluczem = ten sam efekt — do uzupełnienia dla wybranych operacji.
  • Idempotency key można reprezentować także jako Identifier (sekcja 12) z odpowiednim system. POST /v1/posting-instructions działa jako add-or-update po identyfikatorze dokumentu — ponowny POST z tym samym identyfikatorem nadpisuje bufor.

14. Dokumenty pionowe i terminologia

Dokumenty pionowe (profile wymiany dokumentów) są opisane w verticals/ — rejestr: verticals/README.md, indeks: verticals-index.md.

14.1 Typy pakietów pionowych

Typ Przykład Artefakt główny
rest-only eod-bos (historyczne API obiegu dokumentów) dokumentacja początkowa (poza tym przewodnikiem)
hybrid mp (skierowanie medycyny pracy) Profil CDA + schemat JSON; REST — TBD
cda (przyszłe) Profil CDA

Historyczne OpenAPI obiegu dokumentów — dokumentacja początkowa; wpis w rejestrze verticals bez przenoszenia plików. W openapi/ tego przewodnika są wyłącznie kontrakty odbiorcy: API-ERP-Notification-Receiver.yaml i API-ERP-Report-Receiver.yaml.

14.2 ValueSet.url (FHIR)

Kanoniczny adres value setów w rozwiązaniach ERP KAMSOFT:

https://api-erp.kamsoft.pl/vs/{slug}

  • {slug} — kebab-case (np. oh-exam-type, esm-document-type).
  • Prefiks value setów profilu pionowego w slug — skrót domeny po angielsku (np. oh- dla occupational health / medycyny pracy; pion mp).
  • ValueSet.url jest stabilny; warianty wydania przez ValueSet.version, nie przez zmianę URL.
  • OID w CDA (codeSystem, root) pozostają w profilu; powiązanie OID ↔ URL — w ValueSet.identifier lub NamingSystem.

Przykład mapowania dla profilu mp: verticals/mp/profile/profil-cda.html.

14.3 Wiele powierzchni API, jeden kontrakt

Przy dokumentach wymienianych między ERP a MED (np. skierowanie MP):

  • API.ERP — emisja (źródło prawdy, podpis, eksport CDA).
  • API.MED — intake kliniczny (import, walidacja, rejestracja wizyty).

Wspólny model kontraktu (JSON schema / CDA / value sety) — jeden pakiet w verticals/{slug}/, bez duplikowania definicji.

14.4 OpenAPI per pion

Nowe specyfikacje REST dla dokumentów pionowych — w verticals/{slug}/contracts/ (osobny plik). Nie mieszać z kontraktami odbiorcy w openapi/ bez decyzji architektonicznej.