---
**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`.
---
**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`.
Operations
GET /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.
Authentication
[
{
"patAuth": []
}
]
Request, responses and operation details
{
"summary": "List IT incidents (unplanned break/fix tickets)",
"parameters": [
{
"$ref": "#/components/parameters/InstanceId"
},
{
"in": "query",
"name": "limit",
"schema": {
"type": "integer",
"default": 50
},
"description": "Legacy page size (default 50). Prefer $top. Ignored when $top/$skip are used."
},
{
"in": "query",
"name": "cursor",
"schema": {
"type": "string"
},
"description": "Legacy keyset cursor — pass the previous response's nextCursor. Prefer $skip/$top."
},
{
"in": "query",
"name": "$filter",
"schema": {
"type": "string"
},
"description": "OData 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\"."
},
{
"in": "query",
"name": "$select",
"schema": {
"type": "string"
},
"description": "Comma-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."
},
{
"in": "query",
"name": "$orderby",
"schema": {
"type": "string"
},
"description": "Sort clause(s), comma-separated, each \"field [asc|desc]\" (asc is the default). Example: \"createdAt desc, lastName asc\". Null values sort last."
},
{
"in": "query",
"name": "$search",
"schema": {
"type": "string"
},
"description": "Free-text, case-insensitive substring match across the resource's searchable fields."
},
{
"in": "query",
"name": "$top",
"schema": {
"type": "integer"
},
"description": "Maximum number of items to return (page size)."
},
{
"in": "query",
"name": "$skip",
"schema": {
"type": "integer"
},
"description": "Number of matching items to skip before returning results (offset paging). Combine with $top."
},
{
"in": "query",
"name": "$count",
"schema": {
"type": "boolean"
},
"description": "When true, include @odata.count (total matches after $filter/$search, before paging) in the response."
}
],
"responses": {
"200": {
"description": "Paginated list",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"data": {
"type": "array",
"items": {
"$ref": "#/components/schemas/Incident"
}
},
"nextCursor": {
"type": "string",
"nullable": true,
"description": "Cursor for the next page, or null on the last page. With $top/$skip this is the next $skip value; otherwise a keyset cursor."
},
"total": {
"type": "integer",
"description": "Total documents in the collection."
},
"@odata.count": {
"type": "integer",
"description": "Present only when $count=true: total matches after $filter/$search."
},
"@odata.truncated": {
"type": "boolean",
"description": "Present and true only when the collection exceeded the in-memory query cap and results may be incomplete."
}
}
}
}
}
},
"400": {
"description": "Invalid OData query (e.g. malformed $filter)"
}
},
"description": "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."
}
POST /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.
Authentication
[
{
"patAuth": []
}
]
Request, responses and operation details
{
"summary": "Open a new IT incident ticket",
"parameters": [
{
"$ref": "#/components/parameters/InstanceId"
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Incident"
}
}
}
},
"responses": {
"201": {
"description": "Created",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Incident"
}
}
}
}
},
"description": "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."
}
GET /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.
Authentication
[
{
"patAuth": []
}
]
Request, responses and operation details
{
"summary": "Get one IT incident by ticket number",
"parameters": [
{
"$ref": "#/components/parameters/InstanceId"
},
{
"in": "path",
"name": "id",
"required": true,
"schema": {
"type": "string"
}
}
],
"responses": {
"200": {
"description": "Found",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Incident"
}
}
}
},
"404": {
"description": "Not found"
}
},
"description": "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."
}
PATCH /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.
Authentication
[
{
"patAuth": []
}
]
Request, responses and operation details
{
"summary": "Update an IT incident (reassign, reprioritise, resolve)",
"description": "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": [
{
"$ref": "#/components/parameters/InstanceId"
},
{
"in": "path",
"name": "id",
"required": true,
"schema": {
"type": "string"
}
}
],
"requestBody": {
"description": "Fields to update (partial)",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Incident"
}
}
}
},
"responses": {
"200": {
"description": "Updated",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Incident"
}
}
}
},
"404": {
"description": "Not found"
}
}
}
DELETE /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.
Authentication
[
{
"patAuth": []
}
]
Request, responses and operation details
{
"summary": "Delete an IT incident record",
"parameters": [
{
"$ref": "#/components/parameters/InstanceId"
},
{
"in": "path",
"name": "id",
"required": true,
"schema": {
"type": "string"
}
}
],
"responses": {
"200": {
"description": "Deleted",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"success": {
"type": "boolean"
}
}
}
}
}
},
"404": {
"description": "Not found"
}
},
"description": "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."
}
POST /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.
Authentication
[
{
"patAuth": []
}
]
Request, responses and operation details
{
"summary": "Escalate an incident to the next support tier",
"description": "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": [
{
"$ref": "#/components/parameters/InstanceId"
},
{
"in": "path",
"name": "id",
"required": true,
"schema": {
"type": "string"
}
}
],
"requestBody": {
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"escalation_notes": {
"type": "string",
"example": "Customer impact escalating; looping in senior support"
}
}
}
}
}
},
"responses": {
"200": {
"description": "Updated incident after escalation",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Incident"
}
}
}
},
"400": {
"description": "Incident already at maximum escalation tier (3)"
},
"404": {
"description": "Not found"
},
"422": {
"description": "Cannot escalate a resolved or closed incident"
}
}
}
GET /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'.
Authentication
[
{
"patAuth": []
}
]
Request, responses and operation details
{
"summary": "List change requests (planned IT changes)",
"parameters": [
{
"$ref": "#/components/parameters/InstanceId"
},
{
"in": "query",
"name": "limit",
"schema": {
"type": "integer",
"default": 50
},
"description": "Legacy page size (default 50). Prefer $top. Ignored when $top/$skip are used."
},
{
"in": "query",
"name": "cursor",
"schema": {
"type": "string"
},
"description": "Legacy keyset cursor — pass the previous response's nextCursor. Prefer $skip/$top."
},
{
"in": "query",
"name": "$filter",
"schema": {
"type": "string"
},
"description": "OData 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\"."
},
{
"in": "query",
"name": "$select",
"schema": {
"type": "string"
},
"description": "Comma-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."
},
{
"in": "query",
"name": "$orderby",
"schema": {
"type": "string"
},
"description": "Sort clause(s), comma-separated, each \"field [asc|desc]\" (asc is the default). Example: \"createdAt desc, lastName asc\". Null values sort last."
},
{
"in": "query",
"name": "$search",
"schema": {
"type": "string"
},
"description": "Free-text, case-insensitive substring match across the resource's searchable fields."
},
{
"in": "query",
"name": "$top",
"schema": {
"type": "integer"
},
"description": "Maximum number of items to return (page size)."
},
{
"in": "query",
"name": "$skip",
"schema": {
"type": "integer"
},
"description": "Number of matching items to skip before returning results (offset paging). Combine with $top."
},
{
"in": "query",
"name": "$count",
"schema": {
"type": "boolean"
},
"description": "When true, include @odata.count (total matches after $filter/$search, before paging) in the response."
}
],
"responses": {
"200": {
"description": "Paginated list",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"data": {
"type": "array",
"items": {
"$ref": "#/components/schemas/Change"
}
},
"nextCursor": {
"type": "string",
"nullable": true,
"description": "Cursor for the next page, or null on the last page. With $top/$skip this is the next $skip value; otherwise a keyset cursor."
},
"total": {
"type": "integer",
"description": "Total documents in the collection."
},
"@odata.count": {
"type": "integer",
"description": "Present only when $count=true: total matches after $filter/$search."
},
"@odata.truncated": {
"type": "boolean",
"description": "Present and true only when the collection exceeded the in-memory query cap and results may be incomplete."
}
}
}
}
}
},
"400": {
"description": "Invalid OData query (e.g. malformed $filter)"
}
},
"description": "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'."
}
POST /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.
Authentication
[
{
"patAuth": []
}
]
Request, responses and operation details
{
"summary": "Raise a change request",
"parameters": [
{
"$ref": "#/components/parameters/InstanceId"
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Change"
}
}
}
},
"responses": {
"201": {
"description": "Created",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Change"
}
}
}
}
},
"description": "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."
}
GET /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.
Authentication
[
{
"patAuth": []
}
]
Request, responses and operation details
{
"summary": "Get one change request",
"parameters": [
{
"$ref": "#/components/parameters/InstanceId"
},
{
"in": "path",
"name": "id",
"required": true,
"schema": {
"type": "string"
}
}
],
"responses": {
"200": {
"description": "Found",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Change"
}
}
}
},
"404": {
"description": "Not found"
}
},
"description": "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."
}
PATCH /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.
Authentication
[
{
"patAuth": []
}
]
Request, responses and operation details
{
"summary": "Update a change request's details or status",
"description": "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": [
{
"$ref": "#/components/parameters/InstanceId"
},
{
"in": "path",
"name": "id",
"required": true,
"schema": {
"type": "string"
}
}
],
"requestBody": {
"description": "Fields to update (partial)",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Change"
}
}
}
},
"responses": {
"200": {
"description": "Updated",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Change"
}
}
}
},
"404": {
"description": "Not found"
}
}
}
DELETE /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.
Authentication
[
{
"patAuth": []
}
]
Request, responses and operation details
{
"summary": "Delete a change request",
"parameters": [
{
"$ref": "#/components/parameters/InstanceId"
},
{
"in": "path",
"name": "id",
"required": true,
"schema": {
"type": "string"
}
}
],
"responses": {
"200": {
"description": "Deleted",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"success": {
"type": "boolean"
}
}
}
}
}
},
"404": {
"description": "Not found"
}
},
"description": "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."
}
POST /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.
Authentication
[
{
"patAuth": []
}
]
Request, responses and operation details
{
"summary": "Approve a change at the Change Advisory Board",
"description": "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": [
{
"$ref": "#/components/parameters/InstanceId"
},
{
"in": "path",
"name": "id",
"required": true,
"schema": {
"type": "string"
}
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"approved_by": {
"type": "string",
"example": "manager1@acme.com"
}
},
"required": [
"approved_by"
]
}
}
}
},
"responses": {
"200": {
"description": "Updated change after CAB approval",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Change"
}
}
}
},
"404": {
"description": "Not found"
},
"422": {
"description": "Change cannot be approved in its current state"
}
}
}
POST /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.
Authentication
[
{
"patAuth": []
}
]
Request, responses and operation details
{
"summary": "Reject a change at the Change Advisory Board",
"description": "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": [
{
"$ref": "#/components/parameters/InstanceId"
},
{
"in": "path",
"name": "id",
"required": true,
"schema": {
"type": "string"
}
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"rejected_by": {
"type": "string",
"example": "manager2@acme.com"
},
"reason": {
"type": "string",
"example": "Insufficient testing evidence provided"
}
},
"required": [
"rejected_by",
"reason"
]
}
}
}
},
"responses": {
"200": {
"description": "Updated change after CAB rejection",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Change"
}
}
}
},
"404": {
"description": "Not found"
},
"422": {
"description": "Change cannot be rejected in its current state"
}
}
}
GET /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.
Authentication
[
{
"patAuth": []
}
]
Request, responses and operation details
{
"summary": "List SLA policies (response/resolution targets)",
"parameters": [
{
"$ref": "#/components/parameters/InstanceId"
},
{
"in": "query",
"name": "limit",
"schema": {
"type": "integer",
"default": 50
},
"description": "Legacy page size (default 50). Prefer $top. Ignored when $top/$skip are used."
},
{
"in": "query",
"name": "cursor",
"schema": {
"type": "string"
},
"description": "Legacy keyset cursor — pass the previous response's nextCursor. Prefer $skip/$top."
},
{
"in": "query",
"name": "$filter",
"schema": {
"type": "string"
},
"description": "OData 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\"."
},
{
"in": "query",
"name": "$select",
"schema": {
"type": "string"
},
"description": "Comma-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."
},
{
"in": "query",
"name": "$orderby",
"schema": {
"type": "string"
},
"description": "Sort clause(s), comma-separated, each \"field [asc|desc]\" (asc is the default). Example: \"createdAt desc, lastName asc\". Null values sort last."
},
{
"in": "query",
"name": "$search",
"schema": {
"type": "string"
},
"description": "Free-text, case-insensitive substring match across the resource's searchable fields."
},
{
"in": "query",
"name": "$top",
"schema": {
"type": "integer"
},
"description": "Maximum number of items to return (page size)."
},
{
"in": "query",
"name": "$skip",
"schema": {
"type": "integer"
},
"description": "Number of matching items to skip before returning results (offset paging). Combine with $top."
},
{
"in": "query",
"name": "$count",
"schema": {
"type": "boolean"
},
"description": "When true, include @odata.count (total matches after $filter/$search, before paging) in the response."
}
],
"responses": {
"200": {
"description": "Paginated list",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"data": {
"type": "array",
"items": {
"$ref": "#/components/schemas/SlaPolicy"
}
},
"nextCursor": {
"type": "string",
"nullable": true,
"description": "Cursor for the next page, or null on the last page. With $top/$skip this is the next $skip value; otherwise a keyset cursor."
},
"total": {
"type": "integer",
"description": "Total documents in the collection."
},
"@odata.count": {
"type": "integer",
"description": "Present only when $count=true: total matches after $filter/$search."
},
"@odata.truncated": {
"type": "boolean",
"description": "Present and true only when the collection exceeded the in-memory query cap and results may be incomplete."
}
}
}
}
}
},
"400": {
"description": "Invalid OData query (e.g. malformed $filter)"
}
},
"description": "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."
}
POST /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.
Authentication
[
{
"patAuth": []
}
]
Request, responses and operation details
{
"summary": "Create an SLA policy",
"parameters": [
{
"$ref": "#/components/parameters/InstanceId"
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/SlaPolicy"
}
}
}
},
"responses": {
"201": {
"description": "Created",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/SlaPolicy"
}
}
}
}
},
"description": "Defines a new service-level target — name, the priority it applies to, responseTimeHours and resolutionTimeHours. Configuration only; it does not alter any existing incident."
}
GET /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.
Authentication
[
{
"patAuth": []
}
]
Request, responses and operation details
{
"summary": "Get one SLA policy",
"parameters": [
{
"$ref": "#/components/parameters/InstanceId"
},
{
"in": "path",
"name": "id",
"required": true,
"schema": {
"type": "string"
}
}
],
"responses": {
"200": {
"description": "Found",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/SlaPolicy"
}
}
}
},
"404": {
"description": "Not found"
}
},
"description": "Fetches a single SLA policy by id (e.g. SLA-001) with its response/resolution targets and its active and paused flags."
}
PATCH /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.
Authentication
[
{
"patAuth": []
}
]
Request, responses and operation details
{
"summary": "Update an SLA policy's targets",
"description": "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": [
{
"$ref": "#/components/parameters/InstanceId"
},
{
"in": "path",
"name": "id",
"required": true,
"schema": {
"type": "string"
}
}
],
"requestBody": {
"description": "Fields to update (partial)",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/SlaPolicy"
}
}
}
},
"responses": {
"200": {
"description": "Updated",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/SlaPolicy"
}
}
}
},
"404": {
"description": "Not found"
}
}
}
DELETE /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.
Authentication
[
{
"patAuth": []
}
]
Request, responses and operation details
{
"summary": "Delete an SLA policy",
"parameters": [
{
"$ref": "#/components/parameters/InstanceId"
},
{
"in": "path",
"name": "id",
"required": true,
"schema": {
"type": "string"
}
}
],
"responses": {
"200": {
"description": "Deleted",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"success": {
"type": "boolean"
}
}
}
}
}
},
"404": {
"description": "Not found"
}
},
"description": "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."
}
POST /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.
Authentication
[
{
"patAuth": []
}
]
Request, responses and operation details
{
"summary": "Pause an SLA policy (stop the clock)",
"description": "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": [
{
"$ref": "#/components/parameters/InstanceId"
},
{
"in": "path",
"name": "id",
"required": true,
"schema": {
"type": "string"
}
}
],
"responses": {
"200": {
"description": "Updated SLA policy after pause",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/SlaPolicy"
}
}
}
},
"404": {
"description": "Not found"
},
"422": {
"description": "SLA policy is already paused"
}
}
}
POST /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.
Authentication
[
{
"patAuth": []
}
]
Request, responses and operation details
{
"summary": "Resume a paused SLA policy (restart the clock)",
"description": "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": [
{
"$ref": "#/components/parameters/InstanceId"
},
{
"in": "path",
"name": "id",
"required": true,
"schema": {
"type": "string"
}
}
],
"responses": {
"200": {
"description": "Updated SLA policy after resume",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/SlaPolicy"
}
}
}
},
"404": {
"description": "Not found"
},
"422": {
"description": "SLA policy is not paused and cannot be resumed"
}
}
}
GET /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'.
Authentication
[
{
"patAuth": []
}
]
Request, responses and operation details
{
"summary": "List problems (root causes behind repeat incidents)",
"parameters": [
{
"$ref": "#/components/parameters/InstanceId"
},
{
"in": "query",
"name": "limit",
"schema": {
"type": "integer",
"default": 50
},
"description": "Legacy page size (default 50). Prefer $top. Ignored when $top/$skip are used."
},
{
"in": "query",
"name": "cursor",
"schema": {
"type": "string"
},
"description": "Legacy keyset cursor — pass the previous response's nextCursor. Prefer $skip/$top."
},
{
"in": "query",
"name": "$filter",
"schema": {
"type": "string"
},
"description": "OData 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\"."
},
{
"in": "query",
"name": "$select",
"schema": {
"type": "string"
},
"description": "Comma-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."
},
{
"in": "query",
"name": "$orderby",
"schema": {
"type": "string"
},
"description": "Sort clause(s), comma-separated, each \"field [asc|desc]\" (asc is the default). Example: \"createdAt desc, lastName asc\". Null values sort last."
},
{
"in": "query",
"name": "$search",
"schema": {
"type": "string"
},
"description": "Free-text, case-insensitive substring match across the resource's searchable fields."
},
{
"in": "query",
"name": "$top",
"schema": {
"type": "integer"
},
"description": "Maximum number of items to return (page size)."
},
{
"in": "query",
"name": "$skip",
"schema": {
"type": "integer"
},
"description": "Number of matching items to skip before returning results (offset paging). Combine with $top."
},
{
"in": "query",
"name": "$count",
"schema": {
"type": "boolean"
},
"description": "When true, include @odata.count (total matches after $filter/$search, before paging) in the response."
}
],
"responses": {
"200": {
"description": "Paginated list",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"data": {
"type": "array",
"items": {
"$ref": "#/components/schemas/Problem"
}
},
"nextCursor": {
"type": "string",
"nullable": true,
"description": "Cursor for the next page, or null on the last page. With $top/$skip this is the next $skip value; otherwise a keyset cursor."
},
"total": {
"type": "integer",
"description": "Total documents in the collection."
},
"@odata.count": {
"type": "integer",
"description": "Present only when $count=true: total matches after $filter/$search."
},
"@odata.truncated": {
"type": "boolean",
"description": "Present and true only when the collection exceeded the in-memory query cap and results may be incomplete."
}
}
}
}
}
},
"400": {
"description": "Invalid OData query (e.g. malformed $filter)"
}
},
"description": "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'."
}
POST /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.
Authentication
[
{
"patAuth": []
}
]
Request, responses and operation details
{
"summary": "Open a problem investigation",
"parameters": [
{
"$ref": "#/components/parameters/InstanceId"
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Problem"
}
}
}
},
"responses": {
"201": {
"description": "Created",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Problem"
}
}
}
}
},
"description": "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."
}
GET /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.
Authentication
[
{
"patAuth": []
}
]
Request, responses and operation details
{
"summary": "Get one problem record",
"parameters": [
{
"$ref": "#/components/parameters/InstanceId"
},
{
"in": "path",
"name": "id",
"required": true,
"schema": {
"type": "string"
}
}
],
"responses": {
"200": {
"description": "Found",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Problem"
}
}
}
},
"404": {
"description": "Not found"
}
},
"description": "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."
}
PATCH /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.
Authentication
[
{
"patAuth": []
}
]
Request, responses and operation details
{
"summary": "Update a problem investigation",
"description": "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": [
{
"$ref": "#/components/parameters/InstanceId"
},
{
"in": "path",
"name": "id",
"required": true,
"schema": {
"type": "string"
}
}
],
"requestBody": {
"description": "Fields to update (partial)",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Problem"
}
}
}
},
"responses": {
"200": {
"description": "Updated",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Problem"
}
}
}
},
"404": {
"description": "Not found"
}
}
}
DELETE /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.
Authentication
[
{
"patAuth": []
}
]
Request, responses and operation details
{
"summary": "Delete a problem record",
"parameters": [
{
"$ref": "#/components/parameters/InstanceId"
},
{
"in": "path",
"name": "id",
"required": true,
"schema": {
"type": "string"
}
}
],
"responses": {
"200": {
"description": "Deleted",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"success": {
"type": "boolean"
}
}
}
}
}
},
"404": {
"description": "Not found"
}
},
"description": "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."
}
GET /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'.
Authentication
[
{
"patAuth": []
}
]
Request, responses and operation details
{
"summary": "List service requests (asks from the service catalog)",
"parameters": [
{
"$ref": "#/components/parameters/InstanceId"
},
{
"in": "query",
"name": "limit",
"schema": {
"type": "integer",
"default": 50
},
"description": "Legacy page size (default 50). Prefer $top. Ignored when $top/$skip are used."
},
{
"in": "query",
"name": "cursor",
"schema": {
"type": "string"
},
"description": "Legacy keyset cursor — pass the previous response's nextCursor. Prefer $skip/$top."
},
{
"in": "query",
"name": "$filter",
"schema": {
"type": "string"
},
"description": "OData 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\"."
},
{
"in": "query",
"name": "$select",
"schema": {
"type": "string"
},
"description": "Comma-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."
},
{
"in": "query",
"name": "$orderby",
"schema": {
"type": "string"
},
"description": "Sort clause(s), comma-separated, each \"field [asc|desc]\" (asc is the default). Example: \"createdAt desc, lastName asc\". Null values sort last."
},
{
"in": "query",
"name": "$search",
"schema": {
"type": "string"
},
"description": "Free-text, case-insensitive substring match across the resource's searchable fields."
},
{
"in": "query",
"name": "$top",
"schema": {
"type": "integer"
},
"description": "Maximum number of items to return (page size)."
},
{
"in": "query",
"name": "$skip",
"schema": {
"type": "integer"
},
"description": "Number of matching items to skip before returning results (offset paging). Combine with $top."
},
{
"in": "query",
"name": "$count",
"schema": {
"type": "boolean"
},
"description": "When true, include @odata.count (total matches after $filter/$search, before paging) in the response."
}
],
"responses": {
"200": {
"description": "Paginated list",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"data": {
"type": "array",
"items": {
"$ref": "#/components/schemas/ServiceRequest"
}
},
"nextCursor": {
"type": "string",
"nullable": true,
"description": "Cursor for the next page, or null on the last page. With $top/$skip this is the next $skip value; otherwise a keyset cursor."
},
"total": {
"type": "integer",
"description": "Total documents in the collection."
},
"@odata.count": {
"type": "integer",
"description": "Present only when $count=true: total matches after $filter/$search."
},
"@odata.truncated": {
"type": "boolean",
"description": "Present and true only when the collection exceeded the in-memory query cap and results may be incomplete."
}
}
}
}
}
},
"400": {
"description": "Invalid OData query (e.g. malformed $filter)"
}
},
"description": "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'."
}
POST /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.
Authentication
[
{
"patAuth": []
}
]
Request, responses and operation details
{
"summary": "Submit a service request",
"parameters": [
{
"$ref": "#/components/parameters/InstanceId"
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ServiceRequest"
}
}
}
},
"responses": {
"201": {
"description": "Created",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ServiceRequest"
}
}
}
}
},
"description": "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."
}
GET /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?'.
Authentication
[
{
"patAuth": []
}
]
Request, responses and operation details
{
"summary": "Get one service request",
"parameters": [
{
"$ref": "#/components/parameters/InstanceId"
},
{
"in": "path",
"name": "id",
"required": true,
"schema": {
"type": "string"
}
}
],
"responses": {
"200": {
"description": "Found",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ServiceRequest"
}
}
}
},
"404": {
"description": "Not found"
}
},
"description": "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?'."
}
PATCH /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.
Authentication
[
{
"patAuth": []
}
]
Request, responses and operation details
{
"summary": "Update or progress a service request",
"description": "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": [
{
"$ref": "#/components/parameters/InstanceId"
},
{
"in": "path",
"name": "id",
"required": true,
"schema": {
"type": "string"
}
}
],
"requestBody": {
"description": "Fields to update (partial)",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ServiceRequest"
}
}
}
},
"responses": {
"200": {
"description": "Updated",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ServiceRequest"
}
}
}
},
"404": {
"description": "Not found"
}
}
}
DELETE /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.
Authentication
[
{
"patAuth": []
}
]
Request, responses and operation details
{
"summary": "Delete a service request",
"parameters": [
{
"$ref": "#/components/parameters/InstanceId"
},
{
"in": "path",
"name": "id",
"required": true,
"schema": {
"type": "string"
}
}
],
"responses": {
"200": {
"description": "Deleted",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"success": {
"type": "boolean"
}
}
}
}
}
},
"404": {
"description": "Not found"
}
},
"description": "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."
}
GET /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'.
Authentication
[
{
"patAuth": []
}
]
Request, responses and operation details
{
"summary": "List CMDB configuration items (IT assets)",
"parameters": [
{
"$ref": "#/components/parameters/InstanceId"
},
{
"in": "query",
"name": "limit",
"schema": {
"type": "integer",
"default": 50
},
"description": "Legacy page size (default 50). Prefer $top. Ignored when $top/$skip are used."
},
{
"in": "query",
"name": "cursor",
"schema": {
"type": "string"
},
"description": "Legacy keyset cursor — pass the previous response's nextCursor. Prefer $skip/$top."
},
{
"in": "query",
"name": "$filter",
"schema": {
"type": "string"
},
"description": "OData 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\"."
},
{
"in": "query",
"name": "$select",
"schema": {
"type": "string"
},
"description": "Comma-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."
},
{
"in": "query",
"name": "$orderby",
"schema": {
"type": "string"
},
"description": "Sort clause(s), comma-separated, each \"field [asc|desc]\" (asc is the default). Example: \"createdAt desc, lastName asc\". Null values sort last."
},
{
"in": "query",
"name": "$search",
"schema": {
"type": "string"
},
"description": "Free-text, case-insensitive substring match across the resource's searchable fields."
},
{
"in": "query",
"name": "$top",
"schema": {
"type": "integer"
},
"description": "Maximum number of items to return (page size)."
},
{
"in": "query",
"name": "$skip",
"schema": {
"type": "integer"
},
"description": "Number of matching items to skip before returning results (offset paging). Combine with $top."
},
{
"in": "query",
"name": "$count",
"schema": {
"type": "boolean"
},
"description": "When true, include @odata.count (total matches after $filter/$search, before paging) in the response."
}
],
"responses": {
"200": {
"description": "Paginated list",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"data": {
"type": "array",
"items": {
"$ref": "#/components/schemas/ConfigurationItem"
}
},
"nextCursor": {
"type": "string",
"nullable": true,
"description": "Cursor for the next page, or null on the last page. With $top/$skip this is the next $skip value; otherwise a keyset cursor."
},
"total": {
"type": "integer",
"description": "Total documents in the collection."
},
"@odata.count": {
"type": "integer",
"description": "Present only when $count=true: total matches after $filter/$search."
},
"@odata.truncated": {
"type": "boolean",
"description": "Present and true only when the collection exceeded the in-memory query cap and results may be incomplete."
}
}
}
}
}
},
"400": {
"description": "Invalid OData query (e.g. malformed $filter)"
}
},
"description": "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'."
}
POST /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.
Authentication
[
{
"patAuth": []
}
]
Request, responses and operation details
{
"summary": "Add a configuration item to the CMDB",
"parameters": [
{
"$ref": "#/components/parameters/InstanceId"
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ConfigurationItem"
}
}
}
},
"responses": {
"201": {
"description": "Created",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ConfigurationItem"
}
}
}
}
},
"description": "Registers a new managed asset in the CMDB — name, type, environment, owning team and lifecycle status. Inventory only; it does not create any ticket."
}
GET /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.
Authentication
[
{
"patAuth": []
}
]
Request, responses and operation details
{
"summary": "Get one CMDB configuration item",
"parameters": [
{
"$ref": "#/components/parameters/InstanceId"
},
{
"in": "path",
"name": "id",
"required": true,
"schema": {
"type": "string"
}
}
],
"responses": {
"200": {
"description": "Found",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ConfigurationItem"
}
}
}
},
"404": {
"description": "Not found"
}
},
"description": "Fetches a single configuration item by id (e.g. CI-a1b2c3d4) with its type, environment, owner and operational status."
}
PATCH /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.
Authentication
[
{
"patAuth": []
}
]
Request, responses and operation details
{
"summary": "Update a CMDB configuration item",
"description": "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": [
{
"$ref": "#/components/parameters/InstanceId"
},
{
"in": "path",
"name": "id",
"required": true,
"schema": {
"type": "string"
}
}
],
"requestBody": {
"description": "Fields to update (partial)",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ConfigurationItem"
}
}
}
},
"responses": {
"200": {
"description": "Updated",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ConfigurationItem"
}
}
}
},
"404": {
"description": "Not found"
}
}
}
DELETE /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.
Authentication
[
{
"patAuth": []
}
]
Request, responses and operation details
{
"summary": "Delete a CMDB configuration item",
"parameters": [
{
"$ref": "#/components/parameters/InstanceId"
},
{
"in": "path",
"name": "id",
"required": true,
"schema": {
"type": "string"
}
}
],
"responses": {
"200": {
"description": "Deleted",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"success": {
"type": "boolean"
}
}
}
}
}
},
"404": {
"description": "Not found"
}
},
"description": "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."
}
GET /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.
Authentication
[
{
"patAuth": []
}
]
Request, responses and operation details
{
"summary": "Search the IT knowledge base",
"parameters": [
{
"$ref": "#/components/parameters/InstanceId"
},
{
"in": "query",
"name": "limit",
"schema": {
"type": "integer",
"default": 50
},
"description": "Legacy page size (default 50). Prefer $top. Ignored when $top/$skip are used."
},
{
"in": "query",
"name": "cursor",
"schema": {
"type": "string"
},
"description": "Legacy keyset cursor — pass the previous response's nextCursor. Prefer $skip/$top."
},
{
"in": "query",
"name": "$filter",
"schema": {
"type": "string"
},
"description": "OData 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\"."
},
{
"in": "query",
"name": "$select",
"schema": {
"type": "string"
},
"description": "Comma-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."
},
{
"in": "query",
"name": "$orderby",
"schema": {
"type": "string"
},
"description": "Sort clause(s), comma-separated, each \"field [asc|desc]\" (asc is the default). Example: \"createdAt desc, lastName asc\". Null values sort last."
},
{
"in": "query",
"name": "$search",
"schema": {
"type": "string"
},
"description": "Free-text, case-insensitive substring match across the resource's searchable fields."
},
{
"in": "query",
"name": "$top",
"schema": {
"type": "integer"
},
"description": "Maximum number of items to return (page size)."
},
{
"in": "query",
"name": "$skip",
"schema": {
"type": "integer"
},
"description": "Number of matching items to skip before returning results (offset paging). Combine with $top."
},
{
"in": "query",
"name": "$count",
"schema": {
"type": "boolean"
},
"description": "When true, include @odata.count (total matches after $filter/$search, before paging) in the response."
}
],
"responses": {
"200": {
"description": "Paginated list",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"data": {
"type": "array",
"items": {
"$ref": "#/components/schemas/KbArticle"
}
},
"nextCursor": {
"type": "string",
"nullable": true,
"description": "Cursor for the next page, or null on the last page. With $top/$skip this is the next $skip value; otherwise a keyset cursor."
},
"total": {
"type": "integer",
"description": "Total documents in the collection."
},
"@odata.count": {
"type": "integer",
"description": "Present only when $count=true: total matches after $filter/$search."
},
"@odata.truncated": {
"type": "boolean",
"description": "Present and true only when the collection exceeded the in-memory query cap and results may be incomplete."
}
}
}
}
}
},
"400": {
"description": "Invalid OData query (e.g. malformed $filter)"
}
},
"description": "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."
}
POST /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.
Authentication
[
{
"patAuth": []
}
]
Request, responses and operation details
{
"summary": "Publish a knowledge base article",
"parameters": [
{
"$ref": "#/components/parameters/InstanceId"
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/KbArticle"
}
}
}
},
"responses": {
"201": {
"description": "Created",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/KbArticle"
}
}
}
}
},
"description": "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."
}
GET /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.
Authentication
[
{
"patAuth": []
}
]
Request, responses and operation details
{
"summary": "Get one knowledge base article",
"parameters": [
{
"$ref": "#/components/parameters/InstanceId"
},
{
"in": "path",
"name": "id",
"required": true,
"schema": {
"type": "string"
}
}
],
"responses": {
"200": {
"description": "Found",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/KbArticle"
}
}
}
},
"404": {
"description": "Not found"
}
},
"description": "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."
}
PATCH /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.
Authentication
[
{
"patAuth": []
}
]
Request, responses and operation details
{
"summary": "Update a knowledge base article",
"description": "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": [
{
"$ref": "#/components/parameters/InstanceId"
},
{
"in": "path",
"name": "id",
"required": true,
"schema": {
"type": "string"
}
}
],
"requestBody": {
"description": "Fields to update (partial)",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/KbArticle"
}
}
}
},
"responses": {
"200": {
"description": "Updated",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/KbArticle"
}
}
}
},
"404": {
"description": "Not found"
}
}
}
DELETE /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.
Authentication
[
{
"patAuth": []
}
]
Request, responses and operation details
{
"summary": "Delete a knowledge base article",
"parameters": [
{
"$ref": "#/components/parameters/InstanceId"
},
{
"in": "path",
"name": "id",
"required": true,
"schema": {
"type": "string"
}
}
],
"responses": {
"200": {
"description": "Deleted",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"success": {
"type": "boolean"
}
}
}
}
}
},
"404": {
"description": "Not found"
}
},
"description": "DESTRUCTIVE and irreversible: unpublishes and erases the article, so users searching the knowledge base will no longer find that guidance."
}
GET /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'.
Authentication
[
{
"patAuth": []
}
]
Request, responses and operation details
{
"summary": "List monitoring alerts from observability tools",
"parameters": [
{
"$ref": "#/components/parameters/InstanceId"
},
{
"in": "query",
"name": "limit",
"schema": {
"type": "integer",
"default": 50
},
"description": "Legacy page size (default 50). Prefer $top. Ignored when $top/$skip are used."
},
{
"in": "query",
"name": "cursor",
"schema": {
"type": "string"
},
"description": "Legacy keyset cursor — pass the previous response's nextCursor. Prefer $skip/$top."
},
{
"in": "query",
"name": "$filter",
"schema": {
"type": "string"
},
"description": "OData 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\"."
},
{
"in": "query",
"name": "$select",
"schema": {
"type": "string"
},
"description": "Comma-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."
},
{
"in": "query",
"name": "$orderby",
"schema": {
"type": "string"
},
"description": "Sort clause(s), comma-separated, each \"field [asc|desc]\" (asc is the default). Example: \"createdAt desc, lastName asc\". Null values sort last."
},
{
"in": "query",
"name": "$search",
"schema": {
"type": "string"
},
"description": "Free-text, case-insensitive substring match across the resource's searchable fields."
},
{
"in": "query",
"name": "$top",
"schema": {
"type": "integer"
},
"description": "Maximum number of items to return (page size)."
},
{
"in": "query",
"name": "$skip",
"schema": {
"type": "integer"
},
"description": "Number of matching items to skip before returning results (offset paging). Combine with $top."
},
{
"in": "query",
"name": "$count",
"schema": {
"type": "boolean"
},
"description": "When true, include @odata.count (total matches after $filter/$search, before paging) in the response."
}
],
"responses": {
"200": {
"description": "Paginated list",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"data": {
"type": "array",
"items": {
"$ref": "#/components/schemas/Alert"
}
},
"nextCursor": {
"type": "string",
"nullable": true,
"description": "Cursor for the next page, or null on the last page. With $top/$skip this is the next $skip value; otherwise a keyset cursor."
},
"total": {
"type": "integer",
"description": "Total documents in the collection."
},
"@odata.count": {
"type": "integer",
"description": "Present only when $count=true: total matches after $filter/$search."
},
"@odata.truncated": {
"type": "boolean",
"description": "Present and true only when the collection exceeded the in-memory query cap and results may be incomplete."
}
}
}
}
}
},
"400": {
"description": "Invalid OData query (e.g. malformed $filter)"
}
},
"description": "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'."
}
POST /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.
Authentication
[
{
"patAuth": []
}
]
Request, responses and operation details
{
"summary": "Record a monitoring alert",
"parameters": [
{
"$ref": "#/components/parameters/InstanceId"
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Alert"
}
}
}
},
"responses": {
"201": {
"description": "Created",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Alert"
}
}
}
}
},
"description": "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."
}
GET /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.
Authentication
[
{
"patAuth": []
}
]
Request, responses and operation details
{
"summary": "Get one monitoring alert",
"parameters": [
{
"$ref": "#/components/parameters/InstanceId"
},
{
"in": "path",
"name": "id",
"required": true,
"schema": {
"type": "string"
}
}
],
"responses": {
"200": {
"description": "Found",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Alert"
}
}
}
},
"404": {
"description": "Not found"
}
},
"description": "Fetches a single alert by id (e.g. ALT-0001) with its severity, source, trigger time and whether it has been acknowledged or resolved."
}
PATCH /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.
Authentication
[
{
"patAuth": []
}
]
Request, responses and operation details
{
"summary": "Acknowledge or resolve a monitoring alert",
"description": "Updates an alert — most often setting status to 'acknowledged' when someone picks it up or 'resolved' once the condition clears, and stamping resolvedAt.",
"parameters": [
{
"$ref": "#/components/parameters/InstanceId"
},
{
"in": "path",
"name": "id",
"required": true,
"schema": {
"type": "string"
}
}
],
"requestBody": {
"description": "Fields to update (partial)",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Alert"
}
}
}
},
"responses": {
"200": {
"description": "Updated",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Alert"
}
}
}
},
"404": {
"description": "Not found"
}
}
}
DELETE /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.
Authentication
[
{
"patAuth": []
}
]
Request, responses and operation details
{
"summary": "Delete a monitoring alert",
"parameters": [
{
"$ref": "#/components/parameters/InstanceId"
},
{
"in": "path",
"name": "id",
"required": true,
"schema": {
"type": "string"
}
}
],
"responses": {
"200": {
"description": "Deleted",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"success": {
"type": "boolean"
}
}
}
}
}
},
"404": {
"description": "Not found"
}
},
"description": "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."
}