REST API Projects - edmozley/freeitsm GitHub Wiki
The complete usage guide for the Projects module of the REST API - projects, their stages and gate decisions, scope, RAID log and budget. Mirrors the interactive documentation at System โ API โ Documentation (with its live "Try it" tester).
Note
New to the API? The basics table on REST API: Tickets covers base URL, authentication, the response envelope, error codes, rate limits and PATCH semantics - identical across all modules.
What's distinctive about Projects:
| ๐ค The key acts as its analyst | The module's own rules apply unchanged: who may create a project, who may change one (its team, or everyone - Projects โ Settings โ General), and that only the project manager, the creator or someone who manages Projects may delete one. A key with projects.update whose analyst is not on the team gets 403 with the module's own words. |
| ๐ Proposals (3.3.0) |
approval - null (needed none), pending, approved or rejected - on every project; estimated_cost and estimated_benefit are writable on create and PATCH. Approving and rejecting happen in the app. A pending proposal refuses any status but proposed or cancelled (422). |
| ๐ท๏ธ Priority (3.3.0) |
priority - low, medium (default), high or critical - on every project, and writable on create and PATCH. The words a screen shows for each are a setting; the API always uses these four keys. |
| ๐ฉบ Health is worked out, never stored |
health is what the portfolio shows - set by hand, or worked out from tasks, dates, asset targets, linked tickets and tolerances. health_mode says which. ?health=red filters on that worked-out value. |
| ๐ Same code as the screens | Every write goes through the services the Projects screens use, so a change made through the API gets the same validation, history (with source: api), workflow events, Calendar entries and bell alerts. |
| ๐ข Company-scoped | The list is limited to the key's companies; a project outside them is a 404, never a 403. Stages, scope, RAID and budget lines are reached only through their project, so they share its scope. |
| ๐ท Currencies are never added | Budget amounts are in the project's own currency. A budget line naming a contract in another currency shows it with currency_mismatch: true and does not count it. |
B="https://your-server/api/v1"; K="Authorization: Bearer fitsm_โฆ"
# A project, already planned from a built-in template
P=$(curl -s -X POST "$B/projects" -H "$K" -H "Content-Type: application/json" -d '{
"name": "Leeds office move", "template": "builtin:office_move", "start_date": "2026-11-02"
}' | jq -r '.data.id')
# Its stages; start the first one
curl -s "$B/projects/$P/stages" -H "$K"
curl -s -X PATCH "$B/projects/$P/stages/118" -H "$K" -H "Content-Type: application/json" -d '{"status": "active"}'
# Log a risk, then record spend
curl -s -X POST "$B/projects/$P/raid" -H "$K" -H "Content-Type: application/json" \
-d '{"type": "risk", "title": "Landlord delays access", "probability": 3, "impact": 4}'
curl -s -X POST "$B/projects/$P/budget-lines" -H "$K" -H "Content-Type: application/json" \
-d '{"title": "40 replacement laptops", "category": "hardware", "planned": 36000, "actual": 34250}'
# Close the stage at its gate - the next one starts
curl -s -X POST "$B/projects/$P/stages/118/gate" -H "$K" -H "Content-Type: application/json" \
-d '{"decision": "go_with_conditions", "notes": "Label the patch panels before move day"}'
# Every live project that is off track
curl -s "$B/projects?status=proposed,active&health=red" -H "$K"| Method | Path | Permission | What it does |
|---|---|---|---|
| GET | /projects |
projects.read |
List and filter: status, health, methodology, project_manager_id, company_id, q, sort, paging |
| POST | /projects |
projects.create |
Create; template (builtin:<key> / saved:<id>) starts it already planned |
| GET | /projects/{id} |
projects.read |
One project: health, progress, active stage, exceptions, budget totals |
| PATCH | /projects/{id} |
projects.update |
Change any field; only what is sent changes |
| DELETE | /projects/{id} |
projects.delete |
Delete; its tasks are kept and detached (tasks_detached) |
| GET / POST | /projects/{id}/stages |
read / update | Its phases, stages or sprints; add one |
| PATCH / DELETE | /projects/{id}/stages/{stage_id} |
projects.update |
Change or delete a stage (its tasks stay in the project) |
| POST | /projects/{id}/stages/{stage_id}/gate |
projects.update |
Record go, go_with_conditions (notes required) or stop
|
| GET / POST | /projects/{id}/items |
read / update | Scope: deliverables with MoSCoW (must, should, could, wont) |
| PATCH / DELETE | /projects/{id}/items/{item_id} |
projects.update |
Change or delete a deliverable |
| GET / POST | /projects/{id}/raid |
read / update | The RAID log (?type=, ?status=); log an entry. 3.3.0: type may be dependency; a decision takes decided_by, decided_date, rationale; each entry returns escalation (or null) and actions (its follow-up tasks) |
| PATCH / DELETE | /projects/{id}/raid/{raid_id} |
projects.update |
Change or delete an entry |
| GET | /projects/{id}/budget |
projects.read |
Planned, actual, remaining, (3.3.0) forecast and cost_basis, labour (with to_come_hours / to_come_cost) and every line (with planned_date, spent_date, forecast, forecast_entered) |
| POST | /projects/{id}/budget-lines |
projects.update |
Add a budget line - (3.3.0) also planned_date, spent_date (not in the future) and forecast
|
| PATCH / DELETE | /projects/{id}/budget-lines/{line_id} |
projects.update |
Change (send actual: null to go back to the contract's value) or delete |
| GET | /projects/{id}/tasks |
projects.read |
Its top-level tasks - change them through /tasks |
| GET | /projects/{id}/links |
projects.read |
What it is connected to, by kind |
| GET | /projects/{id}/history |
projects.read |
Every change, newest first, paged |
-
Changing a sub-resource is changing the project - stages, scope, RAID and budget lines all need
projects.update, and the key's analyst must be allowed to change that project. -
A stage's
kind(phase,stage,sprint) follows the project's way of running. Staged and Agile projects allow one active stage at a time. -
A gate on a planned stage is refused;
gocloses a stage that is still open and starts the next planned one. - A RAID entry's linked ticket, and a budget line's contract and cost centre, are checked as on screen: the ticket must be one the key's analyst can open in the project's company; the contract must be linked to the project and the analyst must have Contracts; the cost centre must be active and in the project's company.
-
Budget amounts take at most two decimals. Labour in
/budgetfollows Projects โ Settings โ Budget;costisnullwhen labour is shown in hours. The API never returns one person's hourly rate. -
History rows written through the API carry
source: "api".
See also: Projects ยท Projects - Developer Guide ยท REST API ยท REST API: Tasks