Tracker
Package tracker is your org's issue tracker: projects, issues, and the filters to find them.
Package tracker is your org's issue tracker: projects, issues, and the filters to find them.
| Base URL | https://api.hanzo.ai |
| Operations | 10 |
| Auth | Authorization: Bearer $HANZO_API_KEY |
tracker
GET /v1/tracker/projects/{key}/issues/{num}
Returns one issue of one tracker project by its per-project number — title, description, status, priority, assignee, labels, kind, source and its git bindings. 404 when the project or the issue does not exist in the caller's org.
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
key | path | string | yes | Key is the issue's project, from the path. |
num | path | integer | yes | Num is the issue's number within that project — the digits of KEY-14. |
PATCH /v1/tracker/projects/{key}/issues/{num}
Edits one issue in place and returns it — retitle it, rewrite its
body, move it between board columns, reprioritize, reassign, or replace its
labels. Every field is optional: one the caller omits keeps its stored value,
and labels REPLACES the set rather than adding to it.
The issue's kind, source and git bindings are not editable here: they record where the work item came FROM, which is a fact about its origin rather than its current state.
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
key | path | string | yes | Key is the issue's project, from the path. |
num | path | integer | yes | Num is the issue's number within that project, from the path. |
Request body — application/json (required)
| Field | Type | Required | Description |
|---|---|---|---|
assignee | string | — | Assignee is who owns the issue, at most 256 characters. |
description | string | — | Description is the issue body, at most 32768 characters. |
key | string | — | Key is the issue's project, from the path. |
labels | string[] | — | Labels REPLACES the issue's labels with exactly this set. |
num | integer | — | Num is the issue's number within that project, from the path. |
priority | string | — | Priority is none, urgent, high, medium or low. |
status | string | — | Status moves the issue between board columns: backlog, todo, in_progress, done or canceled. |
title | string | — | Title is the issue's one-line summary. |
DELETE /v1/tracker/projects/{key}/issues/{num}
Removes one issue from a tracker project and answers 204 with no body. 404 when the project or the issue does not exist in the caller's org.
The issue's number is NOT reused: the next issue on the board takes the next number, so a deleted identifier stays retired rather than silently pointing at different work.
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
key | path | string | yes | Key is the issue's project, from the path. |
num | path | integer | yes | Num is the issue's number within that project — the digits of KEY-14. |
GET /v1/tracker/projects/{key}/issues
Returns the issues of one tracker project, optionally filtered by status, kind, repo and source.
This is the ONE place a surface takes its slice of the shared issue table: hanzo.team passes no filter or a status, a git repository's Issues tab passes kind=issue&repo=<r> and its Pull Requests tab kind=pr&repo=<r>. A filter value outside its closed set is refused with 400 rather than silently returning an empty board.
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
key | path | string | yes | Key is the project whose issues to list, from the path. |
status | query | string | — | Status keeps only issues in that board column: backlog, todo, in_progress, done or canceled. |
kind | query | string | — | Kind keeps only work items of that shape: issue, pr or epic. |
repo | query | string | — | Repo keeps only issues bound to that git repository. |
source | query | string | — | Source keeps only issues opened from that surface: team, git, crm, helpdesk, cms or agent. |
POST /v1/tracker/projects/{key}/issues
File an issue on a tracker board
Files a work item on one board and returns it, carrying the identifier — KEY-<number> — it will be known by everywhere else.
THE NUMBER IS THE SERVER'S TO ASSIGN and is not accepted from the caller: it is the board's highest plus one, taken inside the insert's own transaction, and it counts PER BOARD — ENG-1 and OPS-1 are different issues.
title is required; everything else is optional and defaults. kind (issue, pr, epic) says what the item IS, source (team, git, crm, helpdesk, cms, agent) says which surface OPENED it, and the two are orthogonal — an issue escalated from support is kind=issue&source=helpdesk. status defaults to backlog, priority to none. A value outside one of these closed sets is 400, never silently defaulted. labels may not contain a comma, the storage separator.
repo and extRef RECORD an external binding; they do not create one. Filing here writes to your tracker and reaches no external system — nothing is pushed to GitHub. The GitHub integration runs the other way, mirroring upstream issues INTO this tracker.
404 when the caller's org has no board under that key. The org is the validated bearer's own and the board is resolved within the caller's selected IAM project; 403 without a validated org. Free by default, on the same balance gate as the board create — an epic, a pull request and an issue are priced identically, since the fee is per work item rather than per kind.
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
key | path | string | yes |
GET /v1/tracker/projects/{key}
Returns one tracker project of the caller's org by its key — its name, description and timestamps. 404 when the org has no project under that key.
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
key | path | string | yes | Key is the project's org-unique handle: 2-8 uppercase alphanumerics starting with a letter ("ENG", "OPS2"). |
PATCH /v1/tracker/projects/{key}
Renames a tracker project or rewrites its description, and returns the updated project. Both fields are optional: one the caller omits keeps its stored value.
The project KEY is never editable — it prefixes every issue identifier already filed under the board, so changing it would rewrite the human handle of every issue in it.
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
key | path | string | yes | Key is the project to update, from the path. |
Request body — application/json (required)
| Field | Type | Required | Description |
|---|---|---|---|
description | string | — | Description is the board's free-form blurb, at most 32768 characters. |
key | string | — | Key is the project to update, from the path. |
name | string | — | Name is the project's display name. |
DELETE /v1/tracker/projects/{key}
Removes one tracker project of the caller's org AND every issue filed under it, and answers 204 with no body. 404 when the org has no project under that key.
The cascade is the point: an issue has no meaning without the board whose key names it, so deleting the board deletes them together rather than leaving orphans addressable by an identifier that no longer resolves.
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
key | path | string | yes | Key is the project's org-unique handle: 2-8 uppercase alphanumerics starting with a letter ("ENG", "OPS2"). |
GET /v1/tracker/projects
Returns every tracker project in the caller's org, newest first.
A project is the board: it owns a KEY (the uppercase handle that prefixes every issue identifier, "ENG-14") and the issues filed under it. The listing is org-scoped server-side — the org is the validated bearer claim, never a client-supplied header — so one org can never see another's boards.
POST /v1/tracker/projects
Open a tracker board in your org
Creates a board and returns it, including the KEY that will prefix every issue identifier filed under it — the same key GET, PATCH and DELETE address the board by, and the ENG in ENG-14.
name is required. key is optional and is UPPERCASED: omit it and one is derived from the name — its first four letters and digits, or PRJ when that yields nothing usable. A key that is not 2-8 characters starting with a letter is 400.
THE KEY IS UNIQUE PER ORG AND A COLLISION IS REFUSED, NOT MERGED: a second board on a key already taken is 409, and the derived key is not made unique for you, so two similarly named boards collide and the second caller must name a key. Re-POSTing is therefore not idempotent — it fails rather than returning the existing board.
The org is the validated bearer's own, never a client header, and the board is stored under the caller's selected IAM PROJECT: the same key in two IAM projects is two unrelated boards. 403 without a validated org.
Free by default. The create runs the shared per-org balance gate at a fee of zero unless a deployment prices it, and a priced deployment out of balance refuses with the nested {"error":{"code","message"}} body at 402/503 rather than a flat error.
How is this guide?