Required query parameter: workflowId (GUID). Returns 400 Bad Request (workflowId is required.) if omitted or empty.
Lists projects under that workflow that the caller can read, sorted by name. search matches project name (contains). A workflowId that doesn't correspond to any workflow simply returns an empty list (200), not an error.
An admin-linked key sees every project in the workflow, with no access filtering at all.
Response 200
{
"items": [
{
"id": 1,
"name": "Downtown Substation Upgrade",
"roadmap": "a1c2...",
"currentPhase": 3,
"status": 2,
"description": "...",
"visibility": true,
"location": "Austin, TX",
"latitude": 30.2672,
"longitude": -97.7431,
"suggestedProjectId": null,
"suggestedProjectName": null,
"createdAt": "2025-02-01T00:00:00+00:00",
"updatedAt": "2026-04-15T00:00:00+00:00"
}
],
"page": 1,
"pageSize": 20,
"totalCount": 1,
"totalPages": 1
}
roadmap is the id of the published roadmap the project is on, not the specific roadmap version id. Two projects on different versions of the same roadmap will show the same value here.
status is one of:
| Value | Meaning |
|---|---|
| 0 | Deleted |
| 1 | Draft |
| 2 | Active |
| 3 | Inactive |
| 4 | Completed |
In practice you'll never see 0 (Deleted) in a response. Deleted projects are excluded from every query, not just this list.
id: integer.
Response 200: single project object, same shape as above.
Response 404: project doesn't exist.
Response 403: exists but caller cannot read it. Both come back as the structured { "status": 0, "message": "..." } body.
Requires a Read & write key. The fields below are the only ones this endpoint can change; cost, currency, OPU, area, business segment, nature, tags, and roadmap are not writable through this API.
Body (all optional)
{
"name": "New Name",
"currentPhase": 4,
"status": 3,
"description": "Updated description",
"visibility": false,
"location": "Dallas, TX",
"latitude": 32.7767,
"longitude": -96.797,
"suggestedProjectId": "abc123",
"suggestedProjectName": "Suggested Name"
}
status, if provided, must be one of the values in the table above, otherwise 400 Bad Request (Invalid status value.).
currentPhase is not validated against the project's roadmap. Setting it to a phase id that isn't actually part of this project's roadmap will be saved as-is and can break the project in the web UI. Confirm the phase id is valid for this project's roadmap before sending it.
Completed or inactive projects cannot be updated, even by a caller who normally has write access to the project. This comes back as 403, not 404.
A successful 204 doesn't guarantee anything was actually written. Sending values that match the project's current state still returns 204.
Response 204 on success.
Response 404: project doesn't exist.
Response 403: project is Completed/Inactive, or caller lacks write access.
Requires a Read & write key. Soft-deletes the project, and cascades to soft-delete its phases and activities too. Same Completed/Inactive restriction as PATCH applies.