Skip to main content

Check out Port for yourself ➜ 

Incident.io

Custom Ocean integration

This integration was created using the custom Ocean integration builder.
Please note that:

  1. This integration will not be listed in the Data sources page of your Port application, and must be installed manually using the instructions on this page.
  2. 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:

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:

  1. Log in to your Incident.io dashboard.
  2. Navigate to Settings and select API keys.
  3. Click Create API key and give it a descriptive name (e.g., "Port Integration").
  4. Select Read-only access for all required resources.
  5. Copy and store the generated API key securely - it will only be shown once.
Keep your API key secure

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:

Prerequisites

  • A Kubernetes cluster - the integration's container chart will be deployed to this cluster.

  • kubectl and helm must be installed on your machine. Your kubectl CLI must be connected to the Kubernetes cluster where you plan to install the integration.

Installation

  1. Add Port's Helm repo and install the Ocean Custom Integration:
Replace placeholders

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"
Selecting a Port API URL by account region

The port_region, port.baseUrl, portBaseUrl, port_base_url and OCEAN__PORT__BASE_URL parameters select which Port API instance to use:

Configuration parameters

This table summarizes the available parameters for the installation.

ParameterDescriptionExampleRequired
port.clientIdYour Port client ID
port.clientSecretYour Port client secret
port.baseUrlYour Port API URL - https://api.port.io for EU, https://api.us.port.io for US
integration.config.baseUrlThe base URL of the Incident.io APIhttps://api.incident.io
integration.config.authTypeThe authentication type (use bearer_token for Incident.io)bearer_token
integration.secrets.tokenYour Incident.io API key
integration.config.paginationTypePagination method used by the Incident.io APIcursor
integration.config.paginationParamThe query parameter name for the cursorafter
integration.config.cursorPathDot-notation path to the cursor value in the responsepagination_meta.after
integration.config.hasMorePathDot-notation path to check if more pages existpagination_meta.after
integration.config.pageSizeNumber of items to fetch per page100
integration.config.sizeParamThe query parameter name for the page sizepage_size
integration.eventListener.typeThe event listener type. Read more about event listenersPOLLING
integration.typeThe integration type (must be custom for Ocean Custom Integration)custom
integration.identifierUnique identifier for the integration instancemy-ocean-incidentio-integration
scheduledResyncIntervalThe number of minutes between each resync. Read more about scheduledResyncInterval60
initializePortResourcesWhen set to true, the integration will create default blueprints and the Port app config mappingtrue
sendRawDataExamplesEnable sending raw data examples from the Incident.io API to Port for testing and managing the integration mapping. Default is truetrue

Advanced integration configuration

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:

  1. Go to your Builder page.

  2. Click + Blueprint.

  3. Click the {...} Edit JSON button in the top right corner of the form.

  4. Copy and paste each blueprint JSON from the section below.

    If you plan to sync catalog_types, catalog_entries, severities, teams, or follow_ups, create their matching blueprints and relations before adding the corresponding mappings in the Configuration section.

    Create blueprints in order

    We 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
    }
    }
    }
  5. 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.

Incident.io API reference

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.

Sync order matters

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:

  1. Go to your data sources page.

  2. Find your Incident.io integration in the list.

  3. Click on the integration to open the mapping editor.

  4. 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/users
    selector:
    query: "true"
    data_path: ".users"
    port:
    entity:
    mappings:
    identifier: .id
    title: .name
    blueprint: '"incidentioUser"'
    properties:
    email: .email
    role: .role
    slackUserId: .slack_user_id
    createdAt: .created_at
    Alert sources mapping (click to expand)

    API reference: GET /v2/alert_sources

    resources:
    - kind: /v2/alert_sources
    selector:
    query: "true"
    data_path: ".alert_sources"
    port:
    entity:
    mappings:
    identifier: .id
    title: .name
    blueprint: '"incidentioAlertSource"'
    properties:
    sourceType: .source_type
    createdAt: .created_at
    updatedAt: .updated_at
    Schedules mapping (click to expand)

    API reference: GET /v2/schedules

    resources:
    - kind: /v2/schedules
    selector:
    query: "true"
    data_path: ".schedules"
    port:
    entity:
    mappings:
    identifier: .id
    title: .name
    blueprint: '"incidentioSchedule"'
    properties:
    timezone: .timezone
    createdAt: .created_at
    updatedAt: .updated_at
    relations:
    currentOnCall: >-
    .current_shifts // [] | map(.user.id)
    Alerts mapping (click to expand)

    API reference: GET /v2/alerts

    resources:
    - kind: /v2/alerts
    selector:
    query: "true"
    data_path: ".alerts"
    port:
    entity:
    mappings:
    identifier: .id
    title: .title
    blueprint: '"incidentioAlert"'
    properties:
    description: .description
    status: .status
    priority: >-
    (.attributes // [] | map(select(.attribute.name == "Priority")) | first | .value.label) // null
    sourceUrl: .source_url
    deduplicationKey: .deduplication_key
    createdAt: .created_at
    updatedAt: .updated_at
    relations:
    alertSource: .alert_source_id
    Incidents mapping (click to expand)

    API reference: GET /v2/incidents

    resources:
    - kind: /v2/incidents
    selector:
    query: "true"
    data_path: ".incidents"
    port:
    entity:
    mappings:
    identifier: .id
    title: .name
    blueprint: '"incidentioIncident"'
    properties:
    status: .status
    severity: .severity.name
    summary: .summary
    permalink: .permalink
    resolvedAt: .resolved_at
    createdAt: .created_at
    updatedAt: .updated_at
    relations:
    commander: >-
    .incident_role_assignments // [] |
    map(select(.role.role_type == "commander")) |
    first | .assignee.id // null
    Catalog types mapping (click to expand)

    API reference: GET /v3/catalog_types

    resources:
    - kind: /v3/catalog_types
    selector:
    query: "true"
    data_path: ".catalog_types"
    port:
    entity:
    mappings:
    identifier: .id
    title: .name
    blueprint: '"incidentioCatalogType"'
    properties:
    description: .description
    typeName: .type_name
    categories: .categories
    sourceRepoUrl: .source_repo_url
    createdAt: .created_at
    Catalog entries mapping (click to expand)

    API reference: GET /v3/catalog_types/{catalog_type_id}/entries

    resources:
    - kind: /v3/catalog_types/{catalog_type_id}/entries
    selector:
    query: "true"
    data_path: ".catalog_entries"
    path_parameters:
    catalog_type_id:
    endpoint: /v3/catalog_types
    field: .id
    filter: "true"
    port:
    entity:
    mappings:
    identifier: .id
    title: .name
    blueprint: '"incidentioCatalogEntry"'
    properties:
    externalId: .external_id
    attributeValues: .attribute_values
    createdAt: .created_at
    relations:
    catalogType: .__catalog_type_id
    Severities mapping (click to expand)

    API reference: GET /v1/severities

    resources:
    - kind: /v1/severities
    selector:
    query: "true"
    data_path: ".severities"
    port:
    entity:
    mappings:
    identifier: .id
    title: .name
    blueprint: '"incidentioSeverity"'
    properties:
    description: .description
    rank: .rank
    createdAt: .created_at
    Teams mapping (click to expand)

    API reference: GET /v3/teams

    resources:
    - kind: /v3/teams
    selector:
    query: "true"
    data_path: ".teams"
    port:
    entity:
    mappings:
    identifier: .id
    title: .name
    blueprint: '"incidentioTeam"'
    properties:
    slackChannelId: .slack_channel_id
    memberCount: "(.members // [] | length)"
    createdAt: .created_at
    Follow-ups mapping (click to expand)

    API reference: GET /v2/follow_ups

    resources:
    - kind: /v2/follow_ups
    selector:
    query: "true"
    data_path: ".follow_ups"
    port:
    entity:
    mappings:
    identifier: .id
    title: .title
    blueprint: '"incidentioFollowUp"'
    properties:
    description: .description
    status: .status
    priority: .priority.name
    createdAt: .created_at
    relations:
    incident: .incident_id
  5. 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:

  1. Test your Incident.io API endpoints with live data.
  2. Automatically detect the data structure and field types.
  3. Generate blueprints and resource mappings tailored to your preferences.
  4. 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