REST API
Releases and tests
Releases, release notes, test cases and test cycles.
GET /releases(tracker:read): releases with status,kind(versionorota),stage(currentis the one that's live, one per track: the project's version and OTA each have their own;previous,approved,testing,development,planned,cancelled),stage_label(the name on screen),is_next(the next to go live), dates, open issues and the last Release Gate decision. Query:projectandstatus(comma-separated list).GET /releases/{id}(tracker:read): the release withkind,stage,stage_label,is_next, the screen's summary (summary:headline,contextandnext_step), the metrics and the gate suggestion (gate.applies; on an OTA without a BLOCKED recorded,gate.suggestion.decisionisnot_applicableand instead of the metrics comesgate.validation, the issue count:ready_for_qa,testing,approved,failed), the last decision, the issues, the test cycles and the release notes.POST /releases(tracker:write): creates a release,{"project": "MOB", "version": "2.7.0", "build": "...", "environment": "...", "planned_date": "YYYY-MM-DD", "notes": "...", "kind": "version"};kindisversion(the default) orota. A release that already went live (an OTA already sent, a backend deploy, a version published outside tracker) can be born in production, without the gate:"status": "production"andreleased_date(default: today). PO/PM or admin. The version is unique in the project: repeating the request returns the release that already exists (200,already_existed: true), without changing anything in it. For CI to record a delivery:POST /releases, thenPOST /issues/bulkwith"action": "release"and the issues, andPOST /releases/{id}/status.POST /releases/{id}/status(tracker:write):{"status": "in_development"}. The path is planned → in_development → staging (testing), and from approved to production; cancelled leaves the path. An OTA (kind: "ota") goes toproductiondirectly, from planned, in_development, staging or approved, without the gate decision, unless the last decision is BLOCKED; validation follows afterwards through the linked issues (thesummary.next_stepofGET /releases/{id}says how many are in Ready for QA, testing, approved and failed). Other releases reach approved through the gate's APPROVED decision, recorded by a person on screen, and production requires that decision. Outside that path (approved directly, included) only an admin, withoverride_note.POST /releases/{id}/move(tracker:write):{"to_project": "PLT"}moves the release to another project in the company (e.g. backend deploys born in the app go to the platform project). It takes history, gate decisions and notes along; the issues stay linked, even those from other projects. PO/PM or admin in both projects; the version can't exist in the target and a release with a test cycle doesn't move. MCP:move_release.PUT /releases/{id}/notes(tracker:write): saves the release notes, the customer-facing text the screen copies and sends by e-mail:{"release_notes": "# App 2.7.0\n\n## What's new\n\n- You can now..."}. Simple markdown (#title,##section,-item; no bold or links). Replaces the whole text; empty ornullgoes back to the draft generated from the resolved issues. PO/PM or admin. The response hasrelease_notesandrelease_notes_saved. Doesn't send the e-mail.GET /test-cases(tracker:read): active test cases. Query:project,q(part of the code or title) andinclude_archived.POST /test-cases(tracker:write): creates a case,{"project": "MOB", "title": "...", "module": "...", "priority": "high", "steps": [{"action": "...", "expected": "..."}]}. QA or admin. The code (TC-MOB-0001) is generated.GET /test-cycles(tracker:read): most recent cycles with their progress. Query:projectandstatus.GET /test-cycles/{id}(tracker:read): the cycle with each case and its result (pass,fail,blocked,in_progress,not_started), the comment, who tested and the issue opened from the fail.POST /test-cycles(tracker:write): creates a cycle,{"project": "MOB", "name": "2.7.0 regression", "release": "2.7.0", "environment": "...", "cases": ["TC-MOB-0001"]}. Withoutcases, all the project's active cases go in. QA or admin.POST /test-cycles/{id}/results(tracker:write): CI results, up to 200 per request,{"results": [{"test_case": "TC-MOB-0001", "status": "fail", "comment": "...", "open_issue": true}]}.status:pass,fail,blockedorin_progress; a comment is required for fail and blocked. Withopen_issue, the fail opens the issue already filled in with the case (or returns the one that already exists); if the issue doesn't open, the result stays saved and the item comes back withwarning. Item by item, withrecorded,failedandresults. QA or admin.POST /test-cycles/{id}/status(tracker:write):{"action": "start" | "finish" | "cancel" | "reopen"}. A closed cycle doesn't accept results until it's reopened.