This guide explains how items and fields work at the API level. It covers the JSON shape of an item, how to discover which fields are available for a given container and process, and how the permission model affects what you can read and write. For the conceptual overview, see Items, Fields, and Processes.
DataItem schema
Every work item in Ekso is a DataItem. When you fetch or create an item through the API, the JSON looks like this:
{
"id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"containerId": "f9e8d7c6-b5a4-3210-fedc-ba0987654321",
"processId": "d4c3b2a1-0987-6543-2109-876543210fed",
"sequence": 42,
"boardId": "b0a1b2c3-d4e5-f678-90ab-cdef01234567",
"cycleId": "c1d2e3f4-a5b6-7890-cdef-1234567890ab",
"resourceType": 1,
"resourceId": "u1234567-89ab-cdef-0123-456789abcdef",
"dateOpened": "2025-11-01T09:00:00Z",
"dateWorking": "2025-11-02T14:30:00Z",
"dateClosed": null,
"field": [
{ "fieldId": "Name", "data": "Fix login timeout" },
{ "fieldId": "Priority", "data": "p-high-id" },
{ "fieldId": "Status", "data": "s-working-id" },
{ "fieldId": "OwnedBy", "data": "u1234567-89ab-cdef-0123-456789abcdef" },
{ "fieldId": "Description", "data": "Users report a 30-second delay on the login page." }
],
"time": [],
"meta": [],
"created": "2025-11-01T09:00:00Z",
"createdBy": "u1234567-89ab-cdef-0123-456789abcdef",
"updated": "2025-11-03T11:15:00Z",
"updatedBy": "u1234567-89ab-cdef-0123-456789abcdef"
}
Top-level properties
| Property | Type | Description |
|---|
id | string | Unique item identifier. |
containerId | string | The container this item belongs to. |
processId | string | The process that defines the item’s workflow and fields. |
sequence | integer | Auto-incremented number within the container. Combined with the container key to form the item key (e.g., GEM-42). |
boardId | string | The board the item is planned on, if any. |
cycleId | string | The cycle within the board, if any. |
resourceType | integer | 0 = unassigned, 1 = User, 2 = JobRole. |
resourceId | string | ID of the assigned user or job role. |
dateOpened | datetime | When the item was opened. |
dateWorking | datetime | When work began. |
dateClosed | datetime | When the item was closed. |
field | array | Field values — see the field array below. |
time | array | Time log entries. See Time tracking. |
meta | array | Key-value metadata pairs. |
created | datetime | Record creation timestamp. |
createdBy | string | User ID of the creator. |
updated | datetime | Last update timestamp. |
updatedBy | string | User ID of the last updater. |
The field array
The field array is where most of the item’s data lives. Each entry is a simple pair:
| Property | Type | Description |
|---|
fieldId | string | References a field definition. Can be a system field name (e.g., Name, Priority) or a custom field ID. |
data | string | The field’s value, always stored as a string regardless of the field type. |
All field values are strings. A date field stores "2025-12-15T00:00:00Z", an integer stores "42", a toggle stores "true" or "false". Your integration must interpret the string according to the field’s type — use the screen endpoint to get the full field definition alongside each value.
Field definitions
The GET /api/field endpoint returns every field definition in your tenant. Each field definition describes the field’s type, validation rules, and configuration.
Field types
Ekso supports ten field types. Each type serializes its value as a string in the data property:
| Type | Description | Example data value |
|---|
| Text | Plain text, multiline, or rich text. | "Fix the login timeout" |
| List | Single or multi-select from predefined values. | "list-value-id" |
| Picker | References another entity (user, container, board, etc.). | "entity-id" |
| Date | UTC date/time. | "2025-12-15T00:00:00Z" |
| Integer | Whole number within min/max bounds. | "42" |
| Decimal | Decimal number within min/max bounds. | "99.50" |
| Percent | Percentage value (0–100 by default). | "75" |
| Time | Duration (days, hours, minutes). | "02:30" |
| Toggle | Boolean on/off. | "true" |
For a full explanation of each type and the system fields, see Fields.
Key field properties
Every field definition includes these properties:
| Property | Type | Description |
|---|
id | string | Unique field identifier. |
name | string | Field name, used as the fieldId in item data (e.g., Name, Priority). |
prompt | string | Display label for the field. |
description | string | Admin-facing description of the field’s purpose. |
fieldType | string | One of: Text, List, Picker, Date, Integer, Decimal, Percent, Time, Toggle. |
defaultValue | string | Default value applied when creating an item. |
isCore | boolean | true for system fields, false for custom fields. |
placement | array | Where the field appears — Process (item forms) or Board (board views). |
usage | array | How the field is used — System, Input, Filter, Condition, Action. |
Picker scopes
Picker fields reference a specific entity type. The scope property tells you what kind of entity the picker selects:
| Scope | Picks from |
|---|
User | Workspace members |
Container | Containers (projects, products, etc.) |
Area | Areas within a container |
Board | Planning boards |
Cycle | Cycles within a board |
Process | Process types |
Resource | Users and job roles |
UserGroup | Security groups |
CostCenter | Cost centers |
Crm | CRM / customer records |
Sku | Billable time codes |
JobRole | Job roles |
List field values
List fields (e.g., Priority, Severity, Status, Resolution) have a data array containing the valid options:
{
"fieldType": "List",
"name": "Priority",
"data": [
{ "id": "p-critical", "value": "Critical", "image": "", "metadata": "", "active": true },
{ "id": "p-high", "value": "High", "image": "", "metadata": "", "active": true },
{ "id": "p-medium", "value": "Medium", "image": "", "metadata": "", "active": true },
{ "id": "p-low", "value": "Low", "image": "", "metadata": "", "active": true }
]
}
| Property | Type | Description |
|---|
id | string | The value you send in the item’s data property. |
value | string | Display text. |
image | string | Optional icon path. |
metadata | string | Additional metadata — for Status fields, this indicates the lifecycle verb (Open, Working, Closed, Blocked). |
active | boolean | false means the value is retired — it won’t appear in selection lists but existing items retain it. |
When setting a list field value, always send the list item id, not the display text. For example, send "p-high" not "High".
Process field configuration
A process controls which fields appear on an item and whether each field is required. The GET /api/process endpoint returns process definitions, each with a fields array:
{
"id": "proc-defect-id",
"name": "Defect",
"fields": [
{ "fieldId": "Name", "order": 1, "required": true },
{ "fieldId": "Description", "order": 2, "required": false },
{ "fieldId": "Priority", "order": 3, "required": true },
{ "fieldId": "Severity", "order": 4, "required": true },
{ "fieldId": "Status", "order": 5, "required": true },
{ "fieldId": "OwnedBy", "order": 6, "required": false },
{ "fieldId": "custom-field-id", "order": 7, "required": false }
]
}
| Property | Type | Description |
|---|
fieldId | string | References the field definition. |
order | integer | Display order on item forms. |
required | boolean | Whether the field must have a value when creating or updating an item. |
The same field can be required in one process and optional in another. For example, Severity might be required for Defects but optional for Change Requests.
Every process always includes certain system fields — Name, Description, Status, OwnedBy, RestrictedTo, and audit fields — even if they’re not listed in the fields array. These are always present on every item.
The screen endpoint
The POST /api/item/screen endpoint is the primary discovery tool for API consumers. It combines field definitions, current values, required flags, and permission filtering into a single response — giving you exactly the fields the current user can work with.
Request
Send an ItemScreenRequest:
{
"containerId": "CONTAINER_ID",
"processId": "PROCESS_ID",
"itemId": "",
"stage": 2,
"source": "Api"
}
| Property | Type | Required | Description |
|---|
containerId | string | Yes | The container the item belongs to (or will be created in). |
processId | string | Yes | The process type. |
itemId | string | No | The item ID for existing items. Leave empty when creating a new item. |
stage | integer | Yes | The screen stage — determines which permission column to evaluate. |
source | string | No | Origin of the request. Use "Api" for API integrations. |
Screen stages
The stage parameter controls which permission column the endpoint evaluates:
| Stage | Value | Use when… |
|---|
| See | 1 | Viewing an item — returns fields the user can read. |
| Set | 2 | Creating an item — returns fields the user can set on creation. |
| Change | 3 | Updating an item — returns fields the user can modify. |
Response
The endpoint returns an ItemScreenModel:
{
"item": { },
"stage": 2,
"workflow": [
{ "id": "s-open", "value": "Open", "metadata": "Open", "active": true },
{ "id": "s-working", "value": "In Progress", "metadata": "Working", "active": true }
],
"field": [
{
"definition": {
"id": "field-name-id",
"name": "Name",
"prompt": "Name",
"fieldType": "Text",
"defaultValue": "",
"isCore": true
},
"data": "",
"required": true
},
{
"definition": {
"id": "field-priority-id",
"name": "Priority",
"prompt": "Priority",
"fieldType": "List",
"defaultValue": "p-medium",
"isCore": true,
"data": [
{ "id": "p-critical", "value": "Critical", "active": true },
{ "id": "p-high", "value": "High", "active": true },
{ "id": "p-medium", "value": "Medium", "active": true },
{ "id": "p-low", "value": "Low", "active": true }
]
},
"data": "p-medium",
"required": true
}
]
}
| Property | Type | Description |
|---|
item | object | The full item record (blank defaults for stage Set). |
stage | integer | The screen stage that was evaluated. |
workflow | array | Valid next statuses from the item’s current state — only populated for stages Set and Change. |
field | array | Ordered list of fields the user can access, each with its full definition, current value, and required flag. |
Each entry in the field array contains:
| Property | Type | Description |
|---|
definition | object | The full polymorphic field definition — includes type-specific properties like data for List fields, scope for Picker fields, or maximum for Text fields. |
data | string | The field’s current value (or default value for new items). |
required | boolean | Whether this field must be provided. |
The screen endpoint only returns fields the current user has permission to access. If a field is missing from the response, the user’s group does not have the required access level for that field at the requested stage.
Field-level permissions
Each container can configure per-field permissions for every process. Three access levels control who can interact with each field:
| Access level | Stage | Controls |
|---|
| See | 1 | Which user groups can view the field value. |
| Set | 2 | Which user groups can provide a value when creating an item. |
| Change | 3 | Which user groups can modify the value after creation. |
By default, all three levels are set to Everyone — all users in the workspace can see, set, and change every field. Admins can restrict any level to specific user groups.
The screen endpoint respects these permissions automatically. When you call it with a particular stage, the response includes only the fields that the authenticated user’s groups have access to for that stage.
For the conceptual explanation and configuration details, see Field-level access control.
If you send field values for fields the user cannot edit, the API will reject the request. Always use the screen endpoint to discover which fields are available before building your request payload.
Creating an item via the API
Discover available fields
Call the screen endpoint with stage Set to find out which fields the current user can provide:curl -X POST https://{tenant}.ekso.app/api/item/screen \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"containerId": "CONTAINER_ID",
"processId": "PROCESS_ID",
"itemId": "",
"stage": 2,
"source": "Api"
}'
The response field array tells you every field you can set, its type, default value, and whether it’s required. Build the field array
Using the screen response, build your field array. Include all required fields and any optional fields you want to set:[
{ "fieldId": "Name", "data": "Fix login timeout" },
{ "fieldId": "Priority", "data": "p-high" },
{ "fieldId": "Severity", "data": "s-major" },
{ "fieldId": "Description", "data": "Users report a 30-second delay on the login page." }
]
Use the field definition’s name as the fieldId. For List and Picker fields, use the list item id or entity id as the data value. Create the item
Send a POST to /api/item with the container, process, and field values:curl -X POST https://{tenant}.ekso.app/api/item \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"containerId": "CONTAINER_ID",
"processId": "PROCESS_ID",
"field": [
{ "fieldId": "Name", "data": "Fix login timeout" },
{ "fieldId": "Priority", "data": "p-high" },
{ "fieldId": "Severity", "data": "s-major" },
{ "fieldId": "Description", "data": "Users report a 30-second delay on the login page." }
]
}'
The response includes the created item with its generated key (e.g., GEM-42), all field values, and default values applied by the system. Handle validation errors
If required fields are missing or values are invalid, the API returns a 400 with details:{
"kind": "Validation",
"message": "One or more fields failed validation.",
"fields": [
{ "field": "Name", "code": "required" }
]
}
Check the fields array to identify which values need correction.
Updating an item via the API
Fetch the item
Retrieve the current item by ID:curl -X POST https://{tenant}.ekso.app/api/item/ITEM_ID \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"containerId": "CONTAINER_ID"
}'
Discover editable fields
Call the screen endpoint with stage Change to find which fields the user can modify:curl -X POST https://{tenant}.ekso.app/api/item/screen \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"containerId": "CONTAINER_ID",
"processId": "PROCESS_ID",
"itemId": "ITEM_ID",
"stage": 3,
"source": "Api"
}'
The response includes each field’s current value in the data property. The workflow array shows the valid next statuses. Update the item
Send a PUT to /api/item/{id} with the updated field values:curl -X PUT https://{tenant}.ekso.app/api/item/ITEM_ID \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"containerId": "CONTAINER_ID",
"processId": "PROCESS_ID",
"field": [
{ "fieldId": "Status", "data": "s-working" },
{ "fieldId": "Priority", "data": "p-critical" }
]
}'
Only include the fields you want to change. The API merges your updates with the existing field values.
Next steps