Klienci i pracownicy w Codenica API

Techniczna nazwa tego zasobu w Public API to clients, a typ zwracany przez API to client. W tej kolekcji możesz obsługiwać dane klientów oraz pracowników - zależnie od roli, typu i informacji zapisanych w Twojej bazie. W żądaniach korzystasz z jednego zasobu, a rozróżnienie wynika z wartości pól rekordu.

Zanim wyślesz pierwsze żądanie, przygotuj klucz opisany w artykule Codenica API - wprowadzenie. Dalej znajdziesz kompletny przebieg pracy: od sprawdzenia schematu i listowania, przez utworzenie oraz edycję, aż po relacje, pliki, operacje batch i usunięcie rekordu.

  • pobieranie list klientów i pracowników z paginacją, sortowaniem oraz filtrami;
  • odczyt tylko tych pól, których potrzebuje integracja;
  • tworzenie rekordów i częściowa edycja danych kontaktowych lub organizacyjnych;
  • ochrona zmian przez ETag i If-Match;
  • bezpieczne ponawianie operacji dzięki Idempotency-Key;
  • łączenie rekordów z zasobami, dokumentami, zgłoszeniami i innymi obsługiwanymi obiektami;
  • przesyłanie, pobieranie, podpinanie i usuwanie plików;
  • statystyki, wartości pól oraz operacje zbiorcze.

Wymagane pola i dostępne wartości mogą zależeć od konfiguracji Twojej bazy. Przed zapisem pobierz aktualny schemat dla typu danych, z którym pracujesz.


Klienci i pracownicy - adres API i wybór instalacji

Żądania kieruj do publicznego adresu, pod którym dostępna jest Twoja instalacja Codenica. Nie używaj adresu samej bazy danych, kontenera ani portu dostępnego wyłącznie wewnątrz serwera. Ścieżki klientów i pracowników zaczynają się od:

{BASE_URL}/api/v1/clients

W Codenica Cloud użyj domeny przypisanej do Twojej instalacji:

export BASE_URL="https://twoja-firma.codenica.com"

W domyślnej instalacji On-Premise adres lokalnie rejestrowany przez Codenica Discovery to:

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

Jeśli administrator wystawił instalację On-Premise przez firmową domenę, reverse proxy, HTTPS albo inny port zewnętrzny, użyj dokładnego adresu przekazanego dla tej instalacji:

export BASE_URL="https://api.twoja-firma.example"

Właściwa baza jest wybierana na podstawie adresu hosta. Nie próbuj wskazywać jej przez tenantId, dodatkowe pole w query stringu ani wartość w body. Nie używaj localhost, jeśli program integrujący działa na innym komputerze niż API. W produkcji korzystaj z HTTPS, gdy instalacja jest opublikowana z certyfikatem.

BASE_URL nie powinien zawierać końcowego /api/v1:

# Codenica Cloud:
export BASE_URL="https://twoja-firma.codenica.com"

# Domyślne On-Premise z Codenica Discovery:
# export BASE_URL="http://codenica.local:5150"

# On-Premise z własną domeną lub reverse proxy:
# export BASE_URL="https://api.twoja-firma.example"

Klienci i pracownicy - klucz API i zakresy dostępu

Klucz dla zewnętrznej integracji utwórz w systemie Codenica w Ustawienia - API - API Keys. Nadaj mu nazwę opisującą aplikację, środowisko i przeznaczenie, na przykład CRM produkcja - Klienci. Następnie wybierz tylko zakresy potrzebne danej integracji i zapisz jednorazowo pokazany Client ID oraz Client Secret w bezpiecznym magazynie sekretów.

Pełny przebieg obsługi klientów i pracowników z tego artykułu wymaga następujących zakresów:

  • clients:read, clients:write i clients:delete - odczyt, tworzenie, edycja i usuwanie rekordów;
  • clients:schema - schemat pól i celów relacji;
  • clients:stats - statystyki i wartości pól;
  • clients:relationships:read oraz clients:relationships:write - odczyt i zmiana relacji;
  • clients:files:read oraz clients:files:write - obsługa plików.

Jeżeli integracja łączy rekordy z innym obiektem, potrzebuje również zakresu odczytu tego celu, na przykład assets:read dla istniejących zasobów. Sam zakres relacji klientów nie zastępuje uprawnienia do odczytu obiektu docelowego.

Dla integracji tylko odczytującej zwykle wystarczą:

clients:read
clients:schema

Limity aktywnych kluczy wynikają z licencji:

Licencja
Public API
Aktywne klucze
Starter
niedostępne
0
Plus
dostępne
50
Enterprise
dostępne
100

Panel API pokazuje utworzone klucze i pozwala je rotować albo usuwać. Usunięty klucz nie może już uwierzytelniać żądań i nie jest liczony jako aktywny. Client Secret jest wyświetlany tylko przy utworzeniu lub rotacji. Nie zapisuj go w repozytorium, adresie URL, logach, historii poleceń ani w kodzie działającym w przeglądarce.


Klienci i pracownicy - nagłówki uwierzytelniające

Zewnętrzna aplikacja wykonuje żądania serwer-serwer przy użyciu dwóch nagłówków:

export CLIENT_ID="cna_twoj_client_id"
export CLIENT_SECRET="cns_twoj_client_secret"

curl --request GET --url "$BASE_URL/api/v1/clients" \
  --header "Accept: application/json" \
  --header "X-Codenica-Client-Id: $CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $CLIENT_SECRET"

Nie używaj w integracji Bearer JWT administratora ani sesji panelu. JWT służy do logowania użytkownika do Codenica, a klucz API do połączenia zewnętrznej aplikacji z wybraną bazą. Poza środowiskiem testowym używaj HTTPS.

Żądania zmieniające dane wymagają również unikalnego nagłówka:

Idempotency-Key: public-api-clients-create-20260905104704

Po odczycie rekordu do żądania zmieniającego dołącz bieżący ETag:

If-Match: "aktualny-etag-klienta"

Nie generuj nowego klucza idempotencji przy ponowieniu tego samego żądania. Ten sam klucz i identyczne body pozwalają bezpiecznie odtworzyć wynik operacji, która mogła zakończyć się timeoutem.


Klienci i pracownicy - sprawdzenie kontekstu instalacji

Przed rozpoczęciem synchronizacji pobierz kontekst:

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"

Sprawdź w odpowiedzi apiVersion, contractVersion, identyfikator bazy, tenant.resolvedDomain, caller.authentication równe api_key, wymagane zakresy oraz clients w capabilities.resources. Odczytaj także limity stron, uploadu i liczby żądań.

W zakończonym przebiegu testowym context potwierdził między innymi zakresy clients:read, clients:write, clients:delete, clients:schema, clients:stats, zakresy relacji i plików, a także obsługę batch, relacji, plików, ETagów oraz idempotencji.

Zachowuj meta.requestId. Jeżeli kontekst wskazuje niewłaściwą instalację albo brakuje zakresu, zatrzymaj synchronizację i popraw adres lub klucz. Nie próbuj zmieniać bazy w body żądania.


Klienci i pracownicy - schemat pól i typ danych

Schemat pokazuje, które pola można odczytać i zapisać oraz jakie wartości są akceptowane w Twojej bazie:

curl --request GET --url "$BASE_URL/api/v1/clients/schema" \
  --header "Accept: application/json" \
  --header "X-Codenica-Client-Id: $CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $CLIENT_SECRET"

W odpowiedzi data.itemType ma wartość client. W aktualnym schemacie wymagane i unikalne są:

Pole
Typ
Wymagane
Unikalne
Przykładowe znaczenie
firstName
string
tak
nie
imię lub pierwsza część nazwy
lastName
string
tak
nie
nazwisko lub druga część nazwy
email
string
tak
tak
adres kontaktowy

Do często używanych pól opcjonalnych należą:

customId, displayName, gender, position, category, contractType,
type, role, status, phone, phoneWork, phoneMobile, address, country,
city, state, zipCode, location, department, section, roomNumber, tag,
link, number, value, isLicensed, isVerified, comments, description,
notification, preferredLanguage

Przed użyciem dodatkowego pola sprawdź jego readable, writable, typ i limit długości w schema. Nie zakładaj, że wartości status, type, category lub role są identyczne w każdym wdrożeniu. Tworzenie Klienta nie wymaga technicznego itemType w body - API zwraca go jako client.

Schema potwierdza również cele relacji: assets, documents, tickets, notes, worktasks, confirmations i requesteditems. W bieżącym schemacie clients nie występuje jako cel relacji Klient - Klient.


Klienci i pracownicy - mapa endpointów

Poniższa mapa obejmuje główne operacje. W miejsce wartości w nawiasach wstaw identyfikatory otrzymane z odpowiedzi API.

  • GET /api/v1/clients - lista;
  • GET /api/v1/clients/schema - schemat pól i relacji;
  • GET /api/v1/clients/stats - statystyki;
  • GET /api/v1/clients/values - wartości pól;
  • GET /api/v1/clients/{id} - pojedynczy rekord;
  • POST /api/v1/clients - utworzenie;
  • PATCH /api/v1/clients/{id} - częściowa edycja;
  • DELETE /api/v1/clients/{id} - usunięcie;
  • POST /api/v1/clients:batch - operacje create, update i delete;
  • GET /api/v1/clients/{id}/relationships - lista relacji;
  • POST /api/v1/clients/{id}/relationships - dodanie relacji;
  • POST /api/v1/clients/{id}/relationships:batch - grupowa zmiana relacji;
  • DELETE /api/v1/clients/{id}/relationships/{targetDataSet}/{targetId} - usunięcie relacji;
  • GET /api/v1/clients/{id}/files - lista plików;
  • POST /api/v1/clients/{id}/files - upload;
  • POST /api/v1/clients/{id}/files/{fileId} - podpięcie istniejącego pliku;
  • PUT /api/v1/clients/{id}/files/{fileId}/main - ustawienie głównego pliku;
  • DELETE /api/v1/clients/{id}/files/{fileId} - usunięcie lub odpięcie pliku;
  • GET /api/v1/clients/{id}/files/{fileId}/content - pobranie treści.

Odpowiedź 403 oznacza zwykle brak zakresu albo brak uprawnienia użytkownika przypisanego do klucza.


Klienci i pracownicy - listowanie i paginacja

Listę pobieraj stronicami. Przykład zwraca pierwsze dwadzieścia rekordów:

curl --request GET --url "$BASE_URL/api/v1/clients?page=1&pageSize=20&sort=displayName&direction=asc" \
  --header "Accept: application/json" \
  --header "X-Codenica-Client-Id: $CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $CLIENT_SECRET"

W odpowiedzi kolekcji znajdziesz items, page, pageSize, totalItems, totalPages i hasNextPage. Kontynuuj pobieranie, dopóki hasNextPage ma wartość true. Jeżeli kolejność ma znaczenie dla synchronizacji, zawsze ustaw sortowanie.

Limit pageSize odczytaj z contextu. Nie zakładaj, że pierwsza strona zawiera wszystkie rekordy ani że domyślna kolejność pozostanie taka sama.


Klienci i pracownicy - wyszukiwanie i filtrowanie

Przykład z testu wyszukuje rekord po własnym identyfikatorze, statusie i typie danych:

curl --request GET --url "$BASE_URL/api/v1/clients?customId=PUBLIC-API-CLI-20260905104704-SOURCE&status=Active&sort=customId&direction=asc&page=1&pageSize=10" \
  --header "Accept: application/json" \
  --header "X-Codenica-Client-Id: $CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $CLIENT_SECRET"

W zależności od schema używaj między innymi parametrów ids, search, firstName, lastName, displayName, email, status, category, type, role, location, department, customId, tag, createdAfter, createdBefore, updatedAfter i updatedBefore.

Do precyzyjnych warunków użyj filter:

filter=status:eq:Active
filter=displayName:contains:Public
filter=category:in:Customer,Employee
filter=description:notEmpty:

Operatory obejmują eq, ne, in, contains, startsWith, endsWith, empty, notEmpty, gt, gte, lt i lte. Wartości ze spacjami i znakami specjalnymi zakoduj zgodnie z zasadami URL.


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

Parametr fields ogranicza odpowiedź do potrzebnych pól:

curl --request GET --url "$BASE_URL/api/v1/clients?fields=id,itemType,customId,displayName,email,status,department" \
  --header "X-Codenica-Client-Id: $CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $CLIENT_SECRET"

Do odczytu plików i relacji razem z rekordem użyj include:

curl --request GET --url "$BASE_URL/api/v1/clients/$CLIENT_RECORD_ID?fields=customId,displayName,email,status,description&include=files,relationships" \
  --header "X-Codenica-Client-Id: $CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $CLIENT_SECRET"

W teście odpowiedź zawierała żądane pola oraz kolekcje files i relationships. Zakres odczytu danych dołączonych musi być przyznany osobno. Brak clients:files:read albo clients:relationships:read nie może być obchodzony przez fields=*.


Klienci i pracownicy - utworzenie rekordu

Do utworzenia rekordu użyj POST /api/v1/clients. Zapisywalne pola umieść w attributes. Poniższy przykład przedstawia pełny profil klienta lub pracownika otrzymany z systemu CRM:

export IDEMPOTENCY_KEY="public-api-clients-create-source-20260905104704"

curl --request POST --url "$BASE_URL/api/v1/clients" \
  --header "Accept: application/json" \
  --header "Content-Type: application/json" \
  --header "X-Codenica-Client-Id: $CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $CLIENT_SECRET" \
  --header "Idempotency-Key: $IDEMPOTENCY_KEY" \
  --data-raw '{
    "attributes": {
      "customId": "PUBLIC-API-CLI-20260905104704-SOURCE",
      "firstName": "Public API",
      "lastName": "Client source 20260905104704",
      "displayName": "Public API client source 20260905104704",
      "email": "[email protected]",
      "category": "Customer",
      "type": "External",
      "role": "Customer",
      "status": "Active",
      "preferredLanguage": "pl",
      "phone": "+48 600 000 001",
      "department": "Customer Service",
      "description": "Source client used by the complete Public API Clients flow."
    }
  }'

Dla tego zasobu w body nie dodajesz technicznego itemType. API samo zwraca itemType: client. W sprawdzonym schemacie wymagane były firstName, lastName i unikalny email. Twoja baza może wymagać dodatkowych pól lub innych wartości.

Poprawna odpowiedź ma status 201 Created. Zapisz data.id, ETag z nagłówka HTTP i data.meta.etag. customId ułatwia późniejsze wyszukanie rekordu w systemie zewnętrznym.


Klienci i pracownicy - bezpieczne ponowienie utworzenia

Jeżeli po wysłaniu danych wystąpi timeout i nie wiesz, czy rekord został zapisany, wyślij dokładnie to samo żądanie z tym samym Idempotency-Key i identycznym body:

curl --request POST --url "$BASE_URL/api/v1/clients" \
  --header "Content-Type: application/json" \
  --header "X-Codenica-Client-Id: $CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $CLIENT_SECRET" \
  --header "Idempotency-Key: public-api-clients-create-source-20260905104704" \
  --data-raw '{
    "attributes": {
      "customId": "PUBLIC-API-CLI-20260905104704-SOURCE",
      "firstName": "Public API",
      "lastName": "Client source 20260905104704",
      "displayName": "Public API client source 20260905104704",
      "email": "[email protected]",
      "category": "Customer",
      "type": "External",
      "role": "Customer",
      "status": "Active",
      "preferredLanguage": "pl",
      "phone": "+48 600 000 001",
      "department": "Customer Service",
      "description": "Source client used by the complete Public API Clients flow."
    }
  }'

W zakończonym teście drugie identyczne żądanie zwróciło ten sam identyfikator rekordu i ten sam ETag. Nie powstał drugi Klient. Zmiana body albo użycie tego samego klucza do innej operacji nie jest ponowieniem - dla nowej operacji utwórz nowy klucz.


Klienci i pracownicy - odczyt i częściowa edycja

Po utworzeniu zachowaj UUID rekordu. Pojedynczy profil odczytasz tak:

curl --request GET --url "$BASE_URL/api/v1/clients/$CLIENT_ID_VALUE" \
  --header "Accept: application/json" \
  --header "X-Codenica-Client-Id: $CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $CLIENT_SECRET"

PATCH zmienia tylko przekazane pola. Przykład aktualizuje nazwę wyświetlaną i opis:

curl --request PATCH --url "$BASE_URL/api/v1/clients/$CLIENT_ID_VALUE" \
  --header "Content-Type: application/json" \
  --header "X-Codenica-Client-Id: $CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $CLIENT_SECRET" \
  --header "If-Match: $CURRENT_ETAG" \
  --header "Idempotency-Key: public-api-clients-update-source-20260905104704" \
  --data-raw '{
    "attributes": {
      "displayName": "Public API client source updated",
      "description": "Updated through the Codenica Public API Clients flow."
    }
  }'

Udana edycja zwraca 200 OK i nowy ETag. Po każdej zmianie zastąp stary ETag nowym. Operacje relacji i plików także mogą zmienić wersję rekordu, dlatego przed następną mutacją pobierz aktualny ETag.


Klienci i pracownicy - ochrona przed nadpisaniem zmian

Jeżeli inna operacja zmieni rekord po pobraniu przez integrację ETagu, stara wartość If-Match zostanie odrzucona:

HTTP/1.1 412 Precondition Failed
{
  "type": "https://docs.codenica.com/errors/if_match_failed",
  "title": "Precondition failed.",
  "status": 412,
  "detail": "The supplied ETag is not the current client version.",
  "instance": "/api/v1/clients/{clientId}",
  "code": "if_match_failed",
  "requestId": "request-id-from-response"
}

Po takim błędzie nie nadpisuj rekordu na ślepo. Pobierz Klienta ponownie, porównaj zmiany i dopiero wtedy przygotuj nowy PATCH z aktualnym ETagiem. Pominięcie If-Match przy operacji wymagającej kontroli wersji zwraca:

HTTP/1.1 428 Precondition Required

{
  "code": "if_match_required",
  "status": 428,
  "detail": "Send the ETag returned by GET in the If-Match header."
}

Klienci i pracownicy - dostępne cele relacji

Aktualny schema wskazuje następujące zbiory docelowe:

  • assets - zasoby, na przykład computer;
  • documents - typ dokumentu zwrócony przez schema;
  • tickets - typ zgłoszenia zwrócony przez schema;
  • notes - typ notatki zwrócony przez schema;
  • worktasks - typ zadania zwrócony przez schema;
  • confirmations - typ potwierdzenia zwrócony przez schema;
  • requesteditems - typ zapotrzebowania zwrócony przez schema.

targetItemType musi odpowiadać rzeczywistemu typowi celu. W zakończonym teście wybrano dynamicznie dwa istniejące zasoby typu computer. Jeżeli relacja prowadzi do zasobów, klucz musi mieć również assets:read. Dla innych celów użyj odpowiedniego zakresu odczytu.

W bieżącym schema clients nie występuje jako cel relacji Klient - Klient. Relacje twórz wyłącznie z obiektami wskazanymi przez aktualną odpowiedź schematu.


Klienci i pracownicy - dodanie i odczyt relacji

Przykład łączy rekord z istniejącym zasobem. Body relacji zawiera identyfikator celu, jego zbiór, typ oraz rodzaj relacji:

{
  "targetId": "635d6518-1ac0-496a-abb7-95636b1b19b9",
  "targetDataSet": "assets",
  "targetItemType": "computer",
  "relationshipType": "related"
}
curl --request POST --url "$BASE_URL/api/v1/clients/$CLIENT_ID_VALUE/relationships" \
  --header "Content-Type: application/json" \
  --header "X-Codenica-Client-Id: $CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $CLIENT_SECRET" \
  --header "If-Match: $CURRENT_ETAG" \
  --header "Idempotency-Key: public-api-clients-relationship-add-20260905104704" \
  --data @client-relationship.json

Udane dodanie zwraca 201 Created i opis celu, między innymi targetId, targetDataSet, targetItemType, relationshipType, customId i name. Kolekcję relacji odczytasz tak:

curl --request GET --url "$BASE_URL/api/v1/clients/$CLIENT_ID_VALUE/relationships?targetDataSet=assets&targetItemType=computer&relationshipType=related&page=1&pageSize=50" \
  --header "Accept: application/json" \
  --header "X-Codenica-Client-Id: $CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $CLIENT_SECRET"

Odpowiedź ma model paginacji taki sam jak lista klientów. Po jednym dodaniu w teście totalItems wynosiło 1.


Klienci i pracownicy - batch relacji i usuwanie pojedynczego powiązania

Do wykonania kilku zmian w jednej operacji użyj relationships:batch:

{
  "add": [
    {
      "targetId": "5ddc5b5a-5bdc-46f9-ab7e-5ad8f6775b3a",
      "targetDataSet": "assets",
      "targetItemType": "computer",
      "relationshipType": "related"
    }
  ],
  "remove": []
}
curl --request POST --url "$BASE_URL/api/v1/clients/$CLIENT_ID_VALUE/relationships:batch" \
  --header "Content-Type: application/json" \
  --header "X-Codenica-Client-Id: $CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $CLIENT_SECRET" \
  --header "If-Match: $CURRENT_ETAG" \
  --header "Idempotency-Key: public-api-clients-relationship-batch-20260905104704" \
  --data @client-relationship-batch.json

Odpowiedź podaje liczniki added, removed i skipped. Po batchu pobierz nowy ETag Klienta.

Pojedynczą relację usuń przez:

curl --request DELETE --url "$BASE_URL/api/v1/clients/$CLIENT_ID_VALUE/relationships/assets/635d6518-1ac0-496a-abb7-95636b1b19b9?relationshipType=related" \
  --header "X-Codenica-Client-Id: $CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $CLIENT_SECRET" \
  --header "If-Match: $CURRENT_ETAG" \
  --header "Idempotency-Key: public-api-clients-relationship-remove-20260905104704"

Sukces zwraca 200 OK z data: true. Po usunięciu ostatniej relacji kolekcja powinna zwrócić totalItems: 0.


Klienci i pracownicy - lista plików i upload

Pliki są obsługiwane osobno od pól rekordu. Nowy Klient ma początkowo pustą kolekcję:

curl --request GET --url "$BASE_URL/api/v1/clients/$CLIENT_ID_VALUE/files?page=1&pageSize=50" \
  --header "Accept: application/json" \
  --header "X-Codenica-Client-Id: $CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $CLIENT_SECRET"

Prześlij plik jako multipart/form-data. Poniższy przykład tworzy główny plik dokumentacyjny:

curl --request POST --url "$BASE_URL/api/v1/clients/$CLIENT_ID_VALUE/files?makeMain=true&relationshipType=documentation" \
  --header "X-Codenica-Client-Id: $CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $CLIENT_SECRET" \
  --header "If-Match: $CURRENT_ETAG" \
  --header "Idempotency-Key: public-api-clients-file-upload-primary-20260905104704" \
  --form "[email protected];type=text/plain"

Odpowiedź zawiera między innymi id, fileName, contentType, size, relationshipType, isMain i względny downloadUrl. Testowy plik clients-primary.txt miał 62 bajty. Po uploadzie sprawdź listę plików, ponieważ to ona pokazuje ostateczny stan isMain.


Klienci i pracownicy - pobranie pliku i zmiana pliku głównego

Treść pliku pobierz przez endpoint content. Użyj zapisu binarnego:

curl --request GET --url "$BASE_URL/api/v1/clients/$CLIENT_ID_VALUE/files/$FILE_ID/content" \
  --header "X-Codenica-Client-Id: $CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $CLIENT_SECRET" \
  --output clients-primary.downloaded.txt

Drugi plik możesz przesłać z makeMain=false:

curl --request POST --url "$BASE_URL/api/v1/clients/$CLIENT_ID_VALUE/files?makeMain=false&relationshipType=manual" \
  --header "X-Codenica-Client-Id: $CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $CLIENT_SECRET" \
  --header "If-Match: $CURRENT_ETAG" \
  --header "Idempotency-Key: public-api-clients-file-upload-secondary-20260905104704" \
  --form "[email protected];type=text/plain"

Aby przełączyć go na główny:

curl --request PUT --url "$BASE_URL/api/v1/clients/$CLIENT_ID_VALUE/files/$SECONDARY_FILE_ID/main" \
  --header "X-Codenica-Client-Id: $CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $CLIENT_SECRET" \
  --header "If-Match: $CURRENT_ETAG" \
  --header "Idempotency-Key: public-api-clients-file-set-main-20260905104704"

Operacja zwraca data: true. Po niej pierwszy plik ma isMain: false, a drugi isMain: true. ETag rekordu zmienia się, więc pobierz go ponownie przed kolejną mutacją.


Klienci i pracownicy - podpięcie istniejącego pliku

Jeżeli plik jest już zapisany przy jednym Kliencie, możesz podpiąć go do kolejnego rekordu bez ponownego uploadu:

owner client: 8844622a-f948-4f2a-a718-81f61fa5ab21
target client: 3569dead-82b1-439e-8ecd-e4ee6b5f886b
file: cd60b8ce-1a97-47a9-b9fc-b1abe8b4dee4
curl --request POST --url "$BASE_URL/api/v1/clients/3569dead-82b1-439e-8ecd-e4ee6b5f886b/files/cd60b8ce-1a97-47a9-b9fc-b1abe8b4dee4?makeMain=true&relationshipType=manual" \
  --header "X-Codenica-Client-Id: $CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $CLIENT_SECRET" \
  --header "If-Match: $CURRENT_ETAG" \
  --header "Idempotency-Key: public-api-clients-file-attach-existing-20260905104704"

Stan isMain zweryfikuj na liście plików Klienta docelowego, a nie tylko w bezpośredniej odpowiedzi attachu. Odpięcie wykonasz przez:

curl --request DELETE --url "$BASE_URL/api/v1/clients/3569dead-82b1-439e-8ecd-e4ee6b5f886b/files/cd60b8ce-1a97-47a9-b9fc-b1abe8b4dee4" \
  --header "X-Codenica-Client-Id: $CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $CLIENT_SECRET" \
  --header "If-Match: $CURRENT_ETAG" \
  --header "Idempotency-Key: public-api-clients-file-detach-20260905104704"

Detach usuwa podłączenie u Klienta docelowego, ale nie usuwa pliku z Klienta właściciela.


Klienci i pracownicy - usunięcie pliku

Przed usunięciem pliku pobierz świeżą listę i ETag rekordu. Jeżeli usuwasz bieżący plik główny, system może automatycznie wybrać inny plik jako główny:

curl --request DELETE --url "$BASE_URL/api/v1/clients/$CLIENT_ID_VALUE/files/$FILE_ID" \
  --header "X-Codenica-Client-Id: $CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $CLIENT_SECRET" \
  --header "If-Match: $CURRENT_ETAG" \
  --header "Idempotency-Key: public-api-clients-file-delete-20260905104704"

Po odpowiedzi 200 zaktualizuj ETag i sprawdź listę. Usunięcie ostatniego pliku nie usuwa rekordu klienta ani pracownika, tylko pozostawia pustą kolekcję plików. Jeżeli plik był jedynie podpięty do rekordu, usuń relację, a dopiero potem rozważ jego usunięcie w miejscu, w którym został zapisany.


Klienci i pracownicy - statystyki i wartości pól

Statystyki pokazują rozkład danych, a endpoint values zwraca wartości przydatne do budowania filtrów:

curl --request GET --url "$BASE_URL/api/v1/clients/stats?field=status&limit=20" \
  --header "X-Codenica-Client-Id: $CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $CLIENT_SECRET"

curl --request GET --url "$BASE_URL/api/v1/clients/values?field=status&search=Act&limit=20" \
  --header "X-Codenica-Client-Id: $CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $CLIENT_SECRET"

W teście statystyka pokazała między innymi statusy aktywny, Active, w magazynie i Urlop płatny. Taki mieszany wynik jest możliwy, gdy dane pochodzą z różnych źródeł - nie zakładaj, że statusy będą wyłącznie po polsku albo po angielsku.

Przykładowa odpowiedź values:

{
  "data": {
    "field": "status",
    "values": ["Active"]
  },
  "meta": {
    "requestId": "request-id-from-response"
  }
}

Statystyki i wartości nie zmieniają danych. Używaj values do budowy filtrów i podpowiedzi zamiast tworzyć słowniki na stałe w kodzie.


Klienci i pracownicy - batch tworzenia

Batch pozwala utworzyć kilka rekordów w jednym żądaniu. Element tworzenia zawiera operation: create oraz obiekt create z polami attributes:

{
  "items": [
    {
      "operation": "create",
      "create": {
        "attributes": {
          "customId": "PUBLIC-API-CLI-20260905104704-BATCH-A",
          "firstName": "Public API",
          "lastName": "Clients batch A 20260905104704",
          "displayName": "Public API clients batch A 20260905104704",
          "email": "[email protected]",
          "category": "Customer",
          "role": "Customer",
          "status": "Active",
          "description": "Client created by the Public API batch flow."
        }
      }
    },
    {
      "operation": "create",
      "create": {
        "attributes": {
          "customId": "PUBLIC-API-CLI-20260905104704-BATCH-B",
          "firstName": "Public API",
          "lastName": "Clients batch B 20260905104704",
          "displayName": "Public API clients batch B 20260905104704",
          "email": "[email protected]",
          "category": "Employee",
          "role": "Employee",
          "status": "Active"
        }
      }
    }
  ]
}
curl --request POST --url "$BASE_URL/api/v1/clients:batch" \
  --header "Content-Type: application/json" \
  --header "X-Codenica-Client-Id: $CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $CLIENT_SECRET" \
  --header "Idempotency-Key: public-api-clients-batch-create-20260905104704" \
  --data @clients-batch-create.json

W zakończonym teście odpowiedź 200 OK miała succeeded: 2, failed: 0 i dwa elementy ze statusami operacji 201. Każdy nowy UUID i ETag zachowaj osobno.


Klienci i pracownicy - batch aktualizacji i częściowe powodzenie

Aktualizacja wymaga id, bieżącego ifMatch i obiektu update. Poniższy przykład pokazuje także niepoprawny element, aby wyjaśnić odpowiedź częściową:

{
  "items": [
    {
      "operation": "update",
      "id": "942f8323-bb7b-4915-80a9-81eaae657cb8",
      "ifMatch": "\"3drgMRaLiRYP6p6nCd6JDh_UHVRhYIAwWFDO4YLOUvc\"",
      "update": {
        "attributes": {
          "displayName": "Public API client batch A updated",
          "description": "Updated inside a partial Clients batch."
        }
      }
    },
    {
      "operation": "invalid"
    }
  ]
}
curl --request POST --url "$BASE_URL/api/v1/clients:batch" \
  --header "Content-Type: application/json" \
  --header "X-Codenica-Client-Id: $CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $CLIENT_SECRET" \
  --header "Idempotency-Key: public-api-clients-batch-partial-20260905104704" \
  --data @clients-batch-partial.json

W teście odpowiedź miała 207 Multi-Status:

{
  "data": {
    "succeeded": 1,
    "failed": 1,
    "items": [
      {"operation": "update", "status": 200},
      {
        "operation": "invalid",
        "status": 400,
        "error": {"code": "invalid_batch_item"}
      }
    ]
  }
}

207 nie oznacza całkowitego niepowodzenia. Wynik każdej operacji sprawdzaj osobno, a dla operacji delete pamiętaj o osobnym ifMatch:

{
  "operation": "delete",
  "id": "4db45845-ddec-4740-bb4b-f3c57836d3b5",
  "ifMatch": "\"NAHxuB2XecVkevWAbNdCeT6aQkwyyYHc_TDtgLvfI_U\""
}

Klienci i pracownicy - usunięcie rekordu

Usunięcie profilu jest operacją nieodwracalną z poziomu API. Najpierw odczytaj bieżący ETag:

curl --request GET --url "$BASE_URL/api/v1/clients/$CLIENT_ID_VALUE" \
  --header "Accept: application/json" \
  --header "X-Codenica-Client-Id: $CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $CLIENT_SECRET"

Następnie wykonaj DELETE:

curl --request DELETE --url "$BASE_URL/api/v1/clients/$CLIENT_ID_VALUE" \
  --header "X-Codenica-Client-Id: $CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $CLIENT_SECRET" \
  --header "If-Match: $CURRENT_ETAG" \
  --header "Idempotency-Key: public-api-clients-delete-source-20260905104704"

Sukces zwraca 200 OK i data: true. Po usunięciu kolejne pobranie zwróci 404 Not Found z kodem client_not_found. Filtrowanie po prefiksie PUBLIC-API-CLI-20260905104704 powinno zwrócić totalItems: 0.


Klienci i pracownicy - błędy, limity i bezpieczeństwo

Błędy zwracane są w formacie Problem Details. Najważniejsze pola to status, code, detail i requestId. Logikę aplikacji opieraj na stabilnym polu code.

  • 400 - niepoprawne pola, typ celu albo element batch;
  • 401 - brak lub nieprawidłowe poświadczenia;
  • 403 - brak zakresu albo uprawnienia;
  • 404 - rekord, plik lub cel nie istnieje albo nie jest widoczny;
  • 409 - konflikt danych, na przykład zajęty unikalny e-mail;
  • 412 - nieaktualny ETag;
  • 413 - plik przekracza limit;
  • 422 - błąd walidacji domenowej;
  • 428 - brakuje If-Match lub Idempotency-Key;
  • 429 - przekroczony limit żądań;
  • 503 - usługa chwilowo niedostępna;
  • 207 - batch wykonany częściowo.

Odczytuj X-RateLimit-Limit i X-RateLimit-Remaining. Przy 429 zastosuj Retry-After, jeśli został zwrócony, oraz opóźnienie rosnące przy kolejnych próbach. Nie loguj X-Codenica-Client-Secret, sekretów ani treści wrażliwych plików.


Klienci i pracownicy - kompletny przebieg integracji

  1. Ustaw BASE_URL zgodnie z rzeczywistym adresem Codenica Cloud albo On-Premise.
  2. Utwórz klucz w Ustawienia - API - API Keys, wybierz minimalne zakresy i zapisz sekret w magazynie poświadczeń.
  3. Pobierz /api/v1/context i potwierdź właściwą bazę, caller, zakresy oraz limity.
  4. Pobierz /api/v1/clients/schema i odczytaj wymagane pola, wartości oraz cele relacji.
  5. Wykonaj filtrowany GET z unikalnym customId, aby wykluczyć duplikat.
  6. Utwórz rekord klienta lub pracownika z unikalnym Idempotency-Key.
  7. Zachowaj UUID i ETag z odpowiedzi. Jeżeli odpowiedź zaginęła, powtórz identyczne tworzenie tym samym kluczem.
  8. Pobierz profil z fields i opcjonalnym include=files,relationships.
  9. Zmień pola przez PATCH z aktualnym If-Match i nowym kluczem idempotencji.
  10. Dodawaj, odczytuj i usuwaj wyłącznie relacje zgodne ze schematem. Sprawdzaj targetItemType celu.
  11. Obsługuj pliki przez dedykowane endpointy, pamiętając o aktualnym ETagu i rozróżnieniu podpięcia od usunięcia pliku.
  12. Po każdym uploadzie, attachu, ustawieniu pliku głównego i DELETE sprawdź listę plików.
  13. Wykorzystuj stats i values do synchronizacji filtrów oraz słowników.
  14. Dla większych partii korzystaj z clients:batch i obsłuż zarówno 200, jak i 207.
  15. Przed usunięciem odczytaj ETag, wykonaj DELETE i potwierdź kod client_not_found.

Przykłady w artykule pochodzą z przebiegu z prefiksem PUBLIC-API-CLI-20260905104704. Własna integracja musi korzystać z identyfikatorów otrzymanych z Twojej bazy, a nie z wartości demonstracyjnych.

context = GET /api/v1/context
schema = GET /api/v1/clients/schema

client = POST /api/v1/clients
  Idempotency-Key: unique-create-key

client = GET /api/v1/clients/{id}
etag = client.data.meta.etag

updated = PATCH /api/v1/clients/{id}
  If-Match: etag
  Idempotency-Key: unique-update-key

relationship = POST /api/v1/clients/{id}/relationships
  If-Match: updated-etag
  Idempotency-Key: unique-relationship-key

files = GET /api/v1/clients/{id}/files

deleted = DELETE /api/v1/clients/{id}
  If-Match: latest-etag
  Idempotency-Key: unique-delete-key