Incident.io
Setup Instructions
1. Create API Key
Go to https://app.incident.io/settings/api-keys and create an API key with the following permissions:
- “View data, like public incidents and organisation settings”
- “Create incidents”
- “Edit incidents”
- “View all incident data, including private incidents”
Copy the generated API key.
2. Configure Connection
Go to https://ui.cloud.firetiger.com/settings/connections and create a new HTTP connection with:
Base URL:
https://api.incident.io
Allowed Routes:
GET /v2/incidents
POST /v2/incidents
GET /v2/incidents/{id}
POST /v2/incidents/{id}/actions/edit
GET /v1/severities
GET /v1/severities/{id}
GET /v1/incident_statuses
GET /v1/incident_statuses/{id}
Headers:
Authorization: Bearer <your-api-key>
Content-Type: application/json
Replace <your-api-key> with the API key you copied from step 1.
3. Add Description
In the Description field, paste the content from the markdown block below:
The incident.io Incidents API v2 provides endpoints to create, read, list, and edit incidents. Incidents are a core resource in incident.io, on which many other resources (actions, etc.) are created.
## Available Operations
### 1. List Incidents
**Purpose:** Retrieve a paginated list of all incidents for an organization with advanced filtering capabilities.
**Query Parameters:**
- `page_size` (integer, optional): Number of records to return (default: 25, max: 500)
- `after` (string, optional): Incident ID for pagination - returns incidents after this ID
- `status` (object, optional): Filter by incident status ID
- Operators: `one_of`, `not_in`
- Example: `status[one_of]=01GBSQF3FHF7FWZQNWGHAVQ804`
- `status_category` (object, optional): Filter by status category
- Operators: `one_of`, `not_in`
- Values: `triage`, `declined`, `merged`, `canceled`, `live`, `learning`, `closed`
- Example: `status_category[one_of]=live`
- `created_at` (object, optional): Filter by creation timestamp
- Operators: `gte` (greater than or equal), `lte` (less than or equal), `date_range`
- Format: ISO date (YYYY-MM-DD)
- Example: `created_at[gte]=2024-05-01`
- Date range example: `created_at[date_range]=2024-12-02~2024-12-08`
- `updated_at` (object, optional): Filter by last update timestamp
- Operators: `gte`, `lte`, `date_range`
- Format: ISO date (YYYY-MM-DD)
- Example: `updated_at[lte]=2024-12-31`
- `severity` (object, optional): Filter by severity ID or rank
- Operators: `one_of`, `not_in`, `gte`, `lte`
- Example: `severity[gte]=01GBSQF3FHF7FWZQNWGHAVQ804`
- `incident_type` (object, optional): Filter by incident type ID
- Operators: `one_of`, `not_in`
- Example: `incident_type[one_of]=01GBSQF3FHF7FWZQNWGHAVQ804`
- `incident_role` (object, optional): Filter by incident role assignment status
- Operators: `one_of`, `is_blank`
- Format: `incident_role[ROLE_ID][operator]=value`
- Example: `incident_role[01GBSQF3FHF7FWZQNWGHAVQ804][is_set]=true`
- `custom_field` (object, optional): Filter by custom field values
- Operators vary by field type
- Format: `custom_field[FIELD_ID][operator]=value`
- Example: `custom_field[01GBSQF3FHF7FWZQNWGHAVQ804][one_of]=XYZ`
- `mode` (object, optional): Filter by incident mode
- Operator: `one_of`
- Values: `standard`, `retrospective`, `test`, `tutorial`
- Default: `{"one_of": ["standard", "retrospective"]}` (excludes test and tutorial)
- Example: `mode[one_of]=retrospective`
**Important Notes:**
- All query parameters must be URI encoded
- Multiple filters can be combined (incidents must match ALL filters)
- Maximum page size is 250
- By default, test and tutorial incidents are excluded unless explicitly requested via `mode` filter
**Response:**
```json
{
"incidents": [
{
"id": "01FDAG4SAP5TYPT98WGR2N7W91",
"reference": "INC-123",
"name": "Our database is sad",
"summary": "Our database is really really sad, and we don't know why yet.",
"status": {...},
"severity": {...},
"incident_type": {...},
"mode": "standard",
"visibility": "public",
"created_at": "2021-08-17T13:28:57.801578Z",
"updated_at": "2021-08-17T13:28:57.801578Z",
"slack_channel_id": "C02AW36C1M5",
"slack_channel_name": "inc-165-green-parrot",
"permalink": "https://app.incident.io/incidents/123"
}
],
"pagination_meta": {
"after": "01FCNDV6P870EA6S7TK1DSYDG0",
"page_size": 25,
"total_record_count": 238
}
}
```
**Example Request:**
```json
{
"method": "GET",
"path": "/v2/incidents",
"query_params": {
"status_category[one_of]": "live",
"page_size": "25"
}
}
```
---
### 2. Create Incident
**Purpose:** Create a new incident. When mode is set to "retrospective", the incident will not be announced in Slack.
**Request Body Fields:**
Required fields:
- `idempotency_key` (string, required): Unique string to prevent duplicate incident creation
- `visibility` (string, required): Incident visibility - `public` (open to all in Slack workspace) or `private` (invite-only)
Optional fields:
- `name` (string): Short explanation/title of the incident
- `summary` (string): Detailed description of the incident
- `severity_id` (string): ID of the severity level to assign
- `incident_type_id` (string): ID of the incident type
- `incident_status_id` (string): ID of the status to assign
- `mode` (string): Incident mode - `standard`, `retrospective`, `test`, or `tutorial`
- `slack_team_id` (string): Slack Team ID to create the incident in
- `slack_channel_name_override` (string): Custom name for the Slack channel
- `custom_field_entries` (array): Array of custom field values
- Each entry contains:
- `custom_field_id` (string): ID of the custom field
- `values` (array): Array of value objects with appropriate value type fields
- `incident_role_assignments` (array): Array of role assignments
- Each assignment contains:
- `incident_role_id` (string): ID of the role
- `assignee` (object): Can specify by `id`, `email`, or `slack_user_id`
- `incident_timestamp_values` (array): Array of timestamp values
- Each value contains:
- `incident_timestamp_id` (string): ID of the timestamp field
- `value` (string): ISO 8601 timestamp
- `retrospective_incident_options` (object): Options for retrospective incidents
- `slack_channel_id` (string): Existing Slack channel ID
- `postmortem_document_url` (string): URL to postmortem document
- `external_id` (integer): External reference ID
**Response:**
```json
{
"incident": {
"id": "01FDAG4SAP5TYPT98WGR2N7W91",
"reference": "INC-123",
"name": "Our database is sad",
"summary": "Our database is really really sad, and we don't know why yet.",
"mode": "standard",
"visibility": "public",
"created_at": "2021-08-17T13:28:57.801578Z",
"updated_at": "2021-08-17T13:28:57.801578Z",
"permalink": "https://app.incident.io/incidents/123",
...
}
}
```
**Example Request:**
```json
{
"method": "POST",
"path": "/v2/incidents",
"body": "{\"idempotency_key\": \"alert-uuid-12345\", \"name\": \"Database connection pool exhausted\", \"summary\": \"Production database connection pool has reached capacity\", \"severity_id\": \"01FH5TZRWMNAFB0DZ23FD1TV96\", \"incident_type_id\": \"01FH5TZRWMNAFB0DZ23FD1TV96\", \"mode\": \"standard\", \"visibility\": \"public\"}"
}
```
---
### 3. Get Incident (Show)
**Purpose:** Retrieve a single incident by its ID or reference number.
**Path Parameters:**
- `id` (string, required): The incident's full ID (e.g., `01FDAG4SAP5TYPT98WGR2N7W91`) OR the numeric part of its reference (e.g., `123` for incident `INC-123`)
**Response:**
```json
{
"incident": {
"id": "01FDAG4SAP5TYPT98WGR2N7W91",
"reference": "INC-123",
"name": "Our database is sad",
"summary": "Our database is really really sad, and we don't know why yet.",
"call_url": "https://zoom.us/foo",
"created_at": "2021-08-17T13:28:57.801578Z",
"updated_at": "2021-08-17T13:28:57.801578Z",
"creator": {...},
"custom_field_entries": [...],
"incident_role_assignments": [...],
"incident_status": {...},
"incident_timestamp_values": [...],
"incident_type": {...},
"severity": {...},
"mode": "standard",
"visibility": "public",
"slack_channel_id": "C02AW36C1M5",
"slack_channel_name": "inc-165-green-parrot",
"slack_team_id": "T02A1FSLE8J",
"permalink": "https://app.incident.io/incidents/123",
"postmortem_document_url": "https://docs.google.com/my_doc_id",
"has_debrief": false,
"workload_minutes_total": 60.7,
"workload_minutes_working": 20,
"workload_minutes_sleeping": 0,
"workload_minutes_late": 40.7
}
}
```
**Example Requests:**
```json
{
"method": "GET",
"path": "/v2/incidents/01FDAG4SAP5TYPT98WGR2N7W91"
}
```
```json
{
"method": "GET",
"path": "/v2/incidents/123"
}
```
---
### 4. Edit Incident
**Purpose:** Edit properties of an existing incident such as severity, status, custom fields, role assignments, etc. Only provided fields will be updated (omitted fields are ignored).
**Path Parameters:**
- `id` (string, required): The unique identifier of the incident to edit
**Request Body Fields:**
Required fields:
- `incident` (object, required): Object containing fields to update
- `notify_incident_channel` (boolean, required): Whether to send Slack notifications about the update (won't work if channel is archived)
The `incident` object can contain any of these optional fields:
- `name` (string): Updated incident name
- `summary` (string): Updated incident summary
- `severity_id` (string): New severity ID
- `incident_status_id` (string): New status ID
- `call_url` (string): Video call URL for the incident
- `slack_channel_name_override` (string): Override Slack channel name
- `custom_field_entries` (array): Update custom field values (same structure as create)
- `incident_role_assignments` (array): Update role assignments (same structure as create)
- `incident_timestamp_values` (array): Update timestamp values (same structure as create)
**Response:**
```json
{
"incident": {
"id": "01FDAG4SAP5TYPT98WGR2N7W91",
"reference": "INC-123",
"name": "Our database is sad",
"summary": "Our database is really really sad, and we don't know why yet.",
...
}
}
```
**Example Request:**
```json
{
"method": "POST",
"path": "/v2/incidents/01FDAG4SAP5TYPT98WGR2N7W91/actions/edit",
"body": "{\"incident\": {\"severity_id\": \"01G0J1EXE7AXZ2C93K61WBPYEH\", \"summary\": \"Database connection pool exhausted - identified root cause in connection timeout config\"}, \"notify_incident_channel\": true}"
}
```
---
### 5. List Severities
**Purpose:** Retrieve all incident severities configured for the organization. Severities are required when creating incidents and help categorize incidents by urgency/impact.
**Response:**
```json
{
"severities": [
{
"id": "01FCNDV6P870EA6S7TK1DSYDG0",
"name": "Minor",
"description": "Issues with **low impact**.",
"rank": 1,
"created_at": "2021-08-17T13:28:57.801578Z",
"updated_at": "2021-08-17T13:28:57.801578Z"
}
]
}
```
**Example Request:**
```json
{
"method": "GET",
"path": "/v1/severities"
}
```
---
### 6. Get Severity
**Purpose:** Retrieve a single severity by its ID.
**Path Parameters:**
- `id` (string, required): Unique identifier of the severity
**Response:**
```json
{
"severity": {
"id": "01FCNDV6P870EA6S7TK1DSYDG0",
"name": "Minor",
"description": "Issues with **low impact**.",
"rank": 1,
"created_at": "2021-08-17T13:28:57.801578Z",
"updated_at": "2021-08-17T13:28:57.801578Z"
}
}
```
**Example Request:**
```json
{
"method": "GET",
"path": "/v1/severities/01FCNDV6P870EA6S7TK1DSYDG0"
}
```
---
### 7. List Incident Statuses
**Purpose:** Retrieve all incident statuses configured for the organization. Statuses are required when creating or editing incidents and help communicate where an incident is in its lifecycle.
**Response:**
```json
{
"incident_statuses": [
{
"id": "01FCNDV6P870EA6S7TK1DSYD5H",
"name": "Closed",
"description": "Impact has been **fully mitigated**, and we're ready to learn from this incident.",
"category": "triage",
"rank": 4,
"created_at": "2021-08-17T13:28:57.801578Z",
"updated_at": "2021-08-17T13:28:57.801578Z"
}
]
}
```
**Important Notes:**
- Status categories include: `triage`, `declined`, `merged`, `canceled`, `live`, `learning`, `closed`
- Lower rank numbers appear first in lists
- The `triage` and `declined` statuses are special and cannot be modified
**Example Request:**
```json
{
"method": "GET",
"path": "/v1/incident_statuses"
}
```
---
### 8. Get Incident Status
**Purpose:** Retrieve a single incident status by its ID.
**Path Parameters:**
- `id` (string, required): Unique identifier of the incident status
**Response:**
```json
{
"incident_status": {
"id": "01FCNDV6P870EA6S7TK1DSYD5H",
"name": "Closed",
"description": "Impact has been **fully mitigated**, and we're ready to learn from this incident.",
"category": "triage",
"rank": 4,
"created_at": "2021-08-17T13:28:57.801578Z",
"updated_at": "2021-08-17T13:28:57.801578Z"
}
}
```
**Example Request:**
```json
{
"method": "GET",
"path": "/v1/incident_statuses/01FCNDV6P870EA6S7TK1DSYD5H"
}
```
---
## Best Practices
1. **Idempotency:** Always use unique `idempotency_key` values when creating incidents to prevent duplicates
2. **Avoid Automation Spam:** Be careful with automated incident creation - duplicate incidents can be distracting and impact reporting
3. **Pagination:** When listing incidents, use the `after` parameter with the last incident ID from `pagination_meta` to fetch the next page
4. **Filtering:** Combine multiple filters to narrow down incidents efficiently
5. **Partial Updates:** When editing, only include fields you want to change - omitted fields remain unchanged
6. **Reference Shortcuts:** You can use just the numeric part of an incident reference (e.g., `123` instead of full ID) when getting or editing incidents
7. **Retrospective Mode:** Use `mode: "retrospective"` when importing historical incidents to avoid Slack notifications
8. **URI Encoding:** Always URI encode query parameters, especially when using special characters or operators
9. **Severities and Statuses:** Always list available severities and statuses first before creating/editing incidents to ensure you're using valid IDs
Webhook Ingest (optional)
Send incident.io events into Firetiger as they happen. Events land in Iceberg tables under incident-io/events/{event_type} (one table per event type, schema inferred on first event).
This is separate from the API connection above and can be enabled in addition to it. The API connection uses the api_token field; webhook ingest uses signing_secret.
1. Generate the webhook URL
In the connection’s settings, click Generate Webhook URL. Copy the URL that appears in the Webhook URL field.
2. Add the webhook in incident.io
Go to https://app.incident.io/settings/webhooks → Add webhook:
- URL: paste the URL from step 1
- Events: select the event types to forward (e.g.
incident.created,incident.updated,alert.fired)
incident.io shows the signing secret once after saving. Copy it.
3. Save the signing secret
In the connection’s settings, paste the secret into the Signing Secret field and save. Inbound deliveries are verified with HMAC-SHA256 (Svix scheme); deliveries with no/invalid signature are rejected.