Skip to content

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 ​

  • id string (uuid)

    Unique identifier for the release.

  • name string

    Display 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_id string (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 null here.

  • description_id string (uuid)

    The id of the description record that holds the release body.

  • description_html string

    The release description as HTML. List rows leave it out unless you request it with ?fields=.

  • status string

    Where the release is in its lifecycle. One of unreleased (the default), released, or cancelled.

  • target_date string (date)

    The planned ship date, as YYYY-MM-DD.

  • release_date string (date)

    The date the release actually shipped, as YYYY-MM-DD.

  • lead_id string (uuid)

    The user who leads the release. Must be an active member of the workspace.

  • tag_id string (uuid)

    The version tag, from the workspace release tag catalog.

  • is_latest boolean

    Whether the release is marked as the latest one.

  • is_prerelease boolean

    Whether the release is marked as a pre-release.

  • external_id, external_source string

    Correlation fields for sync and import. Together they map a release to a record in another system.

  • label_ids array of string (uuid)

    The release labels applied to the release. Change them with Add or remove project release labels.

  • created_at string (date-time)

    When the release was created.

  • updated_at string (date-time)

    When the release was last updated.

  • created_by_id string (uuid)

    The user who created the release.

  • updated_by_id string (uuid)

    The user who last updated the release.

Response200
json
{
  "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 ​

MethodPathDescription
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}/ returns 404, 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_id and label_ids reference 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.

RequestNeedsWithout it
List project releasesView releases in the project403 forbidden
Create a project releaseCreate releases in the project403 forbidden
Get a project releaseView the release403 forbidden
Update a release or its changelog, add or remove its labels or work itemsEdit the release403 forbidden
Delete a releaseDelete the release403 forbidden
List or get comments and linksView the release404 not_found
Create a comment or linkView and edit the release404 without view, 403 without edit
Update or delete a comment or linkEdit the release403 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:

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 return 404 for a project release.
  • Adding and removing labels or work items is one POST with {"add": [...], "remove": [...]}, which returns {"added": [...], "removed": [...]}. v1 added with POST and removed with DELETE, passing label_ids or work_item_ids.
  • Listing a release's work items returns full work item objects. v1 returned only id, project_id, and name for each one.

See Migrating from v1 for the full list.