Ionhour Docs
Integrations

Incidents

Declare, acknowledge, resolve, and list incidents from your own system, and keep an external IMS in sync with Ionhour.

The incident endpoints let an external system declare and manage Ionhour incidents. They require an ionh_ key scoped to the mcp:incidents resource (or an unrestricted key). All routes are under https://api.ionhour.com/api/v1.

MethodPathMin rolePurpose
POST/v1/incidentsmemberDeclare a manual incident.
POST/v1/incidents/:id/acknowledgememberAcknowledge an incident.
POST/v1/incidents/:id/resolvememberResolve an incident.
GET/v1/incidentsviewerList incidents (paginated, filterable).
GET/v1/incidents/:idviewerFetch one incident.

State machine

An incident's state is one of ACTIVE, MONITORING, or RESOLVED.

   ACTIVE ───────────────► RESOLVED
     │                        ▲
     └──► MONITORING ─────────┘

What the Integration API can do:

  • Declare creates an incident in ACTIVE.
  • Acknowledge records who acknowledged it and when. It does not change state — the incident stays ACTIVE, now with acknowledgedAt and acknowledgedBy set.
  • Resolve moves the incident to RESOLVED.

MONITORING is a valid state you may observe on incidents (and filter by), but the Integration API has no endpoint to move an incident into it. That transition is driven by Ionhour's own lifecycle and the dashboard.

Acknowledge and resolve are idempotent. Acknowledging an already-acknowledged (or resolved) incident, or resolving an already-resolved one, returns 200 with the incident's current state and does not create a duplicate action.

Declare an incident

POST /v1/incidents

FieldTypeRequiredNotes
titlestringYesMax 255 chars.
descriptionstringNoMax 2000 chars. Rendered as rich HTML on the incident, so it is sanitized on the server.
severitystringNoOne of P1, P2, P3, P4. Defaults to P1.
checkIdnumberNoLink the incident to a check.
jobIdnumberNoLink the incident to a job.
dependencyIdnumberNoLink the incident to a dependency.

Provide at most one of checkId, jobId, or dependencyId — supplying more than one returns 400 VALIDATION_FAILED. The linked monitor must belong to the key's workspace, or you get 404 NOT_FOUND.

You cannot declare an incident against an Ionhour-managed dependency (one sourced from the provider catalog). Those return 403 DEPENDENCY_PROVIDER_MANAGED.

curl -X POST https://api.ionhour.com/api/v1/incidents \
  -H "Authorization: Bearer ionh_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Checkout latency spike",
    "description": "p99 above 3s in eu-west",
    "severity": "P2",
    "checkId": 1234
  }'
const res = await fetch('https://api.ionhour.com/api/v1/incidents', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.IONHOUR_API_KEY}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    title: 'Checkout latency spike',
    description: 'p99 above 3s in eu-west',
    severity: 'P2',
    checkId: 1234,
  }),
});
if (!res.ok) throw new Error(`Ionhour ${res.status}: ${await res.text()}`);
const incident = await res.json();
console.log(incident.id, incident.state);
import os, requests

res = requests.post(
    "https://api.ionhour.com/api/v1/incidents",
    headers={"Authorization": f"Bearer {os.environ['IONHOUR_API_KEY']}"},
    json={
        "title": "Checkout latency spike",
        "description": "p99 above 3s in eu-west",
        "severity": "P2",
        "checkId": 1234,
    },
    timeout=10,
)
res.raise_for_status()
incident = res.json()
print(incident["id"], incident["state"])

A successful call returns the incident:

{
  "id": 5567,
  "publicId": "INC-5567",
  "title": "Checkout latency spike",
  "state": "ACTIVE",
  "reason": "MANUAL",
  "severity": "P2",
  "checkId": 1234,
  "monitorType": null,
  "monitorId": null,
  "dependencyId": null,
  "dependencyName": null,
  "startedAt": "2026-07-10T14:03:11.000Z",
  "acknowledgedAt": null,
  "acknowledgedBy": null,
  "resolvedAt": null
}

Acknowledge

POST /v1/incidents/:id/acknowledge — takes no body.

curl -X POST https://api.ionhour.com/api/v1/incidents/5567/acknowledge \
  -H "Authorization: Bearer ionh_your_api_key"

The response is the incident with acknowledgedAt and acknowledgedBy populated; state remains ACTIVE.

Resolve

POST /v1/incidents/:id/resolve

FieldTypeRequiredNotes
resolutionNotestringNoMax 2000 chars. Added to the incident timeline.
curl -X POST https://api.ionhour.com/api/v1/incidents/5567/resolve \
  -H "Authorization: Bearer ionh_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{ "resolutionNote": "Rolled back deploy #4821" }'

List and fetch

GET /v1/incidents supports these query parameters:

ParamTypeNotes
statestringACTIVE, MONITORING, or RESOLVED.
checkIdnumberOnly incidents linked to this check.
fromISO-8601Incidents started on or after this time.
toISO-8601Incidents started on or before this time.
pagenumberPage number (default 1).
limitnumberPage size (default 25, max 100).
curl -H "Authorization: Bearer ionh_your_api_key" \
  "https://api.ionhour.com/api/v1/incidents?state=ACTIVE&limit=50"

The response is the standard paginated envelope ({ items, total, page, itemCount, pageCount, limit }), newest first.

GET /v1/incidents/:id returns a single incident with a few extra fields — summary (the rich-HTML description), recoveredAt, acknowledgedByUser, and a nested check ({ id, name }) when one is linked.

IMS sync patterns

A typical incident-management integration keeps its own records in step with Ionhour:

  • Your system is the source of truth. When your platform opens an incident, POST /v1/incidents to mirror it into Ionhour; store the returned id. On acknowledge/resolve in your tool, call the matching /acknowledge and /resolve routes. Because those routes are idempotent, retries and duplicate webhooks from your side are safe.
  • Ionhour is the source of truth. Receive Ionhour's own incidents through a Webhook alert channel (incident.created / incident.resolved), open the corresponding record in your IMS, and reconcile periodically with GET /v1/incidents?state=ACTIVE.
  • Reconciliation. Poll GET /v1/incidents with a from window to catch anything a missed webhook left behind; match on id to stay convergent.