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

# Checkly

> Connect Checkly to Rootly to turn synthetic check failures and API monitoring alerts into routed, actionable incidents and on-call pages.

## Overview

Checkly's synthetic checks and API monitors fire webhook alerts the moment something fails. Wire those webhooks at Rootly and every failure becomes a normalized alert that can page on-call, route to the right service, or auto-create an incident through alert workflows. Recovery events from Checkly close the same alert automatically, so your timeline stays clean.

Checkly has first-class support as a dedicated alert source in Rootly — you don't need the Generic Webhook source. The integration ships with vendor-specific payload parsing, pre-mapped fields, a `secret`-header authentication path, and a guided setup wizard in the Rootly dashboard.

<CardGroup cols={2}>
  <Card title="Page On-Call" icon="bell-on">
    Trigger escalation policies the moment a Checkly check fails, paging the right responder in seconds.
  </Card>

  <Card title="Auto-Create Incidents" icon="circle-exclamation">
    Turn a degraded check into a full Rootly incident with custom fields, workflows, and Slack channels.
  </Card>

  <Card title="Auto-Resolve On Recovery" icon="arrows-rotate">
    Map Checkly's recovery event to `rootly_alert_status` and the alert closes itself when the check comes back.
  </Card>

  <Card title="Per-Check Routing" icon="shuffle">
    Send API checks to one team, browser checks to another, all from a single Checkly alert channel.
  </Card>
</CardGroup>

***

## Before You Begin

<Info>
  **You'll need access to both sides of the connection.**

  * **In Rootly** — the **On-Call Admin** or **On-Call User** role so you can create alert sources. See [Schedule Permissions](/on-call/schedules#permissions-access).
  * **In Checkly** — permission to add and configure alert channels under **Alert Settings**.

  A clear routing plan helps too: decide whether every alert from this source should land on the same service or team, or whether routing varies per check.
</Info>

***

## Add the Alert Source in Rootly

The Rootly side hands you a webhook URL and a `secret` value — paste those into Checkly in the next section.

<Steps>
  <Step title="Open Alerts → Sources">
    In the Rootly dashboard, navigate to **Alerts → Sources** and click **New alert source**.
  </Step>

  <Step title="Choose Checkly">
    Select **Checkly** from the list of available sources and give the source a descriptive name — for example, `Checkly — Production Synthetics`.
  </Step>

  <Step title="Set The Default Routing Target (Optional)">
    If every alert from this source should always route to the same service, team, or escalation policy, set the target on the source configuration page. Leave it blank if you want routing to come from each check's payload instead — covered under [Routing Alerts](#routing-alerts).
  </Step>

  <Step title="Copy The Webhook URL And Secret">
    Rootly generates a unique webhook URL and a per-source `secret`. Copy both — they go into Checkly next.

    Without a default routing target:

    ```text theme={null}
    https://webhooks.rootly.com/webhooks/incoming/checkly_webhooks
    ```

    With a default routing target baked into the URL:

    ```text theme={null}
    https://webhooks.rootly.com/webhooks/incoming/checkly_webhooks/notify/<type>/<id>
    ```
  </Step>
</Steps>

***

## Configure the Webhook in Checkly

Create a webhook alert channel in Checkly, point it at the Rootly URL, and use the payload template Rootly expects.

<Steps>
  <Step title="Create A New Webhook Alert Channel">
    In Checkly, navigate to **Alert Settings → Alert Channels** and click **Add channel**. Choose **Webhook**. For the latest Checkly UI specifics, refer to [Checkly's webhook alert channel documentation](https://www.checklyhq.com/docs/alerting-and-retries/webhooks/).
  </Step>

  <Step title="Set The Request Details">
    Configure the request:

    <ParamField path="Method" type="string" required>
      `POST`
    </ParamField>

    <ParamField path="URL" type="string" required>
      The webhook URL you copied from Rootly.
    </ParamField>

    <ParamField path="Custom Header" type="key/value" required>
      Key: `secret` — Value: the secret you copied from Rootly.
    </ParamField>

    <Warning>
      Rootly's Checkly source authenticates the request using the custom `secret` header, not Bearer Token or HMAC. Without it, Rootly returns `401 Unauthorized` and the alert is dropped.
    </Warning>
  </Step>

  <Step title="Paste The Payload Template">
    Use the JSON template below. Checkly substitutes the `{{ }}` Handlebars variables with values from the failing check at send time.

    <Tabs>
      <Tab title="Basic Alert">
        Standard template — alert lands in Rootly and routes based on the source's default target.

        ```json theme={null}
        {
          "alert_type": "{{ALERT_TYPE}}",
          "check_id": "{{CHECK_ID}}",
          "check_result_id": "{{CHECK_RESULT_ID}}",
          "check_name": "{{CHECK_NAME}}",
          "alert_title": "{{ALERT_TITLE}}",
          "started_at": "{{STARTED_AT}}",
          "link": "{{RESULT_LINK}}"
        }
        ```
      </Tab>

      <Tab title="Per-Check Routing">
        Add a `rootly` object to route this specific check to a different service, team, or escalation policy.

        ```json theme={null}
        {
          "alert_type": "{{ALERT_TYPE}}",
          "check_id": "{{CHECK_ID}}",
          "check_name": "{{CHECK_NAME}}",
          "alert_title": "{{ALERT_TITLE}}",
          "started_at": "{{STARTED_AT}}",
          "link": "{{RESULT_LINK}}",
          "rootly": {
            "notification_target": {
              "type": "Service",
              "id": "8c4a5e91-1b2d-4c3e-9f6a-7d8b2c5e9a01"
            }
          }
        }
        ```

        Valid `type` values are the Rootly resource class names: `Service`, `Group`, or `EscalationPolicy`.
      </Tab>

      <Tab title="Recovery (Auto-Resolve)">
        Use this template on a second Checkly alert channel scoped to recovery events. The `rootly_alert_status` field closes the matching alert in Rootly.

        ```json theme={null}
        {
          "check_id": "{{CHECK_ID}}",
          "check_name": "{{CHECK_NAME}}",
          "alert_title": "{{ALERT_TITLE}}",
          "started_at": "{{STARTED_AT}}",
          "rootly_alert_status": "resolved"
        }
        ```
      </Tab>
    </Tabs>
  </Step>

  <Step title="Save And Attach To Checks">
    Save the alert channel, then attach it to the checks (or check groups) you want forwarded to Rootly. New failures on those checks POST to the Rootly webhook URL within seconds.
  </Step>
</Steps>

***

## Payload Reference

Rootly's Checkly source parses these fields from each incoming webhook. The full raw payload is also preserved on the alert record, so any extra fields Checkly sends remain accessible to alert routes, workflows, and field mappings.

<ParamField path="check_name" type="string" required>
  The name of the Checkly check that fired. Joined with `alert_title` using `" - "` to form the Rootly alert's summary.
</ParamField>

<ParamField path="alert_title" type="string" required>
  The descriptive title Checkly attached to the alert. Combined with `check_name` for the alert summary.
</ParamField>

<ParamField path="check_id" type="string" required>
  Stable identifier for the check. Rootly uses this as the **External Identifier** to match recovery events back to the original alert for auto-resolution.
</ParamField>

<ParamField path="started_at" type="ISO 8601 datetime">
  When the check first failed. Populates the alert's started-at timestamp.
</ParamField>

<ParamField path="link" type="URL">
  Direct link back to the failing check in the Checkly dashboard. Preserved on the alert record for responders to jump straight to the source.
</ParamField>

<ParamField path="rootly.notification_target" type="object">
  Optional. Sets the routing target for this specific alert. Used only when the alert source does **not** have a default URL-based target — if a URL target is configured on the source, it takes precedence and the payload target is ignored. Expects `type` (`Service`, `Group`, or `EscalationPolicy`) and `id` (the Rootly resource's internal ID).
</ParamField>

<ParamField path="rootly_alert_status" type="string">
  Optional. Sets the alert state directly. Use `resolved` on recovery channels so Checkly's "check is back" event closes the original Rootly alert.
</ParamField>

***

## Routing Alerts

Two ways to point a Checkly alert at the right responder. URL-based routing takes precedence when both are set on the same request.

<Tabs>
  <Tab title="By URL (One Target)">
    Set a default routing target when you create the alert source. Rootly bakes it into the webhook URL:

    ```text theme={null}
    https://webhooks.rootly.com/webhooks/incoming/checkly_webhooks/notify/Service/<service-id>
    ```

    Every alert from this Checkly channel routes to that target — no payload-level routing needed.

    **Best when**: a single Checkly account corresponds to one Rootly team or service.
  </Tab>

  <Tab title="By Payload (Per Check)">
    Leave the default target empty on the Rootly source. In each Checkly alert channel's payload template, add a `rootly` object naming the target:

    ```json theme={null}
    "rootly": {
      "notification_target": {
        "type": "Service",
        "id": "8c4a5e91-1b2d-4c3e-9f6a-7d8b2c5e9a01"
      }
    }
    ```

    Valid `type` values are the Rootly resource class names: `Service`, `Group`, or `EscalationPolicy`. The `id` is the Rootly resource's internal ID — open the resource in Rootly and copy it from the edit page. Names and slugs aren't accepted.

    **Best when**: different checks need to page different teams. You can hardcode targets per channel, or use Checkly's per-check variables to switch them dynamically.
  </Tab>
</Tabs>

***

## Auto-Resolution

Checkly fires a recovery event whenever a failing check comes back to passing. Rootly closes the original alert automatically when the recovery payload includes `"rootly_alert_status": "resolved"`.

The cleanest pattern is **two separate Checkly alert channels** scoped to different alert events:

* **Failure channel** — uses the **Basic Alert** payload from the [Configure step](#configure-the-webhook-in-checkly) above, unchanged. No `rootly_alert_status` field needed; Rootly defaults to a triggered state when one isn't present.
* **Recovery channel** — uses the **Recovery (Auto-Resolve)** template, which hardcodes `"rootly_alert_status": "resolved"`.

Rootly matches the two events using the **External Identifier** (`check_id`) and transitions the same alert from triggered to resolved.

See [Alert Statuses](/alerts/alert-statuses) for the full lifecycle.

***

## Test the Integration

After saving the alert channel in Checkly, run a test to confirm the connection works end-to-end.

<Steps>
  <Step title="Send A Test Webhook From Checkly">
    Open the alert channel you created and click **Send test webhook**. Checkly POSTs a sample payload to the Rootly URL.
  </Step>

  <Step title="Confirm The Alert Appears In Rootly">
    Open the Checkly alert source in Rootly. The test alert should appear in the source's recent activity within a few seconds. Click into it to verify the title, started-at timestamp, and link populated correctly.
  </Step>

  <Step title="Optional — Trigger A Real Failure">
    For full end-to-end verification, deliberately fail a check (point an API check at a 500-returning endpoint, for example) and confirm the alert reaches Rootly with the correct routing target and triggers the workflow you expect.
  </Step>
</Steps>

<Check>
  A successful test alert in Rootly means the webhook URL, the `secret` header, and the payload template are all wired correctly. You're ready to attach the channel to production checks.
</Check>

***

## Troubleshooting

<AccordionGroup>
  <Accordion title="Rootly returns 401 Unauthorized" icon="lock">
    The `secret` header is missing or doesn't match the value shown on the Rootly source configuration. Re-copy the secret from Rootly, paste it as a custom header in the Checkly alert channel (header key: `secret`, value: the secret string), and re-send a test.
  </Accordion>

  <Accordion title="The webhook returns 200 but no alert appears in Rootly" icon="ghost">
    Rootly processes webhooks asynchronously, so check again after a few seconds. If the alert still doesn't appear:

    * Confirm the routing target referenced in the URL or payload exists and isn't archived
    * Inspect the source's recent activity in Rootly to verify the payload was received
    * Verify `check_name` and `alert_title` aren't empty in the payload template
  </Accordion>

  <Accordion title="Recovery events don't resolve the original alert" icon="arrows-rotate">
    Either the recovery payload has a different `check_id` than the failure event, or the `rootly_alert_status` field isn't set to `resolved` (case-sensitive). Confirm both events come from the same Checkly check and that the recovery channel's template hardcodes `"rootly_alert_status": "resolved"`.
  </Accordion>

  <Accordion title="Alerts route to the wrong team or service" icon="shuffle">
    URL-based routing takes precedence over payload-based routing. If the webhook URL ends with `/notify/<type>/<id>`, that target wins regardless of the JSON body. Either remove the URL target and rely on payload routing, or update the URL target to the correct destination.
  </Accordion>

  <Accordion title="Checkly retried the webhook five times" icon="rotate">
    Checkly retries up to five times with 20-second backoff on any HTTP response above 399. If Rootly returned `401`, check the `secret` header. If Rootly returned `500`, contact Rootly support with the timestamps so they can correlate against server logs.
  </Accordion>
</AccordionGroup>

***

## Frequently Asked Questions

<AccordionGroup>
  <Accordion title="Do I need to use the Generic Webhook source for Checkly?" icon="code">
    No. Rootly ships a dedicated Checkly alert source with vendor-specific payload parsing, pre-mapped fields, and the `secret`-header authentication shown above. Use it instead of the Generic Webhook source for a cleaner setup and built-in field mappings.
  </Accordion>

  <Accordion title="Can one Checkly account feed multiple Rootly alert sources?" icon="bell">
    Yes. Create a separate Checkly alert channel for each Rootly source you want to feed — each with its own webhook URL and secret — and attach each channel to the relevant checks. Useful when different check groups need to route to different Rootly teams.
  </Accordion>

  <Accordion title="Does the integration support HMAC signatures?" icon="circle-info">
    Rootly's Checkly source authenticates via the `secret` custom header, not HMAC. Checkly's optional `x-checkly-signature` SHA-256 signature isn't required and isn't validated.
  </Accordion>

  <Accordion title="What if I want to page on-call directly instead of just creating an alert?" icon="plus">
    Set the source's default routing target (or the payload's `rootly.notification_target`) to an **Escalation Policy**. Rootly triggers the escalation as soon as the alert is created, paging the on-call responder per the policy's steps.
  </Accordion>

  <Accordion title="Can I customize the alert title beyond what the payload contains?" icon="heading">
    Adjust the payload template in Checkly's alert channel. The `check_name` and `alert_title` Handlebars variables can be combined with static text — for example, `"alert_title": "[{{SEVERITY}}] {{CHECK_NAME}} failing"`. Rootly stores whatever string you produce as the alert summary.
  </Accordion>
</AccordionGroup>

***

## Next Steps

<CardGroup cols={2}>
  <Card title="Alert Routing" icon="route" href="/alerts/alert-routing">
    Configure routes that send alerts from this source to the right responders based on severity, region, or any custom field.
  </Card>

  <Card title="Alert Workflows" icon="bolt" href="/workflows/alert-workflows">
    Auto-create incidents, post Slack notifications, run runbooks, and chain follow-up actions from Checkly alerts.
  </Card>

  <Card title="Alert Fields" icon="brackets-curly" href="/alerts/alert-fields">
    Extract custom fields from the Checkly payload (severity, region, deployment) for richer routing and reporting.
  </Card>

  <Card title="Schedule Permissions" icon="users-gear" href="/on-call/schedules#permissions-access">
    Confirm which Rootly roles can create and edit this alert source.
  </Card>
</CardGroup>
