> ## Documentation Index
> Fetch the complete documentation index at: https://checkly-422f444a-simo-red-1015-maintenance-window-timezone.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Cover every endpoint with uptime monitors

> Turn a list of public pages into URL monitors, tell slow from down, and watch the certificate every one of them depends on, all from a few lines of code.

export const CopyPromptButton = ({label = "Copy setup prompt", targetId = "ai-setup-prompt"}) => {
  const [copied, setCopied] = useState(false);
  const handleCopy = async () => {
    try {
      const el = document.getElementById(targetId);
      const code = el?.querySelector("code");
      const text = code?.textContent || el?.textContent || "";
      await navigator.clipboard.writeText(text);
      setCopied(true);
      setTimeout(() => setCopied(false), 2000);
    } catch (err) {
      console.error("Failed to copy prompt:", err);
    }
  };
  return <button onClick={handleCopy} className="inline-flex items-center gap-2 px-5 py-3 rounded-lg font-semibold text-base
        border border-gray-200 dark:border-gray-700
        bg-white dark:bg-gray-800
        text-gray-800 dark:text-gray-200
        hover:bg-gray-50 dark:hover:bg-gray-700
        transition-colors cursor-pointer my-2">
      {copied ? <>
          <svg width="18" height="18" viewBox="0 0 16 16" fill="none">
            <path d="M13.3 4.3L6 11.6L2.7 8.3" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" />
          </svg>
          Copied!
        </> : <>
          <svg width="18" height="18" viewBox="0 0 16 16" fill="none">
            <rect x="5" y="5" width="9" height="9" rx="1.5" stroke="currentColor" strokeWidth="1.5" />
            <path d="M11 5V3.5C11 2.67 10.33 2 9.5 2H3.5C2.67 2 2 2.67 2 3.5V9.5C2 10.33 2.67 11 3.5 11H5" stroke="currentColor" strokeWidth="1.5" />
          </svg>
          {label}
        </>}
    </button>;
};

By the end of this guide, you have a URL monitor for every page a customer can land on, generated from one list, with thresholds that separate slow from down, and an SSL monitor that warns you two weeks before the certificate under all of them expires.

<Frame>
  <img src="https://mintcdn.com/checkly-422f444a-simo-red-1015-maintenance-window-timezone/dttTjQ9emJL9jpwK/images/guides/uptime-coverage/group.png?fit=max&auto=format&n=dttTjQ9emJL9jpwK&q=85&s=86667fc51927a52a10fb628289d09940" alt="A Checkly group page named Shop uptime with seven passing monitors: five URL monitors for the shop's pages, one for a deliberately slow page, and one SSL monitor, with run results from N. Virginia and Ireland" width="2400" height="2200" data-path="images/guides/uptime-coverage/group.png" />
</Frame>

To follow along without your own app, clone the [sample project](https://github.com/checkly/docs/tree/main/samples/guides/uptime-coverage). It monitors the [Danube demo shop](https://danube-web.shop) and one deliberately slow page on httpbin.org.

<Accordion title="Let your agent do it" icon="sparkles">
  To run this guide from your terminal or your coding agent, run `npx checkly init` in your project first. It installs the Checkly CLI and [Checkly Skills](/ai/skills) for your agent. Then paste the prompt below into Claude Code, Cursor, Codex, or any agent that supports skills. It builds the same setup as this guide, proves it with `npx checkly test --record`, and stops for your confirmation before `npx checkly deploy`.

  <div id="ai-setup-prompt">
    ```txt Prompt theme={null}
    Set up uptime monitoring for this project with Checkly so that every public page is covered from one list.

    Success criteria:
    1. Create `__checks__/group.ts` with a `CheckGroupV2` that runs in parallel from 2 locations, alerts after 1 failed run, and has retries disabled. Export a shared `responseTimes` object with `degradedResponseTime: 3000` and `maxResponseTime: 5000`.
    2. Ask me for the public pages of my site. Create `__checks__/pages.check.ts` with an array of `{ id, path }` entries and a loop that creates one `UrlMonitor` per entry, in the group, spreading `responseTimes`, following redirects, and asserting HTTP 200. Use the `id` in the logical ID so it stays stable when I reorder the list.
    3. Create `__checks__/certificate.check.ts` with an `SslMonitor` for my hostname in the same group, alerting 14 days before expiry.
    4. Tell me which of my pages need more than a status code, and why an API check would be the next step for those.
    5. Run `npx checkly test --record` and show me the session link.
    6. Show me `npx checkly deploy --preview` and wait for my confirmation before deploying.

    Explain each file you changed and why.
    ```
  </div>

  <CopyPromptButton />

  The steps below are what the agent does, in the open.
</Accordion>

## Step 1: Decide what every monitor shares

A shop has a handful of pages a customer can land on, and they all deserve the same treatment: the same locations, the same alert rule, the same idea of what "slow" means. Put those decisions in one place before you write a single monitor, so adding the tenth page costs the same as adding the first.

```ts __checks__/group.ts theme={null}
import { AlertEscalationBuilder, CheckGroupV2, RetryStrategyBuilder } from 'checkly/constructs'

// Every monitor in this guide joins this group and inherits its locations
// and alert policy. Retries are off so a failure shows on the first run.
export const shopGroup = new CheckGroupV2('shop-uptime', {
  name: 'Shop uptime',
  locations: ['us-east-1', 'eu-west-1'],
  runParallel: true,
  alertEscalationPolicy: AlertEscalationBuilder.runBasedEscalation(1),
  retryStrategy: RetryStrategyBuilder.noRetries(),
})

// Slow is not down: over 3 seconds is degraded, over 5 seconds fails.
export const responseTimes = {
  degradedResponseTime: 3000,
  maxResponseTime: 5000,
}
```

The group carries locations and the alert policy, because those belong to the group. Response-time thresholds belong to each monitor, so they live in an exported object that every monitor spreads in. Retries are off in this guide so you can see a failure land on the first run. For real monitoring, [Alerting that doesn't wake you up for nothing](/guides/alerting) shows how to turn them back on.

The project config sets the frequency and tag for everything the group does not cover:

```ts checkly.config.ts theme={null}
import { defineConfig } from 'checkly'
import { Frequency } from 'checkly/constructs'

export default defineConfig({
  projectName: 'Docs guide: Cover every endpoint with uptime monitors',
  logicalId: 'docs-guide-uptime-coverage',
  repoUrl: 'https://github.com/checkly/docs',
  checks: {
    activated: true,
    frequency: Frequency.EVERY_1M,
    tags: ['guide-uptime-coverage'],
    checkMatch: '**/__checks__/**/*.check.ts',
  },
  cli: { runLocation: 'us-east-1' },
})
```

## Step 2: Turn the list of pages into monitors

Now write down the pages. Not the monitors, the pages. The home page, a product page, the cart, the checkout, and the API the storefront calls. A loop turns each line into a URL monitor that inherits everything from Step 1.

```ts __checks__/pages.check.ts theme={null}
import { UrlAssertionBuilder, UrlMonitor } from 'checkly/constructs'
import { responseTimes, shopGroup } from './group'

// Every page a customer can land on. Add a line here to add a monitor.
// The id becomes part of the logical ID, so keep it stable when you reorder.
const pages = [
  { id: 'home', path: '/' },
  { id: 'book', path: '/books/1' },
  { id: 'cart', path: '/cart' },
  { id: 'checkout', path: '/checkout' },
  { id: 'books-api', path: '/api/books' },
]

for (const { id, path } of pages) {
  new UrlMonitor(`shop-${id}`, {
    name: `Shop ${path}`,
    group: shopGroup,
    ...responseTimes,
    request: {
      url: `https://danube-web.shop${path}`,
      followRedirects: true,
      assertions: [UrlAssertionBuilder.statusCode().equals(200)],
    },
  })
}
```

When a new page ships, someone adds one line and deploys. When a page is retired, someone deletes one line and the monitor goes with it. The `id` matters more than it looks: Checkly matches a monitor to its history by logical ID, so `shop-cart` keeps its uptime record no matter where it sits in the array. Generate IDs from array positions and a reorder silently creates five new monitors and deletes five old ones.

<Note>
  A URL monitor answers one question: did this URL return the status code you expect, fast enough? It does not read the response body. The Danube shop is a single-page app that answers 200 for any path, so a monitor for `/api/books` proves the API is reachable, not that it returns books. When you need to check the body, a header, or an authenticated request, that page gets an [API check](/detect/synthetic-monitoring/api-checks/overview) instead.
</Note>

## Step 3: Tell slow from down

Every monitor above spreads `responseTimes`, so every one already knows the difference between slow and down. To see where the lines sit, add a page that is always slow. httpbin.org waits one second before answering, and the network adds a little on top.

```ts __checks__/slow.check.ts theme={null}
import { UrlAssertionBuilder, UrlMonitor } from 'checkly/constructs'
import { responseTimes, shopGroup } from './group'

// A page that always takes about a second, so you can see where the
// degraded and failed thresholds sit relative to a real response time.
new UrlMonitor('shop-slow-page', {
  name: 'Slow page (httpbin delay)',
  group: shopGroup,
  ...responseTimes,
  request: {
    url: 'https://httpbin.org/delay/1',
    assertions: [UrlAssertionBuilder.statusCode().equals(200)],
  },
})
```

That page passes at just over a second. Past three seconds the result is degraded, which shows up in the app and reaches any alert channel that opts in to degraded results, but does not count as downtime. Past five seconds the run fails. The shop pages answer in under 300 milliseconds from both locations, so the same thresholds leave them room to slow down tenfold before anyone is bothered. Set thresholds from what you measure, then tighten them for the pages where speed is the product.

## Step 4: Watch the certificate underneath

Every monitor so far speaks HTTPS, and every HTTPS request starts with the same TLS handshake against the same certificate. A URL monitor fails the moment that certificate expires. That is one layer too late: you want to hear about it while there is still time to renew.

```ts __checks__/certificate.check.ts theme={null}
import { SslMonitor } from 'checkly/constructs'
import { shopGroup } from './group'

// Every HTTPS page above depends on this one certificate.
// Alert two weeks before it expires, while there is still time to renew.
new SslMonitor('shop-certificate', {
  name: 'Shop certificate',
  group: shopGroup,
  request: {
    hostname: 'danube-web.shop',
    port: 443,
    sslConfig: { alertDaysBeforeExpiry: 14 },
  },
})
```

The SSL monitor connects to the host, completes a handshake, and inspects what comes back: expiry, hostname match, chain trust, and the negotiated protocol. It fails when the certificate has fewer than 14 days left, and also when the chain is broken or the hostname does not match, which are the same failures a browser would show your users.

Test everything, then deploy:

```bash Terminal theme={null}
npx checkly test --record
```

```text Terminal theme={null}
Running 7 checks in us-east-1.

__checks__/certificate.check.ts
  ✔ Shop certificate (11ms)
__checks__/pages.check.ts
  ✔ Shop / (15ms)
  ✔ Shop /api/books (22ms)
  ✔ Shop /books/1 (16ms)
  ✔ Shop /cart (15ms)
  ✔ Shop /checkout (16ms)
__checks__/slow.check.ts
  ✔ Slow page (httpbin delay) (2s)

7 passed, 7 total
```

```bash Terminal theme={null}
npx checkly deploy
```

After the first runs, the certificate monitor shows a handshake from each location:

<Frame>
  <img src="https://mintcdn.com/checkly-422f444a-simo-red-1015-maintenance-window-timezone/dttTjQ9emJL9jpwK/images/guides/uptime-coverage/ssl.png?fit=max&auto=format&n=dttTjQ9emJL9jpwK&q=85&s=35292e7a3e30203942a173634952c9b6" alt="A Checkly SSL monitor detail page for Shop certificate, passing, running every minute from N. Virginia and Ireland, with a 9 millisecond and a 141 millisecond handshake" width="2400" height="1600" data-path="images/guides/uptime-coverage/ssl.png" />
</Frame>

## Verify it works

Break both layers on purpose. In `__checks__/slow.check.ts`, change the URL to `https://httpbin.org/status/503`, a page that always answers with a server error. In `__checks__/certificate.check.ts`, change the hostname to `expired.badssl.com`, a host that serves an expired certificate on purpose. Deploy.

Within a minute, the slow page monitor fails from both locations. Its error groups show both what happened and which assertion it broke: a 503 that was expected to equal 200.

<Frame>
  <img src="https://mintcdn.com/checkly-422f444a-simo-red-1015-maintenance-window-timezone/dttTjQ9emJL9jpwK/images/guides/uptime-coverage/verify-url.png?fit=max&auto=format&n=dttTjQ9emJL9jpwK&q=85&s=41b2084693145e29495eb98da09879de" alt="A Checkly URL monitor detail page for Slow page, failing, with failed runs from Ireland and N. Virginia after four passing ones, and error groups reading Expected 503 to be equal to 200 and HTTP 503 Service Unavailable" width="2400" height="1600" data-path="images/guides/uptime-coverage/verify-url.png" />
</Frame>

The certificate monitor fails too. There is no status code at this layer, so the error names the handshake step that broke:

<Frame>
  <img src="https://mintcdn.com/checkly-422f444a-simo-red-1015-maintenance-window-timezone/dttTjQ9emJL9jpwK/images/guides/uptime-coverage/verify-ssl.png?fit=max&auto=format&n=dttTjQ9emJL9jpwK&q=85&s=5f3dd5be119ac91aa6ada7e774b1a3b5" alt="A Checkly SSL monitor detail page for Shop certificate, failing, with failed runs from N. Virginia and Ireland after four passing ones, and one error group reading chain verification failed" width="2400" height="1600" data-path="images/guides/uptime-coverage/verify-ssl.png" />
</Frame>

Change both values back and deploy again. The next run from each location recovers both monitors. Nothing else in the group changed, because everything else was generated from the same list and the same defaults.

## Next

[Monitor the content your customers need to see](/guides/keyword-monitoring): a URL monitor proves a page answered, not what it shows. Assert that the text that sells is on the page, in the right place.

## Reference

* [URL monitors](/detect/uptime-monitoring/url-monitors/overview) and [SSL monitors](/detect/uptime-monitoring/ssl-monitors/overview)
* [API checks](/detect/synthetic-monitoring/api-checks/overview), for when a status code is not enough
* [`UrlMonitor`](/constructs/url-monitor), [`SslMonitor`](/constructs/ssl-monitor), and [`CheckGroupV2`](/constructs/check-group-v2)
* [Checkly Skills](/ai/skills)


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