Zadania w Codenica API

Zanim wyślesz pierwsze żądanie dotyczące zadań, utwórz klucz w ustawieniach swojej instalacji. Jeżeli nie masz jeszcze klucza, otwórz w nowej karcie stronę Codenica API - wprowadzenie. Znajdziesz tam wspólne zasady tworzenia kluczy, uwierzytelniania, obsługi adresu API i bezpiecznego przechowywania sekretu.

Zadanie służy do zapisania konkretnej czynności, obowiązku albo pracy do wykonania. W jednym rekordzie możesz przechować termin, status, priorytet, kategorię, opis, miejsce, dział, odnośnik i tagi. Zadanie może być także powiązane z innymi obiektami używanymi w pracy Service Desk i zarządzaniu zasobami.

W technicznym kontrakcie API pojedynczy rekord ma wartość itemType równą worktask, a kolekcja endpointów nosi nazwę worktasks. Przykłady zawierają bezpieczne wartości demonstracyjne. Identyfikatory, adresy i daty zastąp danymi własnej integracji.


Zadania - adres API i wybór instalacji

Wszystkie trasy dotyczące zadań zaczynają się od adresu:

{BASE_URL}/api/v1/worktasks

BASE_URL oznacza adres aplikacji Codenica bez końcówki /api/v1. Do adresu nie dopisuj nazwy bazy danych ani identyfikatora firmy.

Codenica Cloud: użyj domeny lub subdomeny przypisanej do firmy:

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

Codenica On-Premise: domyślny adres rejestrowany lokalnie przez Codenica Discovery to:

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

Jeżeli administrator udostępnił instalację przez firmową domenę, HTTPS, reverse proxy albo na innym porcie, użyj dokładnego adresu przekazanego dla tej instalacji. Szczegóły wdrożenia znajdziesz w instrukcji instalacji Codenica On-Premise. Adres localhost stosuj tylko w świadomym lokalnym środowisku testowym, gdy klient HTTP i API działają na tym samym komputerze.

Nie przesyłaj tenantId w body ani w parametrach URL. Właściwa baza danych jest wybierana na podstawie adresu i hosta żądania.


Zadania - klucz API i limity licencyjne

Klucz utwórz w panelu Ustawienia -> API -> API Keys. Dla każdej aplikacji i środowiska warto utworzyć osobny klucz, nadać mu czytelną nazwę i wybrać tylko zakresy potrzebne do obsługi zadań.

Licencja
Dostęp do Codenica API
Maksymalna liczba kluczy
Starter
Nie
0
Plus
Tak
50
Enterprise
Tak
100

Usunięcie klucza usuwa jego rekord i zwalnia miejsce w limicie. Wygaśnięcie daty aktywności zatrzymuje uwierzytelnianie, ale nie zastępuje porządkowania listy. Jeżeli data końcowa nie zostanie ustawiona, domyślny okres aktywności wynosi 90 dni, a maksymalny okres jednego klucza to 5 lat.


Zadania - uwierzytelnianie żądań

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

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

Przykład pierwszego odczytu:

export PUBLIC_API_CLIENT_ID="cna_twoj_client_id"
export PUBLIC_API_CLIENT_SECRET="cns_twoj_client_secret"

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

Zewnętrzna integracja nie potrzebuje sesji panelu ani Bearer JWT użytkownika. Sekret przechowuj po stronie serwera albo w menedżerze sekretów. Nie umieszczaj go w kodzie przeglądarkowym, repozytorium, adresie URL, historii poleceń ani logach.


Zadania - sprawdzenie kontekstu połączenia

Przed pobraniem listy albo utworzeniem pierwszego zadania odczytaj kontekst. Sprawdzisz, czy adres prowadzi do właściwej bazy danych oraz czy 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" | jq

W odpowiedzi zweryfikuj data.tenant.id, data.tenant.name, data.tenant.subdomain, data.tenant.resolvedDomain, data.caller.clientId oraz data.caller.scopes. Sprawdź również, czy możliwości obejmują supportsRelationships, supportsFiles, supportsETag i supportsIdempotency.

{
  "data": {
    "apiVersion": "v1",
    "caller": {
      "authentication": "api_key",
      "clientId": "{CLIENT_ID}",
      "scopes": [
        "worktasks:read",
        "worktasks:write"
      ]
    },
    "capabilities": {
      "supportsETag": true,
      "supportsIdempotency": true,
      "supportsRelationships": true,
      "supportsFiles": true
    }
  },
  "meta": {
    "requestId": "{REQUEST_ID}"
  }
}

Jeżeli context wskazuje inną firmę albo nie zawiera potrzebnego zakresu, zatrzymaj integrację i popraw adres lub klucz. Nie próbuj zmieniać bazy danych przez dodanie obcego identyfikatora do body.


Zadania - schema i obsługiwane pola

Schema jest źródłem informacji o aktualnej konfiguracji zadań. Zwraca typy pól, wymagane wartości, zapisywalność, pola techniczne oraz targety relacji dostępne w danej instalacji.

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/worktasks/schema" | jq
{
  "data": {
    "itemType": "worktask",
    "fields": [
      {
        "name": "customId",
        "type": "string",
        "readable": true,
        "writable": true,
        "required": false
      },
      {
        "name": "title",
        "type": "string",
        "readable": true,
        "writable": true,
        "required": false
      }
    ],
    "relationshipTargets": [
      {
        "targetDataSet": "assets",
        "targetItemType": "asset"
      },
      {
        "targetDataSet": "tickets",
        "targetItemType": "ticket"
      }
    ]
  }
}

Nie zakładaj, że konfiguracja wszystkich baz danych jest identyczna. Przed mapowaniem pól sprawdź bieżące schema i respektuj wartości readable, writable, required, technical oraz maxLength.


Zadania - pola do zapisu i pola systemowe

Poniższe pola są przeznaczone do przekazywania w attributes. Jeżeli schema bieżącej instalacji podaje inne ograniczenia, to ono ma pierwszeństwo.

Pole
Typ
Zastosowanie
customId
string
Identyfikator nadany przez system integrujący.
dateDue
date-time
Termin wykonania zadania.
dateEnd
date-time
Data zakończenia pracy.
location
string
Miejsce realizacji.
department
string
Dział albo jednostka odpowiedzialna.
tag
string
Tagi; maksymalnie 2000 znaków.
link
string
Odnośnik do źródła albo szczegółów w innej aplikacji.
title
string
Krótki tytuł zadania.
status
string
Status procesu.
priority
string
Priorytet.
category
string
Kategoria zadania.
description
string
Opis; maksymalnie 10000 znaków.

Pole pin jest tylko do odczytu i zmienia się je przez dedykowaną trasę /pin. Pola techniczne, takie jak authorId, agentId, workTimeId, creator, updater, dateCreated, dateUpdated, importId, importSource i dateImported, są uzupełniane przez system. Nie przesyłaj ich w zwykłym tworzeniu ani w PATCH. Wartość itemType musi zawsze wynosić worktask.


Zadania - najważniejsze endpointy

Poniższa lista pokazuje główne operacje udostępnione dla obiektu worktask. Dodatkowy zakres klucza dobierz do operacji, którą chcesz wykonać.

Metoda
Ścieżka
Zastosowanie
GET
/api/v1/worktasks
Lista, paginacja i filtry.
POST
/api/v1/worktasks
Utworzenie zadania.
GET
/api/v1/worktasks/schema
Schema pól i relacji.
GET
/api/v1/worktasks/stats
Statystyki pól.
GET
/api/v1/worktasks/values
Wartości pól z wyszukiwaniem.
GET
/api/v1/worktasks/{id}
Odczyt jednego zadania.
PATCH
/api/v1/worktasks/{id}
Częściowa edycja.
DELETE
/api/v1/worktasks/{id}
Usunięcie zadania.
POST
/api/v1/worktasks:batch
Tworzenie, edycja i usuwanie zbiorcze.
GET/POST
/api/v1/worktasks/{id}/relationships
Odczyt albo dodanie relacji obiektowej.
POST
/api/v1/worktasks/{id}/relationships:batch
Dodanie i usunięcie wielu relacji.
GET
/api/v1/worktasks/{id}/user-relationships
Odczyt autora i agenta.
GET/POST/DELETE
/api/v1/worktasks/{id}/files...
Lista, upload, attach, detach i treść pliku.
POST
/api/v1/worktasks/{id}/pin
Przypięcie albo odpięcie zadania.

Zadania - listowanie i paginacja

Listę zadań pobieraj stronami. Sortowanie warto ustawić jawnie, aby kolejne odczyty miały przewidywalną kolejność:

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/worktasks?page=1&pageSize=25&sort=dateCreated&direction=desc" | jq

W odpowiedzi odczytaj data.items, page, pageSize, totalItems, totalPages i hasNextPage. Gdy hasNextPage ma wartość true, pobierz następną stronę. Maksymalny rozmiar strony sprawdź w data.capabilities.limits.maxPageSize z context.

Parametr ids służy do pobrania wskazanych UUID-ów. Do synchronizacji lepiej używać stabilnego customId po stronie własnej aplikacji, a następnie zapisywać UUID zwrócony przez Codenica API.


Zadania - wyszukiwanie i filtry

Lista obsługuje wyszukiwanie tekstowe, dopasowanie konkretnych pól oraz filtr strukturalny. Najczęściej używane parametry to customId, search, title, status, priority, category, location, department, tag, createdAfter, createdBefore, updatedAfter i updatedBefore.

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/worktasks?search=stacja&filter=status%3Aeq%3AOpen&sort=dateDue&direction=asc&page=1&pageSize=25" | jq

Filtr ma postać field:operator:value. Przykłady operatorów:

status:eq:Open
priority:ne:Low
title:startswith:Przygotuj
description:contains:stacja
dateDue:gte:2026-09-01T00:00:00Z

Skróty =, !=, ge, le, sw i ew odpowiadają odpowiednio operatorom równości, nierówności, większe lub równe, mniejsze lub równe, startswith i endswith. Wartości zawierające znaki specjalne zakoduj w adresie URL.


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

Parametr fields ogranicza pola zwracane w rekordzie. Dzięki temu odpowiedź jest mniejsza i łatwiejsza do przetwarzania:

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/worktasks?fields=customId,title,status,priority,dateDue&page=1&pageSize=25" | jq

Jeśli potrzebujesz danych powiązanych, 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/worktasks/{WORKTASK_ID}?fields=%2A&include=files%2Crelationships%2Cusers" | jq

Dostępne dołączenia nie zwiększają uprawnień klucza. Aby zobaczyć pliki, relacje albo użytkowników, potrzebujesz odpowiednich zakresów worktasks:files:read, worktasks:relationships:read i worktasks:users:read. Pełne fields=* stosuj tylko wtedy, gdy rzeczywiście potrzebujesz pól technicznych.


Zadania - statystyki i wartości pól

Statystyki pomagają zbudować zestawienia bez pobierania całej kolekcji. Przykład liczby zadań według statusu:

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/worktasks/stats?field=status&limit=20" | jq
{
  "data": {
    "total": 42,
    "field": "status",
    "values": [
      { "value": "Open", "count": 12 },
      { "value": "In progress", "count": 18 },
      { "value": "Closed", "count": 12 }
    ]
  },
  "meta": {
    "requestId": "{REQUEST_ID}"
  }
}

Endpoint values zwraca wartości pola pasujące do wyszukiwania. Przydaje się na przykład do podpowiedzi w formularzu:

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/worktasks/values?field=category&search=oper&limit=20" | jq

Obie trasy są tylko do odczytu i wymagają zakresu worktasks:stats.


Zadania - utworzenie minimalne

Minimalny zapis powinien zawierać itemType oraz obiekt attributes. W praktyce warto od razu nadać własny customId i tytuł:

{
  "itemType": "worktask",
  "attributes": {
    "customId": "ERP-WORKTASK-2026-0042",
    "title": "Przygotowanie stanowiska pracy",
    "status": "Open",
    "priority": "High",
    "category": "IT"
  }
}

Żądanie tworzące rekord:

curl --fail-with-body --silent --show-error \
  --request POST \
  --header "Accept: application/json, application/problem+json" \
  --header "Content-Type: application/json" \
  --header "X-Codenica-Client-Id: $PUBLIC_API_CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $PUBLIC_API_CLIENT_SECRET" \
  --header "Idempotency-Key: erp-worktask-create-2026-0042" \
  --data-raw '{
    "itemType": "worktask",
    "attributes": {
      "customId": "ERP-WORKTASK-2026-0042",
      "title": "Przygotowanie stanowiska pracy",
      "status": "Open",
      "priority": "High",
      "category": "IT"
    }
  }' \
  "$BASE_URL/api/v1/worktasks" | jq

Prawidłowa odpowiedź ma status 201 Created. Zapisz data.id oraz ETag rekordu do dalszej pracy.


Zadania - kompletne utworzenie

Poniższy przykład zapisuje dane, które zwykle są potrzebne do przekazania zadania z systemu planowania pracy:

{
  "itemType": "worktask",
  "attributes": {
    "customId": "ERP-WORKTASK-2026-0042",
    "title": "Przygotowanie stanowiska dla nowej osoby",
    "description": "Zainstaluj komputer, skonfiguruj dostęp do sieci i potwierdź gotowość stanowiska.",
    "status": "Open",
    "priority": "High",
    "category": "Onboarding",
    "dateDue": "2026-09-30T12:00:00Z",
    "location": "Kraków",
    "department": "IT",
    "tag": "onboarding,stanowisko-pracy",
    "link": "https://portal.example.com/tasks/ERP-WORKTASK-2026-0042"
  }
}

Wartości statusu, priorytetu i kategorii powinny odpowiadać konfiguracji używanej w Twojej bazie. API nie tworzy automatycznie własnego słownika tylko dlatego, że integracja przesłała nową nazwę.

curl --fail-with-body --silent --show-error \
  --request POST \
  --header "Accept: application/json, application/problem+json" \
  --header "Content-Type: application/json" \
  --header "X-Codenica-Client-Id: $PUBLIC_API_CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $PUBLIC_API_CLIENT_SECRET" \
  --header "Idempotency-Key: erp-worktask-create-2026-0042" \
  --data-binary @worktask.json \
  "$BASE_URL/api/v1/worktasks" | jq

Zadania - Idempotency-Key i bezpieczne ponowienie

Każda mutacja wykonywana kluczem API wymaga nagłówka Idempotency-Key. Wartość identyfikuje jedną intencję biznesową. Dla ponowienia tego samego żądania zachowaj ten sam klucz i nie zmieniaj body. Dla nowego zadania albo innej operacji wygeneruj inną wartość.

--header "Idempotency-Key: erp-worktask-create-2026-0042"

Jeżeli połączenie zostało przerwane po wysłaniu żądania, najpierw ponów identyczne żądanie z tym samym kluczem. Nie twórz od razu nowego klucza, bo możesz zapisać duplikat. Brak nagłówka kończy mutację odpowiedzią 428 z kodem idempotency_key_required.


Zadania - odczyt pojedynczego rekordu

Po utworzeniu pobierz rekord po UUID zwróconym w data.id:

export WORKTASK_ID="{UUID_Z_ODPOWIEDZI_CREATE}"

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/worktasks/$WORKTASK_ID?fields=customId,title,status,priority,category,dateDue,description" | jq

Pojedynczy rekord zawiera id, itemType, attributes i meta. W meta odczytaj ETag, który będzie potrzebny przy kolejnej mutacji.

{
  "data": {
    "id": "{WORKTASK_ID}",
    "itemType": "worktask",
    "attributes": {
      "customId": "ERP-WORKTASK-2026-0042",
      "title": "Przygotowanie stanowiska dla nowej osoby",
      "status": "Open"
    },
    "meta": {
      "customId": "ERP-WORKTASK-2026-0042",
      "etag": "{CURRENT_ETAG}"
    }
  },
  "meta": {
    "requestId": "{REQUEST_ID}",
    "etag": "{CURRENT_ETAG}"
  }
}

Zadania - edycja z ETag i If-Match

Przed zmianą odczytaj aktualny rekord i zachowaj dokładną wartość ETag, razem z cudzysłowami, jeżeli są jej częścią:

ETAG=$(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/worktasks/$WORKTASK_ID?fields=customId,title,status,priority,description" \
  | jq -r '.data.meta.etag // .meta.etag')

PATCH zmienia tylko wskazane atrybuty. Po powodzeniu zapisz nowy ETag:

curl --fail-with-body --silent --show-error \
  --request PATCH \
  --header "Accept: application/json, application/problem+json" \
  --header "Content-Type: application/json" \
  --header "X-Codenica-Client-Id: $PUBLIC_API_CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $PUBLIC_API_CLIENT_SECRET" \
  --header "If-Match: $ETAG" \
  --header "Idempotency-Key: erp-worktask-update-2026-0042" \
  --data-raw '{
    "attributes": {
      "title": "Konfiguracja stanowiska dla nowej osoby",
      "status": "In progress",
      "priority": "Normal",
      "description": "Komputer i dostęp sieciowy są w trakcie konfiguracji."
    }
  }' \
  "$BASE_URL/api/v1/worktasks/$WORKTASK_ID" | jq

Nie używaj ETag zapisanego przed inną zmianą. Każda udana mutacja może zmienić wersję rekordu.


Zadania - nieaktualny lub brakujący ETag

Jeżeli inna osoba albo integracja zmieniła zadanie, stary ETag kończy się odpowiedzią 412 Precondition Failed z kodem if_match_failed. API nie powinno zastosować odrzuconej zmiany.

{
  "type": "https://docs.codenica.com/errors/if_match_failed",
  "title": "Precondition failed.",
  "status": 412,
  "detail": "The supplied ETag is not the current workTask version.",
  "code": "if_match_failed",
  "requestId": "{REQUEST_ID}"
}

PATCH, DELETE, relacje, pliki i pinowanie bez wymaganego If-Match zwracają 428 Precondition Required z kodem if_match_required. Po 412 pobierz rekord ponownie, zdecyduj, czy zachować lokalną zmianę, i dopiero wtedy wyślij nowe żądanie.


Zadania - przypięcie i odpięcie

Pole pin jest tylko do odczytu w attributes. Zmianę wykonuj przez dedykowany endpoint:

POST /api/v1/worktasks/{WORKTASK_ID}/pin

Przypięcie na poziomie 3:

curl --fail-with-body --silent --show-error \
  --request POST \
  --header "Content-Type: application/json" \
  --header "X-Codenica-Client-Id: $PUBLIC_API_CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $PUBLIC_API_CLIENT_SECRET" \
  --header "If-Match: $ETAG" \
  --header "Idempotency-Key: erp-worktask-pin-2026-0042" \
  --data '{"pin":3}' \
  "$BASE_URL/api/v1/worktasks/$WORKTASK_ID/pin" | jq

Wartość null odpina zadanie:

curl --fail-with-body --silent --show-error \
  --request POST \
  --header "Content-Type: application/json" \
  --header "X-Codenica-Client-Id: $PUBLIC_API_CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $PUBLIC_API_CLIENT_SECRET" \
  --header "If-Match: $NEW_ETAG" \
  --header "Idempotency-Key: erp-worktask-unpin-2026-0042" \
  --data '{"pin":null}' \
  "$BASE_URL/api/v1/worktasks/$WORKTASK_ID/pin" | jq

Po każdej z tych operacji pobierz zadanie ponownie, ponieważ jego ETag może się zmienić.


Zadania - relacje użytkowników: autor i agent

Relacja użytkownika jest dostępna przez osobną trasę i służy do odczytu autora zadania oraz przypisanego agenta:

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/worktasks/$WORKTASK_ID/user-relationships?page=1&pageSize=20" | jq

W kolekcji pojawiają się wyłącznie relacje o typie author albo agent. Przykładowy element może wyglądać tak:

{
  "targetId": "{USER_ID}",
  "targetDataSet": "users",
  "relationshipType": "agent",
  "displayName": "Anna Kowalska",
  "email": "[email protected]",
  "role": "Agent"
}

Pola authorId i agentId są polami technicznymi. Nie próbuj zmieniać ich przez zwykły PATCH attributes. Jeżeli konkretna wersja API udostępnia osobną akcję przypisania, kieruj się jej schema i zakresem uprawnień.


Zadania - dozwolone relacje z obiektami

Schema zadań udostępnia jedenaście grup obiektów, które mogą być targetem relacji:

Target dataset
Przykładowy itemType
Przeznaczenie
assets
computer
Zasób, na przykład komputer albo urządzenie.
clients
client
Klient.
vendors
vendor
Dostawca.
documents
document
Dokument.
tickets
ticket
Zgłoszenie.
changes
change
Zmiana.
problems
problem
Problem.
releases
release
Wydanie.
notes
note
Notatka.
approvals
approval
Akceptacja.
requesteditems
requesteditem
Zapotrzebowanie.

Dla assets typ zależy od konkretnego zasobu. W tabeli pokazano przykład computer, ale przed zapisaniem relacji odczytaj rzeczywiste itemType wybranego obiektu.


Zadania - wybór targetItemType i format relacji

targetItemType musi odpowiadać rzeczywistemu typowi obiektu docelowego. Najbezpieczniejsza kolejność to: pobierz listę albo schema targetu, odczytaj jego itemType, a dopiero potem zbuduj body 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/assets?page=1&pageSize=10&sort=dateCreated&direction=desc" | jq '.data.items[0] | {id, itemType}'

Relacje obiektowe zadań nie przyjmują pola relationshipType. Przekaż tylko identyfikator, nazwę zbioru i typ obiektu:

{
  "targetId": "{ASSET_ID}",
  "targetDataSet": "assets",
  "targetItemType": "computer"
}

Nie kopiuj wartości asset, document albo task bez sprawdzenia konkretnego targetu. Nieprawidłowy typ kończy się błędem walidacji.


Zadania - dodanie, odczyt i usunięcie relacji

Dodanie jednej relacji z zasobem wymaga aktualnego ETag zadania oraz osobnego klucza idempotencji:

curl --fail-with-body --silent --show-error \
  --request POST \
  --header "Content-Type: application/json" \
  --header "X-Codenica-Client-Id: $PUBLIC_API_CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $PUBLIC_API_CLIENT_SECRET" \
  --header "If-Match: $ETAG" \
  --header "Idempotency-Key: erp-worktask-relation-assets-2026-0042" \
  --data '{
    "targetId": "{ASSET_ID}",
    "targetDataSet": "assets",
    "targetItemType": "computer"
  }' \
  "$BASE_URL/api/v1/worktasks/$WORKTASK_ID/relationships" | jq

Relację odczytaj z filtrem zbioru:

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/worktasks/$WORKTASK_ID/relationships?targetDataSet=assets&page=1&pageSize=100" | jq

Usunięcie pojedynczego powiązania:

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: $ETAG" \
  --header "Idempotency-Key: erp-worktask-relation-delete-assets-2026-0042" \
  "$BASE_URL/api/v1/worktasks/$WORKTASK_ID/relationships/assets/{ASSET_ID}" | jq

Po usunięciu odpowiedź powinna zawierać data=true. Dodanie nowej relacji zwraca 201 Created, a w niektórych sytuacjach ponowne wskazanie już istniejącej relacji może zwrócić 200 OK.


Zadania - relacje batch

Wiele relacji możesz dodać albo usunąć jednym żądaniem:

{
  "add": [
    {
      "targetId": "{DOCUMENT_ID}",
      "targetDataSet": "documents",
      "targetItemType": "document"
    }
  ],
  "remove": [
    {
      "targetId": "{ASSET_ID}",
      "targetDataSet": "assets",
      "targetItemType": "computer"
    }
  ]
}
curl --fail-with-body --silent --show-error \
  --request POST \
  --header "Content-Type: application/json" \
  --header "X-Codenica-Client-Id: $PUBLIC_API_CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $PUBLIC_API_CLIENT_SECRET" \
  --header "If-Match: $ETAG" \
  --header "Idempotency-Key: erp-worktask-relationships-batch-2026-0042" \
  --data-binary @worktask-relationships.json \
  "$BASE_URL/api/v1/worktasks/$WORKTASK_ID/relationships:batch" | jq
{
  "data": {
    "added": 1,
    "removed": 1,
    "skipped": 0
  },
  "meta": {
    "requestId": "{REQUEST_ID}"
  }
}

Batch relacji także nie przyjmuje relationshipType. Użyj aktualnego ETag zadania, a limit elementów odczytaj z context. Po operacji zapisz nowy ETag, jeżeli został zwrócony, i odczytaj kolekcję w celu weryfikacji.


Zadania - lista plików i upload

Pliki przypisane do zadania obsługuje osobna grupa endpointów. Najpierw pobierz listę:

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/worktasks/$WORKTASK_ID/files?page=1&pageSize=100" | jq

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

curl --fail-with-body --silent --show-error \
  --request POST \
  --header "Accept: application/json, application/problem+json" \
  --header "X-Codenica-Client-Id: $PUBLIC_API_CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $PUBLIC_API_CLIENT_SECRET" \
  --header "If-Match: $ETAG" \
  --header "Idempotency-Key: erp-worktask-file-upload-2026-0042" \
  --form "file=@./instrukcja-stanowiska.pdf;type=application/pdf" \
  "$BASE_URL/api/v1/worktasks/$WORKTASK_ID/files?relationshipType=instruction" | jq

Upload wymaga zakresu worktasks:files:write, aktualnego ETag i limitu pliku odczytanego z context. Dla zadań API ustawia isMain=false; nie zakładaj osobnego pliku głównego.


Zadania - pobieranie i dołączenie pliku

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

curl --fail-with-body --silent --show-error \
  --output ./instrukcja-stanowiska-pobrana.pdf \
  --header "X-Codenica-Client-Id: $PUBLIC_API_CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $PUBLIC_API_CLIENT_SECRET" \
  "$BASE_URL/api/v1/worktasks/$WORKTASK_ID/files/{FILE_ID}/content"

Jeżeli plik jest już zapisany w systemie, możesz podpiąć go do drugiego zadania bez ponownego wysyłania treści. Pobierz wcześniej ETag drugiego zadania:

curl --fail-with-body --silent --show-error \
  --request POST \
  --header "Accept: application/json, application/problem+json" \
  --header "X-Codenica-Client-Id: $PUBLIC_API_CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $PUBLIC_API_CLIENT_SECRET" \
  --header "If-Match: $SECOND_WORKTASK_ETAG" \
  --header "Idempotency-Key: erp-worktask-file-attach-2026-0042" \
  "$BASE_URL/api/v1/worktasks/$SECOND_WORKTASK_ID/files/{FILE_ID}?relationshipType=reference" | jq

Attach tworzy relację pliku z drugim zadaniem. Ten sam plik może być widoczny w obu rekordach, a reference jest typem relacji pliku, nie relacją obiektową zadania.


Zadania - odłączenie i usunięcie pliku

Odłącz plik od drugiego zadania, używając jego aktualnego ETag:

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: $SECOND_WORKTASK_ETAG" \
  --header "Idempotency-Key: erp-worktask-file-detach-2026-0042" \
  "$BASE_URL/api/v1/worktasks/$SECOND_WORKTASK_ID/files/{FILE_ID}" | jq

Odłączenie powinno zwrócić data=true i nie usuwać relacji pliku ze źródłowego zadania. Aby usunąć plik ze źródła, pobierz jego nowy ETag i wykonaj:

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: $SOURCE_WORKTASK_ETAG" \
  --header "Idempotency-Key: erp-worktask-file-delete-2026-0042" \
  "$BASE_URL/api/v1/worktasks/$WORKTASK_ID/files/{FILE_ID}" | jq

Po usunięciu sprawdź listę plików. Zadania nie mają osobnej trasy ustawiania pliku głównego.


Zadania - operacje batch dla rekordów

Endpoint /api/v1/worktasks:batch pozwala połączyć tworzenie, edycję i usuwanie zadań. Każda pozycja aktualizacji albo usunięcia ma własny ETag:

{
  "items": [
    {
      "operation": "create",
      "create": {
        "itemType": "worktask",
        "attributes": {
          "customId": "ERP-WORKTASK-BATCH-A",
          "title": "Przygotowanie dostępu",
          "status": "Open",
          "priority": "Normal",
          "category": "IT"
        }
      }
    },
    {
      "operation": "update",
      "id": "{WORKTASK_ID}",
      "ifMatch": "{CURRENT_ETAG}",
      "update": {
        "attributes": {
          "title": "Przygotowanie dostępu - etap drugi",
          "status": "In progress"
        }
      }
    },
    {
      "operation": "delete",
      "id": "{OTHER_WORKTASK_ID}",
      "ifMatch": "{OTHER_CURRENT_ETAG}"
    }
  ]
}
curl --fail-with-body --silent --show-error \
  --request POST \
  --header "Content-Type: application/json" \
  --header "X-Codenica-Client-Id: $PUBLIC_API_CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $PUBLIC_API_CLIENT_SECRET" \
  --header "Idempotency-Key: erp-worktasks-batch-2026-0042" \
  --data-binary @worktasks-batch.json \
  "$BASE_URL/api/v1/worktasks:batch" | jq
{
  "data": {
    "items": [
      {
        "index": 0,
        "operation": "create",
        "status": 201,
        "id": "{CREATED_WORKTASK_ID}",
        "data": {
          "meta": {
            "etag": "{CREATED_ETAG}"
          }
        }
      }
    ],
    "succeeded": 1,
    "failed": 0
  },
  "meta": {
    "requestId": "{REQUEST_ID}"
  }
}

Przy częściowym wyniku API może zwrócić 207 Multi-Status. Przejdź wtedy po data.items, sprawdź wynik każdej pozycji i ponów tylko te operacje, które rzeczywiście tego wymagają.


Zadania - usunięcie rekordu

Przed usunięciem ponownie odczytaj rekord, sprawdź UUID i aktualny ETag, a następnie użyj nowego klucza idempotencji:

curl --fail-with-body --silent --show-error \
  --request DELETE \
  --header "Accept: application/json, application/problem+json" \
  --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-worktask-delete-2026-0042" \
  "$BASE_URL/api/v1/worktasks/$WORKTASK_ID" | jq

Prawidłowa odpowiedź zawiera 200 OK i data=true. Po usunięciu zweryfikuj, że rekord 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/worktasks/$WORKTASK_ID"

Oczekiwany status to 404 Not Found. Dodatkowo możesz sprawdzić listę filtrem customId=ERP-WORKTASK-2026-0042 i potwierdzić totalItems=0.


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

Odpowiedzi problemowe mają format Problem Details. Do logiki integracji używaj pola code, a do zgłoszenia problemu zachowaj także requestId. Nie zapisuj w logach sekretu ani pełnych nagłówków.

HTTP
Kod lub sytuacja
Reakcja
400
validation_failed
Popraw body, pole, filtr albo target. Nie ponawiaj bez zmiany danych.
401
authentication_required
Sprawdź oba nagłówki, aktywność klucza i adres instalacji.
403
Brak scope albo dostępu
Nadaj minimalny brakujący zakres albo zmień operację.
404
worktask_not_found
Sprawdź UUID, adres bazy i zakres widoczności.
404
file_not_found
Pobierz aktualną listę plików.
409
Konflikt
Odczytaj aktualny stan i zdecyduj, czy operację można bezpiecznie powtórzyć.
412
if_match_failed
Pobierz aktualny ETag i nie nadpisuj zmian automatycznie.
413
file_too_large
Sprawdź limit w context i zmniejsz plik.
428
if_match_required
Dodaj aktualny If-Match przy mutacji istniejącego rekordu.
428
idempotency_key_required
Dodaj unikalny Idempotency-Key do mutacji.
429
Przekroczony limit
Odczytaj Retry-After i zastosuj backoff.
500
internal_error
Zachowaj requestId, ogranicz ponowienia i zgłoś problem.
207
Częściowy batch
Sprawdź wynik każdej pozycji osobno.

Odczytuj nagłówki X-RateLimit-Limit i X-RateLimit-Remaining. Przy 429 zastosuj rosnące opóźnienie z losowym rozrzutem, ogranicz liczbę prób i nie wykonuj nieskończonej pętli dla błędów 400, 401, 403, 404 albo 412.

Bezpieczna kolejność pracy

  1. Ustal BASE_URL właściwej instalacji i odczytaj context.
  2. Sprawdź scope’y, limity, schema i rzeczywiste itemType targetów relacji.
  3. Utwórz zadanie z własnym Idempotency-Key, a następnie zapisz UUID i ETag.
  4. Przed każdą zmianą, relacją, operacją na pliku albo pinowaniem pobierz aktualny ETag.
  5. Po udanej mutacji zapisz nowy ETag i zweryfikuj wynik odczytem.
  6. Po zakończeniu synchronizacji sprawdź rekord po customId, a dane demonstracyjne usuń osobnym żądaniem.
  7. W n8n użyj węzła HTTP Request; przechowuj Client ID i Client Secret w credentials, a UUID, ETag i klucz idempotencji przekazuj między kolejnymi węzłami.