Project releases overview
A project release groups work from one project into a named, versioned deliverable with its own changelog. It is the same object as a workspace release, except that it belongs to one project. You manage it through the routes under /api/v2/workspaces/{slug}/projects/{project_id}/releases/.
Comments and links on a project release have their own routes, documented in Project release comments and Project release links.
Learn more about project releases
The project release object
Attributes
idstring (uuid)Unique identifier for the release.
namestringDisplay name. Maximum 255 characters. Names are unique across the whole workspace, so a project release can't reuse the name of a workspace release or of a release in another project.
project_idstring (uuid)The project the release belongs to. Set from the route when you create the release and read-only after that. A workspace release returns
nullhere.description_idstring (uuid)The id of the description record that holds the release body.
description_htmlstringThe release description as HTML. List rows leave it out unless you request it with
?fields=.statusstringWhere the release is in its lifecycle. One of
unreleased(the default),released, orcancelled.target_datestring (date)The planned ship date, as
YYYY-MM-DD.release_datestring (date)The date the release actually shipped, as
YYYY-MM-DD.lead_idstring (uuid)The user who leads the release. Must be an active member of the workspace.
tag_idstring (uuid)The version tag, from the workspace release tag catalog.
is_latestbooleanWhether the release is marked as the latest one.
is_prereleasebooleanWhether the release is marked as a pre-release.
external_id,external_sourcestringCorrelation fields for sync and import. Together they map a release to a record in another system.
label_idsarray of string (uuid)The release labels applied to the release. Change them with Add or remove project release labels.
created_atstring (date-time)When the release was created.
updated_atstring (date-time)When the release was last updated.
created_by_idstring (uuid)The user who created the release.
updated_by_idstring (uuid)The user who last updated the release.
{
"id": "3e8a1f52-7c4b-4d9e-a6f1-0b2c5d8e9f14",
"name": "Mobile 4.2.0",
"project_id": "4af68566-94a4-4eb3-94aa-50dc9427067b",
"description_id": "5d2b7e91-4a3c-4f68-9e0d-1c7a8b2f6e35",
"description_html": "<p>Offline mode and the new onboarding flow.</p>",
"status": "unreleased",
"target_date": "2026-02-27",
"release_date": null,
"lead_id": "16c61a3a-512a-48ac-b0be-b6b46fe6f430",
"tag_id": "a41c9e07-2f5d-4b83-8c6e-9d1f0a3b7c52",
"is_latest": false,
"is_prerelease": false,
"external_id": null,
"external_source": null,
"label_ids": ["7f3a2c19-8e4d-4b61-a5c7-2d9e0f1b8a46"],
"created_at": "2026-01-14T09:22:41.478363Z",
"updated_at": "2026-01-14T09:22:41.478363Z",
"created_by_id": "16c61a3a-512a-48ac-b0be-b6b46fe6f430",
"updated_by_id": "16c61a3a-512a-48ac-b0be-b6b46fe6f430"
}Endpoints
| Method | Path | Description |
|---|---|---|
GET | /api/v2/workspaces/{slug}/projects/{project_id}/releases/ | List project releases |
GET | /api/v2/workspaces/{slug}/projects/{project_id}/releases/{pk}/ | Get a project release |
POST | /api/v2/workspaces/{slug}/projects/{project_id}/releases/ | Create a project release |
PATCH | /api/v2/workspaces/{slug}/projects/{project_id}/releases/{pk}/ | Update a project release |
DELETE | /api/v2/workspaces/{slug}/projects/{project_id}/releases/{pk}/ | Delete a project release |
GET | /api/v2/workspaces/{slug}/projects/{project_id}/releases/{pk}/changelog/ | Get a project release changelog |
PATCH | /api/v2/workspaces/{slug}/projects/{project_id}/releases/{pk}/changelog/ | Update a project release changelog |
GET | /api/v2/workspaces/{slug}/projects/{project_id}/releases/{pk}/labels/ | List a project release's labels |
POST | /api/v2/workspaces/{slug}/projects/{project_id}/releases/{pk}/labels/ | Add or remove project release labels |
GET | /api/v2/workspaces/{slug}/projects/{project_id}/releases/{pk}/work-items/ | List a project release's work items |
POST | /api/v2/workspaces/{slug}/projects/{project_id}/releases/{pk}/work-items/ | Add or remove project release work items |
Project releases and workspace releases
Both kinds of release are the same object with the same fields. project_id tells them apart. It holds the project's id on a project release and null on a workspace release, and both the project routes and the workspace routes return it.
The two sets of routes never overlap:
- The project routes return only releases in the project named in the path. A workspace release id, or the id of a release in another project, returns
404. - The workspace routes return only workspace releases. A project release id on
/api/v2/workspaces/{slug}/releases/{pk}/returns404, and so do its comments and links on the workspace comment and link routes. - A release can't change scope. The project comes from the path when you create the release, and no request body field moves it afterward.
Two things are shared across the workspace:
- Release names. A project release can't reuse any release name already taken in the workspace.
- Tags and labels.
tag_idandlabel_idsreference the workspace catalogs at/releases/tags/and/releases/labels/. There is no per-project catalog.
Plan gating
Every project release route, including the comment and link routes, needs the project releases entitlement on your plan. Without it, the API returns 402 payment_required. This entitlement is separate from the one for workspace releases, so having one doesn't give you the other.
The workspace Releases setting (is_release_enabled in workspace features) gates only the creation of workspace releases. While the setting is off, creating a workspace release returns 402 payment_required. Project release routes don't check the setting, and they don't check the project's own Releases feature toggle either.
Permissions
The API checks permissions against your role in the release's project. For the checks on a single release and on its comments and links, a workspace admin passes without a role in the project.
| Request | Needs | Without it |
|---|---|---|
| List project releases | View releases in the project | 403 forbidden |
| Create a project release | Create releases in the project | 403 forbidden |
| Get a project release | View the release | 403 forbidden |
| Update a release or its changelog, add or remove its labels or work items | Edit the release | 403 forbidden |
| Delete a release | Delete the release | 403 forbidden |
| List or get comments and links | View the release | 404 not_found |
| Create a comment or link | View and edit the release | 404 without view, 403 without edit |
| Update or delete a comment or link | Edit the release | 403 forbidden |
An id that doesn't exist in the project always returns 404, before any permission check runs. When you can't view a release, the status depends on what you read. A read of the release itself returns 403, while reads of its comments and links return 404, as if the release didn't exist.
Find the work items in a release
There are two ways to read a release's work items:
- List a project release's work items returns full work item objects in one call. It takes no filters.
- The work items list with
?release_id=combines release membership with every other work item filter, ordering, and cursor pagination, for example?release_id={id}&state_group=started. It's available on the project work items list and the workspace work items list.
Use the child list for a quick read of everything in the release. Use the filter when you need to narrow, sort, or page through the set.
Response shaping
Every read that returns the release object accepts ?fields= for sparse responses and ?expand=lead,tag to embed the lead user and the tag next to their ids. See Sparse fields and Expanding relations. Errors follow the shared problem+json contract.
Changed from v1
- In v1, a project release's labels, work items, changelog, comments, and links were served on the workspace routes, under
/api/v1/workspaces/{slug}/releases/{release_id}/. In v2 they live under the project route, and the workspace routes return404for a project release. - Adding and removing labels or work items is one
POSTwith{"add": [...], "remove": [...]}, which returns{"added": [...], "removed": [...]}. v1 added withPOSTand removed withDELETE, passinglabel_idsorwork_item_ids. - Listing a release's work items returns full work item objects. v1 returned only
id,project_id, andnamefor each one.
See Migrating from v1 for the full list.

