PI Objectives V1 · Endpoints¶
Base URL: https://{yourcompany}.kendis.io/api/v1/… · Auth: HTTP Basic (email : API key). Examples use example.kendis.io. All responses on the /pi-boards routes use the Data (capital D) envelope.
Every route is addressed through its board: /api/v1/pi-boards/{boardId}/…. See the
Overview for the access rules and how progress is calculated.
About the examples
The examples on this page follow one fictional PI board at a motor insurer, PI 2026.4 Claims Modernisation. The Claims Experience team is working on an objective to launch digital first notice of loss (FNOL), with key results for claim intake time, fraud triage and online adoption,. All names, keys and numbers are illustrative.
Common query parameters on list endpoints:
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
fields |
string | No | all |
Comma-separated optional fields, or all. Core fields are always returned. See Field selection. |
startAt |
int | No | 0 |
Pagination offset |
pageLimit |
int | No | 50 |
Page size (max 50; larger values are capped to 50) |
Detail endpoints accept only fields. Linked-item endpoints take expand, startAt and pageLimit, and do
not take fields. All {keyOrId} parameters accept the item's key (e.g. OBJ-205, KR-311, M-21, P-7)
or its internal ID. Objective groups have no key and are addressed by ID only.
0. Find your board ID¶
GET /api/v1/boards
Returns the boards the API user can see. Use the id of a board as {boardId} on every route below.
{
"data": [
{ "id": "<board-id>", "title": "PI 2026.4 Claims Modernisation", "state": { "id": "<state-id>", "title": "Tracking" } }
]
}
Use the id from this endpoint, not the browser URL
The ID in the address bar of a PI board in Kendis (/session?id=…) is not the board ID, and
returns 404 on these routes. Always take {boardId} from List Boards.
Envelope casing
List Boards returns its array under lowercase data. The /pi-boards routes below return
Data (capital D), the same as the Strategic Themes & OKRs API.
1. Get a PI board summary¶
GET /api/v1/pi-boards/{boardId}
{
"Data": {
"id": "<board-id>",
"type": "PI Board",
"title": "PI 2026.4 Claims Modernisation",
"state": { "id": "<state-id>", "title": "Tracking" },
"okrEnabled": true,
"uncommittedObjectivesEnabled": true,
"counts": { "objectiveGroups": 4, "objectives": 12, "keyResults": 9 }
}
}
2. List Objective Groups of a board¶
GET /api/v1/pi-boards/{boardId}/objective-groups
GET https://example.kendis.io/api/v1/pi-boards/<board-id>/objective-groups?startAt=0&pageLimit=50
Authorization: Basic <token>
{
"startAt": 0,
"pageLimit": 50,
"total": 4,
"Data": [
{
"id": "<group-id>",
"level": 1,
"type": "Objective Group",
"title": "Claims Experience",
"groupType": "TeamGroup",
"team": { "id": "<team-id>", "title": "Team Claims", "label": "CLM" },
"completionPct": 41.5,
"status": { "id": "<status-id>", "status": "On Track", "category": "InProgress" },
"objectivesCount": 3,
"bvPlan": 24.0,
"bvActual": 18.0,
"sequence": 1.0,
"createdBy": "user@example.com",
"updatedBy": "user@example.com",
"createdOn": 1785748500000,
"updatedOn": 1791211200000
}
]
}
groupType is TeamGroup (one group per team on the board) or CustomGroup (a group created by hand,
e.g. a PI-level group). team is present on team groups only.
Group title vs team name
The PI board's Objectives screen labels a team group with the team's name. The group's own
title can differ from it; read team.title / team.label when you want the label the board shows.
3. List Objectives in an Objective Group¶
GET /api/v1/pi-boards/{boardId}/objective-groups/{groupId}/objectives
Same query parameters as endpoint 2. Returns Objective objects (see endpoint 5)
in board order. 404 if the group is not on this board.
4. List all Objectives of a board¶
GET /api/v1/pi-boards/{boardId}/objectives
Same query parameters as endpoint 2. A flat list of every objective on the board. An objective linked to
several groups appears once, with every group listed in groups.
5. Get a single Objective¶
GET /api/v1/pi-boards/{boardId}/objectives/{keyOrId}
GET https://example.kendis.io/api/v1/pi-boards/<board-id>/objectives/OBJ-205
Authorization: Basic <token>
{
"Data": {
"id": "<objective-id>",
"level": 2,
"type": "Objective",
"key": "OBJ-205",
"title": "Launch digital first notice of loss (FNOL) for motor claims",
"completionPct": 38.0,
"objType": "Committed",
"status": { "id": "<status-id>", "status": "On Track", "category": "InProgress" },
"groups": [
{ "id": "<group-id>", "title": "Claims Experience", "groupType": "TeamGroup", "weightage": 1.0 }
],
"completionCriteria": "CHILDREN_LINKED_ITEM_STATUS",
"linkedItemsWeight": 1.0,
"keyResultsCount": 3,
"linkedItemsCount": 0,
"keyResults": [
{ "id": "<kr-id-1>", "key": "KR-311", "title": "Cut average claim intake time from 3 days to 1 day" },
{ "id": "<kr-id-2>", "key": "KR-312", "title": "Score every new motor claim for fraud risk at intake" },
{ "id": "<kr-id-3>", "key": "KR-313", "title": "Raise the share of claims reported online to 60%" }
],
"bvPlan": 8.0,
"bvActual": 6.0,
"sequence": 1.0,
"customFields": [],
"createdBy": "user@example.com",
"updatedBy": "user@example.com",
"createdOn": 1786359720000,
"updatedOn": 1791275400000
}
}
404 if the key or ID does not belong to an objective on this board. A key that exists on another board,
or on a Strategic Theme, is a 404 here.
6. List Key Results of an Objective¶
GET /api/v1/pi-boards/{boardId}/objectives/{keyOrId}/key-results
Same query parameters as endpoint 2.
{
"startAt": 0,
"pageLimit": 50,
"total": 3,
"Data": [
{
"id": "<kr-id-1>",
"level": 3,
"type": "Key Result",
"key": "KR-311",
"title": "Cut average claim intake time from 3 days to 1 day",
"completionPct": 62.5,
"criteria": "By Items",
"completionCriteria": "CHILDREN_LINKED_ITEM_STATUS",
"weightage": 1.0,
"objective": { "id": "<objective-id>", "key": "OBJ-205", "title": "Launch digital first notice of loss (FNOL) for motor claims" },
"status": { "id": "<status-id>", "status": "On Track", "category": "InProgress" },
"linkedItemsCount": 1
},
{
"id": "<kr-id-3>",
"level": 3,
"type": "Key Result",
"key": "KR-313",
"title": "Raise the share of claims reported online to 60%",
"completionPct": 30.0,
"criteria": "Target",
"metric": { "baseline": 20.0, "target": 60.0, "unit": "%", "current": 32.0 },
"weightage": 1.0,
"objective": { "id": "<objective-id>", "key": "OBJ-205", "title": "Launch digital first notice of loss (FNOL) for motor claims" },
"status": { "id": "<status-id>", "status": "Planned", "category": "ToDo" },
"linkedItemsCount": 0
}
]
}
PI key results come in two kinds, told apart by criteria:
Target: progress is(current - baseline) / (target - baseline). The values are inmetric. For KR-313 above: (32 - 20) / (60 - 20) = 30%.By Items: progress comes from the cards linked to the key result (endpoint 9), rolled up with the key result'scompletionCriteria.
7. Get a single Key Result¶
GET /api/v1/pi-boards/{boardId}/key-results/{keyOrId}
Returns a single Key Result object inside Data. 404 if the key or ID does
not belong to a key result on this board. An objective key on this route is also a 404.
8. List cards linked to an Objective¶
GET /api/v1/pi-boards/{boardId}/objectives/{keyOrId}/linked-items
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
expand |
string | No | none | children adds each card's sub-items and a progress summary |
startAt |
int | No | 0 |
Pagination offset |
pageLimit |
int | No | 50 |
Page size (max 50) |
The example below lists the card behind KR-311 (endpoint 9 has the same shape). Its 5 of 8 Done stories give the key result its 62.5%.
GET https://example.kendis.io/api/v1/pi-boards/<board-id>/key-results/KR-311/linked-items?expand=children
Authorization: Basic <token>
{
"startAt": 0,
"pageLimit": 50,
"total": 1,
"Data": [
{
"id": "<card-id>",
"almKey": "FEA-412",
"title": "Online claim submission portal",
"cardType": "Feature",
"almType": "Feature",
"status": { "id": "<status-id>", "status": "In Progress", "category": "InProgress" },
"storyPoints": 0.0,
"url": "https://your-jira.example.com/browse/FEA-412",
"teamsAndSprints": [
{
"team": { "id": "<team-id>", "title": "Team Claims", "label": "CLM" },
"sprint": { "id": "<sprint-id>", "title": "Iteration 2", "label": "S2", "startDate": 1793577600000, "endDate": 1794528000000, "isIPSprint": false }
}
],
"createdOn": 1786359720000,
"updatedOn": 1791275400000,
"childrenSummary": {
"totalItems": 8,
"doneItems": 5,
"totalStoryPoints": 40.0,
"doneStoryPoints": 26.0,
"progressPct": 62.5,
"progressPctByStoryPoints": 65.0
},
"children": [
{
"id": "<child-card-id>",
"almKey": "STORY-1188",
"title": "Upload photos of vehicle damage",
"cardType": "UserStory",
"almType": "Story",
"status": { "id": "<status-id>", "status": "Done", "category": "Done" },
"storyPoints": 5.0,
"teamsAndSprints": [ ]
}
]
}
]
}
childrenSummary and children appear only with expand=children. total counts the card links on the
objective; a link whose card is no longer on the board is skipped in Data.
Story points on parent cards
storyPoints is the card's own estimate. For a Feature whose points live on its stories, the
Objectives screen shows the stories' total; read childrenSummary.totalStoryPoints for that figure.
9. List cards linked to a Key Result¶
GET /api/v1/pi-boards/{boardId}/key-results/{keyOrId}/linked-items
Same parameters and response shape as endpoint 8. Use this route for By Items key results.
Milestones and Phases¶
Milestones and phases of a PI board are a separate API: see Milestones & Phases.
Field selection¶
Group, Objective and Key Result endpoints take fields:
| Usage | Result |
|---|---|
omitted, or ?fields=all |
Every available field |
?fields=description,bvPlan,bvActual |
The core fields plus only the listed optional ones |
Core fields (id, key, title, type, level, completionPct, status, counts and relationship
fields) are always returned. The optional fields per object are listed in the
V1 field reference.
Status codes¶
| Code | Meaning |
|---|---|
200 |
Success |
400 |
Invalid parameter (e.g. pageLimit=abc or an unknown type), or the board's objectives live in the legacy objectives view |
401 |
Missing or invalid API key |
404 |
Board, group, objective or key result not found, or not accessible to the API user |
409 |
The board has objectives but its objectives settings are missing, so its objectives and progress cannot be served. Milestone and phase routes still work. |
500 |
Internal server error |
Error bodies on these routes are { "error": "..." }. A parameter with an invalid value is named in the
message (for example Invalid value for parameter 'pageLimit'.); the value you sent is not repeated back.
A board whose Objectives screen has never been used is not an error: it returns 200 with empty results.
See Boards without objectives.
Quick reference¶
| Action | Method | Path |
|---|---|---|
| Find board IDs | GET |
/api/v1/boards |
| PI board summary | GET |
/api/v1/pi-boards/{boardId} |
| Objective Groups of a board | GET |
/api/v1/pi-boards/{boardId}/objective-groups |
| Objectives in a group | GET |
/api/v1/pi-boards/{boardId}/objective-groups/{groupId}/objectives |
| All Objectives of a board | GET |
/api/v1/pi-boards/{boardId}/objectives |
| Get Objective | GET |
/api/v1/pi-boards/{boardId}/objectives/{keyOrId} |
| Key Results of an Objective | GET |
/api/v1/pi-boards/{boardId}/objectives/{keyOrId}/key-results |
| Get Key Result | GET |
/api/v1/pi-boards/{boardId}/key-results/{keyOrId} |
| Cards linked to an Objective | GET |
/api/v1/pi-boards/{boardId}/objectives/{keyOrId}/linked-items |
| Cards linked to a Key Result | GET |
/api/v1/pi-boards/{boardId}/key-results/{keyOrId}/linked-items |
All URLs: https://{yourcompany}.kendis.io + the path above.