Skip to content

API keys

  1. In the app, open Settings › API. Any workspace member can create their own keys.
  2. Under New key, pick a name (what it is for), scopes, and an expiration (30 days · 90 days · 365 days · no expiration), then create it.
  3. The full key (starting with gtk_) is shown once, right after you create it. Once you close that screen you cannot see it again, so copy it into your secret store right away. The list keeps only the prefix.

One person can hold up to 20 active keys in a workspace. Revoke keys you no longer use on the same screen — a revoked key immediately gets 401 API_KEY_REVOKED.

Scope What it allows Who can pick it
read Read issues, comments, workflow states, teams, labels, cycles, wiki spaces and pages, projects, initiatives and milestones; search; list metrics and read metric values Every member
write Create and update issues, change status, assignee and labels, add comments, create and edit wiki pages, create and edit projects, initiatives and milestones Owners, admins, members
metrics:ingest Add metric values Owners, admins, members

A key acts as the person who created it. Anything that person cannot see now, the key cannot see either, and when their role shrinks the key shrinks with it. If the creator leaves the workspace, the key starts returning 403 at once — create long-running integrations from a shared team account.

터미널 창
curl "https://goaltrack.dyld.kr/api/v1/work_items?limit=50" \
-H "Authorization: Bearer $GOALTRACK_API_KEY"
  • A key is bound to the workspace it was created in, so you do not need to name the workspace. If you send an x-workspace-slug header, it must match the key’s workspace; otherwise you get 403 WORKSPACE_MISMATCH.
  • Lists come back as { "items": [...], "next_cursor": "…" }. Fetch the next page with cursor=<next_cursor>; a null next_cursor means you are done. limit is 1–200 (default 50).
  • When you filter the issue list or counts (GET /api/v1/work_items · /work_items/counts) by team, team_id (or team_key) returns issues of exactly that team. To include sub-team issues, also send include_sub_teams=true (that team and every team below it). include_sub_teams=true without team_id or team_key returns 400 VALIDATION.
  • To update an issue, send the version you last read as expected_version in the PATCH body: { "expected_version": 3, "patch": { "priority": "high" } }. Without expected_version you get 412 PRECONDITION_REQUIRED; if someone changed it in the meantime you get 409 VERSION_CONFLICT. Updating a project, initiative or milestone (PATCH) works the same way. Unknown fields reject the whole request with 400 VALIDATION.
  • A write response to a key without the read scope holds only what you need to keep writing — issues (create, update, status, assignee) { "id", "short_id", "version" } · pages (create, update) { "id", "slug", "version" } · comments { "id", "version" } · attaching a label { "work_item_id", "label_id" } · projects and initiatives { "id", "version" } · milestones { "id", "project_id", "version" }. A 409 VERSION_CONFLICT carries only current_version instead of the current content.

Only the requests below accept a key. Calling any other request with a key returns 401 UNAUTHORIZED.

Request Scope Per minute
GET /api/v1/work_items read 120
GET /api/v1/work_items/:id read 120
GET /api/v1/work_items/by-short/:shortId read 120
POST /api/v1/work_items write 120
PATCH /api/v1/work_items/:id write 120
POST /api/v1/work_items/:id/status write 120
PATCH /api/v1/work_items/:id/assignee write 120
POST /api/v1/work_items/:id/labels write 120
DELETE /api/v1/work_items/:id/labels/:labelId write 120
GET /api/v1/work_items/:id/comments read 120
POST /api/v1/work_items/:id/comments write 120
GET /api/v1/workflow_states read 120
GET /api/v1/teams read 120
GET /api/v1/labels read 120
GET /api/v1/cycles read 120
GET /api/v1/projects read 120
GET /api/v1/projects/:id read 120
POST /api/v1/projects write 120
PATCH /api/v1/projects/:id write 120
GET /api/v1/initiatives read 120
GET /api/v1/initiatives/:id read 120
POST /api/v1/initiatives write 120
PATCH /api/v1/initiatives/:id write 120
GET /api/v1/milestones read 120
POST /api/v1/milestones write 120
PATCH /api/v1/milestones/:id write 120
GET /api/v1/wiki_spaces read 120
GET /api/v1/documents read 120
GET /api/v1/documents/:id read 120
GET /api/v1/documents/by-slug/:slug read 120
POST /api/v1/documents write 120
PATCH /api/v1/documents/:id write 120
GET /api/v1/search read 120
GET /api/v1/metric_definitions read 120
GET /api/v1/metric_definitions/:id/values read 120
GET /api/v1/auth/whoami read 120
POST <ingest URL> metrics:ingest 120
POST <ingest URL>/bulk metrics:ingest 20

<ingest URL> is explained in Metric ingest.

  • Limits count all requests from one key together — any mix of the requests in the table adds up to 120 per minute, reset every minute. Batch ingest is additionally capped at 20 per minute within that. Past the limit you get 429 with a Retry-After header (seconds). Wait that long, then retry.
  • Other abuse-prevention limits also apply (for example, to repeatedly sending a wrong key). Whichever limit you hit, a 429 means: wait for Retry-After, then retry.