Incident.io
This integration was created using the custom Ocean integration builder.
Please note that:
- This integration will not be listed in the
Data sourcespage of your Port application, and must be installed manually using the instructions on this page. - This integration will not create components (e.g.
blueprints,mapping, etc.) in your portal automatically, you will need to create them manually using the instructions on this page.
Port's Incident.io integration allows you to model Incident.io resources in your software catalog and ingest data into them using the Ocean Custom Integration framework.
Supported resources
The Incident.io integration can ingest the following resources into Port:
user- Members of your Incident.io organization from/v2/users.alert-source- Configured alert sources from/v2/alert_sources.schedule- On-call schedules and current shifts from/v2/schedules.alert- Fired and resolved alerts from/v2/alerts.incident- Active and historical incidents from/v2/incidents.catalog-type- Catalog type definitions from/v3/catalog_types.catalog-entry- Entries under each catalog type from/v3/catalog_types/{catalog_type_id}/entries.severity- Incident severities from/v1/severities.team- Response and ownership teams from/v3/teams.follow-up- Follow-up actions linked to incidents from/v2/follow_ups.
It is possible to reference any field that appears in the API responses linked above in the mapping configuration.
Prerequisites
To use this integration, you need:
- An Incident.io API key with read access to your organization.
To generate an Incident.io API key:
- Log in to your Incident.io dashboard.
- Navigate to Settings and select API keys.
- Click Create API key and give it a descriptive name (e.g., "Port Integration").
- Select Read-only access for all required resources.
- Copy and store the generated API key securely - it will only be shown once.
Never commit your API key to source control or share it publicly. Store it as a secret in your deployment environment.
Installation
Choose one of the following installation methods to deploy the Ocean Custom Integration:
- Hosted by Port
- Helm
- Docker
Set up in Port
- Go to the custom data source page and open the Ocean custom integration form.
- In the configuration form, enter the following values:
- Identifier:
my-ocean-incidentio-integration. - Base URL:
https://api.incident.io. - Authentication type:
bearer_token. - Token: your Incident.io API key.
- Identifier:
- Expand Advanced configuration and set:
- Pagination type:
cursor. - Pagination parameter:
after. - Cursor path:
pagination_meta.after. - Has more path:
pagination_meta.after. - Page size:
100. - Page size parameter:
page_size.
- Pagination type:
- Click Save & install.
After the integration is installed, continue to the Configuration section on this page and add the resource mappings.
Prerequisites
-
A Kubernetes cluster - the integration's container chart will be deployed to this cluster.
-
kubectlandhelmmust be installed on your machine. YourkubectlCLI must be connected to the Kubernetes cluster where you plan to install the integration.
Installation
- Add Port's Helm repo and install the Ocean Custom Integration:
Remember to replace the placeholders for YOUR_PORT_CLIENT_ID, YOUR_PORT_CLIENT_SECRET, and YOUR_INCIDENT_IO_API_KEY.
helm repo add --force-update port-labs https://port-labs.github.io/helm-charts
helm upgrade --install my-ocean-incidentio-integration port-labs/port-ocean \
--set port.clientId="YOUR_PORT_CLIENT_ID" \
--set port.clientSecret="YOUR_PORT_CLIENT_SECRET" \
--set port.baseUrl="https://api.port.io" \
--set initializePortResources=true \
--set scheduledResyncInterval=60 \
--set integration.identifier="my-ocean-incidentio-integration" \
--set integration.type="custom" \
--set integration.eventListener.type="POLLING" \
--set integration.config.baseUrl="https://api.incident.io" \
--set integration.config.authType="bearer_token" \
--set integration.secrets.token="YOUR_INCIDENT_IO_API_KEY" \
--set integration.config.paginationType="cursor" \
--set integration.config.paginationParam="after" \
--set integration.config.cursorPath="pagination_meta.after" \
--set integration.config.hasMorePath="pagination_meta.after" \
--set integration.config.pageSize=100 \
--set integration.config.sizeParam="page_size"
The port_region, port.baseUrl, portBaseUrl, port_base_url and OCEAN__PORT__BASE_URL parameters select which Port API instance to use:
- EU (app.port.io) →
https://api.port.io - US (app.us.port.io) →
https://api.us.port.io
Configuration parameters
This table summarizes the available parameters for the installation.
| Parameter | Description | Example | Required |
|---|---|---|---|
port.clientId | Your Port client ID | ✅ | |
port.clientSecret | Your Port client secret | ✅ | |
port.baseUrl | Your Port API URL - https://api.port.io for EU, https://api.us.port.io for US | ✅ | |
integration.config.baseUrl | The base URL of the Incident.io API | https://api.incident.io | ✅ |
integration.config.authType | The authentication type (use bearer_token for Incident.io) | bearer_token | ✅ |
integration.secrets.token | Your Incident.io API key | ✅ | |
integration.config.paginationType | Pagination method used by the Incident.io API | cursor | ✅ |
integration.config.paginationParam | The query parameter name for the cursor | after | ✅ |
integration.config.cursorPath | Dot-notation path to the cursor value in the response | pagination_meta.after | ✅ |
integration.config.hasMorePath | Dot-notation path to check if more pages exist | pagination_meta.after | ✅ |
integration.config.pageSize | Number of items to fetch per page | 100 | ✅ |
integration.config.sizeParam | The query parameter name for the page size | page_size | ✅ |
integration.eventListener.type | The event listener type. Read more about event listeners | POLLING | ✅ |
integration.type | The integration type (must be custom for Ocean Custom Integration) | custom | ✅ |
integration.identifier | Unique identifier for the integration instance | my-ocean-incidentio-integration | ✅ |
scheduledResyncInterval | The number of minutes between each resync. Read more about scheduledResyncInterval | 60 | ❌ |
initializePortResources | When set to true, the integration will create default blueprints and the Port app config mapping | true | ❌ |
sendRawDataExamples | Enable sending raw data examples from the Incident.io API to Port for testing and managing the integration mapping. Default is true | true | ❌ |
For advanced configuration such as proxies or self-signed certificates, click here.
To run the integration using Docker for a one-time sync:
Remember to replace the placeholders for YOUR_PORT_CLIENT_ID, YOUR_PORT_CLIENT_SECRET, and YOUR_INCIDENT_IO_API_KEY.
docker run -i --rm --platform=linux/amd64 \
-e OCEAN__EVENT_LISTENER='{"type":"ONCE"}' \
-e OCEAN__INITIALIZE_PORT_RESOURCES=true \
-e OCEAN__SEND_RAW_DATA_EXAMPLES=true \
-e OCEAN__INTEGRATION__CONFIG__BASE_URL="https://api.incident.io" \
-e OCEAN__INTEGRATION__CONFIG__AUTH_TYPE="bearer_token" \
-e OCEAN__INTEGRATION__SECRETS__TOKEN="YOUR_INCIDENT_IO_API_KEY" \
-e OCEAN__INTEGRATION__CONFIG__PAGINATION_TYPE="cursor" \
-e OCEAN__INTEGRATION__CONFIG__PAGINATION_PARAM="after" \
-e OCEAN__INTEGRATION__CONFIG__CURSOR_PATH="pagination_meta.after" \
-e OCEAN__INTEGRATION__CONFIG__HAS_MORE_PATH="pagination_meta.after" \
-e OCEAN__INTEGRATION__CONFIG__PAGE_SIZE="100" \
-e OCEAN__INTEGRATION__CONFIG__SIZE_PARAM="page_size" \
-e OCEAN__PORT__CLIENT_ID="YOUR_PORT_CLIENT_ID" \
-e OCEAN__PORT__CLIENT_SECRET="YOUR_PORT_CLIENT_SECRET" \
-e OCEAN__PORT__BASE_URL="https://api.port.io" \
ghcr.io/port-labs/port-ocean-custom:latest
The port_region, port.baseUrl, portBaseUrl, port_base_url and OCEAN__PORT__BASE_URL parameters select which Port API instance to use:
- EU (app.port.io) →
https://api.port.io - US (app.us.port.io) →
https://api.us.port.io
For advanced configuration such as proxies or self-signed certificates, click here.
Set up data model
Before the integration can sync data, you need to create the required blueprints in Port. These blueprints define the data model for your Incident.io resources.
To create the blueprints:
-
Go to your Builder page.
-
Click + Blueprint.
-
Click the
{...} Edit JSONbutton in the top right corner of the form. -
Copy and paste each blueprint JSON from the section below.
If you plan to sync
catalog_types,catalog_entries,severities,teams, orfollow_ups, create their matching blueprints and relations before adding the corresponding mappings in the Configuration section.Create blueprints in orderWe recommend creating blueprints in the order they appear below. Blueprints with no relations (User and Alert Source) should be created first, since other blueprints reference them.
User blueprint (click to expand)
Members of your Incident.io organization:
{"identifier": "incidentioUser","title": "Incident.io User","icon": "User","description": "A member of your Incident.io organization","schema": {"properties": {"email": {"type": "string","format": "email","title": "Email"},"role": {"type": "string","title": "Role"},"slackUserId": {"type": "string","title": "Slack User ID"},"createdAt": {"type": "string","format": "date-time","title": "Created At"}},"required": []},"mirrorProperties": {},"calculationProperties": {},"aggregationProperties": {},"relations": {}}Alert source blueprint (click to expand)
Configured alert sources in your Incident.io organization:
{"identifier": "incidentioAlertSource","title": "Incident.io Alert Source","icon": "Webhook","description": "A configured alert source in Incident.io","schema": {"properties": {"sourceType": {"type": "string","title": "Source Type"},"createdAt": {"type": "string","format": "date-time","title": "Created At"},"updatedAt": {"type": "string","format": "date-time","title": "Updated At"}},"required": []},"mirrorProperties": {},"calculationProperties": {},"aggregationProperties": {},"relations": {}}Schedule blueprint (click to expand)
On-call schedules with a relation to the users currently on shift:
{"identifier": "incidentioSchedule","title": "Incident.io Schedule","icon": "Calendar","description": "An on-call schedule in Incident.io","schema": {"properties": {"timezone": {"type": "string","title": "Timezone"},"createdAt": {"type": "string","format": "date-time","title": "Created At"},"updatedAt": {"type": "string","format": "date-time","title": "Updated At"}},"required": []},"mirrorProperties": {},"calculationProperties": {},"aggregationProperties": {},"relations": {"currentOnCall": {"title": "Current On-Call","target": "incidentioUser","required": false,"many": true}}}Alert blueprint (click to expand)
Fired and resolved alerts with a relation to their source:
{"identifier": "incidentioAlert","title": "Incident.io Alert","icon": "Alert","description": "A fired or resolved alert in Incident.io","schema": {"properties": {"description": {"type": "string","title": "Description"},"status": {"type": "string","title": "Status","enum": ["firing", "resolved"],"enumColors": {"firing": "red","resolved": "green"}},"priority": {"type": "string","title": "Priority"},"sourceUrl": {"type": "string","format": "url","title": "Source URL"},"deduplicationKey": {"type": "string","title": "Deduplication Key"},"createdAt": {"type": "string","format": "date-time","title": "Created At"},"updatedAt": {"type": "string","format": "date-time","title": "Updated At"}},"required": []},"mirrorProperties": {},"calculationProperties": {},"aggregationProperties": {},"relations": {"alertSource": {"title": "Alert Source","target": "incidentioAlertSource","required": false,"many": false}}}Incident blueprint (click to expand)
Active and historical incidents with relations to the incident commander:
{"identifier": "incidentioIncident","title": "Incident.io Incident","icon": "Incident","description": "An active or historical incident in Incident.io","schema": {"properties": {"status": {"type": "string","title": "Status","enum": ["triage","investigating","fixing","monitoring","resolved","declined"],"enumColors": {"triage": "orange","investigating": "yellow","fixing": "blue","monitoring": "purple","resolved": "green","declined": "lightGray"}},"severity": {"type": "string","title": "Severity"},"summary": {"type": "string","title": "Summary"},"permalink": {"type": "string","format": "url","title": "Permalink"},"resolvedAt": {"type": "string","format": "date-time","title": "Resolved At"},"createdAt": {"type": "string","format": "date-time","title": "Created At"},"updatedAt": {"type": "string","format": "date-time","title": "Updated At"}},"required": []},"mirrorProperties": {},"calculationProperties": {},"aggregationProperties": {},"relations": {"commander": {"title": "Commander","target": "incidentioUser","required": false,"many": false}}}Catalog type blueprint (click to expand)
Catalog type definitions used to classify entities in Incident.io:
{"identifier": "incidentioCatalogType","title": "Incident.io Catalog Type","icon": "Catalog","description": "A catalog type definition in Incident.io","schema": {"properties": {"description": {"type": "string","title": "Description"},"typeName": {"type": "string","title": "Type Name"},"categories": {"type": "array","title": "Categories","items": {"type": "string"}},"sourceRepoUrl": {"type": "string","format": "url","title": "Source Repo URL"},"createdAt": {"type": "string","format": "date-time","title": "Created At"}},"required": []},"mirrorProperties": {},"calculationProperties": {},"aggregationProperties": {},"relations": {}}Catalog entry blueprint (click to expand)
Catalog entries with a relation to their parent catalog type:
{"identifier": "incidentioCatalogEntry","title": "Incident.io Catalog Entry","icon": "DefaultProperty","description": "A catalog entry in Incident.io","schema": {"properties": {"externalId": {"type": "string","title": "External ID"},"attributeValues": {"type": "object","title": "Attribute Values"},"createdAt": {"type": "string","format": "date-time","title": "Created At"}},"required": []},"mirrorProperties": {},"calculationProperties": {},"aggregationProperties": {},"relations": {"catalogType": {"title": "Catalog Type","target": "incidentioCatalogType","required": false,"many": false}}}Severity blueprint (click to expand)
Severity levels used by incidents:
{"identifier": "incidentioSeverity","title": "Incident.io Severity","icon": "Alert","description": "A severity level in Incident.io","schema": {"properties": {"description": {"type": "string","title": "Description"},"rank": {"type": "number","title": "Rank"},"createdAt": {"type": "string","format": "date-time","title": "Created At"}},"required": []},"mirrorProperties": {},"calculationProperties": {},"aggregationProperties": {},"relations": {}}Team blueprint (click to expand)
Teams in your Incident.io workspace:
{"identifier": "incidentioTeam","title": "Incident.io Team","icon": "Team","description": "A team in Incident.io","schema": {"properties": {"slackChannelId": {"type": "string","title": "Slack Channel ID"},"memberCount": {"type": "number","title": "Member Count"},"createdAt": {"type": "string","format": "date-time","title": "Created At"}},"required": []},"mirrorProperties": {},"calculationProperties": {},"aggregationProperties": {},"relations": {}}Follow-up blueprint (click to expand)
Follow-up actions with a relation to the linked incident:
{"identifier": "incidentioFollowUp","title": "Incident.io Follow-up","icon": "Checklist","description": "A follow-up action in Incident.io","schema": {"properties": {"description": {"type": "string","title": "Description"},"status": {"type": "string","title": "Status"},"priority": {"type": "string","title": "Priority"},"createdAt": {"type": "string","format": "date-time","title": "Created At"}},"required": []},"mirrorProperties": {},"calculationProperties": {},"aggregationProperties": {},"relations": {"incident": {"title": "Incident","target": "incidentioIncident","required": false,"many": false}}} -
Click Save after creating each blueprint.
Configuration
After installation, define which endpoints to sync in your integration configuration. Each resource maps an API endpoint to Port entities using JQ expressions to transform the data.
Key mapping components:
kind: The API endpoint path, combined with your base URL to form the full request URL.selector.query: JQ filter to include or exclude entities. Use'true'to sync all.selector.data_path: JQ expression pointing to the array of items in the response.port.entity.mappings: How to map API fields to Port entity properties and relations.
For more details on how the Ocean Custom Integration works, see the How it works section.
The full Incident.io API reference is available at api-docs.incident.io. Each mapping section below links directly to the relevant endpoint documentation.
Incident.io API response format:
All Incident.io API responses follow this structure:
{
"resource_name": [...],
"pagination_meta": {
"page_size": 100,
"after": "CURSOR_VALUE"
}
}
The data array is always nested under a resource-specific key (e.g., alerts, incidents, users). The pagination_meta.after field contains the cursor for the next page and is absent when there are no more pages.
We recommend adding mappings in the order shown below. Sync catalog_types, severities, users, and alert_sources first, then sync dependent resources such as catalog_entries, schedules, teams, alerts, incidents, and follow_ups.
To configure the mappings:
-
Go to your data sources page.
-
Find your Incident.io integration in the list.
-
Click on the integration to open the mapping editor.
-
Add the resource mapping configurations below.
Users mapping (click to expand)
API reference: [
GET /v2/users](https://api-docs.incident.io/#tag/Users-V2/operation/Users V2_List)resources:- kind: /v2/usersselector:query: "true"data_path: ".users"port:entity:mappings:identifier: .idtitle: .nameblueprint: '"incidentioUser"'properties:email: .emailrole: .roleslackUserId: .slack_user_idcreatedAt: .created_atAlert sources mapping (click to expand)
API reference:
GET /v2/alert_sourcesresources:- kind: /v2/alert_sourcesselector:query: "true"data_path: ".alert_sources"port:entity:mappings:identifier: .idtitle: .nameblueprint: '"incidentioAlertSource"'properties:sourceType: .source_typecreatedAt: .created_atupdatedAt: .updated_atSchedules mapping (click to expand)
API reference:
GET /v2/schedulesresources:- kind: /v2/schedulesselector:query: "true"data_path: ".schedules"port:entity:mappings:identifier: .idtitle: .nameblueprint: '"incidentioSchedule"'properties:timezone: .timezonecreatedAt: .created_atupdatedAt: .updated_atrelations:currentOnCall: >-.current_shifts // [] | map(.user.id)Alerts mapping (click to expand)
API reference:
GET /v2/alertsresources:- kind: /v2/alertsselector:query: "true"data_path: ".alerts"port:entity:mappings:identifier: .idtitle: .titleblueprint: '"incidentioAlert"'properties:description: .descriptionstatus: .statuspriority: >-(.attributes // [] | map(select(.attribute.name == "Priority")) | first | .value.label) // nullsourceUrl: .source_urldeduplicationKey: .deduplication_keycreatedAt: .created_atupdatedAt: .updated_atrelations:alertSource: .alert_source_idIncidents mapping (click to expand)
API reference:
GET /v2/incidentsresources:- kind: /v2/incidentsselector:query: "true"data_path: ".incidents"port:entity:mappings:identifier: .idtitle: .nameblueprint: '"incidentioIncident"'properties:status: .statusseverity: .severity.namesummary: .summarypermalink: .permalinkresolvedAt: .resolved_atcreatedAt: .created_atupdatedAt: .updated_atrelations:commander: >-.incident_role_assignments // [] |map(select(.role.role_type == "commander")) |first | .assignee.id // nullCatalog types mapping (click to expand)
API reference:
GET /v3/catalog_typesresources:- kind: /v3/catalog_typesselector:query: "true"data_path: ".catalog_types"port:entity:mappings:identifier: .idtitle: .nameblueprint: '"incidentioCatalogType"'properties:description: .descriptiontypeName: .type_namecategories: .categoriessourceRepoUrl: .source_repo_urlcreatedAt: .created_atCatalog entries mapping (click to expand)
API reference:
GET /v3/catalog_types/{catalog_type_id}/entriesresources:- kind: /v3/catalog_types/{catalog_type_id}/entriesselector:query: "true"data_path: ".catalog_entries"path_parameters:catalog_type_id:endpoint: /v3/catalog_typesfield: .idfilter: "true"port:entity:mappings:identifier: .idtitle: .nameblueprint: '"incidentioCatalogEntry"'properties:externalId: .external_idattributeValues: .attribute_valuescreatedAt: .created_atrelations:catalogType: .__catalog_type_idSeverities mapping (click to expand)
API reference:
GET /v1/severitiesresources:- kind: /v1/severitiesselector:query: "true"data_path: ".severities"port:entity:mappings:identifier: .idtitle: .nameblueprint: '"incidentioSeverity"'properties:description: .descriptionrank: .rankcreatedAt: .created_atTeams mapping (click to expand)
API reference:
GET /v3/teamsresources:- kind: /v3/teamsselector:query: "true"data_path: ".teams"port:entity:mappings:identifier: .idtitle: .nameblueprint: '"incidentioTeam"'properties:slackChannelId: .slack_channel_idmemberCount: "(.members // [] | length)"createdAt: .created_atFollow-ups mapping (click to expand)
API reference:
GET /v2/follow_upsresources:- kind: /v2/follow_upsselector:query: "true"data_path: ".follow_ups"port:entity:mappings:identifier: .idtitle: .titleblueprint: '"incidentioFollowUp"'properties:description: .descriptionstatus: .statuspriority: .priority.namecreatedAt: .created_atrelations:incident: .incident_id -
Click Save to apply the mapping.
Customization
If you want to test different API endpoints or explore the Incident.io API before committing to a configuration, use the interactive builder.
The interactive builder helps you:
- Test your Incident.io API endpoints with live data.
- Automatically detect the data structure and field types.
- Generate blueprints and resource mappings tailored to your preferences.
- Get installation commands with your configuration pre-filled.
Simply provide your Incident.io API details, and the builder will generate everything you need.
Additional resources
- Incident.io API reference - full reference for all available endpoints and response schemas.
- Incident.io API authentication - details on how to authenticate requests to the Incident.io API.
- Ocean Custom Integration overview - learn how the Ocean Custom Integration framework works.
- Ocean Custom Integration configuration - advanced mapping options, nested endpoints, and pagination configuration.