Skip to content

REST API Projects

Ed Mozley edited this page Oct 8, 2026 · 1 revision

πŸš€ REST API: Projects

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.
🩺 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.

πŸš€ Quick start

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"

Endpoints

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
PATCH / DELETE /projects/{id}/raid/{raid_id} projects.update Change or delete an entry
GET /projects/{id}/budget projects.read Planned, actual, remaining, labour and every line
POST /projects/{id}/budget-lines projects.update Add a budget line
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

Rules worth knowing

  • 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; go closes 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 /budget follows Projects β†’ Settings β†’ Budget; cost is null when 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

FreeITSM

Getting Started

Modules

Multi-tenancy (planned)

Blue sky thinking

Bugs resolved

Links

Clone this wiki locally