Plane REST API Endpoints for Creating, Updating, and Managing Work Items (Issues)

The Plane REST API exposes workspace-scoped endpoints under /workspaces/{slug}/projects/{project_id}/work-items/ to list, create, retrieve, patch, and delete issues, with additional routes for identifier-based lookup and full-text search.

The open-source project management platform Plane (makeplane/plane) provides a comprehensive Django-based REST API for issue tracking. According to the source code in apps/api/plane/api/urls/work_item.py, the API follows standard REST conventions with dedicated endpoints for every stage of the work item lifecycle, supporting partial updates, human-readable identifiers, and advanced search capabilities.

Endpoint Overview

All routes are defined in apps/api/plane/api/urls/work_item.py and share common query-string parameters (e.g., cursor, per_page, order_by, fields, expand) defined in plane/utils/openapi.py.

  • List/Create: GET or POST /workspaces/{slug}/projects/{project_id}/work-items/ → IssueListCreateAPIEndpoint using IssueSerializer
  • Detail/Update/Delete: GET, PATCH, or DELETE /workspaces/{slug}/projects/{project_id}/work-items/{pk}/ → IssueDetailAPIEndpoint using IssueSerializer
  • Identifier Lookup: GET /workspaces/{slug}/work-items/{project_identifier}-{issue_identifier}/ → WorkspaceIssueAPIEndpoint using IssueSerializer
  • Search: GET /workspaces/{slug}/work-items/search/ → IssueSearchEndpoint using IssueSearchSerializer

Creating and Listing Work Items

The IssueListCreateAPIEndpoint class in apps/api/plane/api/views/issue.py handles the collection endpoint.

For listing, the view builds a queryset filtered by project_id and workspace slug. It pre-fetches related assignees and labels, and optionally annotates counts for sub-issues, cycles, links, and attachments to optimize response payload.

For creation, the endpoint accepts a POST request with a JSON body validated by IssueSerializer. Upon successful creation, the view triggers background tasks (issue_activity, model_activity) to log the creation event asynchronously.

Retrieving, Updating, and Deleting Individual Work Items

The IssueDetailAPIEndpoint class manages single-resource operations at the detail URL.

  • Retrieve: Returns the work item with annotations for sub-issue counts and related objects.
  • Partial Update: A PATCH request runs the serializer in partial mode, allowing you to update specific fields such as priority, state_id, or assignee_ids. The implementation checks for duplicate external_id/external_source pairs if those fields are provided.
  • Delete: Permanently removes the record after verifying the caller is either the creator or a project admin. A delete activity is emitted before removal.

Note: The view class also implements a PUT method for upsert operations based on external_id and external_source, but the current URL mapping in work_item.py only exposes GET, PATCH, and DELETE on the detail endpoint.

Human-Readable Lookup: The WorkspaceIssueAPIEndpoint resolves issues using the conventional "PROJECT-123" format via the URL pattern /workspaces/{slug}/work-items/{project_identifier}-{issue_identifier}/. This is useful for integrations that reference issues by their display identifier rather than UUID.

Full-Text Search: The IssueSearchEndpoint provides a dedicated search interface at /workspaces/{slug}/work-items/search/. It supports filtering, ordering, and cursor-based pagination, returning lightweight results via IssueSearchSerializer for performant autocomplete scenarios.

Practical API Examples

The following curl commands demonstrate common operations against a Plane instance at https://api.plane.so. Replace {TOKEN} with a valid JWT or session cookie, and substitute placeholders with actual workspace slugs, project UUIDs, and issue identifiers.

List work items with pagination

curl -X GET "https://api.plane.so/workspaces/my-workspace/projects/123e4567-e89b-12d3-a456-426614174000/work-items/?per_page=20" \
     -H "Authorization: Bearer {TOKEN}"

Create a new work item

curl -X POST "https://api.plane.so/workspaces/my-workspace/projects/123e4567-e89b-12d3-a456-426614174000/work-items/" \
     -H "Authorization: Bearer {TOKEN}" \
     -H "Content-Type: application/json" \
     -d '{
           "name": "Add OAuth login",
           "description": "Implement Google and GitHub OAuth",
           "state_id": "b1c2d3e4-f5a6-7890-bcde-f1234567890a",
           "priority": "high",
           "assignee_ids": ["user-uuid-1", "user-uuid-2"],
           "label_ids": ["label-uuid-3"]
         }'

Retrieve a work item by UUID

curl -X GET "https://api.plane.so/workspaces/my-workspace/projects/123e4567-e89b-12d3-a456-426614174000/work-items/9a0b1c2d-3e4f-5678-9abc-def012345678/" \
     -H "Authorization: Bearer {TOKEN}"

Partially update specific fields

curl -X PATCH "https://api.plane.so/workspaces/my-workspace/projects/123e4567-e89b-12d3-a456-426614174000/work-items/9a0b1c2d-3e4f-5678-9abc-def012345678/" \
     -H "Authorization: Bearer {TOKEN}" \
     -H "Content-Type: application/json" \
     -d '{"priority": "urgent", "assignee_ids": ["user-uuid-3"]}'

Delete a work item

curl -X DELETE "https://api.plane.so/workspaces/my-workspace/projects/123e4567-e89b-12d3-a456-426614174000/work-items/9a0b1c2d-3e4f-5678-9abc-def012345678/" \
     -H "Authorization: Bearer {TOKEN}"

Lookup by human-readable identifier

curl -X GET "https://api.plane.so/workspaces/my-workspace/work-items/PROJ-42/" \
     -H "Authorization: Bearer {TOKEN}"

Search work items

curl -X GET "https://api.plane.so/workspaces/my-workspace/work-items/search/?q=OAuth&order_by=-created_at" \
     -H "Authorization: Bearer {TOKEN}"

Summary

  • The Plane REST API implements standard CRUD operations for work items via IssueListCreateAPIEndpoint and IssueDetailAPIEndpoint in apps/api/plane/api/views/issue.py.
  • All project-scoped endpoints live under /workspaces/{slug}/projects/{project_id}/work-items/ and accept common query parameters for pagination and field selection.
  • Partial updates use the PATCH method with the IssueSerializer running in partial mode, while DELETE operations enforce creator or admin permissions.
  • Human-readable lookup is available via WorkspaceIssueAPIEndpoint using the {project_identifier}-{issue_identifier} pattern.
  • Full-text search capabilities are provided by IssueSearchEndpoint with dedicated serialization for efficient result delivery.

Frequently Asked Questions

What is the base URL for Plane work item API endpoints?

All work item endpoints are prefixed with /workspaces/{slug}/projects/{project_id}/work-items/ for project-scoped operations, or /workspaces/{slug}/work-items/ for workspace-wide search and identifier lookup. Replace {slug} with your workspace slug and {project_id} with the project's UUID.

How do I update only specific fields of an existing issue?

Use the PATCH method on the detail endpoint /workspaces/{slug}/projects/{project_id}/work-items/{pk}/. The IssueDetailAPIEndpoint runs the IssueSerializer in partial mode, allowing you to send only the fields you want to change, such as priority, state_id, or assignee_ids.

Can I retrieve an issue using its human-readable identifier like "PROJ-123"?

Yes. The WorkspaceIssueAPIEndpoint provides a GET endpoint at /workspaces/{slug}/work-items/{project_identifier}-{issue_identifier}/ that resolves issues by their project identifier and sequence number, returning the same serialized data as the UUID-based detail endpoint.

Are there endpoints for bulk operations or upserts?

The IssueDetailAPIEndpoint contains logic for PUT requests to upsert records based on external_id and external_source, but this is not currently exposed in the URL configuration at apps/api/plane/api/urls/work_item.py. For bulk operations, you must issue individual POST or PATCH requests to the list or detail endpoints.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →