Skip to content

List cycles

GET/api/v2/workspaces/{slug}/projects/{project_id}/cycles/

Return the cycles in a project as a paginated page. Use it to build a sprint picker, to find the cycle covering a date range, or to reconcile cycles you imported from another tracker.

Filters combine with AND?owned_by_id=…&search=sprint returns only cycles that match both.

Path Parameters

slug:requiredstring

The workspace slug. It appears in your Plane URLs — in https://app.plane.so/my-team/projects/, the slug is my-team.

project_id:requiredstring (uuid)

The project whose cycles you want.

Query Parameters

Filters

owned_by_id:optionalstring (uuid)

Return only cycles owned by this user. This is how you build a "my cycles" view — pass the authenticated user's id. Ownership is assigned by Plane, so this is a read-side filter only.

external_id:optionalstring

Return only cycles whose external_id matches exactly. Pair it with external_source when the same identifier could come from more than one system.

external_source:optionalstring

Return only cycles imported from this source, for example jira.

Search

search:optionalstring

Free-text search term matched against the cycle.

Ordering

order_by:optionalstring

Field to sort by. Prefix with - for descending.

  • sort_order / -sort_order — the project's manual cycle ordering
  • created_at / -created_at — newest or oldest first
  • id / -id

Pagination

per_page:optionalinteger

Page size. Defaults to 50, maximum 200.

offset:optionalinteger

Number of rows to skip from the start of the result set. Maximum 10000 — past that, switch to cursor pagination.

paginate:optionalstring

Set to cursor to opt into the COUNT-free keyset envelope instead of the default offset envelope. The response then carries next_cursor and has_more rather than next, previous, and total_count; pass next_cursor back as cursor to walk to the following page. Use it for deep traversal, where offset paging gets expensive.

count:optionalboolean

Defaults to true. Set to false to skip the COUNT(*) behind total_count — the field is then omitted from the envelope. Worth doing when you only need the rows.

Bad enum values fail silently

order_by and paginate are not validated against their allowed values. An unrecognized order_by falls back to the cycle default ordering, and anything other than paginate=cursor uses offset pagination — so check your spelling, because a typo shows up as an unexpected sort order or envelope rather than an error.

Scopes

projects.cycles:read

Errors

StatusCodeCause
401unauthorizedMissing or invalid credentials.
403forbiddenYour role or token scope can't read cycles in this project.
404resource_not_foundNo such workspace or project, or it's outside your tenant.
429rate_limitedThrottled. Honor the Retry-After header before retrying.
List cycles
bash
curl -X GET \
  "https://api.plane.so/api/v2/workspaces/my-team/projects/4af68566-94a4-4eb3-94aa-50dc9427067b/cycles/?per_page=50&order_by=-created_at" \
  -H "X-Api-Key: $PLANE_API_KEY"
Response200
json
{
  "data": [
    {
      "id": "7c1f9a4e-3b6d-4a52-8f0c-2d9e6b18c3a7",
      "name": "Sprint 24",
      "description": "Checkout rewrite and billing cleanup",
      "start_date": "2026-01-05T00:00:00Z",
      "end_date": "2026-01-19T00:00:00Z",
      "timezone": "America/New_York",
      "owned_by_id": "16c61a3a-512a-48ac-b0be-b6b46fe6f430",
      "sort_order": 65535,
      "logo_props": {},
      "external_id": null,
      "external_source": null,
      "created_at": "2026-01-14T09:22:41.478363Z",
      "created_by_id": "16c61a3a-512a-48ac-b0be-b6b46fe6f430"
    },
    {
      "id": "2b8d5e07-9a41-4c6f-b3d2-71e8a4c05f96",
      "name": "Sprint 23",
      "description": "",
      "start_date": "2025-12-22T00:00:00Z",
      "end_date": "2026-01-05T00:00:00Z",
      "timezone": "America/New_York",
      "owned_by_id": "16c61a3a-512a-48ac-b0be-b6b46fe6f430",
      "sort_order": 55535,
      "logo_props": {},
      "external_id": "SPR-23",
      "external_source": "jira",
      "created_at": "2025-12-18T11:04:07.912004Z",
      "created_by_id": "16c61a3a-512a-48ac-b0be-b6b46fe6f430"
    }
  ],
  "next": 50,
  "previous": null,
  "total_count": 27,
  "pagination": {
    "style": "offset"
  }
}
Response200
json
{
  "data": [
    {
      "id": "7c1f9a4e-3b6d-4a52-8f0c-2d9e6b18c3a7",
      "name": "Sprint 24",
      "description": "Checkout rewrite and billing cleanup",
      "start_date": "2026-01-05T00:00:00Z",
      "end_date": "2026-01-19T00:00:00Z",
      "timezone": "America/New_York",
      "owned_by_id": "16c61a3a-512a-48ac-b0be-b6b46fe6f430",
      "sort_order": 65535,
      "logo_props": {},
      "external_id": null,
      "external_source": null,
      "created_at": "2026-01-14T09:22:41.478363Z",
      "created_by_id": "16c61a3a-512a-48ac-b0be-b6b46fe6f430"
    }
  ],
  "next_cursor": "b3A9MTcxOjA6MA==",
  "has_more": true,
  "pagination": {
    "style": "cursor"
  }
}