Purple ITSM API Documentation

Machine-readable OpenAPI 3.0 specification: https://marketplace.moveworks.com/api/purple-suite/itsm/openapi.json

The consolidated all-apps document at https://marketplace.moveworks.com/api/purple-suite/openapi.json can be narrowed to this app with ?apps=itsm, or combined with other apps comma-separated (e.g. ?apps=itsm,itsm).

Overview

--- **Acting as a user (`X-PS-Impersonate-User`).** Every endpoint accepts an optional `X-PS-Impersonate-User` request header whose value is the email of the instance user to act as. The effective user resolves in this order: the header if present, else the instance's configured default MCP user, else none. User-scoped paths additionally accept the literal `me` in place of an email, and Graph-style apps also serve `/me/…` twins of their `/users/{email}/…` paths that resolve the same way. This header is honored by all operations but is intentionally omitted from each operation's parameter list so it is not surfaced as a per-tool argument by MCP clients; see the `ImpersonateUser` entry under `components.parameters`.

Endpoints

GET /api/purple-suite/itsm/incidents

List IT incidents (unplanned break/fix tickets)

Incidents in Purple ITSM (a ServiceNow-style IT service desk) are unplanned disruptions someone reported — VPN down, laptop broken — with status (open | in_progress | resolved | closed | cancelled), priority P1–P4, category, assignee, reporter and escalation_tier. Distinct from service requests (asking for something), problems (root cause behind repeat incidents) and alerts (raised by monitoring). Supports server-side OData querying — $filter, $search, $orderby, $select, $top, $skip, $count (MCP clients see these as _filter, _search, _orderby, _select, _top, _skip, _count because $ is not a legal tool-input key). Example: $filter=status eq 'open' and priority eq 'P1'&$orderby=createdAt desc.

Parameters

NameInTypeRequiredDescription
X-Instance-IDheaderstringyes
limitqueryintegernoLegacy page size (default 50). Prefer $top. Ignored when $top/$skip are used.
cursorquerystringnoLegacy keyset cursor — pass the previous response's nextCursor. Prefer $skip/$top.
$filterquerystringnoOData filter expression. Comparison operators: eq, ne, gt, ge, lt, le. Logical: and, or, not, with parentheses for grouping. String functions: contains(field,'x'), startswith(field,'x'), endswith(field,'x'). Membership: field in ('a','b'). Case-insensitive matching via tolower(field) / toupper(field). Nested fields use a slash, e.g. pto_balance/vacation_days. String literals use single quotes; dates are ISO-8601. Examples: "status eq 'active'"; "salary gt 50000 and department eq 'Engineering'"; "contains(tolower(name),'acme')"; "closeDate gt 2026-01-01".
$selectquerystringnoComma-separated list of fields to return, e.g. "id,firstName,email". Nested fields via slash ("pto_balance/vacation_days"). The id field is always included.
$orderbyquerystringnoSort clause(s), comma-separated, each "field [asc|desc]" (asc is the default). Example: "createdAt desc, lastName asc". Null values sort last.
$searchquerystringnoFree-text, case-insensitive substring match across the resource's searchable fields.
$topqueryintegernoMaximum number of items to return (page size).
$skipqueryintegernoNumber of matching items to skip before returning results (offset paging). Combine with $top.
$countquerybooleannoWhen true, include @odata.count (total matches after $filter/$search, before paging) in the response.

Responses

200
Paginated list

application/json

  • data array

    array of:

    Incident

    • id string
    • title string
    • status string
    • priority string
    • category string
    • assignee string
    • reporter string
    • escalation_tier integer
    • escalated_at string
    • escalation_notes string
    • reopen_reason string
    • createdAt string
    • updatedAt string
  • nextCursor stringCursor for the next page, or null on the last page. With $top/$skip this is the next $skip value; otherwise a keyset cursor.
  • total integerTotal documents in the collection.
  • @odata.count integerPresent only when $count=true: total matches after $filter/$search.
  • @odata.truncated booleanPresent and true only when the collection exceeded the in-memory query cap and results may be incomplete.
400
Invalid OData query (e.g. malformed $filter)

POST /api/purple-suite/itsm/incidents

Open a new IT incident ticket

Files an incident on the IT service desk — title, priority (P1–P4), category (hardware/software/network/access/other), reporter and assignee. Use this when something is broken; if the user is asking to be GIVEN something (laptop, access, software) create a service request instead.

Parameters

NameInTypeRequiredDescription
X-Instance-IDheaderstringyes

Request body

application/json — required

Incident

  • id string
  • title string
  • status string
  • priority string
  • category string
  • assignee string
  • reporter string
  • escalation_tier integer
  • escalated_at string
  • escalation_notes string
  • reopen_reason string
  • createdAt string
  • updatedAt string

Responses

201
Created

application/json

Incident

  • id string
  • title string
  • status string
  • priority string
  • category string
  • assignee string
  • reporter string
  • escalation_tier integer
  • escalated_at string
  • escalation_notes string
  • reopen_reason string
  • createdAt string
  • updatedAt string

GET /api/purple-suite/itsm/incidents/{id}

Get one IT incident by ticket number

Fetches a single incident by id (e.g. INC-0001) with its current status, priority, assignee, escalation tier and timestamps. Use it to answer 'what's the status of my ticket'; search by other fields with itsm__list__incidents.

Parameters

NameInTypeRequiredDescription
X-Instance-IDheaderstringyes
idpathstringyes

Responses

200
Found

application/json

Incident

  • id string
  • title string
  • status string
  • priority string
  • category string
  • assignee string
  • reporter string
  • escalation_tier integer
  • escalated_at string
  • escalation_notes string
  • reopen_reason string
  • createdAt string
  • updatedAt string
404
Not found

DELETE /api/purple-suite/itsm/incidents/{id}

Delete an IT incident record

DESTRUCTIVE and irreversible: erases the incident and its history from the service desk entirely. This is not how tickets are normally finished — to end a ticket set its status to resolved/closed/cancelled with itsm__update__incidents; delete only for records created in error.

Parameters

NameInTypeRequiredDescription
X-Instance-IDheaderstringyes
idpathstringyes

Responses

200
Deleted

application/json

  • success boolean
404
Not found

PATCH /api/purple-suite/itsm/incidents/{id}

Update an IT incident (reassign, reprioritise, resolve)

The general-purpose incident write: change assignee, priority, category, notes or status. State-machine rules are enforced — valid statuses are open | in_progress | resolved | closed | cancelled; an open incident must pass through in_progress before it can be closed; and reopening a resolved/closed incident requires reopen_reason in the body. To raise the escalation tier use itsm__escalate__incidents, which is the only way that counter moves.

Parameters

NameInTypeRequiredDescription
X-Instance-IDheaderstringyes
idpathstringyes

Request body

Fields to update (partial)

application/json

Incident

  • id string
  • title string
  • status string
  • priority string
  • category string
  • assignee string
  • reporter string
  • escalation_tier integer
  • escalated_at string
  • escalation_notes string
  • reopen_reason string
  • createdAt string
  • updatedAt string

Responses

200
Updated

application/json

Incident

  • id string
  • title string
  • status string
  • priority string
  • category string
  • assignee string
  • reporter string
  • escalation_tier integer
  • escalated_at string
  • escalation_notes string
  • reopen_reason string
  • createdAt string
  • updatedAt string
404
Not found

POST /api/purple-suite/itsm/incidents/{id}/escalate

Escalate an incident to the next support tier

The only way the escalation counter moves: bumps the incident's escalation_tier by 1 (tier 3 is the ceiling — a further call returns 400), stamps escalated_at and stores optional escalation_notes. Use it when a ticket needs senior/urgent attention; use itsm__update__incidents to merely change priority, assignee or status. Fails with 422 on a resolved or closed incident.

Parameters

NameInTypeRequiredDescription
X-Instance-IDheaderstringyes
idpathstringyes

Request body

application/json

  • escalation_notes string

Responses

200
Updated incident after escalation

application/json

Incident

  • id string
  • title string
  • status string
  • priority string
  • category string
  • assignee string
  • reporter string
  • escalation_tier integer
  • escalated_at string
  • escalation_notes string
  • reopen_reason string
  • createdAt string
  • updatedAt string
400
Incident already at maximum escalation tier (3)
404
Not found
422
Cannot escalate a resolved or closed incident

GET /api/purple-suite/itsm/changes

List change requests (planned IT changes)

A Change is a PLANNED modification to the IT estate going through change management — OS upgrade, firewall rule, release — with status (draft | pending_approval | approved | in_progress | implemented | completed | rejected | cancelled), riskLevel, scheduledDate, approver and a cab_approval record. Contrast with incidents, which are unplanned breakages. Supports server-side OData querying — $filter, $search, $orderby, $select, $top, $skip, $count (MCP clients see these as _filter, _search, _orderby, _select, _top, _skip, _count because $ is not a legal tool-input key). Example: $filter=status eq 'pending_approval' and riskLevel eq 'high'.

Parameters

NameInTypeRequiredDescription
X-Instance-IDheaderstringyes
limitqueryintegernoLegacy page size (default 50). Prefer $top. Ignored when $top/$skip are used.
cursorquerystringnoLegacy keyset cursor — pass the previous response's nextCursor. Prefer $skip/$top.
$filterquerystringnoOData filter expression. Comparison operators: eq, ne, gt, ge, lt, le. Logical: and, or, not, with parentheses for grouping. String functions: contains(field,'x'), startswith(field,'x'), endswith(field,'x'). Membership: field in ('a','b'). Case-insensitive matching via tolower(field) / toupper(field). Nested fields use a slash, e.g. pto_balance/vacation_days. String literals use single quotes; dates are ISO-8601. Examples: "status eq 'active'"; "salary gt 50000 and department eq 'Engineering'"; "contains(tolower(name),'acme')"; "closeDate gt 2026-01-01".
$selectquerystringnoComma-separated list of fields to return, e.g. "id,firstName,email". Nested fields via slash ("pto_balance/vacation_days"). The id field is always included.
$orderbyquerystringnoSort clause(s), comma-separated, each "field [asc|desc]" (asc is the default). Example: "createdAt desc, lastName asc". Null values sort last.
$searchquerystringnoFree-text, case-insensitive substring match across the resource's searchable fields.
$topqueryintegernoMaximum number of items to return (page size).
$skipqueryintegernoNumber of matching items to skip before returning results (offset paging). Combine with $top.
$countquerybooleannoWhen true, include @odata.count (total matches after $filter/$search, before paging) in the response.

Responses

200
Paginated list

application/json

  • data array

    array of:

    Change

    • id string
    • title string
    • status string
    • riskLevel string
    • scheduledDate string
    • approver string
    • cab_approval object
      • approved_by string
      • approved_at string
      • rejected_by string
      • reason string
    • createdAt string
    • updatedAt string
  • nextCursor stringCursor for the next page, or null on the last page. With $top/$skip this is the next $skip value; otherwise a keyset cursor.
  • total integerTotal documents in the collection.
  • @odata.count integerPresent only when $count=true: total matches after $filter/$search.
  • @odata.truncated booleanPresent and true only when the collection exceeded the in-memory query cap and results may be incomplete.
400
Invalid OData query (e.g. malformed $filter)

POST /api/purple-suite/itsm/changes

Raise a change request

Creates a change request for planned work — title, riskLevel, scheduledDate and approver — normally starting in draft or pending_approval. Approval itself is not granted here: that happens through itsm__cab_approve__changes.

Parameters

NameInTypeRequiredDescription
X-Instance-IDheaderstringyes

Request body

application/json — required

Change

  • id string
  • title string
  • status string
  • riskLevel string
  • scheduledDate string
  • approver string
  • cab_approval object
    • approved_by string
    • approved_at string
    • rejected_by string
    • reason string
  • createdAt string
  • updatedAt string

Responses

201
Created

application/json

Change

  • id string
  • title string
  • status string
  • riskLevel string
  • scheduledDate string
  • approver string
  • cab_approval object
    • approved_by string
    • approved_at string
    • rejected_by string
    • reason string
  • createdAt string
  • updatedAt string

GET /api/purple-suite/itsm/changes/{id}

Get one change request

Fetches a single change by id (e.g. CHG-0001) with its status, risk, schedule and the cab_approval block recording who approved or rejected it and why.

Parameters

NameInTypeRequiredDescription
X-Instance-IDheaderstringyes
idpathstringyes

Responses

200
Found

application/json

Change

  • id string
  • title string
  • status string
  • riskLevel string
  • scheduledDate string
  • approver string
  • cab_approval object
    • approved_by string
    • approved_at string
    • rejected_by string
    • reason string
  • createdAt string
  • updatedAt string
404
Not found

DELETE /api/purple-suite/itsm/changes/{id}

Delete a change request

DESTRUCTIVE and irreversible: removes the change request and its CAB approval trail. To call off planned work while keeping the audit history, set status to 'cancelled' with itsm__update__changes instead.

Parameters

NameInTypeRequiredDescription
X-Instance-IDheaderstringyes
idpathstringyes

Responses

200
Deleted

application/json

  • success boolean
404
Not found

PATCH /api/purple-suite/itsm/changes/{id}

Update a change request's details or status

Edits change fields — title, riskLevel, scheduledDate, approver — and moves it through non-approval statuses such as in_progress, implemented, completed or cancelled. Do NOT use this to approve or reject: itsm__cab_approve__changes and itsm__cab_reject__changes are the CAB decisions and they also write the auditable cab_approval record.

Parameters

NameInTypeRequiredDescription
X-Instance-IDheaderstringyes
idpathstringyes

Request body

Fields to update (partial)

application/json

Change

  • id string
  • title string
  • status string
  • riskLevel string
  • scheduledDate string
  • approver string
  • cab_approval object
    • approved_by string
    • approved_at string
    • rejected_by string
    • reason string
  • createdAt string
  • updatedAt string

Responses

200
Updated

application/json

Change

  • id string
  • title string
  • status string
  • riskLevel string
  • scheduledDate string
  • approver string
  • cab_approval object
    • approved_by string
    • approved_at string
    • rejected_by string
    • reason string
  • createdAt string
  • updatedAt string
404
Not found

POST /api/purple-suite/itsm/changes/{id}/cab-approve

Approve a change at the Change Advisory Board

Records the formal CAB decision to approve planned work: writes approved_by/approved_at into the change's auditable cab_approval block and sets status to 'approved'. This is the governance action — do not simulate it by patching status with itsm__update__changes, which leaves no approval record. Fails with 422 if the change is already approved, rejected or cancelled.

Parameters

NameInTypeRequiredDescription
X-Instance-IDheaderstringyes
idpathstringyes

Request body

application/json — required

  • approved_by string required

Responses

200
Updated change after CAB approval

application/json

Change

  • id string
  • title string
  • status string
  • riskLevel string
  • scheduledDate string
  • approver string
  • cab_approval object
    • approved_by string
    • approved_at string
    • rejected_by string
    • reason string
  • createdAt string
  • updatedAt string
404
Not found
422
Change cannot be approved in its current state

POST /api/purple-suite/itsm/changes/{id}/cab-reject

Reject a change at the Change Advisory Board

Records the formal CAB decision to refuse planned work: requires rejected_by and a reason, writes them into the change's cab_approval block and sets status to 'rejected'. The counterpart to itsm__cab_approve__changes; prefer it over patching status directly so the refusal is auditable. Fails with 422 if the change is already rejected or implemented.

Parameters

NameInTypeRequiredDescription
X-Instance-IDheaderstringyes
idpathstringyes

Request body

application/json — required

  • rejected_by string required
  • reason string required

Responses

200
Updated change after CAB rejection

application/json

Change

  • id string
  • title string
  • status string
  • riskLevel string
  • scheduledDate string
  • approver string
  • cab_approval object
    • approved_by string
    • approved_at string
    • rejected_by string
    • reason string
  • createdAt string
  • updatedAt string
404
Not found
422
Change cannot be rejected in its current state

GET /api/purple-suite/itsm/sla_policies

List SLA policies (response/resolution targets)

SLA policies are the service-desk's configured time targets, not tickets: each names a priority (P1–P4) with responseTimeHours and resolutionTimeHours, plus active and paused flags. Use it to answer 'what is the SLA for a P1?' or to audit which policies are currently paused. Supports server-side OData querying — $filter, $search, $orderby, $select, $top, $skip, $count (MCP clients see these as _filter, _search, _orderby, _select, _top, _skip, _count because $ is not a legal tool-input key). Example: $filter=paused eq true.

Parameters

NameInTypeRequiredDescription
X-Instance-IDheaderstringyes
limitqueryintegernoLegacy page size (default 50). Prefer $top. Ignored when $top/$skip are used.
cursorquerystringnoLegacy keyset cursor — pass the previous response's nextCursor. Prefer $skip/$top.
$filterquerystringnoOData filter expression. Comparison operators: eq, ne, gt, ge, lt, le. Logical: and, or, not, with parentheses for grouping. String functions: contains(field,'x'), startswith(field,'x'), endswith(field,'x'). Membership: field in ('a','b'). Case-insensitive matching via tolower(field) / toupper(field). Nested fields use a slash, e.g. pto_balance/vacation_days. String literals use single quotes; dates are ISO-8601. Examples: "status eq 'active'"; "salary gt 50000 and department eq 'Engineering'"; "contains(tolower(name),'acme')"; "closeDate gt 2026-01-01".
$selectquerystringnoComma-separated list of fields to return, e.g. "id,firstName,email". Nested fields via slash ("pto_balance/vacation_days"). The id field is always included.
$orderbyquerystringnoSort clause(s), comma-separated, each "field [asc|desc]" (asc is the default). Example: "createdAt desc, lastName asc". Null values sort last.
$searchquerystringnoFree-text, case-insensitive substring match across the resource's searchable fields.
$topqueryintegernoMaximum number of items to return (page size).
$skipqueryintegernoNumber of matching items to skip before returning results (offset paging). Combine with $top.
$countquerybooleannoWhen true, include @odata.count (total matches after $filter/$search, before paging) in the response.

Responses

200
Paginated list

application/json

  • data array

    array of:

    SlaPolicy

    • id string
    • name string
    • responseTimeHours number
    • resolutionTimeHours number
    • priority string
    • active boolean
    • paused boolean
    • createdAt string
    • updatedAt string
  • nextCursor stringCursor for the next page, or null on the last page. With $top/$skip this is the next $skip value; otherwise a keyset cursor.
  • total integerTotal documents in the collection.
  • @odata.count integerPresent only when $count=true: total matches after $filter/$search.
  • @odata.truncated booleanPresent and true only when the collection exceeded the in-memory query cap and results may be incomplete.
400
Invalid OData query (e.g. malformed $filter)

POST /api/purple-suite/itsm/sla_policies

Create an SLA policy

Defines a new service-level target — name, the priority it applies to, responseTimeHours and resolutionTimeHours. Configuration only; it does not alter any existing incident.

Parameters

NameInTypeRequiredDescription
X-Instance-IDheaderstringyes

Request body

application/json — required

SlaPolicy

  • id string
  • name string
  • responseTimeHours number
  • resolutionTimeHours number
  • priority string
  • active boolean
  • paused boolean
  • createdAt string
  • updatedAt string

Responses

201
Created

application/json

SlaPolicy

  • id string
  • name string
  • responseTimeHours number
  • resolutionTimeHours number
  • priority string
  • active boolean
  • paused boolean
  • createdAt string
  • updatedAt string

GET /api/purple-suite/itsm/sla_policies/{id}

Get one SLA policy

Fetches a single SLA policy by id (e.g. SLA-001) with its response/resolution targets and its active and paused flags.

Parameters

NameInTypeRequiredDescription
X-Instance-IDheaderstringyes
idpathstringyes

Responses

200
Found

application/json

SlaPolicy

  • id string
  • name string
  • responseTimeHours number
  • resolutionTimeHours number
  • priority string
  • active boolean
  • paused boolean
  • createdAt string
  • updatedAt string
404
Not found

DELETE /api/purple-suite/itsm/sla_policies/{id}

Delete an SLA policy

DESTRUCTIVE and irreversible: removes the SLA definition, so tickets at that priority no longer have a target. To stop the clock temporarily use itsm__pause__sla_policies instead.

Parameters

NameInTypeRequiredDescription
X-Instance-IDheaderstringyes
idpathstringyes

Responses

200
Deleted

application/json

  • success boolean
404
Not found

PATCH /api/purple-suite/itsm/sla_policies/{id}

Update an SLA policy's targets

Edits a policy's name, priority, response/resolution hours or active flag. For the specific act of suspending or restarting SLA timing use itsm__pause__sla_policies / itsm__resume__sla_policies, which enforce the paused-state transition.

Parameters

NameInTypeRequiredDescription
X-Instance-IDheaderstringyes
idpathstringyes

Request body

Fields to update (partial)

application/json

SlaPolicy

  • id string
  • name string
  • responseTimeHours number
  • resolutionTimeHours number
  • priority string
  • active boolean
  • paused boolean
  • createdAt string
  • updatedAt string

Responses

200
Updated

application/json

SlaPolicy

  • id string
  • name string
  • responseTimeHours number
  • resolutionTimeHours number
  • priority string
  • active boolean
  • paused boolean
  • createdAt string
  • updatedAt string
404
Not found

POST /api/purple-suite/itsm/sla-policies/{id}/pause

Pause an SLA policy (stop the clock)

Suspends a service-level target by setting paused=true, e.g. during a maintenance window so response/resolution clocks do not count against IT. Reverse it with itsm__resume__sla_policies; use itsm__update__sla_policies to change the target hours themselves. Fails with 422 if the policy is already paused.

Parameters

NameInTypeRequiredDescription
X-Instance-IDheaderstringyes
idpathstringyes

Responses

200
Updated SLA policy after pause

application/json

SlaPolicy

  • id string
  • name string
  • responseTimeHours number
  • resolutionTimeHours number
  • priority string
  • active boolean
  • paused boolean
  • createdAt string
  • updatedAt string
404
Not found
422
SLA policy is already paused

POST /api/purple-suite/itsm/sla-policies/{id}/resume

Resume a paused SLA policy (restart the clock)

Puts a suspended service-level target back in force by setting paused=false — the counterpart to itsm__pause__sla_policies, typically once a maintenance window ends. Fails with 422 if the policy is not currently paused.

Parameters

NameInTypeRequiredDescription
X-Instance-IDheaderstringyes
idpathstringyes

Responses

200
Updated SLA policy after resume

application/json

SlaPolicy

  • id string
  • name string
  • responseTimeHours number
  • resolutionTimeHours number
  • priority string
  • active boolean
  • paused boolean
  • createdAt string
  • updatedAt string
404
Not found
422
SLA policy is not paused and cannot be resumed

GET /api/purple-suite/itsm/problems

List problems (root causes behind repeat incidents)

ITIL problem records: the underlying cause investigated behind a pattern of incidents (e.g. 'recurring login failures'), with status open | known_error | resolved and a rootCause classification. Use this for root-cause / known-error questions; individual user-reported breakages are itsm__list__incidents. Supports server-side OData querying — $filter, $search, $orderby, $select, $top, $skip, $count (MCP clients see these as _filter, _search, _orderby, _select, _top, _skip, _count because $ is not a legal tool-input key). Example: $filter=status eq 'known_error'.

Parameters

NameInTypeRequiredDescription
X-Instance-IDheaderstringyes
limitqueryintegernoLegacy page size (default 50). Prefer $top. Ignored when $top/$skip are used.
cursorquerystringnoLegacy keyset cursor — pass the previous response's nextCursor. Prefer $skip/$top.
$filterquerystringnoOData filter expression. Comparison operators: eq, ne, gt, ge, lt, le. Logical: and, or, not, with parentheses for grouping. String functions: contains(field,'x'), startswith(field,'x'), endswith(field,'x'). Membership: field in ('a','b'). Case-insensitive matching via tolower(field) / toupper(field). Nested fields use a slash, e.g. pto_balance/vacation_days. String literals use single quotes; dates are ISO-8601. Examples: "status eq 'active'"; "salary gt 50000 and department eq 'Engineering'"; "contains(tolower(name),'acme')"; "closeDate gt 2026-01-01".
$selectquerystringnoComma-separated list of fields to return, e.g. "id,firstName,email". Nested fields via slash ("pto_balance/vacation_days"). The id field is always included.
$orderbyquerystringnoSort clause(s), comma-separated, each "field [asc|desc]" (asc is the default). Example: "createdAt desc, lastName asc". Null values sort last.
$searchquerystringnoFree-text, case-insensitive substring match across the resource's searchable fields.
$topqueryintegernoMaximum number of items to return (page size).
$skipqueryintegernoNumber of matching items to skip before returning results (offset paging). Combine with $top.
$countquerybooleannoWhen true, include @odata.count (total matches after $filter/$search, before paging) in the response.

Responses

200
Paginated list

application/json

  • data array

    array of:

    Problem

    • id string
    • title string
    • status string
    • rootCause string
    • createdAt string
    • updatedAt string
  • nextCursor stringCursor for the next page, or null on the last page. With $top/$skip this is the next $skip value; otherwise a keyset cursor.
  • total integerTotal documents in the collection.
  • @odata.count integerPresent only when $count=true: total matches after $filter/$search.
  • @odata.truncated booleanPresent and true only when the collection exceeded the in-memory query cap and results may be incomplete.
400
Invalid OData query (e.g. malformed $filter)

POST /api/purple-suite/itsm/problems

Open a problem investigation

Creates a problem record to investigate the root cause behind repeating incidents. Use it when the same failure keeps recurring; log the individual user-facing outages as incidents.

Parameters

NameInTypeRequiredDescription
X-Instance-IDheaderstringyes

Request body

application/json — required

Problem

  • id string
  • title string
  • status string
  • rootCause string
  • createdAt string
  • updatedAt string

Responses

201
Created

application/json

Problem

  • id string
  • title string
  • status string
  • rootCause string
  • createdAt string
  • updatedAt string

GET /api/purple-suite/itsm/problems/{id}

Get one problem record

Fetches a single problem by id (e.g. PRB-0001) with its status and rootCause classification — useful for checking whether a recurring failure is already a known error.

Parameters

NameInTypeRequiredDescription
X-Instance-IDheaderstringyes
idpathstringyes

Responses

200
Found

application/json

Problem

  • id string
  • title string
  • status string
  • rootCause string
  • createdAt string
  • updatedAt string
404
Not found

DELETE /api/purple-suite/itsm/problems/{id}

Delete a problem record

DESTRUCTIVE and irreversible: erases the problem record and its root-cause findings. Normally close an investigation by setting status to 'resolved' with itsm__update__problems instead.

Parameters

NameInTypeRequiredDescription
X-Instance-IDheaderstringyes
idpathstringyes

Responses

200
Deleted

application/json

  • success boolean
404
Not found

PATCH /api/purple-suite/itsm/problems/{id}

Update a problem investigation

Edits the problem's title, status (open | known_error | resolved) or rootCause as the investigation progresses — for example marking it a known error once the cause is identified.

Parameters

NameInTypeRequiredDescription
X-Instance-IDheaderstringyes
idpathstringyes

Request body

Fields to update (partial)

application/json

Problem

  • id string
  • title string
  • status string
  • rootCause string
  • createdAt string
  • updatedAt string

Responses

200
Updated

application/json

Problem

  • id string
  • title string
  • status string
  • rootCause string
  • createdAt string
  • updatedAt string
404
Not found

GET /api/purple-suite/itsm/service_requests

List service requests (asks from the service catalog)

Service requests are people ASKING for something standard — a new laptop, software, access — with status submitted | approved | in_progress | completed | cancelled, requestedBy and a fulfillmentGroup (IT Support, Security, Procurement, Facilities). Use itsm__list__incidents instead when something is broken. Supports server-side OData querying — $filter, $search, $orderby, $select, $top, $skip, $count (MCP clients see these as _filter, _search, _orderby, _select, _top, _skip, _count because $ is not a legal tool-input key). Example: $filter=status eq 'submitted' and fulfillmentGroup eq 'Procurement'.

Parameters

NameInTypeRequiredDescription
X-Instance-IDheaderstringyes
limitqueryintegernoLegacy page size (default 50). Prefer $top. Ignored when $top/$skip are used.
cursorquerystringnoLegacy keyset cursor — pass the previous response's nextCursor. Prefer $skip/$top.
$filterquerystringnoOData filter expression. Comparison operators: eq, ne, gt, ge, lt, le. Logical: and, or, not, with parentheses for grouping. String functions: contains(field,'x'), startswith(field,'x'), endswith(field,'x'). Membership: field in ('a','b'). Case-insensitive matching via tolower(field) / toupper(field). Nested fields use a slash, e.g. pto_balance/vacation_days. String literals use single quotes; dates are ISO-8601. Examples: "status eq 'active'"; "salary gt 50000 and department eq 'Engineering'"; "contains(tolower(name),'acme')"; "closeDate gt 2026-01-01".
$selectquerystringnoComma-separated list of fields to return, e.g. "id,firstName,email". Nested fields via slash ("pto_balance/vacation_days"). The id field is always included.
$orderbyquerystringnoSort clause(s), comma-separated, each "field [asc|desc]" (asc is the default). Example: "createdAt desc, lastName asc". Null values sort last.
$searchquerystringnoFree-text, case-insensitive substring match across the resource's searchable fields.
$topqueryintegernoMaximum number of items to return (page size).
$skipqueryintegernoNumber of matching items to skip before returning results (offset paging). Combine with $top.
$countquerybooleannoWhen true, include @odata.count (total matches after $filter/$search, before paging) in the response.

Responses

200
Paginated list

application/json

  • data array

    array of:

    ServiceRequest

    • id string
    • title string
    • status string
    • requestedBy string
    • fulfillmentGroup string
    • createdAt string
    • updatedAt string
  • nextCursor stringCursor for the next page, or null on the last page. With $top/$skip this is the next $skip value; otherwise a keyset cursor.
  • total integerTotal documents in the collection.
  • @odata.count integerPresent only when $count=true: total matches after $filter/$search.
  • @odata.truncated booleanPresent and true only when the collection exceeded the in-memory query cap and results may be incomplete.
400
Invalid OData query (e.g. malformed $filter)

POST /api/purple-suite/itsm/service_requests

Submit a service request

Raises a catalog request on behalf of someone — title, requestedBy and the fulfillmentGroup that will handle it — normally starting in 'submitted'. For a fault or outage file an incident instead.

Parameters

NameInTypeRequiredDescription
X-Instance-IDheaderstringyes

Request body

application/json — required

ServiceRequest

  • id string
  • title string
  • status string
  • requestedBy string
  • fulfillmentGroup string
  • createdAt string
  • updatedAt string

Responses

201
Created

application/json

ServiceRequest

  • id string
  • title string
  • status string
  • requestedBy string
  • fulfillmentGroup string
  • createdAt string
  • updatedAt string

GET /api/purple-suite/itsm/service_requests/{id}

Get one service request

Fetches a single service request by id (e.g. SR-0001) with its status, requester and fulfillment group — the tool for 'where is my laptop request?'.

Parameters

NameInTypeRequiredDescription
X-Instance-IDheaderstringyes
idpathstringyes

Responses

200
Found

application/json

ServiceRequest

  • id string
  • title string
  • status string
  • requestedBy string
  • fulfillmentGroup string
  • createdAt string
  • updatedAt string
404
Not found

DELETE /api/purple-suite/itsm/service_requests/{id}

Delete a service request

DESTRUCTIVE and irreversible: removes the request and its history. To withdraw a request while keeping the record, set status to 'cancelled' with itsm__update__service_requests instead.

Parameters

NameInTypeRequiredDescription
X-Instance-IDheaderstringyes
idpathstringyes

Responses

200
Deleted

application/json

  • success boolean
404
Not found

PATCH /api/purple-suite/itsm/service_requests/{id}

Update or progress a service request

Edits the request or moves it along its lifecycle by setting status to approved, in_progress, completed or cancelled, and can reroute it to a different fulfillmentGroup.

Parameters

NameInTypeRequiredDescription
X-Instance-IDheaderstringyes
idpathstringyes

Request body

Fields to update (partial)

application/json

ServiceRequest

  • id string
  • title string
  • status string
  • requestedBy string
  • fulfillmentGroup string
  • createdAt string
  • updatedAt string

Responses

200
Updated

application/json

ServiceRequest

  • id string
  • title string
  • status string
  • requestedBy string
  • fulfillmentGroup string
  • createdAt string
  • updatedAt string
404
Not found

GET /api/purple-suite/itsm/cis

List CMDB configuration items (IT assets)

The CMDB inventory of managed IT assets — servers, workstations, network devices, applications, databases, storage — each with name, type, status (operational | maintenance | retired | ordered), environment (production/staging/development/dr) and owning team. Use it to find the asset behind a ticket or audit what is in production. Supports server-side OData querying — $filter, $search, $orderby, $select, $top, $skip, $count (MCP clients see these as _filter, _search, _orderby, _select, _top, _skip, _count because $ is not a legal tool-input key). Example: $filter=type eq 'server' and environment eq 'production'.

Parameters

NameInTypeRequiredDescription
X-Instance-IDheaderstringyes
limitqueryintegernoLegacy page size (default 50). Prefer $top. Ignored when $top/$skip are used.
cursorquerystringnoLegacy keyset cursor — pass the previous response's nextCursor. Prefer $skip/$top.
$filterquerystringnoOData filter expression. Comparison operators: eq, ne, gt, ge, lt, le. Logical: and, or, not, with parentheses for grouping. String functions: contains(field,'x'), startswith(field,'x'), endswith(field,'x'). Membership: field in ('a','b'). Case-insensitive matching via tolower(field) / toupper(field). Nested fields use a slash, e.g. pto_balance/vacation_days. String literals use single quotes; dates are ISO-8601. Examples: "status eq 'active'"; "salary gt 50000 and department eq 'Engineering'"; "contains(tolower(name),'acme')"; "closeDate gt 2026-01-01".
$selectquerystringnoComma-separated list of fields to return, e.g. "id,firstName,email". Nested fields via slash ("pto_balance/vacation_days"). The id field is always included.
$orderbyquerystringnoSort clause(s), comma-separated, each "field [asc|desc]" (asc is the default). Example: "createdAt desc, lastName asc". Null values sort last.
$searchquerystringnoFree-text, case-insensitive substring match across the resource's searchable fields.
$topqueryintegernoMaximum number of items to return (page size).
$skipqueryintegernoNumber of matching items to skip before returning results (offset paging). Combine with $top.
$countquerybooleannoWhen true, include @odata.count (total matches after $filter/$search, before paging) in the response.

Responses

200
Paginated list

application/json

  • data array

    array of:

    ConfigurationItem

    • id string
    • name string
    • type string
    • status string
    • environment string
    • owner string
    • createdAt string
    • updatedAt string
  • nextCursor stringCursor for the next page, or null on the last page. With $top/$skip this is the next $skip value; otherwise a keyset cursor.
  • total integerTotal documents in the collection.
  • @odata.count integerPresent only when $count=true: total matches after $filter/$search.
  • @odata.truncated booleanPresent and true only when the collection exceeded the in-memory query cap and results may be incomplete.
400
Invalid OData query (e.g. malformed $filter)

POST /api/purple-suite/itsm/cis

Add a configuration item to the CMDB

Registers a new managed asset in the CMDB — name, type, environment, owning team and lifecycle status. Inventory only; it does not create any ticket.

Parameters

NameInTypeRequiredDescription
X-Instance-IDheaderstringyes

Request body

application/json — required

ConfigurationItem

  • id string
  • name string
  • type string
  • status string
  • environment string
  • owner string
  • createdAt string
  • updatedAt string

Responses

201
Created

application/json

ConfigurationItem

  • id string
  • name string
  • type string
  • status string
  • environment string
  • owner string
  • createdAt string
  • updatedAt string

GET /api/purple-suite/itsm/cis/{id}

Get one CMDB configuration item

Fetches a single configuration item by id (e.g. CI-a1b2c3d4) with its type, environment, owner and operational status.

Parameters

NameInTypeRequiredDescription
X-Instance-IDheaderstringyes
idpathstringyes

Responses

200
Found

application/json

ConfigurationItem

  • id string
  • name string
  • type string
  • status string
  • environment string
  • owner string
  • createdAt string
  • updatedAt string
404
Not found

DELETE /api/purple-suite/itsm/cis/{id}

Delete a CMDB configuration item

DESTRUCTIVE and irreversible: removes the asset from the CMDB, breaking references from tickets and changes. For decommissioned kit set status to 'retired' with itsm__update__cis instead.

Parameters

NameInTypeRequiredDescription
X-Instance-IDheaderstringyes
idpathstringyes

Responses

200
Deleted

application/json

  • success boolean
404
Not found

PATCH /api/purple-suite/itsm/cis/{id}

Update a CMDB configuration item

Edits an asset record — status (e.g. move it to maintenance or retired), environment, owner or name. Updates inventory metadata only; it does not schedule the work, which belongs in a change request.

Parameters

NameInTypeRequiredDescription
X-Instance-IDheaderstringyes
idpathstringyes

Request body

Fields to update (partial)

application/json

ConfigurationItem

  • id string
  • name string
  • type string
  • status string
  • environment string
  • owner string
  • createdAt string
  • updatedAt string

Responses

200
Updated

application/json

ConfigurationItem

  • id string
  • name string
  • type string
  • status string
  • environment string
  • owner string
  • createdAt string
  • updatedAt string
404
Not found

GET /api/purple-suite/itsm/kb_articles

Search the IT knowledge base

Self-service how-to and troubleshooting articles published by IT (title, category, author, publishedAt, views, helpful counts). Reach for this FIRST when a user asks how to do something, before opening a ticket. Supports server-side OData querying — $filter, $search, $orderby, $select, $top, $skip, $count (MCP clients see these as _filter, _search, _orderby, _select, _top, _skip, _count because $ is not a legal tool-input key). Example: $search=password reset, or $filter=category eq 'Authentication'&$orderby=helpful desc.

Parameters

NameInTypeRequiredDescription
X-Instance-IDheaderstringyes
limitqueryintegernoLegacy page size (default 50). Prefer $top. Ignored when $top/$skip are used.
cursorquerystringnoLegacy keyset cursor — pass the previous response's nextCursor. Prefer $skip/$top.
$filterquerystringnoOData filter expression. Comparison operators: eq, ne, gt, ge, lt, le. Logical: and, or, not, with parentheses for grouping. String functions: contains(field,'x'), startswith(field,'x'), endswith(field,'x'). Membership: field in ('a','b'). Case-insensitive matching via tolower(field) / toupper(field). Nested fields use a slash, e.g. pto_balance/vacation_days. String literals use single quotes; dates are ISO-8601. Examples: "status eq 'active'"; "salary gt 50000 and department eq 'Engineering'"; "contains(tolower(name),'acme')"; "closeDate gt 2026-01-01".
$selectquerystringnoComma-separated list of fields to return, e.g. "id,firstName,email". Nested fields via slash ("pto_balance/vacation_days"). The id field is always included.
$orderbyquerystringnoSort clause(s), comma-separated, each "field [asc|desc]" (asc is the default). Example: "createdAt desc, lastName asc". Null values sort last.
$searchquerystringnoFree-text, case-insensitive substring match across the resource's searchable fields.
$topqueryintegernoMaximum number of items to return (page size).
$skipqueryintegernoNumber of matching items to skip before returning results (offset paging). Combine with $top.
$countquerybooleannoWhen true, include @odata.count (total matches after $filter/$search, before paging) in the response.

Responses

200
Paginated list

application/json

  • data array

    array of:

    KbArticle

    • id string
    • title string
    • category string
    • views integer
    • helpful integer
    • author string
    • publishedAt string
    • createdAt string
    • updatedAt string
  • nextCursor stringCursor for the next page, or null on the last page. With $top/$skip this is the next $skip value; otherwise a keyset cursor.
  • total integerTotal documents in the collection.
  • @odata.count integerPresent only when $count=true: total matches after $filter/$search.
  • @odata.truncated booleanPresent and true only when the collection exceeded the in-memory query cap and results may be incomplete.
400
Invalid OData query (e.g. malformed $filter)

POST /api/purple-suite/itsm/kb_articles

Publish a knowledge base article

Creates a new KB article — title, category (Authentication, Network, Hardware, Software, Security, Onboarding), author and publish date — so users can self-serve instead of raising incidents.

Parameters

NameInTypeRequiredDescription
X-Instance-IDheaderstringyes

Request body

application/json — required

KbArticle

  • id string
  • title string
  • category string
  • views integer
  • helpful integer
  • author string
  • publishedAt string
  • createdAt string
  • updatedAt string

Responses

201
Created

application/json

KbArticle

  • id string
  • title string
  • category string
  • views integer
  • helpful integer
  • author string
  • publishedAt string
  • createdAt string
  • updatedAt string

GET /api/purple-suite/itsm/kb_articles/{id}

Get one knowledge base article

Fetches a single KB article by id (e.g. KB-0001) with its category, author and usefulness stats — use it to cite specific guidance once you have found it via itsm__list__kb_articles.

Parameters

NameInTypeRequiredDescription
X-Instance-IDheaderstringyes
idpathstringyes

Responses

200
Found

application/json

KbArticle

  • id string
  • title string
  • category string
  • views integer
  • helpful integer
  • author string
  • publishedAt string
  • createdAt string
  • updatedAt string
404
Not found

DELETE /api/purple-suite/itsm/kb_articles/{id}

Delete a knowledge base article

DESTRUCTIVE and irreversible: unpublishes and erases the article, so users searching the knowledge base will no longer find that guidance.

Parameters

NameInTypeRequiredDescription
X-Instance-IDheaderstringyes
idpathstringyes

Responses

200
Deleted

application/json

  • success boolean
404
Not found

PATCH /api/purple-suite/itsm/kb_articles/{id}

Update a knowledge base article

Edits an existing article's title, category, author or publication date — for example to correct out-of-date guidance rather than publishing a duplicate.

Parameters

NameInTypeRequiredDescription
X-Instance-IDheaderstringyes
idpathstringyes

Request body

Fields to update (partial)

application/json

KbArticle

  • id string
  • title string
  • category string
  • views integer
  • helpful integer
  • author string
  • publishedAt string
  • createdAt string
  • updatedAt string

Responses

200
Updated

application/json

KbArticle

  • id string
  • title string
  • category string
  • views integer
  • helpful integer
  • author string
  • publishedAt string
  • createdAt string
  • updatedAt string
404
Not found

GET /api/purple-suite/itsm/alerts

List monitoring alerts from observability tools

Machine-generated alerts fired by monitoring systems (Datadog, PagerDuty, Nagios, CloudWatch, Prometheus) with severity critical | warning | info, status active | acknowledged | resolved and trigger/resolve times. These are detections, not human-reported tickets — use itsm__list__incidents for those. Supports server-side OData querying — $filter, $search, $orderby, $select, $top, $skip, $count (MCP clients see these as _filter, _search, _orderby, _select, _top, _skip, _count because $ is not a legal tool-input key). Example: $filter=status eq 'active' and severity eq 'critical'.

Parameters

NameInTypeRequiredDescription
X-Instance-IDheaderstringyes
limitqueryintegernoLegacy page size (default 50). Prefer $top. Ignored when $top/$skip are used.
cursorquerystringnoLegacy keyset cursor — pass the previous response's nextCursor. Prefer $skip/$top.
$filterquerystringnoOData filter expression. Comparison operators: eq, ne, gt, ge, lt, le. Logical: and, or, not, with parentheses for grouping. String functions: contains(field,'x'), startswith(field,'x'), endswith(field,'x'). Membership: field in ('a','b'). Case-insensitive matching via tolower(field) / toupper(field). Nested fields use a slash, e.g. pto_balance/vacation_days. String literals use single quotes; dates are ISO-8601. Examples: "status eq 'active'"; "salary gt 50000 and department eq 'Engineering'"; "contains(tolower(name),'acme')"; "closeDate gt 2026-01-01".
$selectquerystringnoComma-separated list of fields to return, e.g. "id,firstName,email". Nested fields via slash ("pto_balance/vacation_days"). The id field is always included.
$orderbyquerystringnoSort clause(s), comma-separated, each "field [asc|desc]" (asc is the default). Example: "createdAt desc, lastName asc". Null values sort last.
$searchquerystringnoFree-text, case-insensitive substring match across the resource's searchable fields.
$topqueryintegernoMaximum number of items to return (page size).
$skipqueryintegernoNumber of matching items to skip before returning results (offset paging). Combine with $top.
$countquerybooleannoWhen true, include @odata.count (total matches after $filter/$search, before paging) in the response.

Responses

200
Paginated list

application/json

  • data array

    array of:

    Alert

    • id string
    • title string
    • severity string
    • source string
    • status string
    • triggeredAt string
    • resolvedAt string
    • createdAt string
    • updatedAt string
  • nextCursor stringCursor for the next page, or null on the last page. With $top/$skip this is the next $skip value; otherwise a keyset cursor.
  • total integerTotal documents in the collection.
  • @odata.count integerPresent only when $count=true: total matches after $filter/$search.
  • @odata.truncated booleanPresent and true only when the collection exceeded the in-memory query cap and results may be incomplete.
400
Invalid OData query (e.g. malformed $filter)

POST /api/purple-suite/itsm/alerts

Record a monitoring alert

Creates an alert record as if a monitoring tool had fired it — title, severity, source system and triggeredAt. Mostly for simulating observability signals; a person reporting an issue should be filed as an incident.

Parameters

NameInTypeRequiredDescription
X-Instance-IDheaderstringyes

Request body

application/json — required

Alert

  • id string
  • title string
  • severity string
  • source string
  • status string
  • triggeredAt string
  • resolvedAt string
  • createdAt string
  • updatedAt string

Responses

201
Created

application/json

Alert

  • id string
  • title string
  • severity string
  • source string
  • status string
  • triggeredAt string
  • resolvedAt string
  • createdAt string
  • updatedAt string

GET /api/purple-suite/itsm/alerts/{id}

Get one monitoring alert

Fetches a single alert by id (e.g. ALT-0001) with its severity, source, trigger time and whether it has been acknowledged or resolved.

Parameters

NameInTypeRequiredDescription
X-Instance-IDheaderstringyes
idpathstringyes

Responses

200
Found

application/json

Alert

  • id string
  • title string
  • severity string
  • source string
  • status string
  • triggeredAt string
  • resolvedAt string
  • createdAt string
  • updatedAt string
404
Not found

DELETE /api/purple-suite/itsm/alerts/{id}

Delete a monitoring alert

DESTRUCTIVE and irreversible: erases the alert record and its detection history. To clear noise while keeping the trail, set its status to 'resolved' with itsm__update__alerts instead.

Parameters

NameInTypeRequiredDescription
X-Instance-IDheaderstringyes
idpathstringyes

Responses

200
Deleted

application/json

  • success boolean
404
Not found

PATCH /api/purple-suite/itsm/alerts/{id}

Acknowledge or resolve a monitoring alert

Updates an alert — most often setting status to 'acknowledged' when someone picks it up or 'resolved' once the condition clears, and stamping resolvedAt.

Parameters

NameInTypeRequiredDescription
X-Instance-IDheaderstringyes
idpathstringyes

Request body

Fields to update (partial)

application/json

Alert

  • id string
  • title string
  • severity string
  • source string
  • status string
  • triggeredAt string
  • resolvedAt string
  • createdAt string
  • updatedAt string

Responses

200
Updated

application/json

Alert

  • id string
  • title string
  • severity string
  • source string
  • status string
  • triggeredAt string
  • resolvedAt string
  • createdAt string
  • updatedAt string
404
Not found