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

# Sync incident data into your data warehouse

> Join your incident data with the rest of your business data in BigQuery, Snowflake, Redshift, or your BI tool.

Getting your incident data into a warehouse lets you report on it alongside everything else you have there: follow-ups next to Jira tickets, incidents next to revenue. You can sync incidents, follow-ups, actions, alerts, and escalations, and there are three ways to go about it:

* [Fivetran](#fivetran), if you want a managed connector with nothing to run yourself.
* Our [Singer tap](#singer-tap), an open-source exporter you run on your own infrastructure.
* [Your own pipeline](#build-your-own-pipeline) against the API, if you want incremental syncs or control over exactly what you load.

Whichever you pick, have a read of [How incident.io measures incidents](/insights/how-we-measure-incidents) first. It explains what each timestamp and duration means, and which incidents are counted.

## Fivetran

[Fivetran's incident.io connector](https://fivetran.com/docs/connectors/applications/incidentio) loads your incident.io data into any Fivetran destination. Every sync re-imports every table, so there's no incremental logic to set up. Records you delete in incident.io stay in your tables with `_fivetran_deleted` set to `true`. You'll need an [API key](/admin/api-keys) for it, and the rest is in [Fivetran's setup guide](https://fivetran.com/docs/connectors/applications/incidentio/setup-guide).

## Singer tap

Our [Singer tap](/integrations/singer-tap) exports your incident.io data to any [Singer target](https://www.singer.io/), including BigQuery, Snowflake, and Redshift. It's open source, but you run it yourself, on a schedule or from CI, and it exports everything on each run. The [tap's documentation](https://github.com/incident-io/singer-tap/tree/master/docs) covers configuration.

## Build your own pipeline

### What to sync

These are the endpoints you'll want. Each one supports an `updated_at` filter, which means that after the initial import you only need to fetch what's changed:

| Data | Endpoint | `updated_at` filter | Max `page_size` |
| - | - | - | - |
| Incidents | [`GET /v2/incidents`](/api-reference/incidents-v2/list) | Date (`2026-10-01`) | 250 |
| Follow-ups | [`GET /v3/follow_ups`](/api-reference/follow-ups-v3/list) | Timestamp or date | 250 |
| Actions | [`GET /v3/actions`](/api-reference/actions-v3/list) | Timestamp or date | 250 |
| Alerts | [`GET /v2/alerts`](/api-reference/alerts-v2/list) | Timestamp or date | 50 |
| Escalations | [`GET /v2/escalations`](/api-reference/escalations-v2/list) | Date (`2026-10-01`) | 50 |

Use an [API key](/admin/api-keys) with the **View data** permission. Add the **View all incident data** permission to include private incidents.

### Initial import

Page through each endpoint with the largest `page_size` it allows:

```bash theme={null}
curl --get 'https://api.incident.io/v2/incidents' \
  --header 'Authorization: Bearer <YOUR_API_KEY>' \
  --data 'page_size=250'
```

Pass the `after` value from `pagination_meta` to fetch the next page, and keep going until a response comes back without one. Don't be tempted to stop at a short or empty page, as the alerts endpoint can return an empty page with more results still to come.

### Incremental syncs

From then on, fetch only what changed since your last sync:

```bash theme={null}
curl --get 'https://api.incident.io/v2/incidents' \
  --header 'Authorization: Bearer <YOUR_API_KEY>' \
  --data 'page_size=250' \
  --data 'updated_at[gte]=2026-10-01'
```

* Treat every row as an upsert, keyed on `id`. An incremental sync can hand you records you've already loaded.
* Filter by the day of your last sync rather than the exact time. The incidents and escalations endpoints only take a date, so `updated_at[gte]=2026-10-01` gives you everything updated since the start of that day. Follow-ups, actions, and alerts accept a full timestamp too. Either way, set it a little before your last sync ran, so you don't miss a record that was being written at the time.
* Do a full re-sync every so often, to catch anything an incremental window missed.

<Warning>
  Listing incidents is limited to 60 requests a minute, lower than the rest of the API. At 250 incidents a page, that's
  still 15,000 incidents a minute. See [rate limits](/api-reference/introduction#rate-limits).
</Warning>

### Which incidents are included

By default the incidents endpoint doesn't return test or tutorial incidents, or incidents that were declined, canceled, or merged. If you want those too, ask for them explicitly with the `mode` and `status_category` filters. See [Which incidents are counted](/insights/how-we-measure-incidents#which-incidents-are-counted).

### React to changes as they happen

If a scheduled sync isn't quick enough and you want changes landing within seconds, subscribe to [webhooks](/integrations/webhooks). Webhooks can arrive out of order, so when one comes in, fetch the record's latest state from the API and upsert that.
