| title | API Check Construct |
|---|---|
| description | Learn how to configure API Checks with the Checkly CLI. |
| sidebarTitle | API Check |
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.
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.
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",
},
})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),
],
},
})The API Check configuration consists of specific API Check options and inherited general check options.
| 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 |
| 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 |
Usage:
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 |
treatResponseBodyAsText |
boolean |
❌ | false |
Feature-flagged support override for known text responses served with a binary Content-Type header |
queryParameters |
array |
❌ | [] |
Array of { key, value } objects for query parameters |
Examples:
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),
],
},request: {
method: "GET",
url: "https://api.example.com/status",
treatResponseBodyAsText: true,
assertions: [
AssertionBuilder.statusCode().equals(200),
AssertionBuilder.textBody().contains("OK"),
],
},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(),
],
},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"),
],
},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),
],
},Use cases: HTTP endpoint monitoring, REST API testing, GraphQL API validation, authentication testing.
Response time threshold in milliseconds for marking the check as degraded. This provides an early warning before the check fails completely.Usage:
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.
Maximum response time in milliseconds before marking the check as failed. This sets the absolute threshold for check failure based on response time.Usage:
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.
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:
new ApiCheck("negative-test", {
name: "Test Error Handling",
shouldFail: true, // Expect this to fail
request: {
method: "GET",
url: "https://httpbin.org/status/403",
},
})Examples:
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)],
},
})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(),
],
},
})Use cases: Negative testing, error handling validation, security testing.
Script to run before the API Check execution. Useful for setting up test data or authentication tokens.Usage:
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",
},
})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'
}
})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 |
Learn more about writing setup and teardown scripts in the setup and teardown scripts documentation.
Use cases: Test data setup, authentication preparation, environment configuration.
Script to run after the API Check execution. Useful for cleaning up test data or resources.Usage:
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",
},
})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",
},
})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 |
Learn more about writing setup and teardown scripts in the setup and teardown scripts documentation.
Use cases: Test data cleanup, resource cleanup, logging and reporting.
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 404jsonBody(property?): Assert the JSON response body. The property argument accepts a JSON path expressiontextBody(): Assert the body as raw textheaders(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 valueresponseTime(): Assert the total response time of the HTTP request
Learn more in our docs on Assertions.
Assertion Examples
- Asserting an HTTP status code
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
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
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' }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),
],
},
})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(),
],
},
})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"),
],
},
})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),
],
},
})