Potwierdzenia w Codenica API

Pracę z Potwierdzeniami przez Codenica API zaczynasz od utworzenia klucza w ustawieniach Codenica. Jeżeli klucz nie został jeszcze utworzony, otwórz w nowej karcie Codenica API - wprowadzenie. Znajdziesz tam wspólne zasady tworzenia kluczy, przechowywania sekretów i uwierzytelniania.

Potwierdzenie jest rekordem procesu, w którym konkretny klient ma podjąć decyzję. Integracja może przygotować dane, przypisać klienta, dołączyć dokumenty, zasoby, notatki i pliki, a następnie przekazać decyzję do wykonania przez właściwy kontekst Client.

Techniczna nazwa pojedynczego rekordu to confirmation, a nazwa zbioru endpointów to confirmations. Zwykła edycja zmienia opis rekordu. Wyniku decyzji nie zapisuj bezpośrednio w polu status - do zatwierdzenia lub odrzucenia służy dedykowany endpoint /decision.

W przykładach zastosowano identyfikator PUBLIC-API-CONFIRMATION-20260908-0001. Zastąp go własnym identyfikatorem pochodzącym z systemu integrującego, a wartości w nawiasach klamrowych danymi z własnej bazy.


Potwierdzenia - adres API i wybór instalacji

Wszystkie trasy dotyczące Potwierdzeń zaczynają się od:

{BASE_URL}/api/v1/confirmations

BASE_URL oznacza adres serwera Codenica bez końcówki /api/v1. W wersji Cloud użyj domeny lub subdomeny przypisanej do konkretnej firmy:

export BASE_URL="https://{domena-firmy}"

W domyślnej instalacji On-Premise program Codenica Discovery rejestruje lokalnie adres:

export BASE_URL="http://codenica.local:5150"

Jeżeli administrator udostępnił instalację pod firmową domeną, przez HTTPS, reverse proxy albo na innym porcie, użyj dokładnego adresu przekazanego dla tej instalacji:

export BASE_URL="https://{rzeczywisty-adres-instalacji}"

Adres localhost stosuj tylko wtedy, gdy integracja i API działają na tym samym komputerze. Przykład http://localhost:5050 dotyczy lokalnego środowiska deweloperskiego, a nie standardowego adresu On-Premise. Nie przesyłaj tenantId w body ani w query stringu. Właściwa baza danych jest wybierana na podstawie hosta żądania.


Potwierdzenia - zakresy klucza API

Klucz używany do pracy z Potwierdzeniami powinien mieć tylko zakresy potrzebne przez konkretną integrację. Pełny zestaw zakresów modułu wygląda tak:

confirmations:read
confirmations:write
confirmations:delete
confirmations:schema
confirmations:stats
confirmations:relationships:read
confirmations:relationships:write
confirmations:users:read
confirmations:files:read
confirmations:files:write
confirmations:technical:read
confirmations:technical:write
confirmations:pin:write
confirmations:decision:write
users:read

Do odczytu list i rekordów wybierz confirmations:read. Tworzenie i zwykła edycja wymagają confirmations:write, a usuwanie confirmations:delete. Zakresy relacji, plików, statystyk, pól technicznych, przypinania i decyzji dodaj tylko wtedy, gdy integracja będzie wykonywać te operacje.

Jeśli integracja wybiera cele relacji z innych zbiorów, potrzebuje także odpowiednich zakresów odczytu, na przykład assets:read, documents:read, clients:read albo notes:read. Sam zakres klucza nie zastępuje uprawnień użytkownika.


Potwierdzenia - uwierzytelnianie żądań

Każde żądanie Codenica API uwierzytelniaj dwoma nagłówkami:

X-Codenica-Client-Id: {CLIENT_ID}
X-Codenica-Client-Secret: {CLIENT_SECRET}
Accept: application/json

Przykład pierwszego żądania:

export PUBLIC_API_CLIENT_ID="cna_example"
export PUBLIC_API_CLIENT_SECRET="cns_example"

curl --request GET --url "$BASE_URL/api/v1/context" \
  --header "Accept: application/json" \
  --header "X-Codenica-Client-Id: $PUBLIC_API_CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $PUBLIC_API_CLIENT_SECRET"

Zewnętrzna integracja nie potrzebuje administratorowego Bearer JWT ani ciasteczek z panelu Codenica. Client Secret przechowuj po stronie serwera w magazynie sekretów. Nie umieszczaj go w kodzie przeglądarkowym, repozytorium, adresie URL, historii poleceń ani logach. Poza lokalnym developmentem korzystaj z HTTPS.

W odpowiedziach zapisuj meta.requestId. Identyfikator pomaga odnaleźć żądanie w logach, ale nie zastępuje UUID Potwierdzenia i nie jest sekretem.


Potwierdzenia - sprawdzenie kontekstu połączenia

Przed pierwszym zapisem pobierz kontekst. Sprawdzisz w ten sposób, czy adres prowadzi do właściwej bazy danych, a klucz ma wymagane zakresy i limity:

curl --fail-with-body --silent --show-error \
  --header "X-Codenica-Client-Id: $PUBLIC_API_CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $PUBLIC_API_CLIENT_SECRET" \
  "$BASE_URL/api/v1/context"

Weryfikuj między innymi data.apiVersion, data.contractVersion, dane data.tenant, wartość data.caller.authentication równą api_key, rolę i clientId wywołującego, obecność confirmations w data.capabilities.resources, zakresy oraz limity.

{
  "data": {
    "caller": {
      "role": "Administrator",
      "authentication": "api_key",
      "scopes": [
        "confirmations:read",
        "confirmations:write",
        "confirmations:decision:write"
      ]
    },
    "capabilities": {
      "supportsETag": true,
      "supportsIdempotency": true,
      "supportsRelationships": true,
      "supportsFiles": true
    }
  },
  "meta": { "requestId": "{REQUEST_ID}" }
}

Jeżeli kontekst wskazuje inną firmę albo nie zawiera potrzebnego zakresu, popraw adres lub klucz. Nie próbuj kierować żądania do innej bazy przez przesłanie obcego identyfikatora.


Potwierdzenia - schema i cele relacji

Schema jest źródłem informacji o aktualnych polach, ich typach, zapisywalności i dopuszczalnych celach relacji:

curl --fail-with-body --silent --show-error \
  --header "X-Codenica-Client-Id: $PUBLIC_API_CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $PUBLIC_API_CLIENT_SECRET" \
  "$BASE_URL/api/v1/confirmations/schema"

W odpowiedzi znajdziesz między innymi data.itemType, data.fields i data.relationshipTargets. Dla tego modułu itemType ma stałą wartość confirmation. Dla każdego pola sprawdź readable, writable, required, technical, unique i maxLength.

{
  "data": {
    "itemType": "confirmation",
    "fields": [
      { "name": "customId", "type": "string", "writable": true },
      { "name": "status", "type": "string", "writable": false },
      { "name": "pin", "type": "integer", "writable": false }
    ],
    "relationshipTargets": [
      { "targetDataSet": "assets" },
      { "targetDataSet": "clients", "targetItemType": "client" },
      { "targetDataSet": "documents", "targetItemType": "document" },
      { "targetDataSet": "notes", "targetItemType": "note" }
    ]
  }
}

Dla assets schema nie narzuca jednego typu obiektu. Jeżeli konkretny cel ma itemType=computer, w żądaniu relacji użyj computer, a nie automatycznie asset. Nie buduj mapowania wyłącznie na podstawie przykładu - przed uruchomieniem integracji pobierz aktualne schema.


Potwierdzenia - pola biznesowe i pola procesu

Najważniejsze pola, które możesz przekazywać w attributes, to:

Pole
Typ
Zastosowanie
customId
string
Identyfikator po stronie systemu integrującego
location, department
string
Miejsce i dział związany ze sprawą
tag, link
string
Oznaczenia i odnośnik do źródła wniosku
info, description
string
Informacja pomocnicza i opis tego, co ma zostać potwierdzone
type, category
string
Typ i kategoria procesu
status, dateConfirmed, dateDeclined, dateEnd, remark, pin
tylko odczyt
Wynik decyzji, komentarz decyzji i przypięcie

Podstawowe maksymalne długości to między innymi: customId 500, location 300, department 300, tag 2000, link 2000, info 10000, type 300, category 300 i description 10000 znaków. Aktualna odpowiedź schema dla danej bazy ma pierwszeństwo.

Pól status, dateConfirmed, dateDeclined, dateEnd, remark i pin nie zapisuj w zwykłym PATCH. Nie wysyłaj też pól audytowych:

creator
updater
dateCreated
dateUpdated
importId
importSource
dateImported

Potwierdzenia - dostępne endpointy

Najważniejsze trasy modułu confirmations to:

GET    /api/v1/confirmations
POST   /api/v1/confirmations
GET    /api/v1/confirmations/{CONFIRMATION_ID}
PATCH  /api/v1/confirmations/{CONFIRMATION_ID}
DELETE /api/v1/confirmations/{CONFIRMATION_ID}
GET    /api/v1/confirmations/schema
GET    /api/v1/confirmations/stats
GET    /api/v1/confirmations/values
POST   /api/v1/confirmations:batch
GET    /api/v1/confirmations/{CONFIRMATION_ID}/relationships
POST   /api/v1/confirmations/{CONFIRMATION_ID}/relationships
POST   /api/v1/confirmations/{CONFIRMATION_ID}/relationships:batch
DELETE /api/v1/confirmations/{CONFIRMATION_ID}/relationships/{DATASET}/{TARGET_ID}
GET    /api/v1/confirmations/{CONFIRMATION_ID}/user-relationships
GET    /api/v1/confirmations/{CONFIRMATION_ID}/files
POST   /api/v1/confirmations/{CONFIRMATION_ID}/files
POST   /api/v1/confirmations/{CONFIRMATION_ID}/files/{FILE_ID}
DELETE /api/v1/confirmations/{CONFIRMATION_ID}/files/{FILE_ID}
GET    /api/v1/confirmations/{CONFIRMATION_ID}/files/{FILE_ID}/content
POST   /api/v1/confirmations/{CONFIRMATION_ID}/pin
POST   /api/v1/confirmations/{CONFIRMATION_ID}/decision

Odczyty wymagają zakresów read, a poszczególne mutacje dodatkowych zakresów zgodnych z ich przeznaczeniem. Każde żądanie zmieniające dane wymaga Idempotency-Key, a operacja na istniejącym rekordzie dodatkowo aktualnego If-Match.


Potwierdzenia - listowanie i paginacja

Listę Potwierdzeń pobieraj stronami. Możesz podać stały itemType=confirmation, chociaż API i tak używa tego typu dla całego modułu:

curl --fail-with-body --silent --show-error \
  --header "X-Codenica-Client-Id: $PUBLIC_API_CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $PUBLIC_API_CLIENT_SECRET" \
  "$BASE_URL/api/v1/confirmations?itemType=confirmation&page=1&pageSize=25"

Odpowiedź ma kolekcję data.items oraz informacje o stronie:

{
  "data": {
    "items": [
      {
        "id": "{CONFIRMATION_ID}",
        "itemType": "confirmation",
        "attributes": {
          "customId": "ERP-CONFIRMATION-2026-0042",
          "category": "Zakupy",
          "status": "Pending"
        },
        "meta": { "etag": "{ETAG}" }
      }
    ],
    "page": 1,
    "pageSize": 25,
    "totalItems": 1,
    "totalPages": 1,
    "hasNextPage": false
  },
  "meta": { "requestId": "{REQUEST_ID}" }
}

Przechodź do następnej strony na podstawie hasNextPage. Maksymalny rozmiar strony odczytaj z data.capabilities.limits.maxPageSize, zamiast zakładać go na stałe.


Potwierdzenia - wyszukiwanie i filtry

Parametr search służy do szukania tekstu w polach opisowych. Do synchronizacji najlepiej stosować stabilny customId albo UUID:

curl --silent --show-error -G \
  --data-urlencode "search=zakup" \
  --data-urlencode "page=1" \
  --data-urlencode "pageSize=20" \
  --header "X-Codenica-Client-Id: $PUBLIC_API_CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $PUBLIC_API_CLIENT_SECRET" \
  "$BASE_URL/api/v1/confirmations"

Filtry pól możesz łączyć w jednym żądaniu:

curl --silent --show-error -G \
  --data-urlencode "status=Pending" \
  --data-urlencode "category=Zakupy" \
  --data-urlencode "customId=ERP-CONFIRMATION-2026-0042" \
  --header "X-Codenica-Client-Id: $PUBLIC_API_CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $PUBLIC_API_CLIENT_SECRET" \
  "$BASE_URL/api/v1/confirmations"

Dla bardziej precyzyjnego wyszukiwania użyj filtra strukturalnego w postaci field:operator:value:

category:eq:Zakupy
status:ne:Declined
description:contains:komputer
customId:startswith:ERP-CONFIRMATION-
link:notempty:

Przydatne operatory to między innymi eq, ne, contains, startswith, endswith i notempty. Wartości zawierające spacje, dwukropki lub znaki specjalne koduj w adresie URL.


Potwierdzenia - wybór pól i dołączanie danych

Parametr fields ogranicza atrybuty zwracane w odpowiedzi. Przy synchronizacji listy możesz pobierać tylko potrzebne pola:

curl --fail-with-body --silent --show-error \
  --header "X-Codenica-Client-Id: $PUBLIC_API_CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $PUBLIC_API_CLIENT_SECRET" \
  "$BASE_URL/api/v1/confirmations?fields=id,customId,status,category&page=1&pageSize=20"

Jeżeli potrzebujesz od razu plików, relacji i użytkownika tworzącego rekord, użyj include:

curl --fail-with-body --silent --show-error \
  --header "X-Codenica-Client-Id: $PUBLIC_API_CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $PUBLIC_API_CLIENT_SECRET" \
  "$BASE_URL/api/v1/confirmations/{CONFIRMATION_ID}?fields=%2A&include=files%2Crelationships%2Cusers"

Dołączenie plików wymaga confirmations:files:read, relacji confirmations:relationships:read, a użytkowników confirmations:users:read. Ograniczaj fields i include, jeżeli integracja nie potrzebuje pełnego rekordu.


Potwierdzenia - statystyki i wartości pól

Endpoint stats pomaga zbudować podsumowanie widocznych Potwierdzeń, a values dostarcza wartości do list filtrów:

curl --fail-with-body --silent --show-error \
  --header "X-Codenica-Client-Id: $PUBLIC_API_CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $PUBLIC_API_CLIENT_SECRET" \
  "$BASE_URL/api/v1/confirmations/stats?field=category&limit=20"
curl --fail-with-body --silent --show-error \
  --header "X-Codenica-Client-Id: $PUBLIC_API_CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $PUBLIC_API_CLIENT_SECRET" \
  "$BASE_URL/api/v1/confirmations/values?field=category&search=zak&limit=20"

Oba endpointy są odczytowe i wymagają confirmations:stats. Wyniki obejmują tylko rekordy widoczne dla użytkownika przypisanego do klucza i nie wymagają ETag-u. Limit parametru limit sprawdź w aktualnym kontrakcie API.


Potwierdzenia - utworzenie rekordu i przypisanie klienta

Potwierdzenie przeznaczone do decyzji powinno wskazywać biznesowego Clienta. To obiekt klienta z bazy danych, a nie identyfikator technicznego AppUsera używanego do logowania:

{
  "targetId": "{CLIENT_ID}",
  "targetDataSet": "clients",
  "targetItemType": "client"
}

Minimalny payload zawiera stały itemType, opisowe attributes i relację do Clienta:

{
  "itemType": "confirmation",
  "attributes": {
    "customId": "ERP-CONFIRMATION-2026-0042",
    "category": "Zakupy",
    "description": "Potwierdzenie zakupu stacji roboczej."
  },
  "relationships": [
    {
      "targetId": "{CLIENT_ID}",
      "targetDataSet": "clients",
      "targetItemType": "client"
    }
  ]
}

Przypisanie można przekazać już podczas tworzenia. Nie dodawaj do tej relacji pola relationshipType.


Potwierdzenia - kompletny przykład utworzenia

W większej integracji warto zapisać body do pliku, aby móc bezpiecznie powtórzyć identyczne żądanie po chwilowym błędzie połączenia:

{
  "itemType": "confirmation",
  "attributes": {
    "customId": "PUBLIC-API-CONFIRMATION-20260908-0001",
    "location": "Warszawa",
    "department": "IT",
    "tag": "integracja,zakupy,akceptacja",
    "link": "https://erp.example.com/requests/0001",
    "info": "Wniosek przekazany z systemu zakupowego.",
    "type": "Zakup sprzętu",
    "category": "Zakupy",
    "description": "Potwierdzenie zakupu nowej stacji roboczej dla działu IT."
  },
  "relationships": [
    {
      "targetId": "{CLIENT_ID}",
      "targetDataSet": "clients",
      "targetItemType": "client"
    }
  ]
}
curl --fail-with-body --silent --show-error \
  --request POST \
  --header "X-Codenica-Client-Id: $PUBLIC_API_CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $PUBLIC_API_CLIENT_SECRET" \
  --header "Content-Type: application/json" \
  --header "Accept: application/json" \
  --header "Idempotency-Key: erp-confirmation-create-0001" \
  --data-binary @confirmation-create.json \
  "$BASE_URL/api/v1/confirmations"

Sukces tworzenia to 201 Created. Odpowiedź zawiera UUID, itemType, atrybuty, metadane z datami, ETag i requestId. Zapisz UUID i ETag, ponieważ będą potrzebne w następnych krokach.


Potwierdzenia - Idempotency-Key i bezpieczne ponowienie

Każde żądanie zmieniające dane przez klucz API musi mieć własny Idempotency-Key. Jeżeli połączenie przerwie się po wysłaniu żądania, ponów dokładnie ten sam request z tym samym kluczem:

curl --fail-with-body --silent --show-error \
  --request POST \
  --header "X-Codenica-Client-Id: $PUBLIC_API_CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $PUBLIC_API_CLIENT_SECRET" \
  --header "Content-Type: application/json" \
  --header "Idempotency-Key: erp-confirmation-create-0001" \
  --data-binary @confirmation-create.json \
  "$BASE_URL/api/v1/confirmations"

Powtórzenie identycznego żądania z tym samym kluczem nie powinno utworzyć drugiego Potwierdzenia. Nie używaj jednego klucza do różnych body ani do różnych operacji. Klucz idempotencji opisuje jedną operację biznesową.

Utworzenie:  Idempotency-Key = erp-confirmation-create-0001
Ponowienie:  Idempotency-Key = erp-confirmation-create-0001
Nowa edycja: Idempotency-Key = erp-confirmation-update-0001

Dla PATCH, pinowania, decyzji, relacji, plików i usuwania używaj osobnych kluczy. Przy kolejnych zmianach zawsze zapisuj ETag zwrócony przez ostatnią udaną operację.


Potwierdzenia - odczyt pojedynczego rekordu

Po utworzeniu lub otrzymaniu UUID możesz pobrać pełne Potwierdzenie:

curl --fail-with-body --silent --show-error \
  --header "X-Codenica-Client-Id: $PUBLIC_API_CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $PUBLIC_API_CLIENT_SECRET" \
  "$BASE_URL/api/v1/confirmations/{CONFIRMATION_ID}?fields=%2A"

W odpowiedzi zachowaj ETag z nagłówka HTTP ETag albo z data.meta.etag. Do diagnostyki zachowaj także meta.requestId.

curl --fail-with-body --silent --show-error \
  --header "X-Codenica-Client-Id: $PUBLIC_API_CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $PUBLIC_API_CLIENT_SECRET" \
  "$BASE_URL/api/v1/confirmations/{CONFIRMATION_ID}?fields=%2A&include=files%2Crelationships%2Cusers"

Wersja z include pozwala w jednym odczycie zobaczyć przypisanego Clienta, relacje obiektowe, requestera i pliki. Jeżeli pobierasz tylko dane do synchronizacji, ogranicz odpowiedź parametrem fields.


Potwierdzenia - edycja z aktualnym ETagiem

Bezpieczna edycja wygląda zawsze tak: pobierz rekord, odczytaj aktualny ETag, przygotuj mały PATCH, wyślij If-Match i nowy Idempotency-Key, a następnie zapisz nowy ETag:

{
  "attributes": {
    "info": "Dane uzupełnione po weryfikacji w systemie zakupowym.",
    "category": "Zakupy IT",
    "description": "Potwierdzenie zaktualizowane przez integrację."
  }
}
curl --fail-with-body --silent --show-error \
  --request PATCH \
  --header "X-Codenica-Client-Id: $PUBLIC_API_CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $PUBLIC_API_CLIENT_SECRET" \
  --header "Content-Type: application/json" \
  --header "If-Match: {CURRENT_ETAG}" \
  --header "Idempotency-Key: erp-confirmation-update-0001" \
  --data-binary @confirmation-update.json \
  "$BASE_URL/api/v1/confirmations/{CONFIRMATION_ID}"

Sukces to 200 OK i nowy ETag. W zwykłym PATCH możesz zmieniać pola opisowe, ale nie zapisuj w ten sposób status, dat decyzji, dateEnd, remark ani pin.


Potwierdzenia - ochrona przed równoczesną edycją

Jeżeli nie prześlesz nagłówka If-Match, API odrzuci zmianę:

HTTP 428 Precondition Required
code: if_match_required

Jeżeli prześlesz ETag starszy niż aktualna wersja rekordu, otrzymasz:

HTTP 412 Precondition Failed
code: if_match_failed

Po 412 pobierz rekord ponownie, porównaj jego wartości ze zmianą, którą chcesz wykonać, i dopiero wtedy wyślij nowy PATCH. Nie ponawiaj w pętli tego samego żądania ze starym ETagiem.

Nie próbuj omijać kontroli wersji przez wpisywanie pól procesu w body:

{
  "attributes": {
    "status": "Confirmed",
    "dateConfirmed": "2026-09-08T10:30:00Z"
  }
}

Decyzję wykonuje dedykowany endpoint /decision. Dzięki temu system może sprawdzić właściwego Clienta, aktualny stan procesu i współbieżność.


Potwierdzenia - przypinanie i odpinanie

Przypięcie jest osobną operacją i nie należy do zwykłego PATCH. Dozwolone wartości to null albo liczba od 0 do 3:

curl --fail-with-body --silent --show-error \
  --request POST \
  --header "X-Codenica-Client-Id: $PUBLIC_API_CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $PUBLIC_API_CLIENT_SECRET" \
  --header "Content-Type: application/json" \
  --header "If-Match: {CURRENT_ETAG}" \
  --header "Idempotency-Key: erp-confirmation-pin-0001" \
  --data '{"pin":3}' \
  "$BASE_URL/api/v1/confirmations/{CONFIRMATION_ID}/pin"

Aby odpiąć rekord, wyślij null:

curl --fail-with-body --silent --show-error \
  --request POST \
  --header "X-Codenica-Client-Id: $PUBLIC_API_CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $PUBLIC_API_CLIENT_SECRET" \
  --header "Content-Type: application/json" \
  --header "If-Match: {PINNED_ETAG}" \
  --header "Idempotency-Key: erp-confirmation-unpin-0001" \
  --data '{"pin":null}' \
  "$BASE_URL/api/v1/confirmations/{CONFIRMATION_ID}/pin"

Obie operacje wymagają confirmations:pin:write. Po każdym działaniu odczytaj nowy ETag oraz sprawdź wartość pola pin.


Potwierdzenia - decyzja klienta

Decyzja jest czynnością biznesową, a nie zwykłą edycją rekordu. Przed jej wykonaniem Potwierdzenie musi być przypisane do Clienta, a żądanie musi pochodzić z klucza reprezentującego tego właściwego Clienta i mieć zakres confirmations:decision:write. API sprawdza także aktualny ETag.

Zatwierdzenie wykonaj przez payload:

{
  "confirmed": true,
  "remark": "Potwierdzam realizację wniosku."
}
curl --fail-with-body --silent --show-error \
  --request POST \
  --header "X-Codenica-Client-Id: $PUBLIC_API_DECISION_CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $PUBLIC_API_DECISION_CLIENT_SECRET" \
  --header "Content-Type: application/json" \
  --header "If-Match: {DECISION_ETAG}" \
  --header "Idempotency-Key: erp-confirmation-decision-0001" \
  --data '{"confirmed":true,"remark":"Potwierdzam realizację wniosku."}' \
  "$BASE_URL/api/v1/confirmations/{CONFIRMATION_ID}/decision"

Odrzucenie używa tej samej trasy i wartości false:

curl --fail-with-body --silent --show-error \
  --request POST \
  --header "X-Codenica-Client-Id: $PUBLIC_API_DECISION_CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $PUBLIC_API_DECISION_CLIENT_SECRET" \
  --header "Content-Type: application/json" \
  --header "If-Match: {DECISION_ETAG}" \
  --header "Idempotency-Key: erp-confirmation-decision-0002" \
  --data '{"confirmed":false,"remark":"Odrzucam realizację wniosku."}' \
  "$BASE_URL/api/v1/confirmations/{CONFIRMATION_ID}/decision"

Po pozytywnej decyzji status przyjmuje wartość Confirmed, a system zapisuje dateConfirmed, dateEnd i komentarz. Po decyzji negatywnej status to Declined, a system zapisuje dateDeclined, dateEnd i komentarz. Nie ustawiaj tych pól ręcznie.


Potwierdzenia - Client i requester

Relacja do Clienta wskazuje klienta biznesowego, który ma podjąć decyzję. Nie zastępuje jej techniczny identyfikator AppUsera. Przypisanie odczytasz razem z relacjami obiektowymi albo przez pojedynczy rekord z include=relationships.

API udostępnia również osobną, tylko do odczytu kolekcję użytkowników. Zawiera automatycznego requestera, czyli użytkownika, który utworzył Potwierdzenie:

curl --fail-with-body --silent --show-error \
  --header "X-Codenica-Client-Id: $PUBLIC_API_CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $PUBLIC_API_CLIENT_SECRET" \
  "$BASE_URL/api/v1/confirmations/{CONFIRMATION_ID}/user-relationships?relationshipType=requester&page=1&pageSize=20"
{
  "targetId": "{REQUESTER_USER_ID}",
  "targetDataSet": "users",
  "relationshipType": "requester",
  "displayName": "{REQUESTER_NAME}",
  "email": "{REQUESTER_EMAIL}",
  "role": "{REQUESTER_ROLE}"
}

Requester jest ustalany przez system. Nie ustawiaj tej relacji w attributes i nie próbuj zmieniać jej przez endpoint relacji obiektowych. Odczyt wymaga confirmations:users:read.


Potwierdzenia - dozwolone relacje z obiektami

Aktualny katalog celów relacji Potwierdzeń obejmuje cztery grupy:

Zbiór
itemType
Znaczenie
assets
dynamiczny, np. computer
powiązany zasób
clients
client
klient podejmujący decyzję
documents
document lub typ zwrócony przez cel
dokument związany ze sprawą
notes
note
notatka dotycząca decyzji

Każdy cel musi istnieć, być widoczny dla użytkownika przypisanego do klucza i zgadzać się z listą relationshipTargets zwróconą przez schema. Potwierdzenia nie mają w tym katalogu relacji z dowolnymi innymi zbiorami.


Potwierdzenia - format relacji zwykłej i przypisania Clienta

Relacja do zasobu, dokumentu albo notatki ma pole relationshipType. Przykład relacji do dokumentu:

{
  "targetId": "{DOCUMENT_ID}",
  "targetDataSet": "documents",
  "targetItemType": "invoice",
  "relationshipType": "related"
}

Przypisanie Clienta jest wyjątkiem. Ma targetDataSet=clients i targetItemType=client, ale nie ma relationshipType:

{
  "targetId": "{CLIENT_ID}",
  "targetDataSet": "clients",
  "targetItemType": "client"
}

W przypadku zasobów odczytaj rzeczywisty typ obiektu, a następnie prześlij go dokładnie w targetItemType:

assets    - targetItemType: computer
 documents - targetItemType: invoice
 notes     - targetItemType: note

Powyższe wartości są przykładami. Właściwy typ może być inny w Twojej bazie.


Potwierdzenia - dodawanie, odczyt i usuwanie relacji

Dodanie pojedynczej relacji odbywa się przez POST z obiektem relacji bez dodatkowego opakowania:

curl --fail-with-body --silent --show-error \
  --request POST \
  --header "X-Codenica-Client-Id: $PUBLIC_API_CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $PUBLIC_API_CLIENT_SECRET" \
  --header "Content-Type: application/json" \
  --header "If-Match: {CURRENT_ETAG}" \
  --header "Idempotency-Key: erp-confirmation-relation-add-0001" \
  --data '{"targetId":"{DOCUMENT_ID}","targetDataSet":"documents","targetItemType":"invoice","relationshipType":"related"}' \
  "$BASE_URL/api/v1/confirmations/{CONFIRMATION_ID}/relationships"

Relacje odczytasz jako kolekcję:

curl --fail-with-body --silent --show-error \
  --header "X-Codenica-Client-Id: $PUBLIC_API_CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $PUBLIC_API_CLIENT_SECRET" \
  "$BASE_URL/api/v1/confirmations/{CONFIRMATION_ID}/relationships?targetDataSet=documents&relationshipType=related&page=1&pageSize=50"

Usunięcie relacji wymaga aktualnego ETag-u Potwierdzenia. W ścieżce podaj zbiór i UUID celu, a typ relacji przekaż w query:

curl --fail-with-body --silent --show-error \
  --request DELETE \
  --header "X-Codenica-Client-Id: $PUBLIC_API_CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $PUBLIC_API_CLIENT_SECRET" \
  --header "If-Match: {CURRENT_ETAG}" \
  --header "Idempotency-Key: erp-confirmation-relation-delete-0001" \
  "$BASE_URL/api/v1/confirmations/{CONFIRMATION_ID}/relationships/documents/{DOCUMENT_ID}?relationshipType=related"

Dodanie i usunięcie zwraca nową wersję rekordu albo data=true. Po każdej udanej zmianie pobierz nowy ETag.


Potwierdzenia - grupowa zmiana relacji

Jeśli chcesz dodać lub usunąć kilka relacji jednocześnie, użyj relationships:batch. W jednym body możesz przekazać tablice add i remove:

{
  "add": [
    {
      "targetId": "{ASSET_ID}",
      "targetDataSet": "assets",
      "targetItemType": "computer",
      "relationshipType": "related"
    }
  ],
  "remove": [
    {
      "targetId": "{NOTE_ID}",
      "targetDataSet": "notes",
      "targetItemType": "note",
      "relationshipType": "related"
    }
  ]
}
curl --fail-with-body --silent --show-error \
  --request POST \
  --header "X-Codenica-Client-Id: $PUBLIC_API_CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $PUBLIC_API_CLIENT_SECRET" \
  --header "Content-Type: application/json" \
  --header "If-Match: {CURRENT_ETAG}" \
  --header "Idempotency-Key: erp-confirmation-relationships-batch-0001" \
  --data-binary @confirmation-relationships-batch.json \
  "$BASE_URL/api/v1/confirmations/{CONFIRMATION_ID}/relationships:batch"

Odpowiedź zawiera liczniki added, removed i skipped. Batch relacji ma limit odczytywany z kontekstu, wymaga aktualnego ETag-u i zmienia wersję Potwierdzenia. Dla przypisania Clienta zastosuj format bez relationshipType.


Potwierdzenia - lista i upload plików

Najpierw możesz pobrać listę plików przypisanych do Potwierdzenia:

curl --fail-with-body --silent --show-error \
  --header "X-Codenica-Client-Id: $PUBLIC_API_CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $PUBLIC_API_CLIENT_SECRET" \
  "$BASE_URL/api/v1/confirmations/{CONFIRMATION_ID}/files?page=1&pageSize=50"

Element listy zawiera między innymi id, fileName, contentType, size, relationshipType, isMain i downloadUrl. Nowy plik dodaj jako multipart/form-data:

curl --fail-with-body --silent --show-error \
  --request POST \
  --header "X-Codenica-Client-Id: $PUBLIC_API_CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $PUBLIC_API_CLIENT_SECRET" \
  --header "If-Match: {CURRENT_ETAG}" \
  --header "Idempotency-Key: erp-confirmation-file-upload-0001" \
  --form "[email protected];type=application/pdf" \
  "$BASE_URL/api/v1/confirmations/{CONFIRMATION_ID}/files?relationshipType=decision-form"
{
  "data": {
    "id": "{FILE_ID}",
    "fileName": "formularz-decyzji.pdf",
    "contentType": "application/pdf",
    "size": 48231,
    "relationshipType": "decision-form",
    "isMain": false,
    "downloadUrl": "/api/v1/confirmations/{CONFIRMATION_ID}/files/{FILE_ID}/content"
  }
}

Upload wymaga confirmations:files:write, aktualnego ETag-u i nowego klucza idempotencji. Limit rozmiaru odczytaj z data.capabilities.limits.maxUploadBytes. Dla Potwierdzeń API nie udostępnia operacji wyboru pliku głównego - nie buduj integracji oczekującej endpointu /main.


Potwierdzenia - pobieranie, podpinanie i usuwanie plików

Treść pliku pobierz przez endpoint content i zapisz w trybie binarnym:

curl --fail-with-body --silent --show-error \
  --output formularz-decyzji-pobrany.pdf \
  --header "X-Codenica-Client-Id: $PUBLIC_API_CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $PUBLIC_API_CLIENT_SECRET" \
  "$BASE_URL/api/v1/confirmations/{CONFIRMATION_ID}/files/{FILE_ID}/content"

Jeżeli plik jest już zapisany w systemie, możesz podpiąć go do drugiego Potwierdzenia bez ponownego przesyłania treści:

curl --fail-with-body --silent --show-error \
  --request POST \
  --header "X-Codenica-Client-Id: $PUBLIC_API_CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $PUBLIC_API_CLIENT_SECRET" \
  --header "If-Match: {SECOND_CONFIRMATION_ETAG}" \
  --header "Idempotency-Key: erp-confirmation-file-attach-0001" \
  "$BASE_URL/api/v1/confirmations/{SECOND_CONFIRMATION_ID}/files/{FILE_ID}?relationshipType=reference"

Odłączenie pliku od konkretnego Potwierdzenia i usunięcie jego ostatniej relacji korzystają z tej samej trasy DELETE:

curl --fail-with-body --silent --show-error \
  --request DELETE \
  --header "X-Codenica-Client-Id: $PUBLIC_API_CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $PUBLIC_API_CLIENT_SECRET" \
  --header "If-Match: {CONFIRMATION_ETAG}" \
  --header "Idempotency-Key: erp-confirmation-file-delete-0001" \
  "$BASE_URL/api/v1/confirmations/{CONFIRMATION_ID}/files/{FILE_ID}"

Attach tworzy relację do istniejącego pliku. Jeżeli plik jest nadal przypisany do źródłowego Potwierdzenia, odłączenie go od drugiego rekordu nie może usuwać źródłowej relacji. Przed usunięciem ostatniej relacji sprawdź listę plików i upewnij się, że usuwasz właściwy element.


Potwierdzenia - operacje batch

Endpoint /api/v1/confirmations:batch pozwala połączyć tworzenie, edycję i usuwanie rekordów. Format używa tablicy items oraz osobnych obiektów create i update:

{
  "items": [
    {
      "operation": "create",
      "create": {
        "itemType": "confirmation",
        "attributes": {
          "customId": "ERP-BATCH-CONFIRMATION-A",
          "category": "Dostępy",
          "description": "Pierwsze Potwierdzenie utworzone zbiorczo."
        },
        "relationships": [
          {
            "targetId": "{CLIENT_ID}",
            "targetDataSet": "clients",
            "targetItemType": "client"
          }
        ]
      }
    },
    {
      "operation": "update",
      "id": "{EXISTING_ID}",
      "ifMatch": "{EXISTING_ETAG}",
      "update": {
        "attributes": {
          "description": "Opis zaktualizowany w operacji batch."
        }
      }
    },
    {
      "operation": "delete",
      "id": "{RECORD_TO_DELETE_ID}",
      "ifMatch": "{RECORD_TO_DELETE_ETAG}"
    }
  ]
}
curl --fail-with-body --silent --show-error \
  --request POST \
  --header "X-Codenica-Client-Id: $PUBLIC_API_CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $PUBLIC_API_CLIENT_SECRET" \
  --header "Content-Type: application/json" \
  --header "Idempotency-Key: erp-confirmations-batch-0001" \
  --data-binary @confirmations-batch.json \
  "$BASE_URL/api/v1/confirmations:batch"
{
  "data": {
    "items": [
      {
        "index": 0,
        "operation": "create",
        "status": 201,
        "id": "{CREATED_ID}",
        "data": { "meta": { "etag": "{CREATED_ETAG}" } }
      }
    ],
    "succeeded": 1,
    "failed": 0
  }
}

Każda pozycja aktualizacji i usunięcia potrzebuje własnego aktualnego ifMatch. Batch nie jest transakcją all-or-nothing. Przy częściowym wyniku API może zwrócić 207 Multi-Status, dlatego analizuj każdą pozycję osobno i nie ponawiaj operacji, które już zakończyły się sukcesem.


Potwierdzenia - usunięcie rekordu

Przed usunięciem pobierz rekord ponownie, sprawdź UUID i aktualny ETag, a następnie wyślij żądanie z osobnym kluczem idempotencji:

curl --fail-with-body --silent --show-error \
  --request DELETE \
  --header "X-Codenica-Client-Id: $PUBLIC_API_CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $PUBLIC_API_CLIENT_SECRET" \
  --header "If-Match: {CURRENT_ETAG}" \
  --header "Idempotency-Key: erp-confirmation-delete-0001" \
  "$BASE_URL/api/v1/confirmations/{CONFIRMATION_ID}"

Poprawna odpowiedź zwraca 200 OK oraz data=true. Po usunięciu sprawdź, czy UUID nie jest już dostępny:

curl --fail-with-body --silent --show-error \
  --header "X-Codenica-Client-Id: $PUBLIC_API_CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $PUBLIC_API_CLIENT_SECRET" \
  "$BASE_URL/api/v1/confirmations/{CONFIRMATION_ID}"

Oczekiwany wynik to 404 Not Found z kodem confirmation_not_found. Usunięcie Potwierdzenia nie oznacza automatycznego usunięcia powiązanych dokumentów, zasobów ani notatek.


Potwierdzenia - błędy, limity i bezpieczna kolejność pracy

Błędy mają format Problem Details. W logach zapisuj status, code i requestId, ale nigdy Client Secret ani pełne nagłówki:

HTTP
Kod
Reakcja
400
validation_failed
Popraw body, parametr albo wartość pola.
401
authentication_required lub authentication_failed
Sprawdź adres oraz oba nagłówki.
403
confirmation_client_required
Decyzję musi wykonać właściwy Client przypisany do Potwierdzenia.
404
confirmation_not_found
Rekord nie istnieje albo nie jest widoczny.
409
confirmation_unique_constraint lub confirmation_concurrency_conflict
Odczytaj rekord ponownie, sprawdź ETag albo usuń duplikat.
412 / 428
if_match_failed, if_match_required
Pobierz aktualny ETag i wykonaj kontrolowane ponowienie.
422
confirmation_decision_rejected, confirmation_pin_rejected
Sprawdź stan procesu, klucz Clienta i reguły operacji.
429
rate_limit_exceeded
Zastosuj opóźnienie rosnące i odczytaj Retry-After.

Odczytuj X-RateLimit-Limit i X-RateLimit-Remaining. Cache'uj schema i wartości pól, ogranicz równoległość, a przy 429 stosuj backoff.

Bezpieczna kolejność pracy to: context, schema, wybór Clienta, lista lub odczyt, utworzenie z Idempotency-Key, zapisanie UUID i ETagu, relacje lub pliki, edycja z If-Match, pinowanie, decyzja przez /decision, odczyt weryfikacyjny i dopiero na końcu usunięcie. Ten sam układ możesz odwzorować w n8n, przekazując UUID, ETag i klucze idempotencji między kolejnymi krokami.