Notatki w Codenica API
Pracę z notatkami 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 wydawania kluczy, przechowywania sekretu i uwierzytelniania.
Techniczna nazwa modułu to notes, a typ pojedynczego obiektu to note. Notatka jest wpisem zapisanym w systemie Codenica. Może zawierać tytuł, opis, status, priorytet, kategorię, odnośnik i pliki. Flaga isPrivate określa widoczność zgodnie z istniejącymi uprawnieniami, a pin służy do przypięcia wpisu na określonym poziomie.
W kolejnych krokach znajdziesz adres, zakresy, context, schema, pola, listy, filtrowanie, tworzenie, idempotencję, ETag, edycję, pinowanie, relacje, autora, pliki, operacje batch oraz usuwanie.
Przykłady wykorzystują prefix PUBLIC-API-NOTE-20260905141812. W swojej integracji zastąp go własnym identyfikatorem, a adresy, identyfikatory i wartości pól dopasuj do danych w swojej bazie.
Notatki - adres API i wybór instalacji
Wszystkie trasy dotyczące notatek zaczynają się od:
{BASE_URL}/api/v1/notesBASE_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 ani w query stringu.
Notatki - klucz API i limity licencyjne
Klucz API utwórz w Codenica w miejscu Ustawienia - API - API Keys. Sekret jest pokazywany tylko raz, bezpośrednio po utworzeniu albo obróceniu klucza. Zapisz wtedy Client ID i Client Secret w bezpiecznym magazynie używanym przez integrację.
Codenica API jest dostępne dla licencji Plus i Enterprise. Licencja Plus pozwala utworzyć do 50 aktywnych kluczy, a Enterprise do 100. Starter nie udostępnia Codenica API. Dla każdej aplikacji i środowiska utwórz osobny klucz, aby można było niezależnie ograniczyć jego zakresy, obrócić sekret albo usunąć dostęp.
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 kluczy. Jeżeli przy tworzeniu nie ustawisz daty końcowej, domyślny okres ważności wynosi 90 dni. Maksymalny czas aktywności jednego klucza to 5 lat.
Notatki - uwierzytelnianie i bezpieczne żądania
Każde żądanie Codenica API uwierzytelniaj dwoma nagłówkami klucza:
export CLIENT_ID="cna_twoj_client_id"
export CLIENT_SECRET="cns_twoj_client_secret"
curl --request GET --url "$BASE_URL/api/v1/notes?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. Klucza nie umieszczaj w repozytorium, kodzie dostarczanym do przeglądarki, adresie URL, historii poleceń ani logach. Poza lokalnymi testami korzystaj z HTTPS.
W odpowiedzi zachowuj meta.requestId. Jest potrzebny do diagnozowania konkretnego żądania, ale nie zastępuje identyfikatora notatki i nie powinien być używany jako sekret.
Notatki - sprawdzenie kontekstu połączenia
Przed pierwszym zapisem pobierz kontekst. Dzięki temu sprawdzisz, czy adres prowadzi do właściwej bazy, a wybrany klucz ma potrzebne zakresy:
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.apiVersionidata.contractVersion;data.tenant.id,data.tenant.nameidata.tenant.resolvedDomain;data.caller.authenticationrówneapi_key;- obecność
noteswdata.capabilities.resources; - zakresy przypisane do klucza;
- limity stron, relacji, plików i żądań.
Jeżeli kontekst wskazuje inną bazę albo nie zawiera wymaganego zakresu, zatrzymaj integrację i popraw adres lub klucz. Zakresów nie można nadać pojedynczym żądaniem.
Notatki - zakresy uprawnień
Pełna obsługa notatek wymaga zakresów odpowiadających wykorzystywanym operacjom:
notes:read
notes:write
notes:delete
notes:schema
notes:stats
notes:relationships:read
notes:relationships:write
notes:users:read
notes:files:read
notes:files:write
notes:technical:read
notes:technical:write
notes:pin:writeDo zwykłego odczytu wystarczą notes:read i, jeżeli chcesz pobierać aktualny katalog pól, notes:schema. Przy tworzeniu, edycji i usuwaniu dodaj odpowiednio notes:write i notes:delete.
notes:relationships:readinotes:relationships:writedotyczą relacji obiektowych;notes:users:readdotyczy odczytu autora;notes:files:readinotes:files:writedotyczą listowania, pobierania, wysyłania, podłączania i usuwania plików;notes:statsdotyczy statystyk i wartości używanych w filtrach;notes:pin:writejest potrzebny do przypinania i odpinania;- zakresy techniczne stosuj tylko wtedy, gdy integracja korzysta z pól oznaczonych w schema jako techniczne albo z reguł
customValues.
Jeżeli integracja sama wyszukuje cele relacji, przydziel także odpowiednie zakresy odczytu, na przykład assets:read, clients:read, vendors:read, documents:read, tickets:read, changes:read, problems:read, releases:read, approvals:read, confirmations:read, worktasks:read i requesteditems:read. Zakres klucza nie zastępuje uprawnień użytkownika ani dostępu do lokalizacji i działu.
Notatki - schema i pola
Schema pokazuje, które pola można odczytać i zapisać w konkretnej bazie. Pobierz je przed przygotowaniem formularza lub mapowania:
curl --request GET --url "$BASE_URL/api/v1/notes/schema" \
--header "Accept: application/json" \
--header "X-Codenica-Client-Id: $CLIENT_ID" \
--header "X-Codenica-Client-Secret: $CLIENT_SECRET"Schema zwraca między innymi data.itemType, data.fields i data.relationshipTargets. Stała wartość itemType dla tego modułu to note. Dla każdego pola sprawdź readable, writable, required, technical, unique i maxLength. Nie buduj mapowania wyłącznie na podstawie przykładu z tego artykułu, ponieważ konfiguracja pól może różnić się między bazami.
W schemacie znajdziesz także informację, czy możesz używać relacji z danym zbiorem. Używaj tylko celów zwróconych dla aktualnego klucza i użytkownika.
Notatki - pola zapisywalne i systemowe
Publiczny katalog pól biznesowych Notatki obejmuje:
customId
location
department
isPrivate
tag
link
title
status
priority
category
descriptionNajważniejsze ograniczenia pól:
customIdlocation, departmentisPrivatetag, linktitlestatus, priority, categorydescriptionpin jest zwracane w atrybutach, ale nie można go zmieniać przez attributes. Do tego służy osobny endpoint. Pola systemowe i techniczne tylko do odczytu to między innymi:
id
itemType
pin
creator
updater
dateCreated
dateUpdated
importId
importSource
dateImportedid i itemType są częścią zasobu, a daty, autor i edytor są ustalane przez system. Nie próbuj zmieniać ich przez attributes.
Notatki - podstawowe endpointy
Najważniejsze trasy modułu notes to:
GET /api/v1/notes
POST /api/v1/notes
GET /api/v1/notes/{NOTE_ID}
PATCH /api/v1/notes/{NOTE_ID}
DELETE /api/v1/notes/{NOTE_ID}
GET /api/v1/notes/schema
GET /api/v1/notes/stats
GET /api/v1/notes/values
POST /api/v1/notes:batch
GET /api/v1/notes/{NOTE_ID}/relationships
POST /api/v1/notes/{NOTE_ID}/relationships
POST /api/v1/notes/{NOTE_ID}/relationships:batch
DELETE /api/v1/notes/{NOTE_ID}/relationships/{DATASET}/{TARGET_ID}
GET /api/v1/notes/{NOTE_ID}/user-relationships
GET /api/v1/notes/{NOTE_ID}/files
POST /api/v1/notes/{NOTE_ID}/files
POST /api/v1/notes/{NOTE_ID}/files/{FILE_ID}
DELETE /api/v1/notes/{NOTE_ID}/files/{FILE_ID}
GET /api/v1/notes/{NOTE_ID}/files/{FILE_ID}/content
POST /api/v1/notes/{NOTE_ID}/pinKażda trasa wymaga uwierzytelnienia. Operacje zmieniające dane wymagają również Idempotency-Key, a operacje chronione wersją wymagają aktualnego If-Match. Konkretne wymagania sprawdzaj w odpowiedzi context i w schema.
Notatki - listowanie i paginacja
Lista jest stronicowana. Przykładowe żądanie pobiera pierwszą stronę i sortuje notatki od najnowszych:
curl --request GET --url "$BASE_URL/api/v1/notes?itemType=note&page=1&pageSize=20&sort=dateCreated&direction=desc" \
--header "X-Codenica-Client-Id: $CLIENT_ID" \
--header "X-Codenica-Client-Secret: $CLIENT_SECRET"W odpowiedzi znajdziesz między innymi:
data.items
data.page
data.pageSize
data.totalItems
data.totalPages
data.hasNextPageMaksymalny pageSize wynika z kontekstu i standardowo wynosi 100. Pobieraj kolejne strony, dopóki data.hasNextPage ma wartość true. Nie zakładaj, że liczba rekordów zwrócona na pierwszej stronie oznacza kompletną listę.
Notatki - wyszukiwanie, filtry i sortowanie
Do filtrów równościowych możesz użyć między innymi customId, location, department, isPrivate, tag, link, title, status, priority i category. Przykład wyszukania prywatnych otwartych notatek z działu IT:
curl --request GET --url "$BASE_URL/api/v1/notes?isPrivate=true&department=IT&status=Open&page=1&pageSize=50" \
--header "X-Codenica-Client-Id: $CLIENT_ID" \
--header "X-Codenica-Client-Secret: $CLIENT_SECRET"search przeszukuje tekstowe pola notatki, między innymi customId, tag, link, title, status, priority, category i description:
curl --request GET --url "$BASE_URL/api/v1/notes?search=integracja&page=1&pageSize=20" \
--header "X-Codenica-Client-Id: $CLIENT_ID" \
--header "X-Codenica-Client-Secret: $CLIENT_SECRET"Parametr filter może wystąpić wielokrotnie. Format to field:operator:value:
filter=status:eq:Open
filter=status:ne:Closed
filter=title:contains:serwer
filter=title:startswith:Public API
filter=isPrivate:eq:true
filter=description:notempty:Obsługiwane są między innymi operatory eq, ne, gt, gte, lt, lte, contains, startswith, endswith, empty i notempty. Dostępne są także skróty =, !=, ge, le, sw i ew. Możesz dodać zakresy createdAfter, createdBefore, updatedAfter i updatedBefore. Sortuj tylko po polu dopuszczonym przez schema, podając direction=asc albo direction=desc. Wartości zawierające spacje i znaki specjalne koduj w URL.
Notatki - wybór pól i dołączanie danych
Jeżeli integracja potrzebuje tylko części danych, ogranicz odpowiedź przez fields:
curl --request GET --url "$BASE_URL/api/v1/notes?fields=customId%2Ctitle%2Cstatus%2Cpriority%2CisPrivate&page=1&pageSize=20" \
--header "X-Codenica-Client-Id: $CLIENT_ID" \
--header "X-Codenica-Client-Secret: $CLIENT_SECRET"Pojedynczą notatkę możesz pobrać razem z plikami, relacjami i informacją o autorze:
curl --request GET --url "$BASE_URL/api/v1/notes/{NOTE_ID}?fields=customId%2Ctitle%2Cdescription%2Cstatus&include=files%2Crelationships%2Cusers" \
--header "X-Codenica-Client-Id: $CLIENT_ID" \
--header "X-Codenica-Client-Secret: $CLIENT_SECRET"Dozwolone wartości include to files, relationships i users. Każda wymaga osobnego zakresu odczytu. fields=* pozwala zażądać wszystkich pól dostępnych dla klucza, ale pola techniczne pojawią się dopiero przy odpowiednim zakresie.
Notatki - statystyki i wartości pól
Statystyki służą do policzenia widocznych notatek i pogrupowania ich po wybranym polu:
curl --request GET --url "$BASE_URL/api/v1/notes/stats?field=category&limit=20" \
--header "X-Codenica-Client-Id: $CLIENT_ID" \
--header "X-Codenica-Client-Secret: $CLIENT_SECRET"Przykładowa odpowiedź:
{
"data": {
"total": 42,
"field": "category",
"values": [
{
"value": "Integration",
"count": 12
},
{
"value": "Hardware",
"count": 8
}
]
},
"meta": {
"requestId": "request-id-from-response"
}
}Bez parametru field endpoint zwraca łączną liczbę notatek. limit przyjmuje wartości od 1 do 500. Wyniki respektują zakres widoczności użytkownika.
Endpoint values zwraca unikalne wartości przydatne do budowania list wyboru:
curl --request GET --url "$BASE_URL/api/v1/notes/values?field=status&search=Open&limit=20" \
--header "X-Codenica-Client-Id: $CLIENT_ID" \
--header "X-Codenica-Client-Secret: $CLIENT_SECRET"Przykładowa odpowiedź:
{
"data": {
"field": "status",
"values": [
"Open",
"Open - waiting"
]
},
"meta": {
"requestId": "request-id-from-response"
}
}Oba endpointy są odczytowe i nie zmieniają notatek. Odpowiedź values nie jest pełną listą rekordów, tylko listą unikalnych wartości konkretnego pola.
Notatki - tworzenie rekordu
Przy tworzeniu umieść techniczny typ note w body, a pola biznesowe w attributes. W praktycznej integracji warto zapisywać tytuł i opis, nawet jeśli schema konkretnej bazy nie oznacza ich jako wymaganych:
{
"itemType": "note",
"attributes": {
"customId": "NOTE-ERP-2026-0001",
"location": "Warsaw",
"department": "IT",
"isPrivate": true,
"tag": "erp,public-api,notes",
"link": "https://erp.example.com/notes/0001",
"title": "Kontrola integracji serwera",
"status": "Open",
"priority": "Normal",
"category": "Integration",
"description": "Notatka utworzona przez zewnętrzny system ERP."
}
}Zapisz body jako note-create.json i wyślij je z unikalnym kluczem idempotencji:
curl --request POST --url "$BASE_URL/api/v1/notes" \
--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: notes-create-20260905-0001" \
--data-binary @note-create.jsonPrawidłowe utworzenie zwraca 201 Created. Odpowiedź zawiera UUID w data.id, data.itemType=note, zapisane atrybuty, daty systemowe i data.meta.etag. Najbezpieczniej pozostawić nadanie id systemowi.
isPrivate jest flagą widoczności, a nie szyfrowaniem. Nie zapisuj w notatce haseł, tokenów, Client Secret ani innych poufnych danych.
Notatki - bezpieczne ponowienie tworzenia
Jeżeli klient nie wie, czy pierwsze żądanie dotarło, ponów dokładnie ten sam request z tym samym Idempotency-Key:
curl --request POST --url "$BASE_URL/api/v1/notes" \
--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: notes-create-20260905-0001" \
--data-binary @note-create.jsonPowtórzenie logicznie tego samego żądania nie powinno utworzyć drugiej notatki. Odpowiedź powinna wskazać ten sam UUID i ten sam wynik operacji. Nie używaj tego samego klucza dla innego body, innego endpointu ani innej operacji. Każda nowa mutacja musi otrzymać nowy Idempotency-Key.
Przy timeoutcie nie twórz od razu kolejnego rekordu. Najpierw ponów poprzednie żądanie z tym samym body i kluczem idempotencji.
Notatki - odczyt i ETag
Po utworzeniu albo przed zmianą pobierz pojedynczą notatkę i zachowaj jej UUID oraz aktualny ETag:
export NOTE_ID="d7a83ba0-41ce-44f6-b2e9-7ddcec716234"
curl --request GET --url "$BASE_URL/api/v1/notes/$NOTE_ID" \
--header "Accept: application/json" \
--header "X-Codenica-Client-Id: $CLIENT_ID" \
--header "X-Codenica-Client-Secret: $CLIENT_SECRET"ETag pojawia się w nagłówku HTTP ETag, w data.meta.etag oraz w kopercie meta.etag. Przykładowa odpowiedź pojedynczego zasobu:
{
"data": {
"id": "d7a83ba0-41ce-44f6-b2e9-7ddcec716234",
"itemType": "note",
"attributes": {
"customId": "NOTE-ERP-0001",
"title": "Kontrola integracji serwera",
"isPrivate": true
},
"meta": {
"customId": "NOTE-ERP-0001",
"etag": "\"etag-value\""
}
},
"meta": {
"requestId": "request-id-from-response",
"etag": "\"etag-value\""
}
}Po każdej udanej mutacji ETag może się zmienić, także po operacji na relacji, pliku albo pinie. Zastąp poprzednią wartość nową, zanim wykonasz kolejną zmianę.
Notatki - częściowa edycja z If-Match
PATCH zmienia tylko pola przesłane w attributes. Użyj aktualnego ETag-u oraz osobnego klucza idempotencji:
export NOTE_ETAG='"etag-z-ostatniej-odpowiedzi"'
curl --request PATCH --url "$BASE_URL/api/v1/notes/$NOTE_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: $NOTE_ETAG" \
--header "Idempotency-Key: notes-update-20260905-0001" \
--data-raw '{
"attributes": {
"title": "Zaktualizowana kontrola integracji",
"description": "Notatka została zmieniona przez workflow API.",
"status": "In progress",
"priority": "High",
"isPrivate": false
}
}'Nie musisz wysyłać wszystkich pól. Możesz wyczyścić opcjonalną wartość przez null, jeśli schema tej bazy na to pozwala:
{
"attributes": {
"link": null,
"description": null
}
}Puste żądanie PATCH bez atrybutów, reguł wartości i zmian relacji jest odrzucane. Pola systemowe oraz pin nie należą do zwykłej edycji.
Notatki - nieaktualny ETag i brak If-Match
Mutacje Notatki wymagają nagłówka If-Match. Brak nagłówka zwraca 428 Precondition Required:
{
"type": "https://docs.codenica.com/errors/if_match_required",
"title": "Precondition required.",
"status": 428,
"detail": "Send the ETag returned by GET in the If-Match header.",
"instance": "/api/v1/notes/{id}",
"code": "if_match_required",
"requestId": "request-id-from-response"
}Jeżeli wysłany ETag jest stary, API zwróci 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 note version.",
"instance": "/api/v1/notes/{id}",
"code": "if_match_failed",
"requestId": "request-id-from-response"
}Po 412 pobierz notatkę ponownie, porównaj jej aktualny stan ze zmianą, którą chcesz wykonać, i dopiero wtedy wyślij nowy PATCH z nowym ETagiem. Nie ponawiaj bez końca tego samego żądania ze starą wartością.
Notatki - pinowanie i odpinanie
Pole pin jest read-only przy zwykłej edycji. Do ustawienia poziomu przypięcia użyj osobnej trasy:
curl --request POST --url "$BASE_URL/api/v1/notes/$NOTE_ID/pin" \
--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: $NOTE_ETAG" \
--header "Idempotency-Key: notes-pin-20260905-0001" \
--data-raw '{"pin":3}'Dozwolone są liczby całkowite od 0 do 3. Aby odpiąć notatkę, prześlij null:
curl --request POST --url "$BASE_URL/api/v1/notes/$NOTE_ID/pin" \
--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: $NOTE_ETAG" \
--header "Idempotency-Key: notes-unpin-20260905-0001" \
--data-raw '{"pin":null}'Operacja wymaga notes:pin:write, istniejącego uprawnienia do notatki oraz aktualnego ETag-u. Po sukcesie pobierz nowy ETag. Nie ustawiaj pinu przez attributes.pin i nie wysyłaj pustego body.
Przypięte notatki możesz wyszukać filtrem:
curl --request GET --url "$BASE_URL/api/v1/notes?pin=3&page=1&pageSize=20" \
--header "X-Codenica-Client-Id: $CLIENT_ID" \
--header "X-Codenica-Client-Secret: $CLIENT_SECRET"Notatki - dostępne relacje z obiektami
Notatka może być połączona z celami zwróconymi przez schema. Aktualny katalog obejmuje:
assets - asset
clients - client
vendors - vendor
documents - document
tickets - ticket
changes - change
problems - problem
releases - release
approvals - approval
confirmations - confirmation
worktasks - worktask
requesteditems - requesteditemNotatka nie tworzy relacji z samą sobą. Dla większości celów relacja składa się z identyfikatora, zbioru i typu obiektu, dlatego relationshipType należy pominąć. Aktualny model relacji z confirmations przechowuje ten parametr. Przykład celu potwierdzenia:
{
"targetId": "6efaebb6-8650-4674-8478-34fd3e601427",
"targetDataSet": "confirmations",
"targetItemType": "confirmation",
"relationshipType": "client"
}API sprawdza UUID, zgodność targetDataSet i targetItemType, istnienie oraz widoczność celu, uprawnienia i duplikaty. Jeżeli schema nie zwraca danego celu, nie używaj go w integracji.
Notatki - dodawanie, odczyt i usuwanie relacji
Relacje odczytuj przez kolekcję:
curl --request GET --url "$BASE_URL/api/v1/notes/$NOTE_ID/relationships?targetDataSet=assets&targetItemType=asset&page=1&pageSize=50" \
--header "X-Codenica-Client-Id: $CLIENT_ID" \
--header "X-Codenica-Client-Secret: $CLIENT_SECRET"Dodanie relacji z zasobem wymaga notes:relationships:write, aktualnego ETag-u i klucza idempotencji:
curl --request POST --url "$BASE_URL/api/v1/notes/$NOTE_ID/relationships" \
--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: $NOTE_ETAG" \
--header "Idempotency-Key: notes-asset-relationship-20260905-0001" \
--data-raw '{
"targetId": "71ce005d-4cb8-4c9d-8239-ffe7e5e9f3e9",
"targetDataSet": "assets",
"targetItemType": "asset"
}'Element kolekcji może zawierać targetId, targetDataSet, targetItemType, customId i name. Ponowne dodanie tej samej relacji jest bezpieczne i nie powinno tworzyć duplikatu.
Usunięcie jednej relacji:
curl --request DELETE --url "$BASE_URL/api/v1/notes/$NOTE_ID/relationships/assets/71ce005d-4cb8-4c9d-8239-ffe7e5e9f3e9" \
--header "X-Codenica-Client-Id: $CLIENT_ID" \
--header "X-Codenica-Client-Secret: $CLIENT_SECRET" \
--header "If-Match: $NOTE_ETAG" \
--header "Idempotency-Key: notes-asset-relationship-delete-20260905-0001"Dla confirmations dodaj w query parametr relationshipType=client. Poprawna odpowiedź ma status 200 i data=true. Po każdej zmianie relacji odczytaj notatkę ponownie, ponieważ jej ETag może się zmienić.
Notatki - grupowa zmiana relacji
Jeżeli chcesz dodać lub usunąć kilka relacji, użyj relationships:batch. W jednym żądaniu możesz przekazać tablice add i remove:
curl --request POST --url "$BASE_URL/api/v1/notes/$NOTE_ID/relationships:batch" \
--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: $NOTE_ETAG" \
--header "Idempotency-Key: notes-relationships-batch-20260905-0001" \
--data-raw '{
"add": [
{
"targetId": "71ce005d-4cb8-4c9d-8239-ffe7e5e9f3e9",
"targetDataSet": "assets",
"targetItemType": "asset"
}
],
"remove": [
{
"targetId": "385b51cc-fb4d-4599-9b82-3c5b66705ccd",
"targetDataSet": "clients",
"targetItemType": "client"
}
]
}'Odpowiedź zawiera liczniki:
{
"data": {
"added": 1,
"removed": 1,
"skipped": 0
},
"meta": {
"requestId": "request-id-from-response"
}
}Każdy cel musi być widoczny i zgodny z katalogiem relacji. Ponowienie relacji już istniejącej może zostać policzone jako skipped. Puste tablice add i remove są odrzucane, gdy nie zawierają żadnej operacji. Batch relacji również zmienia ETag źródłowej notatki.
Notatki - relacja autora
Autor jest ustawiany przez istniejący przepływ tworzenia notatki. Możesz go odczytać przez relację użytkownikową:
curl --request GET --url "$BASE_URL/api/v1/notes/$NOTE_ID/user-relationships?relationshipType=author&page=1&pageSize=20" \
--header "X-Codenica-Client-Id: $CLIENT_ID" \
--header "X-Codenica-Client-Secret: $CLIENT_SECRET"Przykładowy element odpowiedzi:
{
"targetId": "8e9cbff3-340f-41f6-97ec-6997bb915829",
"targetDataSet": "users",
"relationshipType": "author",
"displayName": "Fred Savage",
"email": "[email protected]",
"role": "Administrator"
}Odczyt wymaga notes:users:read oraz odpowiedniego uprawnienia do listowania notatek. Aktualny kontrakt udostępnia tylko relację author. Nie ma publicznego POST ani DELETE do zmiany lub usunięcia autora. Nie wysyłaj autora w relationships ani w attributes.
Notatki - pliki
Notatki mogą mieć pliki, ale nie mają operacji ustawiania pliku głównego. W każdym zasobie pliku isMain jest równe false. Dostępne trasy to:
GET /api/v1/notes/{NOTE_ID}/files
POST /api/v1/notes/{NOTE_ID}/files
POST /api/v1/notes/{NOTE_ID}/files/{FILE_ID}
DELETE /api/v1/notes/{NOTE_ID}/files/{FILE_ID}
GET /api/v1/notes/{NOTE_ID}/files/{FILE_ID}/contentNajpierw możesz sprawdzić listę plików:
curl --request GET --url "$BASE_URL/api/v1/notes/$NOTE_ID/files?page=1&pageSize=50" \
--header "X-Codenica-Client-Id: $CLIENT_ID" \
--header "X-Codenica-Client-Secret: $CLIENT_SECRET"Element listy zawiera między innymi id, name, fileName, contentType, size, relationshipType, isMain i downloadUrl. Lista i pobranie wymagają notes:files:read. Upload, podłączenie i usuwanie wymagają notes:files:write, uprawnień systemowych, aktualnego ETag-u i klucza idempotencji.
Wysłanie pliku odbywa się jako multipart/form-data:
curl --request POST --url "$BASE_URL/api/v1/notes/$NOTE_ID/files?relationshipType=documentation" \
--header "Accept: application/json" \
--header "X-Codenica-Client-Id: $CLIENT_ID" \
--header "X-Codenica-Client-Secret: $CLIENT_SECRET" \
--header "If-Match: $NOTE_ETAG" \
--header "Idempotency-Key: notes-file-upload-20260905-0001" \
--form "file=@./note-evidence.txt;type=text/plain"Poprawny upload zwraca 201 Created i identyfikator pliku. Parametr relationshipType może opisywać przeznaczenie, na przykład documentation, manual albo evidence. Limit rozmiaru odczytaj z data.capabilities.limits.maxUploadBytes.
Treść pobierzesz przez uwierzytelnioną ścieżkę:
curl --request GET --url "$BASE_URL/api/v1/notes/$NOTE_ID/files/$FILE_ID/content" \
--header "Accept: application/octet-stream" \
--header "X-Codenica-Client-Id: $CLIENT_ID" \
--header "X-Codenica-Client-Secret: $CLIENT_SECRET" \
--output ./note-evidence.downloaded.txtdownloadUrl traktuj jako ścieżkę API, a nie jako publiczny anonimowy link. Odpowiedź endpointu content zawiera bajty pliku, a nie kopertę JSON.
Jeśli plik znajduje się już w magazynie Codenica, możesz podłączyć istniejący identyfikator:
curl --request POST --url "$BASE_URL/api/v1/notes/$NOTE_ID/files/$FILE_ID?relationshipType=manual" \
--header "X-Codenica-Client-Id: $CLIENT_ID" \
--header "X-Codenica-Client-Secret: $CLIENT_SECRET" \
--header "If-Match: $NOTE_ETAG" \
--header "Idempotency-Key: notes-file-attach-20260905-0001"Usunięcie relacji pliku:
curl --request DELETE --url "$BASE_URL/api/v1/notes/$NOTE_ID/files/$FILE_ID" \
--header "X-Codenica-Client-Id: $CLIENT_ID" \
--header "X-Codenica-Client-Secret: $CLIENT_SECRET" \
--header "If-Match: $NOTE_ETAG" \
--header "Idempotency-Key: notes-file-delete-20260905-0001"Po każdej operacji na pliku odczytaj notatkę ponownie i pobierz nowy ETag. Dla Notatek nie wywołuj trasy files/{FILE_ID}/main, ponieważ nie jest częścią kontraktu tego obiektu.
Notatki - operacje batch
Batch pozwala połączyć tworzenie, aktualizację i usuwanie notatek w jednym żądaniu. Każda pozycja jest rozliczana osobno:
curl --request POST --url "$BASE_URL/api/v1/notes:batch" \
--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: notes-batch-create-20260905-0001" \
--data-raw '{
"items": [
{
"operation": "create",
"create": {
"itemType": "note",
"attributes": {
"customId": "NOTE-BATCH-A",
"title": "Notatka batch A",
"description": "Pierwsza notatka z operacji batch.",
"category": "Integration",
"status": "Open",
"priority": "Normal",
"isPrivate": false
}
}
},
{
"operation": "create",
"create": {
"itemType": "note",
"attributes": {
"customId": "NOTE-BATCH-B",
"title": "Notatka batch B",
"description": "Druga notatka z operacji batch.",
"category": "Integration",
"status": "Open",
"priority": "Low",
"isPrivate": true
}
}
}
]
}'Przykładowa odpowiedź zawiera succeeded, failed oraz wynik każdej pozycji:
{
"data": {
"succeeded": 2,
"failed": 0,
"items": [
{
"index": 0,
"operation": "create",
"status": 201,
"id": "note-id-a"
},
{
"index": 1,
"operation": "create",
"status": 201,
"id": "note-id-b"
}
]
},
"meta": {
"requestId": "request-id-from-response"
}
}Przed update i delete pobierz osobno aktualny ETag każdej notatki. W pozycji batch przekaż id, ifMatch oraz odpowiednio blok update. Do usunięcia użyj operacji delete. Batch nie jest transakcją all-or-nothing. Przy częściowym sukcesie API może zwrócić 207 Multi-Status, dlatego sprawdzaj każdą pozycję.
Notatki - usunięcie rekordu
Przed usunięciem pobierz notatkę ponownie i użyj jej aktualnego ETag-u:
curl --request DELETE --url "$BASE_URL/api/v1/notes/$NOTE_ID" \
--header "Accept: application/json" \
--header "X-Codenica-Client-Id: $CLIENT_ID" \
--header "X-Codenica-Client-Secret: $CLIENT_SECRET" \
--header "If-Match: $NOTE_ETAG" \
--header "Idempotency-Key: notes-delete-20260905-0001"Poprawne usunięcie wymaga notes:delete i zwraca 200 OK z data=true. Istniejący przepływ usuwania obsługuje również sprzątnięcie powiązań zgodnie z konfiguracją systemu.
Po operacji sprawdź pojedynczy rekord:
curl --request GET --url "$BASE_URL/api/v1/notes/$NOTE_ID" \
--header "X-Codenica-Client-Id: $CLIENT_ID" \
--header "X-Codenica-Client-Secret: $CLIENT_SECRET"Oczekiwany status to 404 z kodem note_not_found. Dodatkowo sprawdź własny identyfikator:
curl --request GET --url "$BASE_URL/api/v1/notes?customId=NOTE-ERP-2026-0001&page=1&pageSize=10" \
--header "X-Codenica-Client-Id: $CLIENT_ID" \
--header "X-Codenica-Client-Secret: $CLIENT_SECRET"Po poprawnym usunięciu totalItems powinno wynosić 0. Usuń identyfikator z lokalnego indeksu integracji albo oznacz go jako nieaktywny.
Notatki - błędy, limity i bezpieczeństwo
Błędy API używają formatu Problem Details z dodatkowymi polami Codenica:
{
"type": "https://docs.codenica.com/errors/note_not_found",
"title": "Note not found.",
"status": 404,
"detail": "The note does not exist or is outside the caller's access scope.",
"instance": "/api/v1/notes/{id}",
"code": "note_not_found",
"requestId": "request-id-from-response"
}W logice aplikacji używaj przede wszystkim status i code. Tekst detail jest wskazówką dla człowieka i może się zmienić.
400- nieprawidłowe body, parametr, UUID albo wartość pola;401- brak lub nieprawidłowe uwierzytelnienie;403- brak scope'u albo uprawnień użytkownika;404- notatka, plik, relacja lub cel jest niedostępny;409- konflikt identyfikatora, duplikat albo zmiana równoczesna;412- nieaktualny ETag;413- plik albo body przekracza limit;422- istniejący przepływ domenowy odrzucił operację;428- brakuje If-Match albo Idempotency-Key;429- przekroczono limit żądań;500lub503- błąd serwera albo chwilowa niedostępność.
Odczytuj nagłówki X-RateLimit-Limit, X-RateLimit-Remaining i, przy 429, Retry-After. Stosuj kontrolowane ponowienia z rosnącym opóźnieniem. Nigdy nie zapisuj Client Secret w repozytorium, URL-u, kodzie dostarczanym do przeglądarki, historii poleceń ani logach. isPrivate nie zastępuje szyfrowania.
Notatki - kolejność pracy integracji
- Ustal właściwy adres Cloud albo On-Premise i ustaw
BASE_URL. - Utwórz osobny klucz dla aplikacji i środowiska w Ustawienia - API - API Keys.
- Nadaj tylko zakresy potrzebne do odczytu, zapisu, relacji, plików, statystyk lub pinowania.
- Wyślij
GET /api/v1/contexti sprawdź bazę, caller, zakresy oraz limity. - Pobierz
GET /api/v1/notes/schemai zbuduj mapowanie pól oraz celów relacji. - Pobierz listę notatek z paginacją, wyszukiwaniem lub filtrami.
- Utwórz rekord przez
POSTz unikalnymIdempotency-Key. - Zapisz UUID i ETag z odpowiedzi.
- Przy timeoutcie powtórz identyczne żądanie z tym samym kluczem idempotencji.
- Przed każdą mutacją pobierz świeży ETag.
- Używaj
PATCHdo zwykłych pól, a pin do endpointu/pin. - Do relacji używaj wyłącznie celów zwróconych przez schema i poprawnego
targetItemType. - Dla
confirmationsprzekazujrelationshipType=client, a dla pozostałych zbiorów pomiń ten parametr. - Relację autora tylko odczytuj, ponieważ nie ma publicznego zapisu.
- Przy plikach pamiętaj, że Notatki nie mają pliku głównego.
- W batch sprawdzaj wynik każdej pozycji, ponieważ częściowy błąd nie cofa sukcesów.
- Po
412pobierz rekord ponownie i rozstrzygnij konflikt. - Przy
429respektujRetry-After. - Loguj
requestId, status i kod błędu, ale nigdy sekret. - Po zakończeniu integracji usuń nieużywany klucz API.
Taki przebieg pozwala synchronizować notatki z innym systemem bez opierania integracji na założeniach o polach, widoczności, relacjach lub danych systemowych.
