CoreDash Uptime API and MCP Tools: Monitors and Checks

List, add, change and pause uptime monitors with your CoreDash API key, and read their checks over REST or MCP.

Arjen Karel Core Web Vitals Consultant
Arjen Karel - linkedin
Last update: 2026-10-20

Trusted by market leaders · Client results

fotocasahappyhorizonaleteiasnvvpnmarktplaatsperionsaturnmonarchloopearplugserasmusmckpnworkivanina careadevintadpg mediacomparewhowhatwearebaynestlemy work featured on web.devharvard

Uptime monitors over the CoreDash API

Read and change the uptime monitors of your CoreDash projects over REST, with the API key you already use for your RUM data. An AI agent reads them over MCP.

Quick start

  • Base URL https://app.coredash.app/api/uptime/monitors, JSON in and JSON out.
  • Header Authorization: Bearer cdk_your_key, with a project key or a master key.
  • First call: GET /api/uptime/monitors lists your monitors with their state and the uptime of the last 7 days.
curl https://app.coredash.app/api/uptime/monitors \
  -H "Authorization: Bearer cdk_your_key"

API keys for uptime monitors

The uptime endpoints take the keys of the CoreDash API and the Agency API.

KeyStarts withSeesA new monitor goes into
Project keycdk_The monitors of its own projectIts own project, always
Master keycdk_master_The monitors of every project you own or were invited toThe project you name in project_id, one you own

Make a project key on the Connect Your AI page in your project's sidebar: give it a name and click Generate API key. The same keys are in your project settings under API Keys (MCP). Only a project's owners can make them. A master key comes from the Agency API page in the sidebar, on agency accounts. Once a project has expired, its project key gets 401 on every call.

A guest on a project reads its monitors. Adding, changing, moving and deleting them needs a project you own.

The OAuth token of an AI connection such as Claude (mcp_at_) only reads. POST, PATCH and DELETE with it get 403.

Uptime endpoints

Method and pathWhat it doesReturns
GET /api/uptime/monitorsLists every monitor the key can see, sorted by name.200, { "monitors": [...] }, each with a summary
POST /api/uptime/monitorsAdds a monitor. The first check runs in the next round, at :00 or :30.201, { "monitor": {...} }
GET /api/uptime/monitors/:idOne monitor with its checks, newest first. ?limit= sets the number of checks: default 300, at most 2100.200, { "monitor", "summary", "checks", "rum" }
PATCH /api/uptime/monitors/:idChanges the fields you send and leaves the rest.200, { "monitor": {...} }
DELETE /api/uptime/monitors/:idDeletes the monitor and all its checks.200, { "deleted": true }

The origin IP and the header values are secrets. They come back from POST, PATCH and GET /api/uptime/monitors/:id. The list and the MCP tools leave origin_ip out and show every header value as ••••.

The monitor object

FieldMeaning
idThe monitor's id, for the :id in the paths.
name, urlThe name in the app and the URL that gets checked.
project_idThe CoreDash project the monitor belongs to.
pausedtrue while the monitor isn't checked.
expect_statusThe HTTP status that counts as up. Default 200.
origin_checktrue when an origin IP is set, so every round also checks the server itself.
origin_ipThe server's IP. Only in the answers that carry secrets.
headersThe extra request headers, [{ "name", "value" }].
statepending, up, failing, down, warn, blocked or paused. See the states table below.
last_check_at, last_up_atThe last round, and the last round that came back up.
down_sinceWhile down: the time of the first failed round. Otherwise null.
last_downThe last outage that ended, { "from", "to" }, or null.
check_requested_atSet when you add the monitor. The next round clears it.
lastThe last check per kind: edge and origin, each a check object. origin_is_cdn is true when the origin check answered with Cloudflare headers, so the IP you entered isn't your server.
cert_expiresWhen the HTTPS certificate your visitors get runs out.
created_atWhen the monitor was added.

The summary and rum fields

The list and the single monitor both carry a summary: rounds_7d and down_rounds_7d count the rounds of the last 7 days, uptime_7d is the percentage of those rounds without a down check, and recent holds the last 48 rounds, oldest first, each with the worst outcome of that round. A monitor without checks in the last 7 days has summary: null.

The single monitor also carries rum: the TTFB at p75 your real visitors got in the last 7 days, from the project's RUM data, to compare with the checker's ttfb_ms. It is null while the project has no RUM data.

GET /api/uptime/monitors/:id

curl "https://app.coredash.app/api/uptime/monitors/6ad68c7a844fad80b752fd16?limit=2" \
  -H "Authorization: Bearer cdk_your_key"
{
  "monitor": {
    "id": "6ad68c7a844fad80b752fd16",
    "name": "Checkout",
    "url": "https://www.example.com/checkout/",
    "project_id": "655f1f77bcf86cd799439011",
    "paused": false,
    "expect_status": 200,
    "origin_check": true,
    "origin_ip": "203.0.113.10",
    "headers": [{ "name": "X-Staging-Auth", "value": "k7Qp2vX9mR4tL8wZ" }],
    "state": "up",
    "last_check_at": "2026-10-20T08:00:09.000Z",
    "last_up_at": "2026-10-20T08:00:09.000Z",
    "down_since": null,
    "last_down": { "from": "2026-10-18T19:00:11.000Z", "to": "2026-10-18T20:00:10.000Z" },
    "check_requested_at": null,
    "last": {
      "edge": { "at": "2026-10-20T08:00:09.000Z", "server": "scan1", "mode": "edge", "outcome": "up", "status": 200, "ttfb_ms": 212, "total_ms": 388, "connect_ms": 14, "redirects": 0, "final_url": "https://www.example.com/checkout/", "error": null, "error_text": null, "cloudflare": true, "cache_status": "DYNAMIC" },
      "origin": { "at": "2026-10-20T08:00:09.000Z", "server": "scan1", "mode": "origin", "outcome": "up", "status": 200, "ttfb_ms": 640, "total_ms": 702, "connect_ms": 9, "redirects": 0, "final_url": "https://www.example.com/checkout/", "error": null, "error_text": null, "cloudflare": false, "cache_status": null },
      "origin_is_cdn": false
    },
    "cert_expires": "2027-01-02T23:59:59.000Z",
    "created_at": "2026-10-06T09:12:41.000Z"
  },
  "summary": {
    "rounds_7d": 336,
    "down_rounds_7d": 2,
    "uptime_7d": 99.4,
    "recent": [
      { "at": "2026-10-20T07:30:10.000Z", "outcome": "up" },
      { "at": "2026-10-20T08:00:09.000Z", "outcome": "up" }
    ]
  },
  "checks": [
    { "at": "2026-10-20T08:00:09.000Z", "server": "scan1", "mode": "edge", "outcome": "up", "status": 200, "ttfb_ms": 212, "total_ms": 388, "connect_ms": 14, "redirects": 0, "final_url": "https://www.example.com/checkout/", "error": null, "error_text": null, "cloudflare": true, "cache_status": "DYNAMIC" },
    { "at": "2026-10-20T08:00:09.000Z", "server": "scan1", "mode": "origin", "outcome": "up", "status": 200, "ttfb_ms": 640, "total_ms": 702, "connect_ms": 9, "redirects": 0, "final_url": "https://www.example.com/checkout/", "error": null, "error_text": null, "cloudflare": false, "cache_status": null }
  ],
  "rum": { "ttfb_p75": 1920, "rating": "poor", "period": "last 7 days" }
}

In the real answer, recent holds 48 rounds; this example shows the last two.

The check object and its outcomes

Every 30 minutes one round checks every monitor, from two servers in turn: scan1 at :00, scan2 at :30. A round always checks the URL the way visitors reach it, through DNS and your CDN (edge). With an origin IP it also checks your server directly (origin). The API has no call to check a monitor between rounds. Checks are kept for 30 days.

Every check sends the user agent CoreDash/1.0 (uptime; +https://www.coredash.app/bot). When the monitor's URL is on your project's own site (its host, with or without www, or a subdomain), the check also sends the header X-CoreDash-Bot with your project's secret value, from the CoreDash bot token tab in your project settings. A monitor on any other site gets no token. On a redirect the token follows the rule for the headers you set: it goes along only while the redirect stays on the monitor's host. A header of your own named X-CoreDash-Bot is dropped. The CoreDash bot page has more on both.

FieldMeaning
at, serverWhen the server reported the round, and which server ran it: scan1 or scan2. The checks of one round share the same at.
modeedge or origin.
outcomeup, down, blocked or warn.
statusThe HTTP status of the last answer, after redirects. null when nothing answered.
ttfb_ms, total_ms, connect_msTime to first byte and total time, both including redirects, and the time to connect on the first request.
redirects, final_urlThe number of redirects followed and the URL that answered last.
error, error_textWhy the check failed, as a value from the table below and as text.
cloudflare, cache_statusWhether the answer came through Cloudflare, and the CDN's cache header (cf-cache-status or x-cache).

How a check gets its outcome

OutcomeWhen
upThe status equals expect_status, unless that status is a 403, a 429 or 500 or higher: those count as blocked or down first.
downA status of 500 or higher, or an error: dns, connect, connect_timeout (no connection within 10 seconds), timeout (no full answer within 30 seconds), tls, redirects (more than 5) or network.
blockedA 403, a 429 or a Cloudflare challenge: a firewall stopped the checker. Never counted as downtime. Let CoreDash through your firewall.
warnAny other status, such as a 404 on a checkout after a release. Also invalid_ip and invalid_url: the URL or a redirect leads to a private or reserved address, or a redirect points at something that isn't a URL. The checker doesn't request those.

The worst outcome of a round's checks decides the monitor's state, from worst to best: down, blocked, warn, up.

Monitor states

stateIn the appMeans
pendingWaiting for first checkAdded; the first round hasn't run yet.
upUpThe last round got the expected status.
failingFailingOne round failed. One more makes it down.
downDownTwo failed rounds in a row, so both servers saw it fail.
warnUnexpected statusThe last round came back warn.
blockedBlockedA firewall stopped the checker.
pausedPausedNot checked until you set paused to false.

A monitor in a project whose subscription has ended keeps its settings and its last state. It isn't checked until the project is paid again.

Add, change and delete a monitor

POST /api/uptime/monitors

curl -X POST https://app.coredash.app/api/uptime/monitors \
  -H "Authorization: Bearer cdk_master_your_key" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://www.example.com/checkout/",
    "name": "Checkout",
    "project_id": "655f1f77bcf86cd799439011",
    "origin_ip": "203.0.113.10",
    "headers": [{ "name": "X-Staging-Auth", "value": "k7Qp2vX9mR4tL8wZ" }],
    "expect_status": 200
  }'
FieldRules
urlRequired on POST. A full http or https URL, without a username or password.
nameUp to 80 characters; longer names are cut off. Empty on POST: the host of the URL. Empty on PATCH: the old name stays, or the new host when the same PATCH sends a new url.
project_idRequired with a master key: a project you own, with a paid subscription or a running trial. A project key ignores it and uses its own project.
origin_ipA public IPv4 or IPv6 address of your server. Adds the origin check: straight to this IP, past DNS and the CDN. "" or null removes it.
headersUp to 5 extra request headers, [{ "name", "value" }]. Names: letters, numbers and dashes, up to 64 characters. Values: up to 256 characters, longer ones are cut off. On a redirect they go along only while it stays on the monitor's host, with or without www. A redirect to any other host, a subdomain included, gets none of them.
expect_statusThe status that counts as up, 100 to 599. Default 200. A 403, a 429 or any status of 500 or higher never counts as up.
pausedtrue stops the checks, false starts them again.

The answer is 201 with the new monitor, origin IP and header values included:

{
  "monitor": {
    "id": "6ad68c7a844fad80b752fd16",
    "name": "Checkout",
    "url": "https://www.example.com/checkout/",
    "project_id": "655f1f77bcf86cd799439011",
    "paused": false,
    "expect_status": 200,
    "origin_check": true,
    "origin_ip": "203.0.113.10",
    "headers": [{ "name": "X-Staging-Auth", "value": "k7Qp2vX9mR4tL8wZ" }],
    "state": "pending",
    "last_check_at": null,
    "last_up_at": null,
    "down_since": null,
    "last_down": null,
    "check_requested_at": "2026-10-20T09:12:41.000Z",
    "last": {},
    "cert_expires": null,
    "created_at": "2026-10-20T09:12:41.000Z"
  }
}

PATCH /api/uptime/monitors/:id

Send only the fields you change. headers replaces the whole list, so send every header you keep. This pauses a monitor:

curl -X PATCH https://app.coredash.app/api/uptime/monitors/6ad68c7a844fad80b752fd16 \
  -H "Authorization: Bearer cdk_your_key" \
  -H "Content-Type: application/json" \
  -d '{ "paused": true }'

With a master key, project_id moves the monitor, by the same rules as on POST.

DELETE /api/uptime/monitors/:id

curl -X DELETE https://app.coredash.app/api/uptime/monitors/6ad68c7a844fad80b752fd16 \
  -H "Authorization: Bearer cdk_your_key"

There is no undo. To stop the checks and keep the history, send { "paused": true } with PATCH.

Uptime API errors and limits

Errors come back as { "error": "..." } with one of these statuses:

StatusWhen
400The body breaks a rule. The error says which, see below.
401Unauthorized: no key, an unknown, revoked or expired key, or a key tied to an expired project.
403This token can only read. Use a CoreDash API key to change monitors.: a POST, PATCH or DELETE with an OAuth token (mcp_at_). A PATCH or DELETE on a monitor in a project where you are a guest gets 403 with Only the project's owners can change its monitors.
404Monitor not found: the id doesn't exist, or the key can't see that monitor.
405Method not allowed.
400 errorFix
Choose a project for this monitorSend project_id with a master key.
project not foundThe project_id isn't a project you own. Guests can't add monitors or move them there.
This project's subscription has endedAdding or moving a monitor needs a paid project or a running trial.
A project can have up to 25 monitorsDelete one first, or use another project.
A monitor must belong to a projectLeave project_id out of the PATCH, or send a project you own.
url can't contain a username or passwordFor basic auth, send an Authorization header in headers.
origin_ip is not an IP address, origin_ip must be a public IP addressUse the public address of the server itself.
url must be a full http or https URL, e.g. https://www.example.com/, url must start with http:// or https://, headers must be a list of {name, value}, at most 5 headers, "…" isn't a valid header name (letters, numbers and dashes only), expect_status must be an HTTP status codeFix the field the message names. Its rules are in the field table under POST.

Limits: 25 monitors per project, 5 extra headers per monitor, 2100 checks per GET of one monitor, and 30 days of check history.

Uptime MCP tools

The CoreDash MCP server at https://app.coredash.app/api/mcp has two uptime tools next to the RUM tools, plus list_projects for the projects your key reaches. All three only read. To add, change or delete a monitor, use the app or the REST endpoints above with a CoreDash API key. The tools need no project_id: a project key reads its own project, a master key or an OAuth connection such as Claude reads every project you own or were invited to.

ToolAsk your agentReturns
list_projects"Which sites can you see?"{ "projects": [...] } with project_id, name, url and role (owner or guest).
list_uptime_monitors"Is everything up?"{ "monitors": [...] }, with origin IP and header values masked.
get_uptime_monitor"Was the checkout down this week, and since when?"{ "monitor", "summary", "checks" }. Takes monitor_id and limit (default 100, at most 1000); summary gives rounds, down_rounds and uptime_pct over those checks.
curl -X POST https://app.coredash.app/api/mcp \
  -H "Authorization: Bearer cdk_your_key" \
  -H "Content-Type: application/json" \
  -d '{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "tools/call",
    "params": {
      "name": "get_uptime_monitor",
      "arguments": { "monitor_id": "6ad68c7a844fad80b752fd16", "limit": 48 }
    }
  }'

The answer is the JSON-RPC wrapper of the CoreDash API, with the result as a JSON string in result.content[0].text. An unknown monitor gives { "error": "Monitor not found" } there, and result.isError is true.

More on uptime and the CoreDash API

CoreDash Uptime API and MCP Tools: Monitors and Checks Core Web Vitals CoreDash Uptime API and MCP Tools: Monitors and Checks