Goals

Goals

A goal is a target for one metric over a period, such as "12 weeks with a clean pipeline by 31 December", owned by a person and usually a team. Harmony reads the metric from Harmony itself, from a Loop that reports it, or from people's check-ins, and works out how far along the goal is and whether it is keeping pace. Work counts toward a goal when it is linked to it.

Anyone's key can read active goals. Creating, editing, checking in, linking and archiving need an admin's key: one created by an organization owner or admin.

The Goal object

{
  "id": "goal_pipeline",
  "object": "goal",
  "title": "A clean pipeline every Monday",
  "description": "Every open opportunity has an owner, a next step and a close date by Monday morning.",
  "owner": "usr_sam",
  "team": "team_gtm",
  "metric": { "label": "Weeks with a clean pipeline", "unit": null, "direction": "increase" },
  "target": 12,
  "baseline": 0,
  "period_start": 1759276800,
  "period_end": 1767139200,
  "source": { "kind": "connector", "metric": null, "loop": "loop_pipeline_hygiene", "outcome_label": "Clean pipeline" },
  "status": "active",
  "progress": 0.17,
  "on_track": false,
  "latest": { "day": "2026-10-26", "value": 2, "source": "connector" },
  "links": [
    { "kind": "loop", "id": "loop_pipeline_hygiene", "name": "Pipeline hygiene", "linked": 1760918400 }
  ],
  "blocked_by": [],
  "suggestion": null,
  "confirmed": 1759320000
}
Field Type Description
id string The goal's ID.
object string Always goal.
title, description string What the goal is, in its owner's words. description may be null.
owner string or null The user ID of the person who owns it.
team string or null The team it belongs to.
metric object label, unit (or null) and direction: increase when the goal is met by the metric rising, decrease when by it falling.
target, baseline number Where the metric should get to, and where it started (baseline may be null).
period_start, period_end integer The goal's period, in Unix seconds.
source object Where readings come from. kind is harmony (read daily from Harmony, metric names which), connector (reported by a Loop's runs: loop and outcome_label) or manual (check-ins only).
status string suggested, active or archived.
progress number or null How far from baseline to target, 0–1. null until there is a reading.
on_track boolean or null Whether progress keeps pace with the time gone in the period. null until there is a reading.
latest object or null The most recent reading: day, value and source.
links array The work linked to it: kind (loop, workstream, install or goal), id, name and when it was linked. A goal link means this goal is blocked by that one.
blocked_by string[] IDs of the goals this one waits for.
suggestion object or null While it is a suggestion: why Harmony suggested it and what it read (from).
confirmed integer or null When an admin confirmed it, in Unix seconds.

The Harmony metrics a goal can read are tasks_closed, loop_runs_completed, accepted_outcomes, reports_delivered and hours_returned.

List goals

Returns active goals, newest first. An admin's key can pass status=all to include archived ones.

GET /v1/goals

Scope: goals:read

Parameter In Type Description
limit query integer, optional 1–100. Default 20.
cursor query string, optional The next_cursor from the previous page. See Pagination.
status query string, optional active (default) or all (admins' keys).
curl https://api.gonimbus.ai/v1/goals \
  -H "Authorization: Bearer $HARMONY_API_KEY"

Retrieve a goal

GET /v1/goals/{goal}

Scope: goals:read. Returns a Goal.

Create a goal

Creates a goal that is active at once. Needs an admin's key. Send an Idempotency-Key header to retry safely; see Idempotent requests.

POST /v1/goals

Scope: goals:write

Parameter Type Description
title string Up to 140 characters.
metric object label (required), unit (optional, up to 20 characters), direction (increase, the default, or decrease).
target number Where the metric should get to.
period_start, period_end string YYYY-MM-DD or an ISO 8601 timestamp.
description string, optional Up to 1,000 characters.
owner string, optional The owner's user ID.
team string, optional A team ID.
baseline number, optional Where the metric starts.
source object, optional { "kind": "manual" } (default), { "kind": "harmony", "metric": "tasks_closed" } or { "kind": "connector", "loop": "<loop id>", "outcome_label": "<label>" }.

::: code-group

curl https://api.gonimbus.ai/v1/goals \
  -H "Authorization: Bearer $HARMONY_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{
    "title": "Close 40 support tasks a week",
    "team": "team_support",
    "metric": { "label": "Tasks closed", "direction": "increase" },
    "target": 40,
    "period_start": "2026-11-01",
    "period_end": "2026-11-30",
    "source": { "kind": "harmony", "metric": "tasks_closed" }
  }'
const goal = await fetch('https://api.gonimbus.ai/v1/goals', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.HARMONY_API_KEY}`,
    'Content-Type': 'application/json',
    'Idempotency-Key': crypto.randomUUID(),
  },
  body: JSON.stringify({
    title: 'Close 40 support tasks a week',
    team: 'team_support',
    metric: { label: 'Tasks closed', direction: 'increase' },
    target: 40,
    period_start: '2026-11-01',
    period_end: '2026-11-30',
    source: { kind: 'harmony', metric: 'tasks_closed' },
  }),
}).then((r) => r.json())

:::

Returns the new Goal with status 201.

Update a goal

Changes only the fields you send. Takes the same fields as creating one. Needs an admin's key.

PATCH /v1/goals/{goal}

Scope: goals:write

Check in on a goal

Records a reading of the goal's metric for a day: today in UTC when day is left out. A second check-in for the same day replaces the first. Needs an admin's key.

POST /v1/goals/{goal}/check_ins

Scope: goals:write

Parameter Type Description
value number The reading.
day string, optional YYYY-MM-DD.
note string, optional Context people see beside the reading.
curl https://api.gonimbus.ai/v1/goals/goal_pipeline/check_ins \
  -H "Authorization: Bearer $HARMONY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "value": 3, "note": "Two stale deals closed out on Friday." }'

Returns the updated Goal with status 201.

List a goal's check-ins

Returns the goal's readings, newest first: those Harmony took and those people checked in. Each has goal, day, value, source (harmony, connector or manual), note and recorded_by.

GET /v1/goals/{goal}/check_ins

Scope: goals:read. Takes limit and cursor.

Link work to a goal

Links a Loop, a workstream, a Marketplace install or another goal. Linking another goal (kind: "goal") means this goal is blocked by that one; two goals can't block each other. Needs an admin's key.

POST /v1/goals/{goal}/links

Scope: goals:write

Parameter Type Description
kind string loop, workstream, install or goal.
id string The ID of what you're linking.

To remove a link:

DELETE /v1/goals/{goal}/links/{kind}/{id}

Both return the updated Goal.

See what blocks a goal

Returns the goals this one waits for (blocked_by) and the active goals that wait for it (blocking), as full Goal objects.

GET /v1/goals/{goal}/dependencies

Scope: goals:read

Archive a goal

Archives the goal. Needs an admin's key.

POST /v1/goals/{goal}/archive

Scope: goals:write

Suggested goals

Harmony suggests goals from what it knows about your teams' work. A suggestion has status: "suggested" and a suggestion explaining why, and waits for an admin.

Endpoint Scope What it does
GET /v1/goal_suggestions goals:read Lists suggestions. Empty for a key that isn't an admin's. Takes limit and cursor.
POST /v1/goal_suggestions/{goal}/confirm goals:write Makes the suggestion a live goal. Send any of the create fields to change it as you confirm.
POST /v1/goal_suggestions/{goal}/dismiss goals:write Dismisses it.

Errors

Status Code When
400 parameter_invalid A field is missing or invalid, such as an unknown Harmony metric, or a link that would make two goals block each other.
403 insufficient_scope The key lacks the scope, or a write was made with a key that isn't an admin's.
404 resource_missing No goal, Loop, workstream or install with that ID.

FAQs

Who can see a goal? Every key in the organization can read active goals. Archived goals and suggestions are for admins' keys.

How often does a Harmony-sourced goal update? Harmony takes a reading once a day. Connector goals update when their Loop runs; manual goals when someone checks in.

Where do people see goals in the app? On the Outcomes page. See Outcomes and goals.