Skip to documentation

Team goals

Manage the team goals shown in Huddles with a workspace API key. These goals are separate from main OKRs; keyResultId optionally connects a goal to an OKR key result. All routes require teamId. Grant team-goals:read, team-goals:write or team-goals:delete for the operations needed. API keys can address teams throughout their workspace. GET responses use Cache-Control: private, no-store.

7 endpoints

POST

Refresh the Huddle after goal changes

POST /external/v1/team-goals/refresh-huddle

After a batch of goal changes, rebuild the saved Huddle for the chosen team/date so its Goals widget reflects those changes. This is the same full snapshot refresh used by Huddle: it also refreshes customer evidence, delivery, pending actions and comparison data, while preserving conversation sources and reviewed artifacts. An existing daily snapshot is replaced and refreshRevision increases; a missing one is created. Use the current Huddle date unless you intentionally want to rebuild historical state. Only active goals whose dates include this day and which are unassigned to a cycle or belong to the current cycle appear.

Requirements

API scopes required:
team-goals:write

Request

Parameters

NameTypeDescription
teamId *UUIDExplicit team ID in the key’s workspace (query). Find IDs with GET /external/v1/teams and initiatives:read.
date *stringHuddle date as YYYY-MM-DD (body). Match the date selected in Huddle.

Responses

201
Refreshed

Reload Huddle to see the saved snapshot, or read GET /external/v1/huddles/:id with huddles:read or initiatives:read.

400
Invalid input

Invalid or unsupported fields, reversed dates, invalid milestone targets, owner outside the team or cycle outside the team. Correct the input before retrying.

401
Unauthorized

Missing, invalid, expired or disabled API key.

403
Missing scope

Grant the scope named for this endpoint.

404
Not found

Team or goal is outside the key workspace/team, or a linked key result is outside the workspace.

429
Rate limited

Wait for Retry-After before retrying.

Example Request

POST
/external/v1/team-goals/refresh-huddle
curl
curl -X POST 'https://zentrik.ai/api/external/v1/team-goals/refresh-huddle?teamId=33333333-3333-4333-8333-333333333333' -H 'Authorization: Bearer YOUR_API_KEY' -H 'Content-Type: application/json' -d '{"date":"2026-10-21"}'

Example Response

201 Created
json
{
  "huddleId": "55555555-5555-4555-8555-555555555555",
  "teamId": "33333333-3333-4333-8333-333333333333",
  "date": "2026-10-21",
  "refreshRevision": 2
}
GET

List team goals

GET /external/v1/team-goals

List this team’s goals, newest start date first, then newest creation time. Archived goals are excluded by default. Supplying date selects only active goals whose inclusive date range contains that date, matching Huddle eligibility. Returns an array with X-Total-Count, X-Limit, X-Offset and X-Has-More headers. Concurrent edits can shift offset pages.

Requirements

API scopes required:
team-goals:read

Request

Parameters

NameTypeDescription
teamId *UUIDExplicit team ID in the key’s workspace (query). Find IDs with GET /external/v1/teams and initiatives:read.
date stringYYYY-MM-DD; return only active goals for this date, even if includeArchived=true.
includeArchived booleanLiteral true or false. Default false.
limit integer1–100; default 20.
offset integer0–1,000,000; default 0.

Responses

200
Success

The requested team-goal data or deletion confirmation.

400
Invalid input

Invalid or unsupported fields, reversed dates, invalid milestone targets, owner outside the team or cycle outside the team. Correct the input before retrying.

401
Unauthorized

Missing, invalid, expired or disabled API key.

403
Missing scope

Grant the scope named for this endpoint.

404
Not found

Team or goal is outside the key workspace/team, or a linked key result is outside the workspace.

429
Rate limited

Wait for Retry-After before retrying.

Example Request

GET
/external/v1/team-goals
curl
curl -X GET 'https://zentrik.ai/api/external/v1/team-goals?teamId=33333333-3333-4333-8333-333333333333' -H 'Authorization: Bearer YOUR_API_KEY'

Example Response

200 OK
json
[
  {
    "id": "44444444-4444-4444-8444-444444444444",
    "workspaceId": "22222222-2222-4222-8222-222222222222",
    "teamId": "33333333-3333-4333-8333-333333333333",
    "title": "Interview five customers",
    "description": "",
    "startDate": "2026-10-21",
    "endDate": "2026-10-27",
    "progress": 0,
    "status": "active",
    "ownerUserId": null,
    "cycleId": null,
    "keyResultId": null,
    "milestones": [],
    "analysisStatus": "queued",
    "suggestion": null,
    "createdAt": "2026-10-21T09:00:00.000Z",
    "updatedAt": "2026-10-21T09:00:00.000Z"
  }
]
GET

List goal cycles

GET /external/v1/team-goals/cycles

Return the team’s available goal cycles and currentCycleId, or null when there is no current cycle. The cycles array places the current cycle first, followed by the remaining cycles in descending start-date order. Use the returned ID when assigning a goal to a cycle.

Requirements

API scopes required:
team-goals:read

Request

Parameters

NameTypeDescription
teamId *UUIDExplicit team ID in the key’s workspace (query). Find IDs with GET /external/v1/teams and initiatives:read.

Responses

200
Success

The requested team-goal data or deletion confirmation.

400
Invalid input

Invalid or unsupported fields, reversed dates, invalid milestone targets, owner outside the team or cycle outside the team. Correct the input before retrying.

401
Unauthorized

Missing, invalid, expired or disabled API key.

403
Missing scope

Grant the scope named for this endpoint.

404
Not found

Team or goal is outside the key workspace/team, or a linked key result is outside the workspace.

429
Rate limited

Wait for Retry-After before retrying.

Example Request

GET
/external/v1/team-goals/cycles
curl
curl -X GET 'https://zentrik.ai/api/external/v1/team-goals/cycles?teamId=33333333-3333-4333-8333-333333333333' -H 'Authorization: Bearer YOUR_API_KEY'

Example Response

200 OK
json
{
  "currentCycleId": null,
  "cycles": []
}
GET

Get a team goal

GET /external/v1/team-goals/:id

Read one goal, including its recorded progress, accepted milestones and analysisStatus. suggestion is advisory; creating or editing a goal can queue analysis, but suggestions do not silently replace its wording, milestones or progress. Joined user profiles are not returned.

Requirements

API scopes required:
team-goals:read

Request

Parameters

NameTypeDescription
teamId *UUIDExplicit team ID in the key’s workspace (query). Find IDs with GET /external/v1/teams and initiatives:read.
id *UUIDTeam goal ID (path), not an OKR or key-result ID.

Responses

200
Success

The requested team-goal data or deletion confirmation.

400
Invalid input

Invalid or unsupported fields, reversed dates, invalid milestone targets, owner outside the team or cycle outside the team. Correct the input before retrying.

401
Unauthorized

Missing, invalid, expired or disabled API key.

403
Missing scope

Grant the scope named for this endpoint.

404
Not found

Team or goal is outside the key workspace/team, or a linked key result is outside the workspace.

429
Rate limited

Wait for Retry-After before retrying.

Example Request

GET
/external/v1/team-goals/:id
curl
curl -X GET 'https://zentrik.ai/api/external/v1/team-goals/44444444-4444-4444-8444-444444444444?teamId=33333333-3333-4333-8333-333333333333' -H 'Authorization: Bearer YOUR_API_KEY'

Example Response

200 OK
json
{
  "id": "44444444-4444-4444-8444-444444444444",
  "workspaceId": "22222222-2222-4222-8222-222222222222",
  "teamId": "33333333-3333-4333-8333-333333333333",
  "title": "Interview five customers",
  "description": "",
  "startDate": "2026-10-21",
  "endDate": "2026-10-27",
  "progress": 0,
  "status": "active",
  "ownerUserId": null,
  "cycleId": null,
  "keyResultId": null,
  "milestones": [],
  "analysisStatus": "queued",
  "suggestion": null,
  "createdAt": "2026-10-21T09:00:00.000Z",
  "updatedAt": "2026-10-21T09:00:00.000Z"
}
POST

Create a team goal

POST /external/v1/team-goals

Create a team goal for the Goals widget. The workspace comes from the API key. Each successful POST creates a new goal and queues the existing goal review. Save the returned ID for later PATCH requests. Creation is not idempotent: after an uncertain timeout, list and reconcile goals before retrying. Call POST /external/v1/team-goals/refresh-huddle after the batch to update the widget. Creating the goal alone does not rewrite saved Huddle snapshots.

Requirements

API scopes required:
team-goals:write

Request

Parameters

NameTypeDescription
teamId *UUIDExplicit team ID in the key’s workspace (query). Find IDs with GET /external/v1/teams and initiatives:read.
title *stringNonblank title, at most 200 characters.
startDate *stringInclusive start date, YYYY-MM-DD.
endDate *stringInclusive end date, YYYY-MM-DD, on or after startDate.
description stringAt most 4,000 characters. Empty string clears it.
progress integerRecorded progress from 0 to 100. Defaults to 0; milestone completion does not recalculate it.
status stringplanned, active, completed or archived. Defaults to active.
ownerUserId UUID or nullUse userId from GET /external/v1/teams/:teamId/members (teams:read scope). The owner must still belong to this team when saved. Null clears the owner.
cycleId UUID or nullCycle in the same team; find IDs with GET /external/v1/team-goals/cycles. A linked cycle determines the goal dates and overrides supplied dates. Null removes the link.
keyResultId UUID or nullOptional key result in this workspace. Find IDs through GET /external/v1/okrs with okrs:read. Null removes the link.
milestones arrayUp to 50 entries: title (1–200 characters), targetProgress (integer 1–100), optional description (up to 1,000 characters or null), isCompleted (boolean), and existing id (UUID, for updates). Targets must be unique; supplied order determines display order.

Responses

201
Created

The saved team goal. Analysis may still be queued; read the goal to check its status.

400
Invalid input

Invalid or unsupported fields, reversed dates, invalid milestone targets, owner outside the team or cycle outside the team. Correct the input before retrying.

401
Unauthorized

Missing, invalid, expired or disabled API key.

403
Missing scope

Grant the scope named for this endpoint.

404
Not found

Team or goal is outside the key workspace/team, or a linked key result is outside the workspace.

429
Rate limited

Wait for Retry-After before retrying.

Example Request

POST
/external/v1/team-goals
curl
curl -X POST 'https://zentrik.ai/api/external/v1/team-goals?teamId=33333333-3333-4333-8333-333333333333' -H 'Authorization: Bearer YOUR_API_KEY' -H 'Content-Type: application/json' -d '{"title":"Interview five customers","startDate":"2026-10-21","endDate":"2026-10-27"}'

Example Response

201 Created
json
{
  "id": "44444444-4444-4444-8444-444444444444",
  "workspaceId": "22222222-2222-4222-8222-222222222222",
  "teamId": "33333333-3333-4333-8333-333333333333",
  "title": "Interview five customers",
  "description": "",
  "startDate": "2026-10-21",
  "endDate": "2026-10-27",
  "progress": 0,
  "status": "active",
  "ownerUserId": null,
  "cycleId": null,
  "keyResultId": null,
  "milestones": [],
  "analysisStatus": "queued",
  "suggestion": null,
  "createdAt": "2026-10-21T09:00:00.000Z",
  "updatedAt": "2026-10-21T09:00:00.000Z"
}
PATCH

Update a team goal

PATCH /external/v1/team-goals/:id

Update at least one goal field, then call POST /external/v1/team-goals/refresh-huddle to update the widget. Omitted fields remain unchanged. Only ownerUserId, cycleId and keyResultId accept null to clear their links. Supplying milestones replaces the entire list: preserve IDs for milestones you want to keep; [] removes all milestones. Milestone completion does not update recorded progress. Set status to completed or archived to retain the record without showing it as an active Huddle goal.

Requirements

API scopes required:
team-goals:write

Request

Parameters

NameTypeDescription
teamId *UUIDExplicit team ID in the key’s workspace (query). Find IDs with GET /external/v1/teams and initiatives:read.
id *UUIDTeam goal ID (path), not an OKR or key-result ID.
title stringNonblank title, at most 200 characters.
startDate stringInclusive start date, YYYY-MM-DD.
endDate stringInclusive end date, YYYY-MM-DD, on or after startDate.
description stringAt most 4,000 characters. Empty string clears it.
progress integerRecorded progress from 0 to 100. Defaults to 0; milestone completion does not recalculate it.
status stringplanned, active, completed or archived. Defaults to active.
ownerUserId UUID or nullUse userId from GET /external/v1/teams/:teamId/members (teams:read scope). The owner must still belong to this team when saved. Null clears the owner.
cycleId UUID or nullCycle in the same team; find IDs with GET /external/v1/team-goals/cycles. A linked cycle determines the goal dates and overrides supplied dates. Null removes the link.
keyResultId UUID or nullOptional key result in this workspace. Find IDs through GET /external/v1/okrs with okrs:read. Null removes the link.
milestones arrayUp to 50 entries: title (1–200 characters), targetProgress (integer 1–100), optional description (up to 1,000 characters or null), isCompleted (boolean), and existing id (UUID, for updates). Targets must be unique; supplied order determines display order.

Responses

200
Success

The requested team-goal data or deletion confirmation.

400
Invalid input

Invalid or unsupported fields, reversed dates, invalid milestone targets, owner outside the team or cycle outside the team. Correct the input before retrying.

401
Unauthorized

Missing, invalid, expired or disabled API key.

403
Missing scope

Grant the scope named for this endpoint.

404
Not found

Team or goal is outside the key workspace/team, or a linked key result is outside the workspace.

429
Rate limited

Wait for Retry-After before retrying.

Example Request

PATCH
/external/v1/team-goals/:id
curl
curl -X PATCH 'https://zentrik.ai/api/external/v1/team-goals/44444444-4444-4444-8444-444444444444?teamId=33333333-3333-4333-8333-333333333333' -H 'Authorization: Bearer YOUR_API_KEY' -H 'Content-Type: application/json' -d '{"progress":60}'

Example Response

200 OK
json
{
  "id": "44444444-4444-4444-8444-444444444444",
  "workspaceId": "22222222-2222-4222-8222-222222222222",
  "teamId": "33333333-3333-4333-8333-333333333333",
  "title": "Interview five customers",
  "description": "",
  "startDate": "2026-10-21",
  "endDate": "2026-10-27",
  "progress": 60,
  "status": "active",
  "ownerUserId": null,
  "cycleId": null,
  "keyResultId": null,
  "milestones": [],
  "analysisStatus": "queued",
  "suggestion": null,
  "createdAt": "2026-10-21T09:00:00.000Z",
  "updatedAt": "2026-10-21T09:00:00.000Z"
}
DELETE

Delete a team goal

DELETE /external/v1/team-goals/:id

Permanently delete a goal and its milestones. Prefer PATCH with status: archived when you need to retain it. A repeated deletion returns 404. Call POST /external/v1/team-goals/refresh-huddle to remove the goal from a saved current snapshot. Other saved snapshots are not rewritten.

Requirements

API scopes required:
team-goals:delete

Request

Parameters

NameTypeDescription
teamId *UUIDExplicit team ID in the key’s workspace (query). Find IDs with GET /external/v1/teams and initiatives:read.
id *UUIDTeam goal ID (path), not an OKR or key-result ID.

Responses

200
Success

The requested team-goal data or deletion confirmation.

400
Invalid input

Invalid or unsupported fields, reversed dates, invalid milestone targets, owner outside the team or cycle outside the team. Correct the input before retrying.

401
Unauthorized

Missing, invalid, expired or disabled API key.

403
Missing scope

Grant the scope named for this endpoint.

404
Not found

Team or goal is outside the key workspace/team, or a linked key result is outside the workspace.

429
Rate limited

Wait for Retry-After before retrying.

Example Request

DELETE
/external/v1/team-goals/:id
curl
curl -X DELETE 'https://zentrik.ai/api/external/v1/team-goals/44444444-4444-4444-8444-444444444444?teamId=33333333-3333-4333-8333-333333333333' -H 'Authorization: Bearer YOUR_API_KEY'

Example Response

200 OK
json
{
  "id": "44444444-4444-4444-8444-444444444444"
}