Work Tasks in Codenica API
Before sending the first Work Task request, create an API key in your Codenica settings. If you do not have one yet, open Codenica API - introduction in a new tab. That article covers the shared rules for key creation, authentication, API addresses and secure secret storage.
A Work Task records a specific activity, responsibility or piece of work to be completed. One record can contain a due date, status, priority, category, description, location, department, link and tags. A Work Task can also be linked to other objects used in Service Desk work and asset management.
In the API contract, one record has itemType equal to worktask, while the endpoint collection is called worktasks. The examples contain safe demonstration values. Replace identifiers, addresses and dates with values from your integration.
Work Tasks - API address and installation choice
All Work Task routes start with:
{BASE_URL}/api/v1/worktasksBASE_URL is the Codenica application address without the /api/v1 suffix. Do not append a database name or company identifier to the address.
Codenica Cloud: use the domain or subdomain assigned to the company:
export BASE_URL="https://{your-company-domain}"Codenica On-Premise: the default address registered locally by Codenica Discovery is:
export BASE_URL="http://codenica.local:5150"If the administrator exposed the installation through a company domain, HTTPS, a reverse proxy or another port, use the exact address provided for that installation. Details are available in the Codenica On-Premise installation guide. Use localhost only in a deliberate local test environment where the HTTP client and API run on the same computer.
Do not send tenantId in the body or query parameters. The correct database is selected from the request address and host.
Work Tasks - API key and licence limits
Create the key in Settings -> API -> API Keys. A separate key for each application and environment makes access easier to control. Give the key a clear name and select only the scopes needed for Work Tasks.
Deleting a key removes its record and frees a place within the limit. Expiration stops authentication, but it does not replace keeping the key list tidy. If no end date is selected, the default active period is 90 days; the maximum period for one key is 5 years.
Work Tasks - request authentication
Authenticate every Codenica API request with two headers:
X-Codenica-Client-Id: {CLIENT_ID}
X-Codenica-Client-Secret: {CLIENT_SECRET}
Accept: application/jsonExample of the first read:
export PUBLIC_API_CLIENT_ID="cna_your_client_id"
export PUBLIC_API_CLIENT_SECRET="cns_your_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"An external integration does not need a panel session or the user's Bearer JWT. Store the secret on the server side or in a secrets manager. Do not place it in browser code, a repository, a URL, shell history or logs.
Work Tasks - check the connection context
Read the context before downloading a list or creating the first Work Task. This confirms that the address leads to the correct database and that the key has the required scopes and limits.
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" | jqVerify data.tenant.id, data.tenant.name, data.tenant.subdomain, data.tenant.resolvedDomain, data.caller.clientId and data.caller.scopes in the response. Also check that the capabilities include supportsRelationships, supportsFiles, supportsETag and 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}"
}
}If the context points to another company or does not include the required scope, stop the integration and correct the address or key. Do not try to change the database by adding a foreign identifier to the body.
Work Tasks - schema and supported fields
The schema is the source of truth for the current Work Task configuration. It returns field types, required values, writability, technical fields and relationship targets available in the installation.
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"
}
]
}
}Do not assume that every database has the same configuration. Before mapping fields, read the current schema and respect readable, writable, required, technical and maxLength.
Work Tasks - writable and system fields
The following fields are intended for attributes. If the schema for the current installation gives different limits, it takes priority.
customIddateDuedateEndlocationdepartmenttaglinktitlestatusprioritycategorydescriptionThe pin field is read-only and is changed through the dedicated /pin route. Technical fields such as authorId, agentId, workTimeId, creator, updater, dateCreated, dateUpdated, importId, importSource and dateImported are filled by the system. Do not send them in a normal create request or PATCH. The itemType value must always be worktask.
Work Tasks - main endpoints
The list below shows the main operations available for the worktask object. Add only the scope required for the operation you want to perform.
Work Tasks - listing and pagination
Read the Work Task list page by page. Set sorting explicitly so that subsequent reads use a predictable order:
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" | jqRead data.items, page, pageSize, totalItems, totalPages and hasNextPage in the response. When hasNextPage is true, request the next page. Check the maximum page size in data.capabilities.limits.maxPageSize from the context.
Use ids to request selected UUIDs. For synchronization, it is better to keep a stable customId in the integrating application and then store the UUID returned by Codenica API.
Work Tasks - search and filters
The list supports text search, matching selected fields and a structural filter. Common parameters include customId, search, title, status, priority, category, location, department, tag, createdAfter, createdBefore, updatedAfter and 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=workstation&filter=status%3Aeq%3AOpen&sort=dateDue&direction=asc&page=1&pageSize=25" | jqA filter has the form field:operator:value. Examples of operators:
status:eq:Open
priority:ne:Low
title:startswith:Prepare
description:contains:workstation
dateDue:gte:2026-09-01T00:00:00ZThe shortcuts =, !=, ge, le, sw and ew correspond to equality, inequality, greater than or equal, less than or equal, startswith and endswith. URL-encode values containing special characters.
Work Tasks - field selection and included data
Use fields to limit the fields returned in a record. This keeps the response smaller and easier to process:
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" | jqUse include when related data is needed:
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" | jqIncluded data does not increase the key's permissions. To see files, relationships or users, the key needs worktasks:files:read, worktasks:relationships:read and worktasks:users:read. Use full fields=* only when technical fields are actually needed.
Work Tasks - statistics and field values
Statistics help build summaries without downloading the entire collection. Example: count Work Tasks by status:
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}"
}
}The values endpoint returns field values matching a search. This is useful, for example, for suggestions in a form:
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" | jqBoth routes are read-only and require the worktasks:stats scope.
Work Tasks - minimal creation
A minimal write should contain itemType and an attributes object. In practice, set your own customId and title immediately:
{
"itemType": "worktask",
"attributes": {
"customId": "ERP-WORKTASK-2026-0042",
"title": "Prepare workstation",
"status": "Open",
"priority": "High",
"category": "IT"
}
}Request that creates the record:
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": "Prepare workstation",
"status": "Open",
"priority": "High",
"category": "IT"
}
}' \
"$BASE_URL/api/v1/worktasks" | jqA successful response has status 201 Created. Save data.id and the record ETag for further work.
Work Tasks - complete creation
The following example records the data normally needed to pass a Work Task from a work planning system:
{
"itemType": "worktask",
"attributes": {
"customId": "ERP-WORKTASK-2026-0042",
"title": "Prepare a workstation for a new employee",
"description": "Install the computer, configure network access and confirm that the workstation is ready.",
"status": "Open",
"priority": "High",
"category": "Onboarding",
"dateDue": "2026-09-30T12:00:00Z",
"location": "Krakow",
"department": "IT",
"tag": "onboarding,workstation",
"link": "https://portal.example.com/tasks/ERP-WORKTASK-2026-0042"
}
}Status, priority and category values should match the configuration used in your database. The API does not create a new dictionary automatically just because an integration sends a new name.
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" | jqWork Tasks - Idempotency-Key and safe retries
Every mutation made with an API key requires an Idempotency-Key header. The value identifies one business intent. For a retry of the same request, keep the same key and do not change the body. Generate a different value for a new Work Task or another operation.
--header "Idempotency-Key: erp-worktask-create-2026-0042"If the connection breaks after the request is sent, first repeat the identical request with the same key. Do not immediately create a new key, because that may create a duplicate. Without the header, the mutation ends with 428 and code idempotency_key_required.
Work Tasks - read one record
After creation, read the record using the UUID returned in data.id:
export WORKTASK_ID="{UUID_FROM_CREATE_RESPONSE}"
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" | jqA single record contains id, itemType, attributes and meta. Read the ETag from meta; it is needed for the next mutation.
{
"data": {
"id": "{WORKTASK_ID}",
"itemType": "worktask",
"attributes": {
"customId": "ERP-WORKTASK-2026-0042",
"title": "Prepare a workstation for a new employee",
"status": "Open"
},
"meta": {
"customId": "ERP-WORKTASK-2026-0042",
"etag": "{CURRENT_ETAG}"
}
},
"meta": {
"requestId": "{REQUEST_ID}",
"etag": "{CURRENT_ETAG}"
}
}Work Tasks - update with ETag and If-Match
Before changing a record, read its current version and keep the exact ETag value, including quotation marks when they are part of it:
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 changes only the selected attributes. Save the new ETag after success:
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": "Configure workstation for a new employee",
"status": "In progress",
"priority": "Normal",
"description": "The computer and network access are being configured."
}
}' \
"$BASE_URL/api/v1/worktasks/$WORKTASK_ID" | jqDo not use an ETag saved before another change. Every successful mutation can change the record version.
Work Tasks - stale or missing ETag
If another person or integration changed the Work Task, an old ETag ends with 412 Precondition Failed and code if_match_failed. The API should not apply the rejected change.
{
"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, relationships, files and pinning without the required If-Match return 428 Precondition Required with code if_match_required. After 412, read the record again, decide whether to keep the local change, and only then send a new request.
Work Tasks - pin and unpin
The pin field is read-only inside attributes. Change it through the dedicated endpoint:
POST /api/v1/worktasks/{WORKTASK_ID}/pinPin at level 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" | jqThe value null unpins the Work Task:
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" | jqRead the Work Task again after either operation because its ETag may change.
Work Tasks - author and agent user relationships
The user relationship has its own route and is used to read the Work Task author and assigned agent:
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" | jqThe collection contains only relationships with type author or agent. An example item:
{
"targetId": "{USER_ID}",
"targetDataSet": "users",
"relationshipType": "agent",
"displayName": "Anna Kowalska",
"email": "[email protected]",
"role": "Agent"
}authorId and agentId are technical fields. Do not try to change them through a normal PATCH attributes. If the API version provides a separate assignment action, follow its schema and required scope.
Work Tasks - permitted object relationships
The Work Task schema exposes eleven object groups that can be relationship targets:
For assets, the type depends on the specific asset. The table uses computer as an example; read the actual itemType of the selected object before saving the relationship.
Work Tasks - choosing targetItemType and relationship format
targetItemType must match the actual type of the target object. The safest order is: read the target list or schema, read its itemType, and only then build the relationship body.
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}'Work Task object relationships do not accept relationshipType. Send only the identifier, collection name and object type:
{
"targetId": "{ASSET_ID}",
"targetDataSet": "assets",
"targetItemType": "computer"
}Do not copy asset, document or task without checking the specific target. An incorrect type ends with a validation error.
Work Tasks - add, read and remove a relationship
Adding one asset relationship requires the current Work Task ETag and a separate idempotency key:
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" | jqRead the relationship with a dataset filter:
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" | jqRemove one relationship:
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}" | jqAfter removal, the response should contain data=true. Adding a new relationship returns 201 Created; in some situations, pointing to an existing relationship again may return 200 OK.
Work Tasks - relationship batch
Add or remove multiple relationships in one request:
{
"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}"
}
}Relationship batches also do not accept relationshipType. Use the current Work Task ETag and read the item limit from the context. Save the new ETag if one is returned, then read the collection to verify the result.
Work Tasks - file list and upload
Files assigned to a Work Task use a separate endpoint group. Start by reading the 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" | jqA list item includes id, fileName, contentType, size, relationshipType, isMain and downloadUrl. Upload a new file as 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=@./workstation-instructions.pdf;type=application/pdf" \
"$BASE_URL/api/v1/worktasks/$WORKTASK_ID/files?relationshipType=instruction" | jqUpload requires worktasks:files:write, the current ETag and the file limit read from the context. For Work Tasks, the API sets isMain=false; do not assume a separate main-file operation.
Work Tasks - download and attach a file
Download file content through the content route and save it in binary mode:
curl --fail-with-body --silent --show-error \
--output ./workstation-instructions-downloaded.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"If a file is already stored in the system, attach it to a second Work Task without uploading the content again. Read the second Work Task ETag first:
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" | jqAttach creates a file relationship with the second Work Task. The same file can be visible in both records, and reference is the file relationship type, not an object relationship type.
Work Tasks - detach and delete a file
Detach the file from the second Work Task using its current 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}" | jqDetaching should return data=true and should not remove the file relationship from the source Work Task. To remove the file from the source, read its new ETag and run:
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}" | jqCheck the file list after deletion. Work Tasks do not have a separate endpoint for setting a main file.
Work Tasks - batch operations for records
The /api/v1/worktasks:batch endpoint combines Work Task creation, updates and deletion. Each update or delete item has its own ETag:
{
"items": [
{
"operation": "create",
"create": {
"itemType": "worktask",
"attributes": {
"customId": "ERP-WORKTASK-BATCH-A",
"title": "Prepare access",
"status": "Open",
"priority": "Normal",
"category": "IT"
}
}
},
{
"operation": "update",
"id": "{WORKTASK_ID}",
"ifMatch": "{CURRENT_ETAG}",
"update": {
"attributes": {
"title": "Prepare access - second stage",
"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}"
}
}For a partial result, the API may return 207 Multi-Status. Go through data.items, inspect each item and retry only operations that actually need another attempt.
Work Tasks - delete a record
Before deletion, read the record again, check its UUID and current ETag, and use a new idempotency key:
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" | jqA successful response contains 200 OK and data=true. After deletion, verify that the record is no longer available:
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"The expected status is 404 Not Found. You can also filter the list with customId=ERP-WORKTASK-2026-0042 and confirm totalItems=0.
Work Tasks - errors, limits and safe order of operations
Problem responses use the Problem Details format. Use code in integration logic and keep requestId as well when reporting a problem. Do not put the secret or complete headers in logs.
validation_failedauthentication_requiredworktask_not_foundfile_not_foundif_match_failedfile_too_largeif_match_requiredidempotency_key_requiredinternal_errorRead X-RateLimit-Limit and X-RateLimit-Remaining headers. At 429, use increasing delays with jitter, limit the number of attempts and never loop indefinitely for 400, 401, 403, 404 or 412.
Safe order of operations
- Set
BASE_URLfor the correct installation and read thecontext. - Check scopes, limits, schema and the actual
itemTypeof relationship targets. - Create a Work Task with its own
Idempotency-Key, then save the UUID and ETag. - Read the current ETag before every change, relationship, file operation or pin action.
- Save the new ETag after a successful mutation and verify the result with a read.
- After synchronization, check the record by
customIdand delete demonstration data with a separate request. - In n8n, use the HTTP Request node; keep the Client ID and Client Secret in credentials and pass the UUID, ETag and idempotency key between nodes.
