🚀 Feature: Work item archive/unarchive endpoints in the public API (parity with Python SDK & MCP server)
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 59.6k
- Forks
- 5.8k
- Avg merge
- 1d 22h
- Merged PRs (30d)
- 49
Description
Summary
The public REST API (apps/api/plane/api/) has no archive/unarchive endpoints for work items, while the official plane-python-sdk and plane-mcp-server both publish this capability. As a result, the official toolchain fails with HTTP 404 against self-hosted / Community Edition instances.
Current state
The SDK exposes (plane/api/work_items/base.py):
work_items.archive()->POST /{slug}/projects/{project_id}/work-items/{id}/archivework_items.unarchive()->DELETE /{slug}/projects/{project_id}/work-items/{id}/unarchivework_items.list_archived()->GET /{slug}/projects/{project_id}/archived-work-items
The MCP server builds on it (plane_mcp/tools/work_items.py): manage_work_item_archive, list_archived_work_items.
The server, however, only implements archive endpoints for cycles and modules in the public API (apps/api/plane/api/urls/cycle.py, module.py) - apps/api/plane/api/urls/work_item.py has no archive routes at all (verified on preview and on the v1.3.1 release).
The feature itself exists server-side - the internal app API has it (apps/api/plane/app/urls/issue.py: POST .../issues/<pk>/archive/, used by the web UI) - so this is purely a public API surface gap, not new functionality.
Impact
Calling manage_work_item_archive (MCP) or client.work_items.archive(...) (SDK) against a self-hosted instance returns HTTP 404. There is no workaround via the public API; the only way to archive a work item is the web UI.
Proposal
Add an IssueArchiveUnarchiveAPIEndpoint to apps/api/plane/api/views/issue.py, mirroring:
- the existing
CycleArchiveUnarchiveAPIEndpointpattern (same URL/verb structure), and - the internal app archive semantics (
apps/api/plane/app/views/issue/archive.py): only work items whose state group iscompletedorcancelledcan be archived;issue_activityis emitted; unarchive restores the item.
Routes registered in both URL families of urls/work_item.py:
POST .../work-items/<pk>/archive/(+ deprecated/issues/alias)DELETE .../work-items/<pk>/unarchive/(+ alias)GET .../archived-work-items/(+archived-issues/alias)
matching the paths already published by the SDK.
I have a working implementation with contract tests and will open a PR referencing this issue.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with apps/api/plane/api/views/issue.py and the CycleArchiveUnarchiveAPIEndpoint pattern, then inspect apps/api/plane/api/urls/work_item.py and apps/api/plane/app/views/issue/archive.py. Run the contract tests mentioned in the issue; done means the archive, unarchive, archived-list routes and deprecated aliases match the SDK paths and stated semantics.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- django, python
- Domain
- api, backend
- Issue type
- Feature
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Clearly specified
- Newbie friendliness
- 35/100