Repository navigation
REST API Projects
Ed Mozley edited this page Oct 8, 2026
·
1 revision
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. |
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 |
| 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 |
-
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
FreeITSM β an open-source IT Service Management platform Β· github.com/edmozley/freeitsm Β· MIT licence
- Installation
- β° Scheduled tasks (cron jobs)
- Architecture
- π§ͺ Developer tests
- AI Providers
- Internationalisation (i18n)
- Timezones & Time Handling
- π Date & Time Formats
- Theming & Dark Mode
- ποΈ Recent β getting back to what you were doing
- β¨οΈ Command palette (βK)
- π Searching inside tickets
- π Attached documents
-
MobileβFriendly
- β³ π« Mobile: Tickets
- β³ π» Mobile: Assets
- β³ π Mobile: Calendar
- β³ π Mobile: Knowledge
- β³ π¦ Mobile: Service Status
- β³ πΌ Mobile: Watchtower
- β³ π§© Mobile: Problem Management
- β³ π Mobile: Change Management
- β³ πΏ Mobile: Software
- β³ β Mobile: Tasks
- β³ π Mobile: Forms
- β³ π Mobile: Contracts
- β³ π Mobile: Domains
- β³ π Mobile: People
- β³ π Mobile: Projects
- β³ π Mobile: LMS
- β³ πΊοΈ Mobile: CMDB
- β³ πΊοΈ Mobile: Network Mapper
- β³ π§ Mobile: Process Mapper
- β³ βοΈ Mobile: Workflow
- β³ π₯οΈ Mobile: System
- β³ π Mobile: Reporting
- β³ π Mobile: System Wiki
- β³ π Mobile: Self-Service Portal
- β³ π§° Mobile: Techniques & Tricks
-
Security
- Layer 1 β which modules you can enter
- β³ π§© Module Access Control
- β³ π οΈ Module Access β Developer Guide
- Layer 2 β what you can administer
- β³ π Roles & Permissions
- β³ π οΈ Roles β Developer Guide
- β³ π€ Why capabilities are constants
- Layer 3 β the System module
- β³ π Admin Access Control
- Hardening
- β³ π Security review response 2026-08
- β³ π‘οΈ Security hardening 2026-08
- β³ π οΈ Security hardening 2026-08 β Developer Guide
- β³ π‘οΈ Round three β plain English
- β³ π οΈ Round three β Developer Guide
- β³ π‘οΈ CSRF protection (S4) β Developer Guide
- Single Sign-On (SSO)
- ποΈ LDAP & Active Directory
- π CardDAV contact sync
- Browser Extension
- API Reference
-
π REST API β how it works
- β³ π« REST API: Tickets
- β³ π» REST API: Assets
- β³ π΄ REST API: Problems
- β³ π REST API: Changes
- β³ π REST API: Knowledge
- β³ β REST API: Tasks
- β³ ποΈ REST API: CMDB
- β³ π REST API: Contracts
- β³ ποΈ REST API: Calendar
- β³ πΏ REST API: Software
- β³ π REST API: Domains
- β³ π¦ REST API: Service Status
- β³ βοΈ REST API: Morning Checks
- β³ π REST API: Forms
- β³ βοΈ REST API: Workflow
- β³ π·οΈ REST API: Cost centres
- β³ πΊοΈ REST API: Network Mapper
- β³ π§ Using the API docs page
- β³ π OpenAPI specification
- β³ β OpenAPI: kept correct
- β³ π οΈ Maintaining the catalogue
- Watchtower
-
Tickets
- β³ π Rota copy and paste β Developer Deep Dive
- β³ β Checklists & SOPs
- β³ βοΈ Mandatory fields
- β³ π·οΈ Ticket categories
- β³ π₯ Assigning tickets to a team, and escalation
- β³ π’ One board across every company
- β³ Mailbox Authentication
- β³ π€ Email send log
- β³ Basic IMAP mailboxes
- β³ Email rendering & images
- β³ SLA Management
- β³ WhatsApp channel
-
β³
βοΈ Telegram channel - β³ β CSAT company scope and filters β Developer Guide
- β³ π₯ Microsoft Teams channel
- β³ π¨οΈ Mattermost channel
- β³ π¬ Web chat channel
- β³ π£ Slack channel
- β³ π Linking tickets
- β³ β Record previews
- β³ π Ticket notes: internal or shared
- β³ ποΈ Canned responses
- β³ βοΈ Limiting replies to particular senders
- β³ π¨ Telling the analyst a ticket is theirs
- β³ βοΈ Email signatures
- β³ π The public web address
- β³ π’ Ticket numbering
- β³ π Raising a ticket for someone else
- β³ π Merging tickets
- β³ π Confidential tickets
- β³ π₯ Portal managers
- β³ π Who has seen a ticket
- β³ π Reading long tickets
- β³ β Splitting tickets
- β³ β Selecting several tickets
- β³ ποΈ The folder pane
- β³ π½ Just my tickets, or no closed ones
- β³ π οΈ Snoozing tickets β Developer Guide
- β³ π₯ Collision detection
- β³ β±οΈ Time tracking
- β³ π Scheduled work in your own calendar
- Problem Management
- Tasks
- π Projects
-
Assets
- β³ π’ Moving an asset between companies
- β³ π Shared asset locations
- β³ π§βπΌ Assigning assets to analysts
- β³ π Warranty and lease alerts
- β³ π Saved table views
- β³ π¨οΈ Recording anything, and importing it
- β³ π·οΈ QR asset labels
- β³ π Who holds what, and handover documents
- β³ π₯οΈ The inventory agent (PowerShell)
- β³ ποΈ Proxmox VE servers
- β³ βοΈ VMware Cloud Director servers
- β³ π Linking equipment to tickets
- β³ βοΈ Follow-up tasks on a ticket
- Knowledge
- Change Management
- Calendar
- Morning Checks
- Reporting
- Software
-
Forms
- β³ π¨ The form designer β Developer Guide
- β³ π Layout & the grid β Developer Guide
- β³ ποΈ Collections β grouping submissions
- β³ π Submissions as PDFs
- β³ β‘ What happens next β a form's own actions
- β³ π οΈ Sections & conditional logic β Developer Guide
- β³ π οΈ Lookup fields β Developer Guide
- β³ π‘οΈ Catalogue request approvals
- People
- Domains
- Contracts
- Service Status
- π Notifications
- π¨ War Room
- Self-Service Portal
- LMS
- Process Mapper
- CMDB
- Network Mapper
- Workflows
- Issue trackers (Jira, Azure DevOps)
- System
-
Overview
- β³ π Progress tracker
- β³ Concepts & vocabulary
- β³ Email routing & mailboxes
- β³ Settings: global vs per-company
- β³ Users & self-service
- β³ Staff cross-company access
- β³ π’ One board across every company
- β³ Worked examples
- β³ Pitfalls & gotchas
- β³ Scope: what it's for
- β³ π οΈ Developer Guide (make a module multi-company)
- β³ ποΈ Case study: CMDB (a linked graph)
- β³ π§ͺ Test harness (prove it's isolated)
- What this is
-
π Bugs resolved
- β³ πΌοΈ Logo and courses broke on Apache with PHP-FPM
- β³ π’ Chat tickets ignored your ticket numbering
- β³ π Dates shown as a dash, or in server time
- β³ π Assets β Users showed people from other companies
- β³ π Restricted analysts could read other modules' data
- β³ πΌοΈ Replies with a picture in the thread failed to send
- β³ π Reply attachments never reached the customer
- β³ π οΈ Outbound email attachments β Developer Guide
- β³ π A global SSO provider was missing from the portal
- β³ π Behind a proxy, the SSO redirect said http
- β³ βοΈ The portal tagline moved when you saved it
- β³ π¨ The portal settings screen forgot what you saved
- β³ π‘οΈ The approvals inbox said "Error" and nothing else
- β³ π A table's answers were missing from the PDF
- β³ β A single-select column let you tick every option
- β³ π The portal ignored a form's field widths
- β³ π The tasks board stopped taking clicks
- β³ ποΈ #121 The index list is out of date after upgrading
- β³ π #133 The calendar subscription was empty
- β³ π #131 Tasks always reopened on the board
- β³ π₯ #129 Every page returned HTTP 500 after upgrading
- β³ π³ #127 A PHP warning above the System page
- β³ π #126 Notes stamped with the server's clock
- β³ π Storing every date in UTC
- β³ πͺ The portal was down for everyone signed in
- β³ βοΈ #120 Workflow notes could never be written
- β³ βοΈ #123 Three errors when running Database Verification
- β³ π #122 The description box was a stub in the corner
- β³ π£ Demo data deleted real accounts
- β³ π #117 Sign-in redirected to the wrong address
- β³ π¨ #108 The priority dot was invisible
- β³ β±οΈ #116 Time logged from the right-click menu
- β³ π #114 API keys refused by our own guard
- β³ ποΈ #110 Assigning a task told nobody
- β³ πͺ #107 Signed out while still working
- β³ π #103 "Share with Requester" reached nobody
- β³ π #102 Search found nothing for hyphens
- β³ πͺ #101 Source code editor opened behind
- β³ βοΈ #88 Subtasks could not be ticked off
- β³ π» #84 Asset deep link selected nothing
- β³ π« #79 A new ticket arrived with no status
- β³ π§ #79 A ticket from email did not say so
- β³ π #78 Bell opened to nothing
- β³ π¬ #77 Mail only collected from Inbox
- β³ π #74 The default password could not be changed
- β³ π¦ #70 Renaming an impact level
- β³ π€ #67 App-only mailboxes could not send
- β³ π #45 Verify only ever worked for Microsoft
- β³ π #45 IMAP reported as not authenticated
- β³ βοΈ An email template stopped escaping itself
- β³ π The portal dashboard showed the wrong time
- β³ π’ The folder said 99 and the list showed 96