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

# Multistep Check Construct

> Learn how to configure multistep checks with the Checkly CLI.

> [!TIP]
>
> Learn more about Multistep Checks in [the Multistep Checks overview](https://www.checklyhq.com/docs/detect/synthetic-monitoring/multistep-checks/overview.md).

Use Multistep Checks to run complex end-to-end workflows with Playwright that span multiple endpoints. The examples below show how to configure Multistep Checks for different testing scenarios.

> **Prerequisites**
>
> Before creating Multistep Checks, ensure you have:
>
> * An initialized Checkly CLI project
> * Public endpoints you want to monitor
> * Runtime `2023.09` or later (Multistep Checks require [newer runtimes](https://www.checklyhq.com/docs/platform/runtimes/runtime-specification.md))
>
> For additional setup information, see [CLI overview](https://www.checklyhq.com/docs/cli/overview.md).

```ts Basic Example theme={null}
import { MultiStepCheck } from "checkly/constructs"
import * as path from "path"

new MultiStepCheck("multistep-check-1", {
  name: "Multistep Check #1",
  description: "Validates user signup and login flow.",
  locations: ["us-east-1", "eu-west-1"],
  code: {
    entrypoint: path.join(__dirname, "multi-step.spec.ts"),
  },
})
```

```ts Advanced Example theme={null}
import { MultiStepCheck, Frequency } from "checkly/constructs"
import { secret } from "checkly/util"
import * as path from "path"

new MultiStepCheck("complex-multistep-check", {
  name: "Complex User Journey",
  description: "Validates user signup and login flow.",
  activated: true,
  runtimeId: "2025.04",
  frequency: Frequency.EVERY_15M,
  locations: ["us-east-1", "eu-west-1"],
  tags: ["e2e", "user-journey", "critical"],
  environmentVariables: [
    { key: "BASE_URL", value: "https://app.example.com" },
    { key: "TEST_USER_EMAIL", value: "test@example.com" },
    { key: "TEST_USER_PASSWORD", value: secret("TEST_USER_PASSWORD"), secret: true },
  ],
  code: {
    entrypoint: path.join(__dirname, "user-journey.spec.ts"),
  },
})
```

## Configuration

**Multistep Check**

| Parameter | Type | Required | Default | Description |
| - | - | - | - | - |
| `code` | `object` | ✅ | - | The Playwright test code |

**General Check**

| Property | Type | Required | Default | Description |
| - | - | - | - | - |
| `name` | `string` | ✅ | - | Friendly name for your check |
| `description` | `string` | ❌ | `null` | A description of the check. Supports markdown. Max 500 characters |
| `intent` | `CheckIntent` | ❌ | - | Structured guidance for root cause analysis and check repair. See [General Check Options](#general-check-options). |
| `aiAutoRepairEnabled` | `boolean \| null` | ❌ | - | Enable or disable automatic repair, or inherit the account setting. Requires CLI 9.4.0 or later. See [General Check Options](#general-check-options). |
| `activated` | `boolean` | ❌ | `true` | Whether the check is enabled |
| `alertChannels` | `AlertChannel[]` | ❌ | `[]` | Array of AlertChannel objects for notifications |
| `alertEscalationPolicy` | `AlertEscalationPolicy` | ❌ | - | Advanced alert settings |
| `environmentVariables` | `object[]` | ❌ | `[]` | Check-level environment variables |
| `frequency` | `Frequency` | ❌ | - | How often to run your check |
| `group` | `CheckGroup` | ❌ | - | The CheckGroup this check belongs to |
| `locations` | `string[]` | ❌ | `[]` | Array of public location codes |
| `muted` | `boolean` | ❌ | `false` | Whether alert notifications are muted |
| `runtimeId` | `string` | ❌ | - | The ID of the runtime to use (2023.09 or later required) |
| `privateLocations` | `string[]` | ❌ | `[]` | Array of Private Location slugs |
| `retryStrategy` | `RetryStrategy` | ❌ | [`singleRetry()`](https://www.checklyhq.com/docs/constructs/retry-strategy#default-retry-strategy) | Strategy for configuring retries |
| `runParallel` | `boolean` | ❌ | `false` | Run checks in parallel or round-robin |
| `tags` | `string[]` | ❌ | `[]` | Array of tags to organize checks |
| `testOnly` | `boolean` | ❌ | `false` | Only run with test, not during deploy |
| `triggerIncident` | `IncidentTrigger` | ❌ | - | Create and resolve an incident based on the check's alert configuration |

### Multistep Check Options

**code** `object` *required*

The Playwright test code that defines your Multistep Check monitor.

**Usage:**

```ts theme={null}
// Using file reference
code: {
  entrypoint: path.join(__dirname, "user-journey.spec.ts")
}

// Using inline content
code: {
  content: `
    import { test, expect } from "@playwright/test"

    test("complete workflow", async ({ request }) => {
      // Multistep logic here
    })
  `
}
```

**Parameters:**

| Parameter | Type | Required | Description |
| - | - | - | - |
| `entrypoint` | `string` | ❌ | Path to a `.spec.js` or `.spec.ts` file containing the Playwright test |
| `content` | `string` | ❌ | Inline JavaScript/TypeScript code as a string |

> [!NOTE]
>
> You must provide either `entrypoint` or `content`, but not both.

**Examples:**

**CRUD API**

```ts theme={null}
new MultiStepCheck("onboarding-flow", {
  name: "Complete User Onboarding",
  runtimeId: "2025.04",
  code: {
    entrypoint: path.join(__dirname, "group.spec.ts")
  }
})

// group.spec.ts
import { test, expect } from "@playwright/test"

const baseUrl = "https://api.checklyhq.com/v1"

const headers = {
  Authorization: `Bearer ${process.env.API_KEY}`,
  "x-checkly-account": process.env.ACCOUNT_ID,
}

test("Verify Group API", async ({ request }) => {
  /**
   * Create a group
   */
  const group = await test.step("POST /check-groups", async () => {
    const response = await request.post(`${baseUrl}/check-groups/`, {
      data: {
        locations: ["eu-west-1"],
        name: "createdViaApiCheck",
      },
      headers,
    })
    expect(response).toBeOK()

    return response.json()
  })

  /**
   * Get the newly created group
   */
  await test.step("GET /check-groups/{id}", async () => {
    const response = await request.get(`${baseUrl}/check-groups/${group.id}`, {
      headers,
    })
    expect(response).toBeOK()

    const receivedGroup = await response.json()
    expect(receivedGroup.id).toEqual(group.id)
  })

  /**
   * Update the new group
   */
  await test.step("PUT /check-groups/{id}", async () => {
    const response = await request.put(`${baseUrl}/check-groups/${group.id}`, {
      data: {
        tags: ["public-api", "added-by-check"],
      },
      headers,
    })
    expect(response).toBeOK()
  })

  /**
   * Delete the new group
   */
  await test.step("DELETE /check-group/{id}", async () => {
    const response = await request.delete(
      `${baseUrl}/check-groups/${group.id}`,
      { headers },
    )
    expect(response).toBeOK()
  })
})
```

**Degraded state**

```ts theme={null}
new MultiStepCheck("degraded-example", {
  name: "Degraded Example",
  runtimeId: "2025.04",
  code: {
    entrypoint: path.join(__dirname, "degraded.spec.ts")
  },
})

// degraded.spec.ts
import { test, expect } from "@playwright/test"
import { getAPIResponseTime, markCheckAsDegraded } from "@checkly/playwright-helpers"

const baseUrl = "https://api.spacexdata.com/v3"

test("SpaceX-API Dragon Capsules & Next Launch", async ({ request }) => {
  await test.step("get all capsules", async () => {
    const response = await request.get(`${baseUrl}/dragons`)

    // Check 200 status code
    expect(response).toBeOK()

    // Check degraded status
    expect.soft(getAPIResponseTime(response), 'GET /dragons too slow').toBeLessThanOrEqual(200)

    return response.json()
  })

  // Trigger degraded state if check failed due to soft assertion
  if (test.info().errors.length) {
    markCheckAsDegraded('Check degraded due to soft assertion failure.')
  }
})
```

**Use cases**: Complex API journeys, end-to-end API workflows, business process validation.

### General Check Options

**name** `string` *required*

Friendly name for your multistep check that will be displayed in the Checkly dashboard and used in notifications.

**Usage:**

```ts highlight={2} theme={null}
new MultiStepCheck("my-multistep", {
  name: "Complete User Journey Test"
})
```

**runtimeId** `string`

The Checkly runtime version used to execute the Multistep Check. Runtimes are managed execution environments for Browser and Multistep Checks. They include fixed Checkly-provided dependencies, such as Playwright, browser binaries, and runtime libraries.

Multistep checks require runtime `2023.09` or later.

Usage:

```ts highlight={3} theme={null}
new MultiStepCheck("my-multistep", {
  name: 'My Multistep Check',
  runtimeId: "2025.04" // Use latest runtime for best performance
  /* More options... */
})
```

> [!WARNING]
>
> Multistep checks require runtime `2023.09` or later. Earlier runtimes do not support multistep functionality.

**frequency** `Frequency`

How often the multistep check should run. Use the `Frequency` enum to set the check interval.

Usage:

```ts highlight={5} theme={null}
import { Frequency } from 'checkly/constructs'

new MultiStepCheck("my-multistep", {
  name: "My Multistep Check",
  frequency: Frequency.EVERY_15M,
  /* More options... */
})
```

**Available frequencies**: `EVERY_1M`, `EVERY_2M`, `EVERY_5M`, `EVERY_10M`, `EVERY_15M`, `EVERY_30M`, `EVERY_1H`, `EVERY_2H`, `EVERY_3H`, `EVERY_6H`, `EVERY_12H`, `EVERY_24H`

**locations** `string[]` (default: \[])

Array of public location codes where the multistep check should run. Multiple locations provide geographic coverage and user experience insights.

Usage:

```ts highlight={3} theme={null}
new MultiStepCheck("global-check", {
  name: "Global Multistep Check",
  locations: ["us-east-1", "eu-west-1", "ap-southeast-1"]
  /* More options... */
})
```

Examples:

**Global User Experience**

```ts theme={null}
// Worldwide API testing
new MultiStepCheck("global-journey", {
  name: "Global API Journey",
  locations: [
    "us-east-1",      // N. Virginia
    "us-west-1",      // N. California
    "eu-west-1",      // Ireland
    "ap-southeast-1", // Singapore
    "ap-northeast-1"  // Tokyo
  ],
  /* More options... */
})
```

**Regional Focus**

```ts theme={null}
// European user focus
new MultiStepCheck("eu-workflow", {
  name: "European API Journey",
  locations: ["eu-west-1", "eu-central-1"],
  /* More options... */
})
```

**Use cases**: Global API monitoring, regional API testing, geographic compliance validation.

> [!WARNING]
>
> Multistep checks are only supported on runtime `2023.09` or later. Make sure to specify a compatible `runtimeId` in your check configuration.

**intent** `CheckIntent | null`

Describe what your check is intended to verify and the behavior that should be preserved. Checkly uses intent for root cause analysis across all check types. It is separate from `description` and does not replace executable assertions. Left unset, or set to `null`, the check has no intent.

> [!NOTE]
>
> Intent is used for [automatic repair](https://www.checklyhq.com/docs/resolve/automatic-check-repair.md) only for Browser and Multistep Checks.

The object accepts the following fields:

| Field | Type | Required | Description |
| - | - | - | - |
| `goal` | `string` | Yes | The outcome your check should verify. Must contain 1–2,000 characters after trimming. |
| `constraints` | `CheckIntentConstraint[]` | No | Outcomes and guardrails that refine the goal. Omitted constraints become an empty array. |

Each constraint has a required `type` and `statement`:

* `REQUIRED_OUTCOME`: an outcome the check must verify.
* `MUST_PRESERVE`: behavior or an assertion that should be preserved when repairing the check.

Each `statement` must contain 1–1,000 characters after trimming. You can specify at most 20 constraints of each type. The CLI trims leading and trailing whitespace from the goal and statements and rejects unknown fields.

For example, configure intent on a Browser Check:

```ts theme={null}
import { BrowserCheck } from "checkly/constructs"

new BrowserCheck("dashboard-intent", {
  name: "Authenticated dashboard",
  code: {
    entrypoint: "./dashboard.spec.ts",
  },
  intent: {
    goal: "Verify that authenticated users can open the dashboard.",
    constraints: [
      {
        type: "REQUIRED_OUTCOME",
        statement: "Authentication succeeds for a valid user.",
      },
      {
        type: "MUST_PRESERVE",
        statement: "Do not remove or weaken the authentication assertion.",
      },
    ],
  },
})
```

**aiAutoRepairEnabled** `boolean | null`

Requires Checkly CLI 9.4.0 or later. Set `true` to enable automatic repair or `false` to disable it. Left unset, or set to `null`, the check follows your account default.

You also need a valid check intent. See [Configure automatic repair](https://www.checklyhq.com/docs/resolve/automatic-check-repair.md#define-intent-with-monitoring-as-code) for a complete example and repair prerequisites.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.