> ## Documentation Index
> Fetch the complete documentation index at: https://support.configview.com/llms.txt
> Use this file to discover all available pages before exploring further.

# incident.io setup

## Part 1: incident.io Data Ingestion

Set up an incident.io API key so ConfigView can pull your responders, incidents,
alerts, on-call schedules and escalation paths, service catalog, and the API
keys, secrets and workflows that can act on your account.

incident.io runs three API versions side by side. ConfigView collects each
resource from the newest version that serves it, so some tables come from V1,
some from V2 and some from V3. You do not have to configure anything for this —
one API key covers all three.

***

### Step 1: Create an incident.io API Key

1. Go to: [https://app.incident.io/\~/settings/api-keys](https://app.incident.io/~/settings/api-keys)
2. Click **Add new API key**
3. **Name:** `ConfigView`
4. Grant the key the **view / read** permissions for every area you want
   inventoried — incidents, alerts, on-call schedules, the catalog, and
   organisation settings. ConfigView never writes, so no create, edit or delete
   permission is needed.
5. Leave the key **account-wide** rather than scoping it to a team, unless you
   deliberately want ConfigView to see only that team's data. A team-scoped key
   silently returns a subset, which looks identical to a small tenant.
6. Click **Create** and copy the key — you will only see it once

> **On least privilege.** Listing API keys and reading the IP allowlist need
> organisation-admin-level scope. If you would rather not grant that, everything
> else still works: those two collectors record a skip instead of failing, and
> the health check reports them as gated rather than broken.

***

### Step 2: Add the Key to ConfigView

1. Go to your ConfigView dashboard: `https://{companyname}.configview.com/admin/secret/`
2. Click **Add Secret**
3. **Secret name:** `INCIDENTIO_API_KEY`
4. **Secret value:** Paste the key from Step 1
5. Click **Save**

***

### Step 3: Enable the incident.io App in ConfigView

1. Go to: `https://{companyname}.configview.com/admin/cron/`
2. You should see **incident.io** in the list of available apps
3. Select the scripts you want to run — all 50 are listed below, grouped by area
4. Click **Save**

Enabling the folder creates every table and registers each collector on the
default daily schedule.

> **Dependencies.** Thirteen collectors read a parent table before they can run:
> anything per-incident needs **Incidents** first, per-user needs **Users**,
> catalog entries need **Catalog Types**, and so on. The scheduler enforces the
> order, but if you enable a child without its parent the child records "no rows
> in parent table yet" and does nothing until the parent has run once.

**Identity** — Who exists in the tenant, and which teams they belong to.

* **Users** — Every responder including deactivated ones, with base role, custom roles, and which response and on-call seats they consume.
* **Teams** — Teams and their linked catalog entry — the unit incident.io scopes API keys, alert sources, and escalation paths to.
* **Team Members** — One row per person per team, so team membership is joinable instead of buried in a nested list.

**Incidents** — The incident record and everything hanging off it.

* **Incidents** — The full incident record with severity, status, type, reporter, Slack channel, and the workload minutes each one consumed.
* **Incident Updates** — Every status and severity change on an incident, with who made it and when.
* **Incident Statuses** — The tenant's configured statuses and their categories.
* **Incident Types** — Incident types, their owning teams, and whether they force private incidents.
* **Incident Roles** — Role definitions such as Lead and Communications, with the instructions given to whoever is assigned.
* **Incident Timestamps** — The timestamp definitions the tenant measures incidents against.
* **Severities** — Severity levels and their ranking.
* **Custom Fields** — Custom field definitions, their types, and any catalog type they draw values from.
* **Custom Field Options** — The selectable values behind every option-backed custom field.
* **Actions** — In-incident actions with assignee and completion state.
* **Follow-ups** — Post-incident follow-ups with assignee, owning team, priority, and any linked Jira or GitHub issue.
* **Postmortem Documents** — Postmortem metadata and document links. Document contents are deliberately not collected.
* **Incident Relationships** — Links between related and duplicate incidents.
* **Incident Attachments** — External resources pinned to an incident, such as dashboards, tickets, and pull requests.
* **Incident Participants** — Who took part in each incident, split into active responders and passive observers.
* **Incident Participant Workloads** — Minutes each responder spent per incident, broken out into working, late, and sleeping hours.

**Alerting** — Alerts, where they came from, and how they became incidents.

* **Alerts** — Alerts with source, status, deduplication key, and resolution time.
* **Alert Sources** — Every configured alert source with its type and heartbeat settings. Webhook secret tokens are never stored.
* **Alert Routes** — Alert routes and whether each one is currently enabled.
* **Alert Attributes** — The attribute schema alerts are enriched against.
* **Incident Alerts** — The join between an alert and the incident it was escalated into.
* **Alert Notes** — Notes left on alerts, with their author.

**On-call** — Schedules, escalation paths, and how each responder gets paged.

* **Escalations** — Escalations with status, priority, the path used, and the alerts and incidents they relate to.
* **Escalation Paths** — Escalation path configuration including levels, repeat behaviour, and working hours.
* **Escalation Path Responders** — Who is currently reachable on each escalation path, as a flat table.
* **Schedules** — On-call schedules with timezone, owning teams, rotation count, and holiday configuration.
* **Schedule Rotations** — Rotation configuration per schedule: scheduling mode, handover timing, layers, and the users in the pool.
* **Schedule Current Shifts** — Who is on call right now on every schedule.
* **Schedule Entries** — The resolved rota after overrides are applied — who was actually on call, and when.
* **Schedule Overrides** — Cover and swap overrides against each schedule.
* **Schedule Sync Targets** — Slack user groups kept in sync with an on-call schedule.
* **User Notification Methods** — Each responder's phone, email, and app notification methods, including whether the method is actually usable.
* **User Notification Rules** — The escalation rules that decide how and how quickly each responder gets paged.
* **User Paging Providers** — Which responders are still paged through a legacy provider rather than incident.io.

**Catalog** — The service catalog: its schema and its contents.

* **Catalog Types** — Catalog type definitions — the schema behind the services, environments, and vendors the tenant models.
* **Catalog Type Attributes** — Every attribute on every catalog type, with its mode and backing resource type.
* **Catalog Entries** — The catalog itself: each entry with its aliases, external ID, and attribute values.
* **Catalog Resources** — The attribute types the catalog can reference.

**Governance** — Credentials and automation that can act on the account.

* **API Keys** — Every API key with its granted roles, team scope, creator, and last-used date — the dormant-credential question in one table.
* **API Key Roles** — One row per key per granted role, so privilege is a WHERE clause rather than a string search.
* **Secrets** — Metadata for credentials stored in incident.io for its own integrations. Only the last four characters are ever returned.
* **IP Allowlist** — Whether IP allowlisting is enabled and which ranges are permitted.
* **Workflows** — Automation workflows, their triggers and steps, and whether each one reaches private incidents.

**Status pages & maintenance** — What was communicated externally, and when alerting was suppressed.

* **Status Pages** — Public status pages and their URLs.
* **Status Page Incidents** — What was communicated publicly, with component impacts and each published update.
* **Status Page Maintenances** — Scheduled maintenance published to a status page, with affected components.
* **Maintenance Windows** — Internal alert-suppression windows — including any that were never closed.

***

### Step 4: Verify

1. Go to: `https://{companyname}.configview.com/admin/status/`
2. Run the **incident.io** health check
3. The core checks must pass:

   * Secret Manager access (`INCIDENTIO_API_KEY`)
   * incident.io API auth (`/v1/identity`) — this also prints the key's name, whether it is account-wide or team-scoped, and the roles it holds
   * Users endpoint (`/v2/users`)

   The remaining checks report **ok** when reachable or **skip** with a plan/scope note. A skip is expected on tenants without On-call or Status Pages, and on keys without org-admin scope.

***

### Data Tables

Each enabled script creates and populates one table.

#### Identity

| Table                     | Script       | Key Columns                                                                                                   |
| ------------------------- | ------------ | ------------------------------------------------------------------------------------------------------------- |
| `incidentio_users`        | Users        | `user_id`, `user_name`, `user_email`, `is_active`, `role`, `base_role_id`                                     |
| `incidentio_teams`        | Teams        | `team_id`, `team_name`, `catalog_entry_id`, `catalog_entry_name`, `catalog_entry_external_id`, `member_count` |
| `incidentio_team_members` | Team Members | `team_id`, `team_name`, `member_user_id`, `member_name`, `member_email`, `member_slack_user_id`               |

#### Incidents

| Table                                       | Script                                             | Key Columns                                                                                                                            |
| ------------------------------------------- | -------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------- |
| `incidentio_incidents`                      | Incidents                                          | `incident_id`, `reference`, `incident_name`, `summary`, `permalink`, `mode`                                                            |
| `incidentio_incident_updates`               | Incident Updates                                   | `update_id`, `incident_id`, `message`, `merged_into_incident_id`, `new_status_id`, `new_status_name`                                   |
| `incidentio_incident_statuses`              | Incident Statuses                                  | `status_id`, `status_name`, `description`, `category`, `rank`, `status_created_at`                                                     |
| `incidentio_incident_types`                 | Incident Types                                     | `incident_type_id`, `incident_type_name`, `description`, `is_default`, `create_in_triage`, `private_incidents_only`                    |
| `incidentio_incident_roles`                 | Incident Roles                                     | `role_id`, `role_name`, `shortform`, `description`, `instructions`, `role_type`                                                        |
| `incidentio_incident_timestamps`            | Incident Timestamps                                | `timestamp_id`, `timestamp_name`, `rank`                                                                                               |
| `incidentio_severities`                     | Severities                                         | `severity_id`, `severity_name`, `description`, `rank`, `severity_created_at`, `severity_updated_at`                                    |
| `incidentio_custom_fields`                  | Custom Fields                                      | `custom_field_id`, `name`, `description`, `field_type`, `catalog_type_id`, `group_by_catalog_attribute_id`                             |
| `incidentio_custom_field_options`           | Custom Field Options *(needs Custom Fields)*       | `custom_field_id`, `custom_field_name`, `option_id`, `option_value`, `sort_key`                                                        |
| `incidentio_actions`                        | Actions                                            | `action_id`, `incident_id`, `description`, `status`, `assignee_id`, `assignee_name`                                                    |
| `incidentio_follow_ups`                     | Follow-ups                                         | `follow_up_id`, `incident_id`, `title`, `description`, `status`, `assignee_id`                                                         |
| `incidentio_postmortem_documents`           | Postmortem Documents                               | `document_id`, `incident_id`, `title`, `document_url`, `document_type`, `status`                                                       |
| `incidentio_incident_relationships`         | Incident Relationships *(needs Incidents)*         | `incident_id`, `incident_reference`, `relationship_id`, `related_incident_id`, `related_incident_name`, `related_incident_external_id` |
| `incidentio_incident_attachments`           | Incident Attachments *(needs Incidents)*           | `incident_id`, `incident_reference`, `attachment_id`, `resource_type`, `resource_external_id`, `resource_title`                        |
| `incidentio_incident_participants`          | Incident Participants *(needs Incidents)*          | `incident_id`, `incident_reference`, `participation`, `participant_type`, `participant_user_id`, `participant_name`                    |
| `incidentio_incident_participant_workloads` | Incident Participant Workloads *(needs Incidents)* | `incident_id`, `incident_reference`, `participant_type`, `participant_user_id`, `participant_name`, `participant_email`                |

#### Alerting

| Table                         | Script           | Key Columns                                                                                                             |
| ----------------------------- | ---------------- | ----------------------------------------------------------------------------------------------------------------------- |
| `incidentio_alerts`           | Alerts           | `alert_id`, `title`, `description`, `status`, `alert_source_id`, `deduplication_key`                                    |
| `incidentio_alert_sources`    | Alert Sources    | `alert_source_id`, `source_name`, `source_type`, `has_secret_token`, `alert_events_url`, `auto_resolve_incident_alerts` |
| `incidentio_alert_routes`     | Alert Routes     | `alert_route_id`, `route_name`, `enabled`                                                                               |
| `incidentio_alert_attributes` | Alert Attributes | `attribute_id`, `attribute_name`, `attribute_type`, `is_array`, `required`, `emoji`                                     |
| `incidentio_incident_alerts`  | Incident Alerts  | `incident_alert_id`, `alert_route_id`, `alert_id`, `alert_title`, `alert_status`, `alert_source_id`                     |
| `incidentio_alert_notes`      | Alert Notes      | `note_id`, `alert_id`, `alert_group_id`, `content`, `image_count`, `creator_type`                                       |

#### On-call

| Table                                   | Script                                    | Key Columns                                                                                                               |
| --------------------------------------- | ----------------------------------------- | ------------------------------------------------------------------------------------------------------------------------- |
| `incidentio_escalations`                | Escalations                               | `escalation_id`, `title`, `status`, `escalation_path_id`, `priority_name`, `creator_type`                                 |
| `incidentio_escalation_paths`           | Escalation Paths                          | `escalation_path_id`, `path_name`, `team_ids`, `repeat_after_seconds`, `delay_repeat_on_activity`, `level_count`          |
| `incidentio_escalation_path_responders` | Escalation Path Responders                | `escalation_path_id`, `path_name`, `responder_user_id`, `responder_name`, `responder_email`, `responder_role`             |
| `incidentio_schedules`                  | Schedules                                 | `schedule_id`, `name`, `timezone`, `permalink`, `team_ids`, `rotation_count`                                              |
| `incidentio_schedule_rotations`         | Schedule Rotations                        | `schedule_id`, `schedule_name`, `rotation_id`, `rotation_name`, `scheduling_mode`, `effective_from`                       |
| `incidentio_schedule_current_shifts`    | Schedule Current Shifts                   | `schedule_id`, `schedule_name`, `entry_id`, `rotation_id`, `layer_id`, `fingerprint`                                      |
| `incidentio_schedule_entries`           | Schedule Entries *(needs Schedules)*      | `schedule_id`, `schedule_name`, `entry_id`, `rotation_id`, `layer_id`, `fingerprint`                                      |
| `incidentio_schedule_overrides`         | Schedule Overrides *(needs Schedules)*    | `schedule_id`, `schedule_name`, `override_id`, `rotation_id`, `layer_id`, `override_start_at`                             |
| `incidentio_schedule_sync_targets`      | Schedule Sync Targets                     | `sync_target_id`, `slack_team_id`, `slack_user_group_id`, `add_bot_to_group`, `linked_schedule_count`, `linked_schedules` |
| `incidentio_user_notification_methods`  | User Notification Methods *(needs Users)* | `user_id`, `user_email`, `user_name`, `method_id`, `method_type`, `address`                                               |
| `incidentio_user_notification_rules`    | User Notification Rules *(needs Users)*   | `user_id`, `user_email`, `user_name`, `rule_id`, `rule_type`, `method_type`                                               |
| `incidentio_user_paging_providers`      | User Paging Providers *(needs Users)*     | `user_id`, `user_email`, `user_name`, `preferred_escalation_provider`                                                     |

#### Catalog

| Table                                | Script                                  | Key Columns                                                                                                  |
| ------------------------------------ | --------------------------------------- | ------------------------------------------------------------------------------------------------------------ |
| `incidentio_catalog_types`           | Catalog Types                           | `catalog_type_id`, `name`, `type_name`, `description`, `categories`, `color`                                 |
| `incidentio_catalog_type_attributes` | Catalog Type Attributes                 | `catalog_type_id`, `catalog_type_name`, `schema_version`, `attribute_id`, `attribute_name`, `attribute_type` |
| `incidentio_catalog_entries`         | Catalog Entries *(needs Catalog Types)* | `catalog_type_id`, `catalog_type_name`, `catalog_entry_id`, `entry_name`, `external_id`, `aliases`           |
| `incidentio_catalog_resources`       | Catalog Resources                       | `resource_type`, `label`, `category`, `description`, `value_docstring`                                       |

#### Governance

| Table                      | Script        | Key Columns                                                                                         |
| -------------------------- | ------------- | --------------------------------------------------------------------------------------------------- |
| `incidentio_api_keys`      | API Keys      | `api_key_id`, `key_name`, `comments`, `creator_type`, `creator_user_id`, `creator_user_name`        |
| `incidentio_api_key_roles` | API Key Roles | `api_key_id`, `key_name`, `role_name`, `role_description`                                           |
| `incidentio_secrets`       | Secrets       | `secret_id`, `secret_name`, `description`, `last_four_chars`, `version`, `owning_team_ids`          |
| `incidentio_ip_allowlist`  | IP Allowlist  | `enabled`, `allowlist_version`, `entry_label`, `entry_value`, `entry_count`, `allowlist_updated_at` |
| `incidentio_workflows`     | Workflows     | `workflow_id`, `workflow_name`, `folder`, `shortform`, `state`, `version`                           |

#### Status pages & maintenance

| Table                                 | Script                                          | Key Columns                                                                                                         |
| ------------------------------------- | ----------------------------------------------- | ------------------------------------------------------------------------------------------------------------------- |
| `incidentio_status_pages`             | Status Pages                                    | `status_page_id`, `name`, `description`, `public_url`                                                               |
| `incidentio_status_page_incidents`    | Status Page Incidents *(needs Status Pages)*    | `status_page_id`, `status_page_name`, `status_page_incident_id`, `incident_name`, `incident_status`, `published_at` |
| `incidentio_status_page_maintenances` | Status Page Maintenances *(needs Status Pages)* | `status_page_id`, `status_page_name`, `maintenance_id`, `maintenance_name`, `maintenance_status`, `published_at`    |
| `incidentio_maintenance_windows`      | Maintenance Windows                             | `maintenance_window_id`, `window_name`, `incident_id`, `lead_type`, `lead_user_id`, `lead_user_name`                |

***

### Snapshot Convention

Every table is a **per-run snapshot** stamped with `run_at`. Query the latest with:

```sql theme={null}
SELECT * FROM incidentio_incidents
WHERE run_at = (SELECT MAX(run_at) FROM incidentio_incidents);
```

Comparing two `run_at` values is how you see drift — a responder who lost their
notification rules, an API key that went dormant, an escalation path that
emptied out.

***

### Rate Limits

incident.io meters per API key, not per organisation, so ConfigView's budget is
shared with anything else pointed at the same key. The collectors pace
themselves against three buckets:

| Bucket      | Collectors | Safe rate | Why                                                                                                                                                          |
| ----------- | ---------- | --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `default`   | 39         | 600/min   | Half of the documented 1200/min default                                                                                                                      |
| `incidents` | 5          | 30/min    | Listing incidents is capped at **60/min**, twenty times tighter than everything else. Every per-incident collector inherits this bucket                      |
| `schedules` | 6          | 180/min   | Schedule preview is 6/min — the tightest limit incident.io publishes — so neighbouring schedule endpoints are treated as tighter than default until measured |

incident.io reports the live position on every response (`X-RateLimit-Remaining`)
and answers a 429 with `Retry-After`; the collectors honour both and back off
rather than failing the run.

> **First run on a large tenant.** The per-incident collectors fan out over
> incidents updated in the last **90 days**. On a tenant with thousands of live
> incidents that is the longest part of the sync. Widen or narrow the window in
> `incidentio_get_incident_*.py` if you need a different history depth.

***

### What ConfigView Deliberately Does Not Collect

| Not collected                     | Reason                                                                                                                                                                                                  |
| --------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `secret_token` on alert sources   | It is the live shared secret for that source's webhook. Anyone holding it can forge alerts into your tenant, so it has no business in an inventory database. ConfigView records only whether one is set |
| Postmortem document *contents*    | `/v1/postmortem_documents/{id}/content` returns the prose, which routinely contains customer and personnel detail. ConfigView stores the metadata and the link                                          |
| Stored secret values              | The API only ever returns the last four characters, and that is all that is kept                                                                                                                        |
| Write, ping and preview endpoints | ConfigView reads. No collector can create, modify or resolve anything in incident.io                                                                                                                    |

***

### Troubleshooting

| Issue                                                            | Fix                                                                                                                                                                                                            |
| ---------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Health check fails on "incident.io API auth"                     | Verify the `INCIDENTIO_API_KEY` secret has no leading or trailing spaces, and that the key has not been revoked at [https://app.incident.io/\~/settings/api-keys](https://app.incident.io/~/settings/api-keys) |
| Health check shows **skip** on API keys or IP allowlist          | Expected. Those need org-admin scope, and IP allowlisting is an Enterprise feature. A skip does not fail the check                                                                                             |
| Health check shows **skip** on schedules, alerts or status pages | Expected if your tenant does not have the On-call or Status Pages product                                                                                                                                      |
| A table is empty but its parent is populated                     | The child collector ran before the parent had data. It self-corrects on the next scheduled run                                                                                                                 |
| `incidentio_users` looks short                                   | The key is team-scoped. Recreate it account-wide (Step 1, point 5)                                                                                                                                             |
| Sync is slow on the first run                                    | The per-incident fan-outs are paced against the 60/min incidents bucket. Subsequent runs only cover the rolling 90-day window                                                                                  |
| Every table is empty and the health check passes                 | The key authenticates but was granted no view scopes. Re-check the permissions on the key itself                                                                                                               |
