Zapotrzebowania w Codenica API
Pracę z Zapotrzebowaniami przez Codenica API zaczynasz od utworzenia klucza w ustawieniach Codenica. Jeśli klucz nie został jeszcze utworzony, otwórz w nowej karcie Codenica API - wprowadzenie. Znajdziesz tam wspólne zasady tworzenia klucza, przechowywania sekretu i uwierzytelniania.
Techniczna nazwa zbioru w API to requesteditems, a typ pojedynczego obiektu to requesteditem. Zapotrzebowanie służy do zapisania potrzeby zakupu, dostarczenia, przygotowania lub wykonania określonej pozycji. Oprócz opisu może zawierać termin, ilość, cenę, koszt, wartość, podatek, budżet, priorytet i status.
Przykłady wykorzystują prefix PUBLIC-API-REQUESTEDITEM-20260906053922. W swojej integracji zastąp go własnym identyfikatorem, a adresy, UUID i wartości pól dopasuj do danych w swojej bazie.
Zapotrzebowania - adres API i wybór instalacji
Wszystkie trasy dotyczące Zapotrzebowań zaczynają się od:
{BASE_URL}/api/v1/requesteditemsBASE_URL oznacza adres serwera Codenica bez końcówki /api/v1. W wersji Cloud użyj publicznej domeny przypisanej do właściwej firmy:
export BASE_URL="https://twoja-firma.codenica.com"W domyślnej instalacji On-Premise adres lokalnie rejestrowany przez program Codenica Discovery to:
export BASE_URL="http://codenica.local:5150"Jeżeli administrator udostępnił instalację pod firmową domeną, przez reverse proxy, z HTTPS albo na innym porcie, użyj dokładnego adresu przekazanego dla tej instalacji:
export BASE_URL="https://api.twoja-firma.example"Nie używaj localhost, jeśli program integrujący działa na innym komputerze niż API. Właściwa baza danych jest wybierana na podstawie adresu, z którym łączy się integracja. Nie przekazuj tenantId w body, query stringu ani dodatkowym nagłówku.
Zapotrzebowania - zakresy klucza API
Klucz używany do pracy z Zapotrzebowaniami powinien mieć tylko zakresy potrzebne przez konkretną integrację. Pełny zestaw zakresów modułu wygląda tak:
requesteditems:read
requesteditems:write
requesteditems:delete
requesteditems:schema
requesteditems:stats
requesteditems:relationships:read
requesteditems:relationships:write
requesteditems:users:read
requesteditems:files:read
requesteditems:files:write
requesteditems:technical:read
requesteditems:technical:write
requesteditems:pin:writeDo samego odczytu list i rekordów wybierz requesteditems:read, a do sprawdzania katalogu pól także requesteditems:schema. Tworzenie i edycja wymagają requesteditems:write, usuwanie wymaga requesteditems:delete. Zakresy relacji, plików, statystyk, requestera i pinowania dodaj dopiero wtedy, gdy integracja będzie korzystać z tych operacji.
Jeśli integracja wyszukuje cele relacji, klucz musi mieć także odpowiednie zakresy odczytu, na przykład assets:read, clients:read, vendors:read, documents:read, tickets:read, changes:read, problems:read, releases:read, notes:read, approvals:read lub worktasks:read. Zakres klucza nie zastępuje uprawnień użytkownika.
Zapotrzebowania - uwierzytelnianie
Każde żądanie Codenica API uwierzytelniaj dwoma nagłówkami:
export CLIENT_ID="cna_twoj_client_id"
export CLIENT_SECRET="cns_twoj_client_secret"
curl --request GET --url "$BASE_URL/api/v1/requesteditems?page=1&pageSize=25" \
--header "Accept: application/json" \
--header "X-Codenica-Client-Id: $CLIENT_ID" \
--header "X-Codenica-Client-Secret: $CLIENT_SECRET"Zewnętrzna integracja nie potrzebuje JWT administratora ani ciasteczek z panelu Codenica. Sekret przechowuj w magazynie sekretów po stronie serwera. Nie umieszczaj go w kodzie dostarczanym do przeglądarki, repozytorium, adresie URL, historii poleceń ani logach. Poza lokalnymi testami korzystaj z HTTPS.
W odpowiedziach zapisuj meta.requestId. Ten identyfikator pomaga znaleźć konkretne żądanie w logach, ale nie zastępuje UUID Zapotrzebowania i nie jest sekretem.
Zapotrzebowania - 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 --request GET --url "$BASE_URL/api/v1/context" \
--header "Accept: application/json" \
--header "X-Codenica-Client-Id: $CLIENT_ID" \
--header "X-Codenica-Client-Secret: $CLIENT_SECRET"W odpowiedzi zweryfikuj data.apiVersion, data.contractVersion, dane data.tenant, wartość data.caller.authentication równą api_key, obecność requesteditems w data.capabilities.resources, zakresy klucza i limity żądań.
Jeżeli kontekst wskazuje inną firmę albo nie zawiera potrzebnego zakresu, popraw adres lub utwórz klucz z właściwymi uprawnieniami. Nie próbuj kierować żądania do innej bazy przez przesłanie obcego tenantId.
Zapotrzebowania - schema i cele relacji
Schema jest źródłem informacji o aktualnych polach, ich typach, zapisywalności i dopuszczalnych celach relacji:
curl --request GET --url "$BASE_URL/api/v1/requesteditems/schema" \
--header "Accept: application/json" \
--header "X-Codenica-Client-Id: $CLIENT_ID" \
--header "X-Codenica-Client-Secret: $CLIENT_SECRET"W odpowiedzi znajdziesz między innymi data.itemType, data.fields i data.relationshipTargets. Dla tego modułu itemType ma wartość requesteditem. Dla każdego pola sprawdź readable, writable, required, technical, unique i maxLength.
Przykładowy fragment schematu:
{
"data": {
"itemType": "requesteditem",
"fields": [
{ "name": "title", "type": "string", "writable": true },
{ "name": "dateDue", "type": "dateTime", "writable": true },
{ "name": "quantity", "type": "integer", "writable": true },
{ "name": "value", "type": "number", "writable": true },
{ "name": "pin", "type": "integer", "writable": false }
],
"relationshipTargets": [
{ "targetDataSet": "assets", "targetItemType": "asset" },
{ "targetDataSet": "documents", "targetItemType": "document" },
{ "targetDataSet": "worktasks", "targetItemType": "worktask" }
]
}
}Nie buduj mapowania wyłącznie na podstawie przykładu. Przed uruchomieniem integracji pobierz schema dla właściwej bazy i używaj tylko zwróconych pól oraz celów.
Zapotrzebowania - pola biznesowe i systemowe
Najważniejsze pola Zapotrzebowania to:
customIddateDue, dateEndlocation, departmenttag, linktitlestatus, priority, category, budget, currencytax, quantitycost, price, valuedescriptionid, itemType, creator, updater, dateCreated, dateUpdated, importId, importSource i dateImported są ustalane przez system albo przeznaczone do odczytu technicznego. Nie wysyłaj ich w attributes.
appUserRequesterId
clientRequesterId
catalogId
catalogItemId
creator
updater
dateCreated
dateUpdated
importId
importSource
dateImportedZapotrzebowania - dostępne endpointy
Najważniejsze trasy modułu requesteditems to:
GET /api/v1/requesteditems
POST /api/v1/requesteditems
GET /api/v1/requesteditems/{REQUESTED_ITEM_ID}
PATCH /api/v1/requesteditems/{REQUESTED_ITEM_ID}
DELETE /api/v1/requesteditems/{REQUESTED_ITEM_ID}
GET /api/v1/requesteditems/schema
GET /api/v1/requesteditems/stats
GET /api/v1/requesteditems/values
POST /api/v1/requesteditems:batch
GET /api/v1/requesteditems/{REQUESTED_ITEM_ID}/relationships
POST /api/v1/requesteditems/{REQUESTED_ITEM_ID}/relationships
POST /api/v1/requesteditems/{REQUESTED_ITEM_ID}/relationships:batch
DELETE /api/v1/requesteditems/{REQUESTED_ITEM_ID}/relationships/{DATASET}/{TARGET_ID}
GET /api/v1/requesteditems/{REQUESTED_ITEM_ID}/user-relationships
GET /api/v1/requesteditems/{REQUESTED_ITEM_ID}/files
POST /api/v1/requesteditems/{REQUESTED_ITEM_ID}/files
POST /api/v1/requesteditems/{REQUESTED_ITEM_ID}/files/{FILE_ID}
DELETE /api/v1/requesteditems/{REQUESTED_ITEM_ID}/files/{FILE_ID}
GET /api/v1/requesteditems/{REQUESTED_ITEM_ID}/files/{FILE_ID}/content
POST /api/v1/requesteditems/{REQUESTED_ITEM_ID}/pinOdczyty wymagają zakresów read, a poszczególne mutacje dodatkowych zakresów zgodnych z tabelą uprawnień. Każde żądanie zmieniające dane wymaga również Idempotency-Key.
Zapotrzebowania - listowanie i paginacja
Listę Zapotrzebowań pobieraj stronami. Przykład:
curl --request GET --url "$BASE_URL/api/v1/requesteditems?itemType=requesteditem&page=1&pageSize=25" \
--header "Accept: application/json" \
--header "X-Codenica-Client-Id: $CLIENT_ID" \
--header "X-Codenica-Client-Secret: $CLIENT_SECRET"Odpowiedź ma kolekcję data.items oraz informacje o stronie:
{
"data": {
"items": [
{
"id": "requested-item-uuid",
"itemType": "requesteditem",
"attributes": {
"customId": "ERP-REQ-2026-0042",
"title": "Trzy monitory do nowego stanowiska",
"status": "Open",
"quantity": 3,
"value": 3136.5
},
"meta": {
"etag": "\"etag-value\""
}
}
],
"page": 1,
"pageSize": 25,
"totalItems": 1,
"totalPages": 1,
"hasNextPage": false
},
"meta": {
"requestId": "request-id"
}
}Przechodź do następnej strony na podstawie hasNextPage. Nie zakładaj, że ostatnia strona zawsze zawiera mniej elementów niż wybrany pageSize. Maksymalny rozmiar strony sprawdź w data.capabilities.limits albo w aktualnym kontrakcie.
Zapotrzebowania - wyszukiwanie i filtry
Do wyszukiwania tekstowego użyj parametru search. Do synchronizacji lepiej stosować stabilny customId, UUID albo jawny filtr:
curl --silent --show-error -G \
--data-urlencode "search=monitory" \
--data-urlencode "page=1" \
--data-urlencode "pageSize=20" \
--header "X-Codenica-Client-Id: $CLIENT_ID" \
--header "X-Codenica-Client-Secret: $CLIENT_SECRET" \
"$BASE_URL/api/v1/requesteditems"Proste filtry mogą korzystać z nazw pól:
curl --silent --show-error -G \
--data-urlencode "status=Open" \
--data-urlencode "priority=High" \
--data-urlencode "customId=ERP-REQ-2026-0042" \
--header "X-Codenica-Client-Id: $CLIENT_ID" \
--header "X-Codenica-Client-Secret: $CLIENT_SECRET" \
"$BASE_URL/api/v1/requesteditems"Filtr strukturalny ma postać field:operator:value:
status:eq:Open
priority:ne:Low
quantity:gte:2
price:lt:1000
title:contains:laptop
customId:startswith:ERP-
link:notempty:Obsługiwane operatory to eq, ne, gt, gte, lt, lte, contains, startswith, endswith i notempty. Wartość filtra URL-encode’uj, zwłaszcza gdy zawiera spację, dwukropek lub znak specjalny.
Zapotrzebowania - wybór pól i dołączanie danych
Jeżeli potrzebujesz tylko części odpowiedzi, użyj fields. Dołączanie plików, relacji i użytkowników wykonuje się przez include:
curl --silent --show-error -G \
--data-urlencode "fields=id,itemType,customId,title,status,priority,dateDue,quantity,value" \
--data-urlencode "include=files,relationships,users" \
--data-urlencode "ids=7512ef99-0010-4962-9453-99383a377e4b" \
--header "X-Codenica-Client-Id: $CLIENT_ID" \
--header "X-Codenica-Client-Secret: $CLIENT_SECRET" \
"$BASE_URL/api/v1/requesteditems"Dostępne wartości include to files, relationships i users. Każda z nich wymaga odpowiedniego zakresu. fields=* nie omija uprawnień do pól technicznych i nie zwraca pól systemowych przeznaczonych do koperty odpowiedzi.
Do filtrowania możesz wykorzystać także createdAfter, createdBefore, updatedAfter, updatedBefore, sort i direction. Nazwy pól w fields, sort i filter sprawdzaj względem aktualnego schema.
Zapotrzebowania - statystyki i wartości pól
Endpoint stats pomaga sprawdzić rozkład danych, a values zwraca wartości przydatne do budowy filtrów:
curl --silent --show-error -G \
--data-urlencode "field=status" \
--data-urlencode "limit=20" \
--header "X-Codenica-Client-Id: $CLIENT_ID" \
--header "X-Codenica-Client-Secret: $CLIENT_SECRET" \
"$BASE_URL/api/v1/requesteditems/stats"
curl --silent --show-error -G \
--data-urlencode "field=category" \
--data-urlencode "search=hard" \
--data-urlencode "limit=20" \
--header "X-Codenica-Client-Id: $CLIENT_ID" \
--header "X-Codenica-Client-Secret: $CLIENT_SECRET" \
"$BASE_URL/api/v1/requesteditems/values"Przykładowa odpowiedź values:
{
"data": {
"field": "category",
"values": ["Hardware", "Office"]
},
"meta": {
"requestId": "request-id"
}
}Statystyki i wartości są odczytami i nie zmieniają Zapotrzebowań. Nie odpytywać ich w krótkiej pętli bez potrzeby - schema i wartości pól można przechowywać w pamięci podręcznej przez czas odpowiedni dla integracji.
Zapotrzebowania - minimalne utworzenie
Utworzenie rekordu wykonuje się przez POST /api/v1/requesteditems. W body podaj itemType oraz pola w attributes:
curl --request POST --url "$BASE_URL/api/v1/requesteditems" \
--header "Content-Type: application/json" \
--header "X-Codenica-Client-Id: $CLIENT_ID" \
--header "X-Codenica-Client-Secret: $CLIENT_SECRET" \
--header "Idempotency-Key: requesteditem-create-unique-001" \
--data-raw '{
"itemType": "requesteditem",
"attributes": {
"customId": "ERP-REQ-2026-0042",
"title": "Zakup materiałów biurowych",
"category": "Office",
"quantity": 10,
"currency": "PLN",
"status": "Open",
"description": "Pozycja utworzona przez integrację."
}
}'Wartość itemType musi wynosić requesteditem. Nazwy i typy pól dopasuj do odpowiedzi schema. Daty wysyłaj jako ISO 8601, a liczby jako JSON numbers, bez formatowania ich jako tekst.
Poprawna odpowiedź ma status 201 Created. Zapisz data.id, ETag z nagłówka HTTP oraz ETag z data.meta.etag.
Zapotrzebowania - kompletne utworzenie z polami finansowymi
Poniższy przykład odpowiada rekordowi z pełnego przebiegu demonstracyjnego. Pokazuje termin, lokalizację, status, priorytet i dane rozliczeniowe:
curl --request POST --url "$BASE_URL/api/v1/requesteditems" \
--header "Content-Type: application/json" \
--header "X-Codenica-Client-Id: $CLIENT_ID" \
--header "X-Codenica-Client-Secret: $CLIENT_SECRET" \
--header "Idempotency-Key: requesteditem-create-20260906053922-source" \
--data-raw '{
"itemType": "requesteditem",
"attributes": {
"customId": "PUBLIC-API-REQUESTEDITEM-20260906053922-SOURCE",
"dateDue": "2026-12-31T17:00:00Z",
"dateEnd": "2027-01-15T17:00:00Z",
"location": "Warsaw",
"department": "IT",
"tag": "public-api,requesteditems,demo",
"link": "https://codenica.com",
"title": "Requested Item API complete flow",
"status": "Open",
"priority": "High",
"category": "Hardware",
"budget": "IT-2026",
"currency": "PLN",
"tax": 23,
"quantity": 3,
"cost": 300,
"price": 100,
"value": 369,
"description": "Demonstracyjne zapotrzebowanie utworzone przez Public API."
},
"customValues": [
{
"name": "description",
"valuePattern": "[requested-item-demo] Public API"
}
]
}'customValues jest opcjonalne. Usuń tę właściwość, jeśli integracja nie korzysta z reguł wartości dodatkowych. Nie wysyłaj pól technicznych tylko dlatego, że pojawiły się w odpowiedzi.
Zapotrzebowania - bezpieczne ponowienie utworzenia
Jeżeli po wysłaniu żądania wystąpi timeout i nie wiesz, czy rekord został zapisany, ponów dokładnie tę samą operację z tym samym Idempotency-Key i identycznym body:
curl --request POST --url "$BASE_URL/api/v1/requesteditems" \
--header "Content-Type: application/json" \
--header "X-Codenica-Client-Id: $CLIENT_ID" \
--header "X-Codenica-Client-Secret: $CLIENT_SECRET" \
--header "Idempotency-Key: requesteditem-create-20260906053922-source" \
--data-binary @requesteditem-create.jsonPlik requesteditem-create.json musi zawierać dokładnie body z pierwszego żądania. Ponowienie zwróci ten sam rekord zamiast tworzyć duplikat. Nowa intencja biznesowa, zmienione body albo inna trasa wymagają nowego klucza. Ponowienie z innym body zwróci 422 idempotency_key_reused.
Klucz idempotencji przechowuj po stronie integracji razem ze statusem operacji. Nie używaj w tym celu Client Secret.
Zapotrzebowania - odczyt rekordu i ETag
Po utworzeniu albo znalezieniu Zapotrzebowania pobierz je po UUID:
export REQUESTED_ITEM_ID="7512ef99-0010-4962-9453-99383a377e4b"
curl --request GET --url "$BASE_URL/api/v1/requesteditems/$REQUESTED_ITEM_ID?include=files,relationships,users" \
--header "Accept: application/json" \
--header "X-Codenica-Client-Id: $CLIENT_ID" \
--header "X-Codenica-Client-Secret: $CLIENT_SECRET"Aktualny ETag znajdziesz w nagłówku HTTP oraz zwykle w data.meta.etag i głównej kopercie meta.etag:
ETag: "etag-value"ETag jest nieprzezroczystą wersją konkretnego rekordu. Nie usuwaj cudzysłowów zwróconych w nagłówku i nie wyliczaj tej wartości samodzielnie. Przed każdą zmianą rekordu, relacji albo pliku pobierz świeży ETag, jeżeli rekord mógł zostać zmieniony przez inną osobę lub integrację.
Zapotrzebowania - częściowa edycja z If-Match
PATCH zmienia tylko pola przesłane w body. Wymaga aktualnego ETagu i nowego klucza idempotencji:
export REQUESTED_ITEM_ETAG='"etag-value-from-get"'
curl --request PATCH --url "$BASE_URL/api/v1/requesteditems/$REQUESTED_ITEM_ID" \
--header "Accept: application/json" \
--header "Content-Type: application/json" \
--header "X-Codenica-Client-Id: $CLIENT_ID" \
--header "X-Codenica-Client-Secret: $CLIENT_SECRET" \
--header "If-Match: $REQUESTED_ITEM_ETAG" \
--header "Idempotency-Key: requesteditem-update-20260906-0001" \
--data-raw '{
"attributes": {
"dateDue": "2027-01-31T17:00:00Z",
"title": "Requested Item API complete flow - updated",
"status": "In progress",
"priority": "Normal",
"quantity": 4,
"price": 125,
"value": 615
}
}'Nie musisz przesyłać całego obiektu. Pola pominięte w body pozostają bez zmian. Po odpowiedzi 200 OK zastąp zapisany ETag wartością zwróconą przez API. Każda kolejna mutacja musi użyć najnowszej wersji.
Zapotrzebowania - nieaktualny ETag i brak If-Match
Brak nagłówka If-Match jest odrzucany, aby integracja nie nadpisała zmian wykonanych przez inną osobę:
curl --request PATCH --url "$BASE_URL/api/v1/requesteditems/$REQUESTED_ITEM_ID" \
--header "Content-Type: application/json" \
--header "X-Codenica-Client-Id: $CLIENT_ID" \
--header "X-Codenica-Client-Secret: $CLIENT_SECRET" \
--header "Idempotency-Key: requesteditem-update-without-etag-0001" \
--data-raw '{"attributes":{"status":"Approved"}}'Oczekiwany wynik to 428 Precondition Required z kodem if_match_required. Jeżeli wyślesz stary ETag, otrzymasz 412 Precondition Failed z kodem if_match_failed:
HTTP 412 Precondition Failed
code: if_match_failedPo błędzie 412 pobierz rekord ponownie, porównaj własną zmianę z aktualnymi danymi i dopiero wtedy wykonaj kolejny PATCH. Nie uruchamiaj ślepej pętli, która nadpisuje zmiany użytkownika.
Zapotrzebowania - pinowanie i odpinanie
Pin jest polem tylko do odczytu w attributes. Ustawia się go osobnym endpointem, z aktualnym ETagiem:
curl --request POST --url "$BASE_URL/api/v1/requesteditems/$REQUESTED_ITEM_ID/pin" \
--header "Content-Type: application/json" \
--header "X-Codenica-Client-Id: $CLIENT_ID" \
--header "X-Codenica-Client-Secret: $CLIENT_SECRET" \
--header "If-Match: $REQUESTED_ITEM_ETAG" \
--header "Idempotency-Key: requesteditem-pin-0001" \
--data '{"pin":3}'Dozwolone są wartości od 0 do 3. Aby usunąć przypięcie, użyj null:
curl --request POST --url "$BASE_URL/api/v1/requesteditems/$REQUESTED_ITEM_ID/pin" \
--header "Content-Type: application/json" \
--header "X-Codenica-Client-Id: $CLIENT_ID" \
--header "X-Codenica-Client-Secret: $CLIENT_SECRET" \
--header "If-Match: $REQUESTED_ITEM_ETAG" \
--header "Idempotency-Key: requesteditem-unpin-0001" \
--data '{"pin":null}'Po każdej operacji zapisz nowy ETag. Nie próbuj zmieniać pin przez zwykły PATCH.
Zapotrzebowania - relacja requester
Każde Zapotrzebowanie może mieć systemową relację requester. Odczytaj ją przez:
curl --request GET --url "$BASE_URL/api/v1/requesteditems/$REQUESTED_ITEM_ID/user-relationships" \
--header "Accept: application/json" \
--header "X-Codenica-Client-Id: $CLIENT_ID" \
--header "X-Codenica-Client-Secret: $CLIENT_SECRET"Requester jest ustalany przez istniejący przepływ systemu i może wskazywać appUserRequesterId albo clientRequesterId. Public API udostępnia odczyt, ale nie ma osobnego POST ani DELETE do zmiany tej relacji. Nie próbuj ustawiać requestera przez nieudokumentowane pole w attributes. Odczyt wymaga requesteditems:users:read oraz odpowiednich uprawnień do danych.
Zapotrzebowania - dozwolone relacje z obiektami
Aktualny katalog celów relacji Zapotrzebowania obejmuje:
assetsassetclients, vendorsclient, vendordocuments, ticketsdocument, ticketchanges, problems, releaseschange, problem, releasenotes, approvalsnote, approvalworktasksworktaskNie ma relacji z samym zbiorem requesteditems ani z confirmations. Cel musi być widoczny dla użytkownika przypisanego do klucza i zgodny z listą relationshipTargets zwróconą przez schema.
Zapotrzebowania - dodawanie, odczyt i usuwanie relacji
Relacja obiektowa nie przechowuje relationshipType. W payloadzie podaj targetId, targetDataSet i zgodny targetItemType:
{
"targetId": "5ddc5b5a-5bdc-46f9-ab7e-5ad8f6775b3a",
"targetDataSet": "assets",
"targetItemType": "asset"
}Dodanie relacji wymaga aktualnego ETagu źródła, zakresu requesteditems:relationships:write i osobnego klucza idempotencji:
curl --request POST --url "$BASE_URL/api/v1/requesteditems/$REQUESTED_ITEM_ID/relationships" \
--header "Content-Type: application/json" \
--header "X-Codenica-Client-Id: $CLIENT_ID" \
--header "X-Codenica-Client-Secret: $CLIENT_SECRET" \
--header "If-Match: $REQUESTED_ITEM_ETAG" \
--header "Idempotency-Key: requesteditem-relationship-asset-0001" \
--data '{
"targetId": "5ddc5b5a-5bdc-46f9-ab7e-5ad8f6775b3a",
"targetDataSet": "assets",
"targetItemType": "asset"
}'Listę relacji odczytaj przez:
curl --request GET --url "$BASE_URL/api/v1/requesteditems/$REQUESTED_ITEM_ID/relationships?page=1&pageSize=50" \
--header "Accept: application/json" \
--header "X-Codenica-Client-Id: $CLIENT_ID" \
--header "X-Codenica-Client-Secret: $CLIENT_SECRET"Pojedynczą relację usuwa się po zbiorze i UUID celu:
curl --request DELETE --url "$BASE_URL/api/v1/requesteditems/$REQUESTED_ITEM_ID/relationships/assets/5ddc5b5a-5bdc-46f9-ab7e-5ad8f6775b3a" \
--header "X-Codenica-Client-Id: $CLIENT_ID" \
--header "X-Codenica-Client-Secret: $CLIENT_SECRET" \
--header "If-Match: $REQUESTED_ITEM_ETAG" \
--header "Idempotency-Key: requesteditem-relationship-asset-delete-0001"Po dodaniu albo usunięciu relacji odczytaj nowe dane źródłowe i zapisz nowy ETag. Jeżeli schema nie zwraca celu, nie używaj go w integracji.
Zapotrzebowania - grupowa zmiana relacji
Do kilku zmian w jednym żądaniu służy relationships:batch. W relacjach Zapotrzebowania nadal pomijaj relationshipType:
curl --request POST --url "$BASE_URL/api/v1/requesteditems/$REQUESTED_ITEM_ID/relationships:batch" \
--header "Content-Type: application/json" \
--header "X-Codenica-Client-Id: $CLIENT_ID" \
--header "X-Codenica-Client-Secret: $CLIENT_SECRET" \
--header "If-Match: $REQUESTED_ITEM_ETAG" \
--header "Idempotency-Key: requesteditem-relationship-batch-0001" \
--data-raw '{
"add": [
{
"targetId": "5ddc5b5a-5bdc-46f9-ab7e-5ad8f6775b3a",
"targetDataSet": "assets",
"targetItemType": "asset"
},
{
"targetId": "88b93fb8-8848-4669-9d87-ed4795e13bcc",
"targetDataSet": "documents",
"targetItemType": "document"
}
],
"remove": [
{
"targetId": "8f42dc16-167b-4e4a-983f-862ae85f3c7a",
"targetDataSet": "worktasks",
"targetItemType": "worktask"
}
]
}'Odpowiedź zawiera liczniki:
{
"data": {
"added": 2,
"removed": 1,
"skipped": 0
},
"meta": {
"requestId": "request-id"
}
}skipped nie powinno być automatycznie traktowane jako sukces biznesowy. Po batchu odczytaj kolekcję relacji i sprawdź wynik każdej zmiany.
Zapotrzebowania - lista i upload plików
Pliki są obsługiwane osobno od pól Zapotrzebowania. Najpierw odczytaj bieżącą listę:
curl --request GET --url "$BASE_URL/api/v1/requesteditems/$REQUESTED_ITEM_ID/files?page=1&pageSize=50" \
--header "Accept: application/json" \
--header "X-Codenica-Client-Id: $CLIENT_ID" \
--header "X-Codenica-Client-Secret: $CLIENT_SECRET"Wyślij plik jako multipart/form-data. Rola pliku jest przekazywana w query stringu:
curl --request POST --url "$BASE_URL/api/v1/requesteditems/$REQUESTED_ITEM_ID/files?relationshipType=request-form" \
--header "X-Codenica-Client-Id: $CLIENT_ID" \
--header "X-Codenica-Client-Secret: $CLIENT_SECRET" \
--header "If-Match: $REQUESTED_ITEM_ETAG" \
--header "Idempotency-Key: requesteditem-file-upload-0001" \
--form "[email protected];type=application/pdf"Element pliku zawiera między innymi id, fileName, contentType, size, relationshipType, isMain i downloadUrl. Przed wysłaniem sprawdź rozmiar i świadomie ustaw typ MIME.
Zapotrzebowania - pobieranie, podpinanie i usuwanie plików
Treść pliku pobierz przez endpoint content i zapisz w trybie binarnym:
curl --request GET --url "$BASE_URL/api/v1/requesteditems/$REQUESTED_ITEM_ID/files/$FILE_ID/content" \
--header "X-Codenica-Client-Id: $CLIENT_ID" \
--header "X-Codenica-Client-Secret: $CLIENT_SECRET" \
--output pobrane-zapotrzebowanie.pdfJeżeli plik istnieje już w systemie, możesz podpiąć go bez ponownego uploadu:
curl --request POST --url "$BASE_URL/api/v1/requesteditems/$REQUESTED_ITEM_ID/files/$FILE_ID?relationshipType=quotation" \
--header "X-Codenica-Client-Id: $CLIENT_ID" \
--header "X-Codenica-Client-Secret: $CLIENT_SECRET" \
--header "If-Match: $REQUESTED_ITEM_ETAG" \
--header "Idempotency-Key: requesteditem-file-attach-0001"Usunięcie pliku z Zapotrzebowania:
curl --request DELETE --url "$BASE_URL/api/v1/requesteditems/$REQUESTED_ITEM_ID/files/$FILE_ID" \
--header "X-Codenica-Client-Id: $CLIENT_ID" \
--header "X-Codenica-Client-Secret: $CLIENT_SECRET" \
--header "If-Match: $REQUESTED_ITEM_ETAG" \
--header "Idempotency-Key: requesteditem-file-delete-0001"Attach tworzy relację z istniejącym plikiem, ale nie przesyła nowej kopii. Aktualny model Zapotrzebowań nie ma endpointu pliku głównego: każdy element ma isMain=false. Nie używaj /files/{FILE_ID}/main ani makeMain dla tego obiektu.
Zapotrzebowania - operacje batch
Endpoint /api/v1/requesteditems:batch pozwala tworzyć, edytować i usuwać wiele rekordów. Nie zastępuje operacji plikowych, pinowania ani relacji batch:
curl --request POST --url "$BASE_URL/api/v1/requesteditems:batch" \
--header "Content-Type: application/json" \
--header "X-Codenica-Client-Id: $CLIENT_ID" \
--header "X-Codenica-Client-Secret: $CLIENT_SECRET" \
--header "Idempotency-Key: requesteditems-batch-20260906-0001" \
--data-raw '{
"items": [
{
"operation": "create",
"create": {
"itemType": "requesteditem",
"attributes": {
"customId": "ERP-REQ-BATCH-001",
"title": "Mysz i klawiatura dla zespołu",
"category": "Hardware",
"quantity": 5,
"price": 150,
"currency": "PLN",
"status": "Open"
}
}
},
{
"operation": "update",
"id": "7dc877ec-4766-42cc-a34a-900e55ab3f46",
"ifMatch": "\"etag-from-get\"",
"update": {
"attributes": {
"status": "Approved",
"quantity": 6
}
}
},
{
"operation": "delete",
"id": "476b8c2e-6da9-409d-bb35-98039619ccfe",
"ifMatch": "\"etag-after-update\""
}
]
}'Każdy element update i delete ma własny ETag. Batch nie jest transakcją all-or-nothing. Przejdź po items w odpowiedzi, zapisz status, UUID i błąd dla każdego elementu. Przy częściowym wyniku możesz otrzymać 207 Multi-Status.
Zapotrzebowania - usunięcie rekordu
Przed usunięciem pobierz rekord ponownie, sprawdź UUID i aktualny ETag oraz upewnij się, że proces biznesowy pozwala na usunięcie:
curl --request DELETE --url "$BASE_URL/api/v1/requesteditems/$REQUESTED_ITEM_ID" \
--header "X-Codenica-Client-Id: $CLIENT_ID" \
--header "X-Codenica-Client-Secret: $CLIENT_SECRET" \
--header "If-Match: $REQUESTED_ITEM_ETAG" \
--header "Idempotency-Key: requesteditem-delete-20260906-0001"Poprawna odpowiedź zwraca 200 OK i data=true. Po usunięciu ponowny odczyt UUID powinien zwrócić 404 Not Found z kodem requestedItem_not_found. Końcową kontrolę możesz wykonać także przez listę filtrowaną po customId i oczekiwać totalItems=0.
Usunięcie rekordu nie jest sposobem na zachowanie historii procesu. Jeśli dane mają znaczenie audytowe, zapisz potrzebne informacje w systemie źródłowym przed wykonaniem DELETE.
Zapotrzebowania - błędy, limity i bezpieczna kolejność pracy
Błędy mają format Problem Details. W logach zapisuj status, code i requestId, ale nie zapisuj Client Secret ani pełnych nagłówków:
authentication_failedscope_or_access_deniedrequestedItem_not_foundif_match_failedif_match_required lub idempotency_key_requiredvalidation_failedrate_limit_exceededRetry-After.Odczytuj X-RateLimit-Limit i X-RateLimit-Remaining. Ogranicz równoległość, cache’uj schema i wartości, a przy 429 stosuj backoff. Bezpieczna kolejność integracji to: context, schema, lista lub odczyt po UUID, utworzenie z Idempotency-Key, zapisanie UUID i ETagu, pliki lub relacje, edycja z If-Match, odczyt weryfikacyjny i dopiero na końcu usunięcie. Ten sam układ można wykorzystać w n8n, jeśli poświadczenia są zapisane jako credential, a UUID, ETag i klucze idempotencji są przekazywane między węzłami.
