REST API Problems - edmozley/freeitsm GitHub Wiki
๐ด REST API: Problems
The complete usage guide for the Problem Management module of the REST API โ every URL, method, parameter and response shape. 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 Problems:
| ๐ข Company-scoped | Problems belong to a company, like tickets. A key's company scope is enforced on every list, read and write โ and linking an incident requires the ticket and problem to belong to the same company. Invisible on single-company installs. |
| ๐ Append-only journal | Problem notes are immutable โ you can add and read them, never edit or delete (same as the UI). |
| ๐๏ธ Delete is permanent | Unlike tickets (trash + restore), deleting a problem is final and takes its links, notes and history with it โ exactly like the UI's delete. |
๐ Quick start
Raise a problem from a monitoring correlation, link the incidents, and record the RCA:
B="https://your-server/api/v1"; K="Authorization: Bearer fitsm_โฆ"
# 1. Create the problem
PRB=$(curl -s -X POST "$B/problems" -H "$K" -H "Content-Type: application/json" -d '{
"title": "Recurring VPN drops on London office link",
"description": "Multiple users disconnected since 28 June.",
"priority": "High"}' | jq -r '.data.id')
# 2. Link the incidents behind it
curl -s -X POST "$B/problems/$PRB/tickets" -H "$K" -H "Content-Type: application/json" -d '{"ticket_id": 140}'
# 3. Later: record the root cause and flag the known error
curl -s -X PATCH "$B/problems/$PRB" -H "$K" -H "Content-Type: application/json" -d '{
"status": "Root Cause Identified",
"root_cause": "Faulty SFP on the primary switch uplink.",
"workaround": "Failover to the secondary link.",
"is_known_error": true}'
Every one of those steps writes the same audit entries the UI writes. ๐งพ
๐ด Problems
๐ข GET /problems โ list / search ย ๐ problems.read
Results are limited to the key's company scope.
| Parameter | Description |
|---|---|
state |
open | closed | all (default all) |
status / status_id |
Filter by problem status name (e.g. Investigating) or id |
priority / priority_id |
Filter by problem priority name or id |
assigned_analyst_id |
Filter by assignee |
is_known_error |
true / false โ the known-error database filter |
company_id |
One company (must be in the key's scope) |
q |
Search title and problem number (PRB-โฆ) |
created_since / updated_since |
ISO 8601 date-time bounds |
sort |
created_at (default, desc), updated_at, closed_at, id, title, problem_number, priority, status โ prefix - for descending |
page / per_page |
Pagination โ default 1 / 25, max per_page 100 |
The problem shape:
{ "id": 5, "problem_number": "PRB-00005",
"title": "Recurring VPN drops on London office link",
"description": "Multiple users disconnected since 28 June.",
"status": { "id": 3, "name": "Root Cause Identified", "is_closed": false },
"priority": { "id": 3, "name": "High" },
"assigned_analyst": { "id": 1, "name": "Administrator" },
"is_known_error": true,
"root_cause": "Faulty SFP on the primary switch uplink.",
"workaround": "Failover to the secondary link.",
"company": { "id": 1, "name": "Default" },
"created_by": { "id": 1, "name": "Administrator" },
"linked_tickets_count": 3,
"created_at": "2026-07-02T23:14:34Z", "updated_at": "2026-07-02T23:14:54Z", "closed_at": null }
๐ต POST /problems โ create ย ๐ problems.create
Creates a problem exactly like the UI: the PRB-##### number is stamped automatically, the module's default status applies if none is given, and a created entry is written to the audit trail. Files under the key's default company unless company_id says otherwise. Returns 201.
| Field | Required | Description |
|---|---|---|
title |
โ | Problem title |
description |
What's the problem? | |
status / status_id |
By name or id (default: the module's default status, usually New) | |
priority / priority_id |
By name or id | |
assigned_analyst_id |
Assign on creation | |
root_cause / workaround |
RCA fields | |
is_known_error |
Boolean | |
company_id |
File under a specific company (must be in the key's scope) |
๐ข GET /problems/{id} โ get one ย ๐ problems.read
The full problem plus its linked incidents and changes inline:
"linked_tickets": [ { "id": 140, "ticket_number": "MJI-729-47540",
"subject": "VPN drop โ J.Smith", "status": "Open",
"linked_at": "2026-07-02T23:15:18Z" } ],
"linked_changes": [ { "id": 42, "title": "Replace SFP on core switch",
"status": "Scheduled", "relation_type": "fixes" } ]
๐ PATCH /problems/{id} โ update ย ๐ problems.update
Send only what changes; null clears nullable fields; identical PATCHes are idempotent. Every change is written to the audit trail with the same field keys the UI writes (title, status, priority, assigned_to, root_cause, workaround, known_error as Yes/No) using display names for lookups. Moving into a closed-type status sets closed_at; moving out clears it.
| Field | Notes |
|---|---|
title |
Cannot be blanked |
description |
null clears |
status / status_id |
Drives closed_at via the status's is_closed flag |
priority / priority_id |
null clears |
assigned_analyst_id |
null unassigns |
root_cause / workaround |
RCA fields, null clears |
is_known_error |
Boolean |
๐ด DELETE /problems/{id} โ delete ย ๐ problems.delete
[!WARNING] Permanent. Deletes the problem and cascades its links, journal and audit trail โ the same as the UI's delete. There is no trash and no restore.
๐ Journal & history
๐ข GET /problems/{id}/notes ย ๐ problem_notes.read
The append-only journal, newest first.
๐ต POST /problems/{id}/notes ย ๐ problem_notes.create
| Field | Required | Description |
|---|---|---|
note |
โ | The note text |
Attributed to the analyst the key acts as. Immutable once written โ no edit, no delete (parity with the UI). Returns 201.
๐ข GET /problems/{id}/audit ย ๐ problem_audit.read
The system-generated change trail (created / modified rows), newest first:
{ "data": [ { "id": 18, "action": "modified", "field": "status",
"old_value": "New", "new_value": "Root Cause Identified",
"analyst": { "id": 1, "name": "Administrator" },
"created_at": "2026-07-02T23:14:54Z" } ] }
๐ Linking incidents & changes
Problems sit behind incidents (the tickets reporting the symptom) and in front of changes (the fix).
๐ต POST /problems/{id}/tickets โ link an incident ย ๐ problem_links.create
Body: {"ticket_id": 140}. Rules, all mirroring the UI:
- The ticket must be visible to the key (its company scope) โ otherwise
404. - Same-company rule: on multi-company installs the ticket and problem must belong to the same company โ otherwise
422"That incident belongs to a different company than this problem." - Already linked โ
409. - Writes a
linked_incidentaudit entry carrying the ticket number.
๐ด DELETE /problems/{id}/tickets/{ticket_id} โ unlink ย ๐ problem_links.delete
Removes the link (no audit entry โ parity with the UI).
๐ต POST /problems/{id}/changes โ link a change ย ๐ problem_links.create
Body: {"change_id": 42}. Links via the shared change-relations mechanism (relation type fixes) and writes a linked_change audit entry. Unknown change โ 422; already linked โ 409; installs without Change Management get a clean 422.
๐ด DELETE /problems/{id}/changes/{change_id} โ unlink ย ๐ problem_links.delete
Removes the change link.
๐ Reference data
Under the shared ๐ reference.read permission:
| Endpoint | Returns |
|---|---|
๐ข GET /problem-statuses |
Problem statuses with is_closed, is_default, colour, is_active (seeded: New, Investigating, Root Cause Identified, Known Error, Resolved, Closed) |
๐ข GET /problem-priorities |
Problem priorities (seeded: Low, Medium, High, Critical) |
๐งช Worked example: known-error database export
A read-only key (problems: read) feeds a status page or client report:
B="https://your-server/api/v1"; K="Authorization: Bearer fitsm_โฆ"
# All current known errors with their workarounds
curl -s -H "$K" "$B/problems?is_known_error=true&state=open&per_page=100" \
| jq -r '.data[] | "\(.problem_number) \(.title)\n Workaround: \(.workaround // "none documented")\n"'
And the monitoring direction โ auto-linking a new alert ticket to its open problem:
# Find the open problem for this symptom, then link the fresh incident to it
PRB=$(curl -s -H "$K" "$B/problems?q=VPN+drops&state=open" | jq -r '.data[0].id')
curl -s -X POST "$B/problems/$PRB/tickets" -H "$K" -H "Content-Type: application/json" \
-d "{\"ticket_id\": $NEW_TICKET_ID}"
Under the hood: REST API โ How It Works ยท Other modules: Tickets ยท Assets ยท Keys & permissions: System โ API (System module) ยท Module docs: Problem Management.