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

# API Check Construct

> Learn how to configure API Checks with the Checkly CLI.

<Tip>
  Learn more about API Checks in [the API Checks overview](/detect/synthetic-monitoring/api-checks/overview).
</Tip>

Use API Checks to monitor HTTP endpoints, REST APIs, GraphQL APIs, and other HTTP-based services. The examples below show how to configure monitoring for different types of API endpoints.

<Accordion title="Prerequisites">
  Before creating API Checks, ensure you have:

  * An initialized Checkly CLI project
  * URLs or HTTP endpoints you want to monitor
  * Understanding of HTTP status codes and response behavior
  * Network access to the URLs you want to monitor

  For additional setup information, see [CLI overview](/cli/overview).
</Accordion>

<CodeGroup>
  ```ts Basic Example theme={null}
  import { ApiCheck } from "checkly/constructs"

  new ApiCheck("hello-api-1", {
    name: "Hello API Check",
    description: "Verifies the `/hello` endpoint returns a **successful** response.",
    request: {
      method: "GET",
      url: "https://api.checklyhq.com/hello",
    },
  })
  ```

  ```ts Advanced Example theme={null}
  import { ApiCheck, AssertionBuilder, Frequency } from "checkly/constructs"

  new ApiCheck("advanced-api-check", {
    name: "Advanced API Check",
    description: "User creation succeeds (201) with valid ID.",
    activated: true,
    frequency: Frequency.EVERY_5M,
    locations: ["us-east-1", "eu-west-1"],
    tags: ["api", "critical"],
    maxResponseTime: 10000,
    degradedResponseTime: 5000,
    request: {
      method: "POST",
      url: "https://api.example.com/users",
      headers: [
        { key: "Content-Type", value: "application/json" },
        { key: "Authorization", value: "Bearer {{API_TOKEN}}" },
      ],
      body: JSON.stringify({ name: "Test User" }),
      assertions: [
        AssertionBuilder.statusCode().equals(201),
        AssertionBuilder.jsonBody("$.id").notEmpty(),
        AssertionBuilder.headers(
          "strict-transport-security",
          "max-age=(\\d+)"
        ).greaterThan(10000),
      ],
    },
  })
  ```
</CodeGroup>

## Configuration

The API Check configuration consists of specific API Check options and inherited general check options.

<Tabs>
  <Tab title="API Check">
    | Parameter              | Type      | Required | Default | Description                                                               |
    | ---------------------- | --------- | -------- | ------- | ------------------------------------------------------------------------- |
    | `request`              | `object`  | ✅        | -       | HTTP request configuration object                                         |
    | `degradedResponseTime` | `number`  | ❌        | `10000` | Response time threshold in milliseconds for degraded status               |
    | `maxResponseTime`      | `number`  | ❌        | `20000` | Maximum response time in milliseconds before marking as failed            |
    | `shouldFail`           | `boolean` | ❌        | `false` | Whether a failure should count as a pass (status 400+ reported as passed) |
    | `setupScript`          | `object`  | ❌        | -       | Script to run before the API Check execution                              |
    | `tearDownScript`       | `object`  | ❌        | -       | Script to run after the API Check execution                               |
  </Tab>

  <Tab title="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       |
    | `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                                   |
    | `privateLocations`      | `string[]`              | ❌        | `[]`    | Array of Private Location slugs                                         |
    | `retryStrategy`         | `RetryStrategy`         | ❌        | -       | Strategy for configuring retries                                        |
    | `runtimeId`             | `string`                | ❌        | -       | The ID of the runtime to use                                            |
    | `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 |
  </Tab>
</Tabs>

### `ApiCheck` Options

<ResponseField name="request" type="object" required>
  The HTTP request configuration that defines the API endpoint to monitor. This is the core component of any API Check.

  **Usage:**

  ```ts theme={null}
  request: {
    method: 'GET',
    url: 'https://api.example.com/users'
  }
  ```

  **Parameters:**

  | Parameter         | Type      | Required | Default | Description                                                                         |
  | ----------------- | --------- | -------- | ------- | ----------------------------------------------------------------------------------- |
  | `method`          | `string`  | ✅        | -       | HTTP method: `GET` \| `POST` \| `PUT` \| `PATCH` \| `HEAD` \| `DELETE` \| `OPTIONS` |
  | `url`             | `string`  | ✅        | -       | The target URL for the HTTP request                                                 |
  | `assertions`      | `array`   | ❌        | `[]`    | Response assertions using `AssertionBuilder`                                        |
  | `basicAuth`       | `object`  | ❌        | -       | Basic auth credentials: `{ username, password }`                                    |
  | `body`            | `string`  | ❌        | -       | HTTP request body content                                                           |
  | `bodyType`        | `string`  | ❌        | `NONE`  | Body type: `JSON` \| `FORM` \| `RAW` \| `GRAPHQL` \| `NONE`                         |
  | `followRedirects` | `boolean` | ❌        | `true`  | Whether to automatically follow 30x redirects                                       |
  | `headers`         | `array`   | ❌        | `[]`    | Array of `{ key, value }` objects for HTTP headers                                  |
  | `skipSSL`         | `boolean` | ❌        | `false` | Whether to skip SSL certificate validation                                          |
  | `queryParameters` | `array`   | ❌        | `[]`    | Array of `{ key, value }` objects for query parameters                              |

  **Examples:**

  <CodeGroup>
    ```ts REST API theme={null}
    request: {
      method: "GET",
      url: "https://api.example.com/users",
      headers: [
        { key: "Authorization", value: "Bearer {{API_TOKEN}}" },
        { key: "Content-Type", value: "application/json" },
      ],
      assertions: [
        AssertionBuilder.statusCode().equals(200),
        AssertionBuilder.jsonBody("$.length").greaterThan(0),
        AssertionBuilder.responseTime().lessThan(1000),
      ],
    },
    ```

    ```ts GraphQL API theme={null}
    request: {
      method: "POST",
      url: "https://api.example.com/graphql",
      headers: [{ key: "Content-Type", value: "application/json" }],
      body: JSON.stringify({
        query: `
        query GetUser($id: ID!) {
          user(id: $id) {
            id
            name
            email
          }
        }
      `,
        variables: { id: "1" },
      }),
      assertions: [
        AssertionBuilder.statusCode().equals(200),
        AssertionBuilder.jsonBody("$.data.user.id").equals("1"),
        AssertionBuilder.jsonBody("$.errors").isEmpty(),
      ],
    },
    ```

    ```ts Form POST theme={null}
    request: {
      method: "POST",
      url: "https://httpbin.org/post",
      headers: [
        { key: "Content-Type", value: "application/x-www-form-urlencoded" },
      ],
      body: "name=John+Doe&email=john%40example.com",
      assertions: [
        AssertionBuilder.statusCode().equals(200),
        AssertionBuilder.jsonBody("$.form.name").equals("John Doe"),
      ],
    },
    ```

    ```ts API with Authentication theme={null}
    request: {
      method: "GET",
      url: "https://api.example.com/protected-resource",
      basicAuth: {
        username: "admin",
        password: "{{SECRET_PASSWORD}}",
      },
      assertions: [
        AssertionBuilder.statusCode().equals(200),
        AssertionBuilder.headers("x-rate-limit-remaining").greaterThan(0),
      ],
    },
    ```
  </CodeGroup>

  **Use cases**: HTTP endpoint monitoring, REST API testing, GraphQL API validation, authentication testing.
</ResponseField>

<ResponseField name="degradedResponseTime" type="number" default="10000">
  Response time threshold in milliseconds for marking the check as degraded. This provides an early warning before the check fails completely.

  **Usage:**

  ```ts highlight={3} theme={null}
  new ApiCheck("performance-check", {
    name: "Performance Monitoring",
    degradedResponseTime: 2000, // Warning at 2 seconds
    maxResponseTime: 5000, // Failure at 5 seconds
    request: {
      method: "GET",
      url: "https://api.example.com/users",
    },
  })
  ```

  **Use cases**: Performance alerting, SLA monitoring, gradual degradation detection.
</ResponseField>

<ResponseField name="maxResponseTime" type="number" default="20000">
  Maximum response time in milliseconds before marking the check as failed. This sets the absolute threshold for check failure based on response time.

  **Usage:**

  ```ts highlight={3} theme={null}
  new ApiCheck("timeout-check", {
    name: "API Timeout Check",
    maxResponseTime: 5000, // Fail if response takes longer than 5 seconds
    request: {
      method: "GET",
      url: "https://api.example.com/slow-endpoint",
    },
  })
  ```

  **Use cases**: Performance monitoring, SLA compliance, timeout management.
</ResponseField>

<ResponseField name="shouldFail" type="boolean">
  Whether a failure should count as a pass. When set to `true`, HTTP status codes 400 and above are reported as passed instead of failed.

  **Usage:**

  ```ts highlight={3} theme={null}
  new ApiCheck("negative-test", {
    name: "Test Error Handling",
    shouldFail: true, // Expect this to fail
    request: {
      method: "GET",
      url: "https://httpbin.org/status/403",
    },
  })
  ```

  **Examples:**

  <CodeGroup>
    ```ts Error Testing theme={null}
    new ApiCheck("error-handling-test", {
      name: "Error Handling Test",
      shouldFail: true, // We expect 4xx/5xx responses
      request: {
        method: "POST",
        url: "https://api.example.com/protected",
        // No auth headers - should return 401
        assertions: [AssertionBuilder.statusCode().equals(401)],
      },
    })
    ```

    ```ts Rate Limit Testing theme={null}
    new ApiCheck("rate-limit-test", {
      name: "Rate Limit Behavior",
      shouldFail: true, // Expecting 429 Too Many Requests
      request: {
        method: "GET",
        url: "https://api.example.com/rate-limited-endpoint",
        assertions: [
          AssertionBuilder.statusCode().equals(429),
          AssertionBuilder.headers("retry-after").isNotNull(),
        ],
      },
    })
    ```
  </CodeGroup>

  **Use cases**: Negative testing, error handling validation, security testing.
</ResponseField>

<ResponseField name="setupScript" type="object">
  Script to run before the API Check execution. Useful for setting up test data or authentication tokens.

  **Usage:**

  <CodeGroup>
    ```ts File Reference highlight={3-5} theme={null}
    new ApiCheck("api-with-setup", {
      name: "API with Setup Script",
      setupScript: {
        entrypoint: path.join(__dirname, "scripts/api-setup.ts"),
      },
      request: {
        method: "GET",
        url: "https://api.example.com/users",
      },
    })
    ```

    ```ts Inline Script highlight={3-8} theme={null}
    new ApiCheck('inline-setup', {
      name: 'API with Inline Setup',
      setupScript: {
        content: `
          const token = await getToken()
          request.headers['Authorization'] = \`Bearer \${token}\`
        `
      },
      request: {
        url: 'https://api.example.com/users'
      }
    })
    ```
  </CodeGroup>

  **Parameters:**

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

  <Info>
    You must provide either `entrypoint` or `content`, but not both.
  </Info>

  <Tip>Learn more about writing setup and teardown scripts in [the setup and teardown scripts documentation](/detect/synthetic-monitoring/api-checks/setup-and-teardown).</Tip>

  **Use cases**: Test data setup, authentication preparation, environment configuration.
</ResponseField>

<ResponseField name="tearDownScript" type="object">
  Script to run after the API Check execution. Useful for cleaning up test data or resources.

  **Usage:**

  <CodeGroup>
    ```ts File Reference highlight={3-5} theme={null}
    new ApiCheck("api-with-teardown", {
      name: "API with Teardown Script",
      tearDownScript: {
        entrypoint: path.join(__dirname, "scripts/api-teardown.ts"),
      },
      request: {
        method: "GET",
        url: "https://api.example.com/users",
      },
    })
    ```

    ```ts Inline Script highlight={3-9} theme={null}
    new ApiCheck("inline-teardown", {
      name: "API with Inline Teardown",
      tearDownScript: {
        content: `
          // Clean up test data
          console.log('Cleaning up test resources');
          // Cleanup logic here
        `,
      },
      request: {
        method: "GET",
        url: "https://api.example.com/users",
      },
    })
    ```
  </CodeGroup>

  **Parameters:**

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

  <Info>
    You must provide either `entrypoint` or `content`, but not both.
  </Info>

  <Tip>Learn more about writing setup and teardown scripts in [the setup and teardown scripts documentation](/detect/synthetic-monitoring/api-checks/setup-and-teardown).</Tip>

  **Use cases**: Test data cleanup, resource cleanup, logging and reporting.
</ResponseField>

### `ApiCheck` Assertions

To define `assertions` for the `request` of an `ApiCheck` you should use the `AssertionBuilder`. The following sources are available for API check assertions:

* `statusCode()`: Assert the HTTP status code for the HTTP request, e.g. 200 or 404
* `jsonBody(property?)`: Assert the JSON response body. The property argument accepts a [JSON path expression](/detect/assertions/#json-responses-with-json-path)
* `textBody()`: Assert the body as raw text
* `headers(propery?, regex?)`: Assert a set of response headers, takes the header name as the property argument and a regex to tease out a string from the header value
* `responseTime()`: Assert the total response time of the HTTP request

Learn more in our docs on [Assertions](/detect/assertions).

**Assertion Examples**

* Asserting an HTTP status code

```ts theme={null}
AssertionBuilder.statusCode().equals(200)
// Equivalent to:
{ source: 'STATUS_CODE', comparison: 'EQUALS', target: '200' }
```

* Asserting a part of a JSON response body using a JSON path expression

```ts theme={null}
AssertionBuilder.jsonBody('$.data').greaterThan(2000),
// Equivalent to:
{ source: 'JSON_BODY', property: '$.data', comparison: 'GREATER_THAN', target: '2000' }
```

* Asserting the value of a part of an HTTP response header. Note that you can pass in a regex as the second argument

```ts theme={null}
AssertionBuilder.headers('strict-transport-security', 'max-age=(\\d+)').greaterThan(10000),
// Equivalent to:
{ source: 'HEADERS', regex: 'max-age=(\d+)', property: 'strict-transport-security', comparison: 'GREATER_THAN', target: '10000' }
```

## Examples

<CodeGroup>
  ```ts REST API Check theme={null}
  new ApiCheck("users-api-check", {
    name: "Users API Check",
    maxResponseTime: 5000,
    degradedResponseTime: 2000,
    request: {
      method: "GET",
      url: "https://api.example.com/users",
      headers: [
        { key: "Authorization", value: "Bearer {{API_TOKEN}}" },
        { key: "Content-Type", value: "application/json" },
      ],
      assertions: [
        AssertionBuilder.statusCode().equals(200),
        AssertionBuilder.jsonBody("$.users.length").greaterThan(0),
        AssertionBuilder.responseTime().lessThan(1000),
      ],
    },
  })
  ```

  ```ts GraphQL API Check theme={null}
  new ApiCheck("graphql-api-check", {
    name: "GraphQL API Check",
    request: {
      method: "POST",
      url: "https://api.example.com/graphql",
      headers: [{ key: "Content-Type", value: "application/json" }],
      body: JSON.stringify({
        query: `
          query GetUser($id: ID!) {
            user(id: $id) {
              id
              name
              email
            }
          }
        `,
        variables: { id: "1" },
      }),
      assertions: [
        AssertionBuilder.statusCode().equals(200),
        AssertionBuilder.jsonBody("$.data.user.id").equals("1"),
        AssertionBuilder.jsonBody("$.errors").isEmpty(),
      ],
    },
  })
  ```

  ```ts Form Submission Check theme={null}
  new ApiCheck("form-api-check", {
    name: "Form Submission Check",
    request: {
      method: "POST",
      url: "https://httpbin.org/post",
      headers: [
        { key: "Content-Type", value: "application/x-www-form-urlencoded" },
      ],
      body: "name=John+Doe&email=john%40example.com",
      assertions: [
        AssertionBuilder.statusCode().equals(200),
        AssertionBuilder.jsonBody("$.form.name").equals("John Doe"),
      ],
    },
  })
  ```

  ```ts Authenticated API Check theme={null}
  new ApiCheck("protected-api-check", {
    name: "Protected API Check",
    request: {
      method: "GET",
      url: "https://api.example.com/protected-resource",
      basicAuth: {
        username: "admin",
        password: "{{SECRET_PASSWORD}}",
      },
      assertions: [
        AssertionBuilder.statusCode().equals(200),
        AssertionBuilder.headers("x-rate-limit-remaining").greaterThan(0),
      ],
    },
  })
  ```
</CodeGroup>

<Warning>
  When using environment variables in your requests (like `{{API_TOKEN}}`), make sure [they are properly configured in your project or check group settings](/platform/variables).
</Warning>
