PolderAPI

Backlog API

Projects

Projects, their milestones and their status updates.

Base URLhttps://backlog.polder.work

A project is a body of work with a lead, a status, optional dates and a list of milestones. A project belongs to a workspace, not to a team: every member of the workspace can read and change every project, guests included. A project in another workspace answers 403.

The MCP server and the Projects screen do the same.

The project object

{
  "id": 14,
  "name": "Website relaunch",
  "slug": "website-relaunch",
  "summary": "New site before the summer",
  "description": "<p>…</p>",
  "status": "in_progress",
  "health": "on_track",
  "priority": 2,
  "icon": "rocket",
  "color": "#6366f1",
  "lead": { "id": 5, "name": "Sanne", "email": "sanne@example.com", "isBot": false },
  "starts_at": "2026-09-01",
  "target_at": "2026-12-01",
  "completed_at": null,
  "deal_stage_id": null,
  "deal_value": null,
  "expected_close_at": null,
  "created_at": "2026-08-30T09:12:44+00:00"
}
Field Description
status deal, backlog, planned, in_progress, completed or canceled. A new project starts as backlog. deal means the project is still in the sales pipeline.
health on_track, at_risk, off_track or null. Read-only: it is the health of the newest project update.
priority 0 (none) to 4.
lead The lead as {id, name, email, isBot}, or null.
starts_at, target_at Days (Y-m-d).
completed_at Set when status becomes completed, cleared when it changes to anything else.
deal_stage_id, deal_value, expected_close_at The sales side. Read-only here.

description is rich text (HTML). It is sanitised on write, so tags that are not allowed are removed.

List projects

GET/api/v1/workspaces/{workspace}/projectsscope projects:read

Projects of the workspace, ordered by name.

Parameter Description
status Only projects with this status.
q Case-insensitive match on a part of the name.
page, per_page Paging. 50 per page by default, at most 200.
curl "https://backlog.polder.work/api/v1/workspaces/7/projects?status=in_progress" \
  -H "Authorization: Bearer $POLDER_TOKEN"
{
  "data": [ { "id": 14, "name": "Website relaunch", "status": "in_progress", "…": "…" } ],
  "meta": { "page": 1, "per_page": 50, "total": 1, "last_page": 1 }
}

Create a project

POST/api/v1/workspaces/{workspace}/projectsscope projects:write

Creates a project and answers 201 with the project object. The history of the project starts with a created entry. A project created with status: "deal" is placed in the first open stage of the sales pipeline.

Body

Field Type Required Description
name string yes Up to 255 characters. The slug is made from it and is unique in the workspace.
summary string or null no Up to 500 characters.
description string or null no Rich text.
status string no One of the statuses above.
priority integer or null no 0 to 4.
icon string or null no Up to 40 characters.
color string or null no Up to 20 characters.
lead_id integer or null no A user id; must be a member of this workspace.
starts_at, target_at date or null no Y-m-d.
curl https://backlog.polder.work/api/v1/workspaces/7/projects \
  -H "Authorization: Bearer $POLDER_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"name": "Website relaunch", "status": "planned", "lead_id": 5, "target_at": "2026-12-01"}'

Invalid input answers 422 with the messages per field.

Note: health cannot be set. Post a project update to change it.

Get a project

GET/api/v1/projects/{project}scope projects:read

One project. 404 when it does not exist, 403 when it is in a workspace you are not a member of.

Change a project

PATCH/api/v1/projects/{project}scope projects:write

Changes the fields you send; fields you leave out stay as they are. The fields are those of Create a project, but name is optional. Send null to clear a nullable field.

Every changed field is written to the project's history under your name. Setting status to completed stamps completed_at, and a status change can move a project to another stage of the sales pipeline. Answers 200 with the project.

curl -X PATCH https://backlog.polder.work/api/v1/projects/14 \
  -H "Authorization: Bearer $POLDER_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"status": "completed"}'

The milestone object

{
  "id": 31,
  "project_id": 14,
  "name": "Beta",
  "description": null,
  "target_at": "2026-10-15",
  "position": 1
}

List milestones

GET/api/v1/projects/{project}/milestonesscope projects:read

The milestones of a project in plan order (position, then id), not in date order. Paged with page and per_page.

Create a milestone

POST/api/v1/projects/{project}/milestonesscope projects:write

Adds a milestone and answers 201. Without position it is appended after the last one.

Field Type Required Description
name string yes Up to 255 characters.
description string or null no
target_at date or null no Y-m-d.
position integer or null no 0 or more. Places the milestone there; the others shift.
curl https://backlog.polder.work/api/v1/projects/14/milestones \
  -H "Authorization: Bearer $POLDER_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"name": "Beta", "target_at": "2026-10-15"}'

Change a milestone

PATCH/api/v1/milestones/{milestone}scope projects:write

Changes the fields you send: name, description, target_at, position (same rules as above). Giving a position moves the milestone and shifts the others. Answers 200 with the milestone.

Delete a milestone

DELETE/api/v1/milestones/{milestone}scope projects:write

Deletes the milestone. Answers 204 without a body.

The project update object

{
  "id": 88,
  "project_id": 14,
  "health": "at_risk",
  "body": "The design review slipped a week.",
  "progress": null,
  "author": { "id": 5, "name": "Sanne", "email": "sanne@example.com", "isBot": false },
  "edited_at": null,
  "created_at": "2026-10-02T08:30:00+00:00"
}

Warning: progress is currently always null. The percentage that was complete when the update was posted is stored, but not yet returned.

List project updates

GET/api/v1/projects/{project}/updatesscope projects:read

The status updates of a project, newest first. Paged with page and per_page.

Post a project update

POST/api/v1/projects/{project}/updatesscope projects:write

Posts a status update as the owner of the token and answers 201. The health of the project becomes the health of the newest update.

Field Type Required Description
health string yes on_track, at_risk or off_track.
body string or null no Up to 20000 characters.
curl https://backlog.polder.work/api/v1/projects/14/updates \
  -H "Authorization: Bearer $POLDER_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"health": "at_risk", "body": "The design review slipped a week."}'

Delete a project update

DELETE/api/v1/project-updates/{update}scope projects:write

Deletes an update. Only its author or a workspace administrator may; anyone else gets 403. The project's health goes back to that of the update before it, or to null when none is left. Answers 204.