Projects
Projects, membership, saved views, boards, analytics, and imports.
Projects
GET /api/projects
Lists projects visible to the caller. This endpoint has no path or query parameters. It has no request body.
Response: a Project array.
POST /api/projects
Creates a project. This endpoint has no path or query parameters.
Request body fields are name (string), identifier (string), description (string, optional, defaults to an empty string), emoji (string or null, optional), and lead_user_id (integer or null, optional). When no lead is supplied and the request has an authenticated user, the creator becomes the lead.
Response: a Project object.
curl -X POST https://your-server.example/api/projects \
-H "Authorization: Bearer <API_KEY>" \
-H "Content-Type: application/json" \
-d '{"name":"Lific","identifier":"LIF"}'{
"id": 1,
"name": "Lific",
"identifier": "LIF",
"description": "",
"emoji": null,
"lead_user_id": 1,
"sort_order": 0,
"created_at": "2026-07-14 12:00:00",
"updated_at": "2026-07-14 12:00:00"
}GET /api/projects/{id}
Returns a project. Path parameter: id (integer project ID). It has no query parameters or request body.
Response: a Project object.
PUT /api/projects/{id}
Updates supplied project fields. Path parameter: id (integer project ID). It has no query parameters.
Request body fields are name (string, optional), identifier (string, optional), description (string, optional), emoji (string, null, or omitted), and lead_user_id (integer, null, or omitted). An omitted nullable field is unchanged. A null nullable field clears its value.
Response: a Project object.
DELETE /api/projects/{id}
Deletes a project. Path parameter: id (integer project ID). It has no query parameters or request body.
Response: the standard delete response.
PUT /api/projects/reorder
Reorders the supplied projects by list position. This endpoint has no path or query parameters.
Request body field: ids (integer array). Response: a Project array in the resulting order.
Project data
GET /api/projects/{id}/board
Returns project issues grouped into named arrays. Path parameter: id (integer project ID). Query parameter: group_by (string, optional). Omit it or use any value other than priority or module to group by status. Use priority or module for those groupings.
It has no request body. Response: an object whose keys are group names and whose values are Issue arrays.
GET /api/projects/{id}/issue-counts
Returns issue counts by status. Path parameter: id (integer project ID). It has no query parameters or request body.
Response: an object with backlog, todo, active, done, cancelled, and total integer fields.
GET /api/projects/{id}/insights
Returns project issue and activity aggregates. Path parameter: id (integer project ID). Query parameter: weeks (integer, optional). The value defaults to 12 and is clamped to 1..=52.
It has no request body. Response: an object with weeks (integer), created_per_week (array of objects with week_start string and count integer), closed_per_week (the same shape), status_counts, priority_counts, module_counts, and top_actors.
status_counts has the same fields as issue counts. priority_counts has urgent, high, medium, low, none, and total integer fields. Each module_counts item has module_id (integer or null), name (string), and count (integer). Each top_actors item has actor_user_id (integer or null), username (string or null), display_name (string or null), is_bot (boolean), actions (integer), last_ts (string), and top_transport (string).
GET /api/projects/{id}/mention-candidates
Lists users who can be mentioned in comments for a project. Path parameter: id (integer project ID). It has no query parameters or request body.
Response: an array of objects with user_id (integer), username (string), and display_name (string).
Membership
GET /api/projects/{id}/members
Lists project members with display identity. Path parameter: id (integer project ID). It has no query parameters or request body.
Response: an array of objects with project_id (integer), user_id (integer), role (string), created_at (string), username (string), and display_name (string).
POST /api/projects/{id}/members
Adds a project member. Path parameter: id (integer project ID). It has no query parameters.
Request body fields are user_id (integer) and role (string, optional). role defaults to viewer. Valid roles are viewer, maintainer, and lead.
Response: an object with project_id (integer), user_id (integer), role (string), and created_at (string).
curl -X POST https://your-server.example/api/projects/1/members \
-H "Authorization: Bearer <API_KEY>" \
-H "Content-Type: application/json" \
-d '{"user_id":2,"role":"viewer"}'{
"project_id": 1,
"user_id": 2,
"role": "viewer",
"created_at": "2026-07-14 12:00:00"
}PATCH /api/projects/{id}/members/{user_id}
Changes a member role. Path parameters are id (integer project ID) and user_id (integer user ID). It has no query parameters.
Request body field: role (string). Valid roles are viewer, maintainer, and lead. Response: a project member object. Demoting the only lead returns a conflict.
DELETE /api/projects/{id}/members/{user_id}
Removes a member. Path parameters are id (integer project ID) and user_id (integer user ID). It has no query parameters or request body.
Response: the standard delete response. Removing or demoting the only lead returns a conflict.
GET /api/projects/{id}/my-role
Returns the caller's effective project role. Path parameter: id (integer project ID). It has no query parameters or request body.
Response: an object with role (string or null), enforced (boolean), and is_admin (boolean).
Saved views
GET /api/projects/{id}/views
Lists saved views owned by the caller for one project. Path parameter: id (integer project ID). It has no query parameters or request body.
Response: an array of objects with id (integer), project_id (integer), user_id (integer), name (string), config (string containing JSON), is_default (boolean), created_at (string), and updated_at (string).
POST /api/projects/{id}/views
Creates a saved view owned by the caller. Path parameter: id (integer project ID). It has no query parameters.
Request body fields are name (string), config (string containing valid JSON), and is_default (boolean, optional). Response: a saved view object.
PATCH /api/projects/{id}/views/{view_id}
Updates a caller-owned saved view. Path parameters are id (integer project ID) and view_id (integer saved view ID). It has no query parameters.
Request body fields are name (string, optional), config (string containing valid JSON, optional), and is_default (boolean, optional). Response: a saved view object.
DELETE /api/projects/{id}/views/{view_id}
Deletes a caller-owned saved view. Path parameters are id (integer project ID) and view_id (integer saved view ID). It has no query parameters or request body.
Response: the standard delete response.
Activity and import
GET /api/projects/{id}/activity
Returns activity for a project, newest first. Path parameter: id (integer project ID). Query parameters are limit (integer, optional) and offset (integer, optional).
It has no request body. Response: an activity feed object with items (activity array) and has_more (boolean). Each activity item has id (integer), ts (string), actor_user_id (integer or null), actor_username (string or null), actor_display_name (string or null), actor_is_bot (boolean), transport (string), entity_type (string), entity_id (integer), entity_label (string or null), project_id (integer or null), issue_id (integer or null), page_id (integer or null), action (string), field (string or null), old_value (string or null), and new_value (string or null).
GET /api/projects/{id}/activity/actors
Returns activity totals grouped by actor. Path parameter: id (integer project ID). It has no query parameters or request body.
Response: an array of actor objects with actor_user_id (integer or null), username (string or null), display_name (string or null), is_bot (boolean), actions (integer), last_ts (string), and top_transport (string).
POST /api/projects/{id}/import/github
Imports GitHub issues into a project, or returns a preview when dry_run is true. Path parameter: id (integer project ID). It has no query parameters.
Request body fields are repo (string in owner/name form), token (string, optional), state (string, optional, defaults to all), map_open (string, optional, defaults to backlog), map_closed (string, optional, defaults to done), and dry_run (boolean, optional, defaults to false).
Response: an object with dry_run (boolean), issues_created (integer), issues_skipped_existing (integer), comments_created (integer), labels_created (integer), comments_planned (integer), labels_planned (integer), skipped_non_issues (integer), skipped_assignees (integer), and skipped_other (integer).