The milestones namespace provides API methods to retrieve, create, update, and delete milestones for a project. The following endpoints are available:
- GET
projects/{project_id}/milestones - POST
projects/{project_id}/milestones - GET
milestones/{milestone_id} - PATCH
milestones/{milestone_id} - DELETE
milestones/{milestone_id} - GET
projects/{project_id}/milestone-types
GET /projects/{project_id}/milestones
Returns all milestones for a project.
This method uses pagination so you might need to request additional pages to retrieve all milestones.
project_id id required
ID of the project.
Request
page integer
Number of page to return (default: first page).
per_page integer
Maximum number of milestones to return (supported: 15, 25, 50, 100; default: 100).
sort string
Sort field for the list of milestones (supported: milestones:created_at, milestones:completed_at; default: milestones:created_at).
order string
Sort order (supported: asc, desc; default: desc).
name string
Filter milestones by name (partial match).
type_id string
Comma-separated list of milestone type IDs to filter by.
is_completed boolean
Limit results to active (false) or completed (true) milestones only.
parent_id string
Comma-separated list of parent milestone IDs to filter by.
root_id string
Comma-separated list of root milestone IDs to filter by.
created_after string
Limit results to milestones created after this date/time (ISO 8601, UTC).
created_before string
Limit results to milestones created before this date/time (ISO 8601, UTC).
created_by string
Comma-separated list of user IDs to filter by creator.
completed_after string
Limit results to milestones completed after this date/time (ISO 8601, UTC).
completed_before string
Limit results to milestones completed before this date/time (ISO 8601, UTC).
starts_after string
Limit results to milestones with a start date on or after this date/time (ISO 8601, UTC).
starts_before string
Limit results to milestones with a start date on or before this date/time (ISO 8601, UTC).
due_from string
Limit results to milestones with a due date on or after this date/time (ISO 8601, UTC).
due_to string
Limit results to milestones with a due date on or before this date/time (ISO 8601, UTC).
automation_tags string
Comma-separated list of automation tag names to filter by.
expands string
Comma-separated list of expands to return.
{
"page": {
"type": "integer",
"format": "int64",
"description": "Number of page to return (default: first page)."
},
"per_page": {
"type": "integer",
"format": "int64",
"enum": [15, 25, 50, 100],
"description": "Maximum number of items to return per page (default: 100)."
},
"sort": {
"type": "string",
"enum": ["milestones:created_at", "milestones:completed_at"],
"default": "milestones:created_at",
"description": "Sort field for the list of milestones."
},
"order": {
"type": "string",
"enum": ["asc", "desc"],
"default": "desc",
"description": "Sort order (ascending or descending)."
},
"name": {
"type": "string",
"description": "Filter milestones by name (partial match)."
},
"type_id": {
"type": "string",
"description": "Comma-separated list of milestone type IDs to filter by."
},
"is_completed": {
"type": "boolean",
"description": "Limit results to active (false) or completed (true) milestones only."
},
"parent_id": {
"type": "string",
"description": "Comma-separated list of parent milestone IDs to filter by."
},
"root_id": {
"type": "string",
"description": "Comma-separated list of root milestone IDs to filter by."
},
"created_after": {
"type": "string",
"format": "date-time",
"description": "Limit results to milestones created after this date/time (ISO 8601, UTC)."
},
"created_before": {
"type": "string",
"format": "date-time",
"description": "Limit results to milestones created before this date/time (ISO 8601, UTC)."
},
"created_by": {
"type": "string",
"description": "Comma-separated list of user IDs to filter by creator."
},
"completed_after": {
"type": "string",
"format": "date-time",
"description": "Limit results to milestones completed after this date/time (ISO 8601, UTC)."
},
"completed_before": {
"type": "string",
"format": "date-time",
"description": "Limit results to milestones completed before this date/time (ISO 8601, UTC)."
},
"starts_after": {
"type": "string",
"format": "date-time",
"description": "Limit results to milestones with a start date on or after this date/time (ISO 8601, UTC)."
},
"starts_before": {
"type": "string",
"format": "date-time",
"description": "Limit results to milestones with a start date on or before this date/time (ISO 8601, UTC)."
},
"due_from": {
"type": "string",
"format": "date-time",
"description": "Limit results to milestones with a due date on or after this date/time (ISO 8601, UTC)."
},
"due_to": {
"type": "string",
"format": "date-time",
"description": "Limit results to milestones with a due date on or before this date/time (ISO 8601, UTC)."
},
"automation_tags": {
"type": "string",
"description": "Comma-separated list of automation tag names to filter by."
},
"expands": {
"type": "string",
"description": "Comma-separated list of expands to return (issues, milestone_stats, milestone_types, milestones, statuses, users)."
}
}
This method supports the following expands so you can automatically include additional information for referenced objects:
issuesmilestone_statsmilestone_typesmilestonesstatusesusers
Response
GET /api/v1/projects/1/milestones
200 OK
{
"page": 1,
"prev_page": null,
"next_page": 2,
"last_page": 2,
"per_page": 100,
"total": 150,
"result": [
{
"id": 1,
"project_id": 1,
"root_id": null,
"parent_id": null,
"type_id": 1,
"name": "v2.0 Release",
"note": "Q3 release",
"is_started": true,
"is_completed": false,
"start_date": null,
"due_date": "2025-09-30",
"automation_tags": [],
"issues": [],
"links": [],
"started_at": "2025-07-01T00:00:00.000000Z",
"created_at": "2025-06-15T10:22:00.000000Z",
"created_by": 2,
"updated_at": null,
"updated_by": null,
"completed_at": null
},
..
],
"expands": {}
}
Examples
// Get all milestones for a project
GET /api/v1/projects/1/milestones
// Filter by name (partial match)
GET /api/v1/projects/1/milestones?name=release
// Get active milestones only
GET /api/v1/projects/1/milestones?is_completed=false
// Get completed milestones ordered by completion date
GET /api/v1/projects/1/milestones?is_completed=true&sort=milestones:completed_at
// Filter by milestone type
GET /api/v1/projects/1/milestones?type_id=1,2
// Filter milestones with a due date in a range
GET /api/v1/projects/1/milestones?due_from=2025-07-01&due_to=2025-09-30
// Filter by creation date
GET /api/v1/projects/1/milestones?created_after=2025-01-01T00:00:00Z
// Include milestone type and user expands
GET /api/v1/projects/1/milestones?expands=milestone_types,users
// Paginate through results
GET /api/v1/projects/1/milestones?page=2&per_page=50
Status codes
200 401 403 422 429 (details)
POST /projects/{project_id}/milestones
Creates a new milestone in the specified project. Only name is required; all other fields are optional.
project_id id required
ID of the project.
Request
name string required
Name of the milestone.
milestone_type_id integer
ID of the milestone type. Use GET /projects/{project_id}/milestone-types to retrieve valid type IDs. If omitted, the project's default milestone type is used. (type_id is also accepted for consistency with the response field name; if both are provided, milestone_type_id takes precedence.)
description string
Short summary shown at the top of the milestone (maximum 80 characters). This maps to the milestone's note field in the response.
note string
Rich text body for the milestone's Notes tab (no length limit). docs is accepted as an alias for this field.
start_date string
Start date of the milestone (YYYY-MM-DD).
due_date string
Due date of the milestone (YYYY-MM-DD).
is_started boolean
Whether the milestone has been started.
is_completed boolean
Whether the milestone has been completed.
started_at string
Timestamp the milestone was started (ISO 8601, UTC). Applies when is_started is true.
completed_at string
Timestamp the milestone was completed (ISO 8601, UTC). Applies when is_completed is true.
automation_tags array
Array of automation tag names to associate with the milestone.
parent_id integer
ID of a parent milestone, to create this milestone as a sub-milestone.
{
"name": {
"type": "string",
"description": "Name of the milestone (required)."
},
"milestone_type_id": {
"type": "integer",
"format": "int64",
"description": "ID of the milestone type. type_id is also accepted; milestone_type_id takes precedence."
},
"description": {
"type": "string",
"maxLength": 80,
"description": "Short summary (max 80 chars). Returned as the note field."
},
"note": {
"type": "string",
"description": "Rich text body for the Notes tab. docs is accepted as an alias."
},
"start_date": {
"type": "string",
"format": "date",
"description": "Start date (YYYY-MM-DD)."
},
"due_date": {
"type": "string",
"format": "date",
"description": "Due date (YYYY-MM-DD)."
},
"is_started": {
"type": "boolean",
"description": "Whether the milestone has been started."
},
"is_completed": {
"type": "boolean",
"description": "Whether the milestone has been completed."
},
"started_at": {
"type": "string",
"format": "date-time",
"description": "Timestamp the milestone was started (ISO 8601, UTC)."
},
"completed_at": {
"type": "string",
"format": "date-time",
"description": "Timestamp the milestone was completed (ISO 8601, UTC)."
},
"automation_tags": {
"type": "array",
"items": { "type": "string" },
"description": "Array of automation tag names."
},
"parent_id": {
"type": "integer",
"format": "int64",
"description": "ID of a parent milestone (creates a sub-milestone)."
}
}
Response
POST /api/v1/projects/1/milestones
201 Created
{
"result": {
"id": 42,
"project_id": 1,
"root_id": null,
"parent_id": null,
"type_id": 1,
"name": "v2.1 Release",
"note": "October feature release",
"is_started": false,
"is_completed": false,
"start_date": "2025-10-01",
"due_date": "2025-10-31",
"automation_tags": [],
"issues": [],
"links": [],
"started_at": null,
"created_at": "2025-09-20T14:05:00.000000Z",
"created_by": 2,
"updated_at": null,
"updated_by": null,
"completed_at": null
},
"expands": {}
}
Examples
// Create a milestone with a name only
POST /api/v1/projects/1/milestones
{
"name": "v2.1 Release"
}
// Create a milestone with type, dates and a summary
POST /api/v1/projects/1/milestones
{
"name": "v2.1 Release",
"milestone_type_id": 1,
"description": "October feature release",
"start_date": "2025-10-01",
"due_date": "2025-10-31"
}
// Create a sub-milestone under an existing milestone
POST /api/v1/projects/1/milestones
{
"name": "Sprint 12",
"milestone_type_id": 2,
"parent_id": 42
}
Status codes
201 400 401 403 404 415 422 429 (details)
GET /milestones/{milestone_id}
Returns a single milestone.
milestone_id id required
ID of the milestone.
Request
expands string
Comma-separated list of expands to return.
{
"expands": {
"type": "string",
"description": "Comma-separated list of expands to return (issues, milestone_stats, milestone_types, milestones, statuses, users)."
}
}
This method supports the following expands so you can automatically include additional information for referenced objects:
issuesmilestone_statsmilestone_typesmilestonesstatusesusers
Response
GET /api/v1/milestones/1
200 OK
{
"result": {
"id": 1,
"project_id": 1,
"root_id": null,
"parent_id": null,
"type_id": 1,
"name": "v2.0 Release",
"note": "Q3 release",
"is_started": true,
"is_completed": false,
"start_date": null,
"due_date": "2025-09-30",
"automation_tags": [],
"issues": [],
"links": [],
"started_at": "2025-07-01T00:00:00.000000Z",
"created_at": "2025-06-15T10:22:00.000000Z",
"created_by": 2,
"updated_at": null,
"updated_by": null,
"completed_at": null
},
"expands": {}
}
Examples
// Get milestone with ID 1
GET /api/v1/milestones/1
// Include milestone type and user expands
GET /api/v1/milestones/1?expands=milestone_types,users
Status codes
200 401 403 404 429 (details)
PATCH /milestones/{milestone_id}
Updates an existing milestone. Only the fields provided in the request body are changed; omitted fields are left untouched.
milestone_id id required
ID of the milestone to update.
Request
name string
New name for the milestone.
milestone_type_id integer
ID of the milestone type. (type_id is also accepted; if both are provided, milestone_type_id takes precedence.)
description string
Short summary shown at the top of the milestone (maximum 80 characters). Maps to the note response field.
note string
Rich text body for the milestone's Notes tab. docs is accepted as an alias.
start_date string
Start date of the milestone (YYYY-MM-DD).
due_date string
Due date of the milestone (YYYY-MM-DD).
is_started boolean
Whether the milestone has been started.
is_completed boolean
Whether the milestone has been completed.
started_at string
Timestamp the milestone was started (ISO 8601, UTC).
completed_at string
Timestamp the milestone was completed (ISO 8601, UTC).
automation_tags array
Array of automation tag names to associate with the milestone.
updated_at string
The milestone's last known updated_at value (ISO 8601, UTC). When provided, the update is rejected if the milestone has changed since — optimistic concurrency control to prevent overwriting concurrent edits.
force_update boolean
Set to true to apply the update even if the milestone has changed since the supplied updated_at (bypasses the concurrency check).
{
"name": {
"type": "string",
"description": "New name for the milestone."
},
"milestone_type_id": {
"type": "integer",
"format": "int64",
"description": "ID of the milestone type. type_id is also accepted; milestone_type_id takes precedence."
},
"description": {
"type": "string",
"maxLength": 80,
"description": "Short summary (max 80 chars). Returned as the note field."
},
"note": {
"type": "string",
"description": "Rich text body for the Notes tab. docs is accepted as an alias."
},
"start_date": {
"type": "string",
"format": "date",
"description": "Start date (YYYY-MM-DD)."
},
"due_date": {
"type": "string",
"format": "date",
"description": "Due date (YYYY-MM-DD)."
},
"is_started": {
"type": "boolean",
"description": "Whether the milestone has been started."
},
"is_completed": {
"type": "boolean",
"description": "Whether the milestone has been completed."
},
"started_at": {
"type": "string",
"format": "date-time",
"description": "Timestamp the milestone was started (ISO 8601, UTC)."
},
"completed_at": {
"type": "string",
"format": "date-time",
"description": "Timestamp the milestone was completed (ISO 8601, UTC)."
},
"automation_tags": {
"type": "array",
"items": { "type": "string" },
"description": "Array of automation tag names."
},
"updated_at": {
"type": "string",
"format": "date-time",
"description": "Last known updated_at for optimistic concurrency control."
},
"force_update": {
"type": "boolean",
"description": "Apply the update even if the milestone changed since updated_at."
}
}
Response
PATCH /api/v1/milestones/42
200 OK
{
"result": {
"id": 42,
"project_id": 1,
"root_id": null,
"parent_id": null,
"type_id": 1,
"name": "v2.1 Release (RC)",
"note": "October feature release",
"is_started": true,
"is_completed": false,
"start_date": "2025-10-01",
"due_date": "2025-11-07",
"automation_tags": [],
"issues": [],
"links": [],
"started_at": "2025-10-01T00:00:00.000000Z",
"created_at": "2025-09-20T14:05:00.000000Z",
"created_by": 2,
"updated_at": "2025-10-02T08:30:00.000000Z",
"updated_by": 2,
"completed_at": null
},
"expands": {}
}
Examples
// Rename a milestone and move its due date
PATCH /api/v1/milestones/42
{
"name": "v2.1 Release (RC)",
"due_date": "2025-11-07"
}
// Mark a milestone as completed
PATCH /api/v1/milestones/42
{
"is_completed": true,
"completed_at": "2025-11-07T17:00:00Z"
}
// Update with optimistic concurrency control
PATCH /api/v1/milestones/42
{
"name": "v2.1 Release",
"updated_at": "2025-10-02T08:30:00Z"
}
Status codes
200 400 401 403 404 409 415 422 429 (details)
DELETE /milestones/{milestone_id}
Deletes a milestone. The deletion is handled safely: the milestone's linked test runs, sessions, and automation runs are unlinked (they are not deleted), their milestone associations are removed, and any sub-milestones are reparented so nothing is left orphaned.
milestone_id id required
ID of the milestone to delete.
Response
DELETE /api/v1/milestones/42
204 No Content
Status codes
204 401 403 404 429 (details)
GET /projects/{project_id}/milestone-types
Returns the list of milestone types configured for the specified project. Use this endpoint to retrieve valid type IDs for use when creating, updating, or filtering milestones.
project_id id required
ID of the project.
Response
GET /api/v1/projects/1/milestone-types
200 OK
{
"result": [
{
"id": 1,
"name": "Release",
"is_default": true
},
{
"id": 2,
"name": "Sprint",
"is_default": false
},
{
"id": 3,
"name": "Phase",
"is_default": false
}
]
}
Status codes
200 401 403 404 429 (details)