REST API Service Status - edmozley/freeitsm GitHub Wiki

๐Ÿšฆ REST API: Service Status

The complete usage guide for the Service Status module of the REST API โ€” the health board and monitoring-driven incidents. 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 Service Status:

๐Ÿงฎ Status is derived, never stored A service has no status column โ€” its live state is computed as the worst impact level across its open incidents, else Operational. The API runs the dashboard's exact worst-severity subquery, so the health board is one call.
๐Ÿค– Built for the monitoring round-trip Open an incident when a probe fails (the service degrades instantly), escalate the impact, resolve on recovery (the service returns to Operational automatically). This module is the natural target for alerting integrations.
๐Ÿ“ One narrative, not a timeline An incident's comment is a single field, overwritten on each update โ€” the product has no append-only update feed. (A timeline table and a public unauthenticated status feed are both future candidates if a customer-facing page is ever wanted; today everything is key-authenticated.)
๐ŸŽฏ Per-service impact One incident can hit several services at different severities โ€” services is an array of {service_id, impact_level} pairs.

๐Ÿš€ Quick start โ€” the full monitoring loop

B="https://your-server/api/v1"; K="Authorization: Bearer fitsm_โ€ฆ"

# Probe fails โ†’ open an incident; the Email service flips to Degraded instantly
INC=$(curl -s -X POST "$B/service-status/incidents" -H "$K" -H "Content-Type: application/json" -d '{
  "title": "Email delivery delays",
  "comment": "SMTP queue growth detected by probe.",
  "services": [ { "service_id": 1, "impact_level": "Degraded" } ]
}' | jq -r '.data.id')

# It got worse โ†’ escalate
curl -s -X PATCH "$B/service-status/incidents/$INC" -H "$K" -H "Content-Type: application/json" \
  -d '{"status": "Identified", "services": [{"service_id": 1, "impact_level": "Major Outage"}]}'

# Probe recovers โ†’ resolve; resolved_at stamps, the service returns to Operational
curl -s -X PATCH "$B/service-status/incidents/$INC" -H "$K" -H "Content-Type: application/json" \
  -d '{"status": "Resolved", "comment": "Queue drained; delivery normal since 14:20."}'

๐Ÿšฆ Services (the health board)

๐ŸŸข GET /service-status/services ย  ๐Ÿ”‘ services.read

Active services (pass is_active=false for retired ones, q to search names), each with its derived live status:

{ "data": [ { "id": 1, "name": "Email", "description": "Exchange Online",
    "is_active": true, "display_order": 0,
    "current_status": { "name": "Degraded", "colour": "#eab308", "severity_order": 3 } } ] }

severity_order ranks worst-first (1 = Major Outage โ€ฆ Operational = 5), so a status page can sort or colour by it directly.

๐ŸŸข GET /service-status/services/{id} ย  ๐Ÿ”‘ services.read

The service plus its open incidents inline โ€” everything a per-service status panel needs.

๐Ÿ”ต POST ยท ๐ŸŸ  PATCH ยท ๐Ÿ”ด DELETE /service-status/services[/{id}] ย  ๐Ÿ”‘ services.create/update/delete

Only name is required to create; description, display_order and is_active optional. Deleting removes the service and its incident links transactionally (the incidents themselves survive).


๐Ÿ”ฅ Incidents

๐ŸŸข GET /service-status/incidents ย  ๐Ÿ”‘ service_incidents.read

Open-first, then most recently updated (the module's ordering).

Parameter Description
state open | resolved | all (default all)
service_id Incidents touching one service
q Search titles
created_since / resolved_since ISO 8601 bounds
page / per_page Pagination

The incident shape:

{ "id": 3, "title": "Email delivery delays",
  "status": { "id": 1, "name": "Investigating", "is_resolved": false, "colour": "#dc2626" },
  "comment": "SMTP queue growth detected by probe.",
  "services": [ { "service_id": 1, "name": "Email",
                  "impact": { "id": 3, "name": "Degraded", "colour": "#eab308", "severity_order": 3 } } ],
  "created_by": { "id": 1, "name": "Administrator" },
  "created_at": "2026-07-03T16:33:12Z", "updated_at": "2026-07-03T16:33:37Z", "resolved_at": null }

๐Ÿ”ต POST /service-status/incidents โ€” open ย  ๐Ÿ”‘ service_incidents.create

Field Required Description
title โœ… Incident title
status / status_id Lifecycle status (default Investigating)
comment The current-state narrative
services Array of {service_id, impact_level | impact_level_id} โ€” impact defaults Operational

Unknown services or impact levels are a 422 โ€” stricter than the UI, which silently skips them (a monitoring integration should never half-apply). Creating directly in a resolved status stamps resolved_at. Returns 201.

๐ŸŸ  PATCH /service-status/incidents/{id} โ€” update / resolve ย  ๐Ÿ”‘ service_incidents.update

Update title, status, comment (replaces the narrative), and/or send services to replace the affected set. The resolution rule is the UI's exactly:

  • moving into a resolved-type status stamps resolved_at once (preserved if already set),
  • reopening (any non-resolved status) clears it.

๐Ÿ”ด DELETE /service-status/incidents/{id} ย  ๐Ÿ”‘ service_incidents.delete

Removes the incident and its service links, transactionally.


๐Ÿ“š Reference data

Under the shared ๐Ÿ”‘ reference.read permission:

Endpoint Returns
๐ŸŸข GET /service-incident-statuses The lifecycle: Investigating โ†’ Identified โ†’ Monitoring โ†’ 3rd Party โ†’ Resolved (with is_resolved flags and colours โ€” resolvedness is the flag, not the name)
๐ŸŸข GET /service-impact-levels Impact levels worst-first: Major Outage (1) โ†’ Partial Outage โ†’ Degraded โ†’ Maintenance โ†’ Operational โ†’ No Disruption

๐Ÿงช Worked example: chat-ops status summary

A read-only key (services: read + service_incidents: read):

B="https://your-server/api/v1"; K="Authorization: Bearer fitsm_โ€ฆ"

# The board, one line per service, warning emoji when not Operational
curl -s -H "$K" "$B/service-status/services" \
  | jq -r '.data[] | "\(if .current_status.severity_order < 5 then "๐Ÿ”ด" else "๐ŸŸข" end) \(.name): \(.current_status.name)"'

# What's open right now, with affected services
curl -s -H "$K" "$B/service-status/incidents?state=open" \
  | jq -r '.data[] | "โ€ข \(.title) [\(.status.name)] โ€” \(.services | map(.name) | join(", "))"'

Under the hood: REST API โ€” How It Works ยท Other modules: Tickets ยท Assets ยท Problems ยท Changes ยท Knowledge ยท Tasks ยท CMDB ยท Contracts ยท Calendar ยท Software ยท Keys & permissions: System โ†’ API (System module) ยท Module docs: Service Status.