APIMonitoringWebsite monitoring API
Website monitoring API. Uptime and 90-day site alerts over REST and MCP, included in your plan.
MarketingTracer checks each site's homepage every 30 minutes and keeps a 90-day log of outages, SSL and https problems, Core Web Vitals drops and SEO changes. Pull every site into your own status board or report with one key, or ask your AI assistant directly. We keep the monitoring back end running, so you don't have to worry about it.
Homepage uptime
Two servers check the homepage every 30 minutes and track uptime, 7-day TTFB, SSL expiry and incidents.
Site alerts feed
Ninety days of outages, SSL and https issues, Core Web Vitals drops and SEO page changes.
REST and MCP
Call the JSON endpoints directly or connect your AI assistant over MCP with the same key.
In every plan
Up to 60 read calls per minute across your sites, at no extra cost.
Endpoints and MCP tools for uptime and site alerts
The uptime endpoints read the 30-minute homepage checker, and alerts reads the site's 90-day event log. You can call every endpoint over POST with a JSON body or over GET with query parameters. Grab your personal API key on the MCP page in the app and send it as a Bearer token. Every call is read-only. Your key allows 60 calls a minute across REST and the MCP server together.
Anyone on a site, guests included, can call the uptime endpoints when Uptime is on for their role, while alerts.summary and alerts.feed need role user or higher and return HTTP 403 to guests.
| Endpoint | MCP tool | What it returns |
|---|---|---|
uptime.status | get_uptime_status | Current homepage state (up, failing, down, blocked, warn or pending), up_since, SSL expiry date, 7-day and 30-day uptime percentages, 7-day median TTFB and 30-day incident count. |
uptime.incidents | get_uptime_incidents | Every run of checks in the last 30 days that were not up, newest first, with UTC start and end, minutes, rounds, worst outcome, HTTP status or error, and the firewall flag. |
uptime.checks | get_uptime_checks | Every 30-minute homepage check from the last 7 days, newest first, with its UTC timestamp and outcome, plus TTFB in milliseconds when the site answered. |
alerts.summary | get_alerts_summary | Event totals over 90 days per kind (uptime, sitecheck, seo, cwv) plus up to five open problems going on right now. Needs role user or higher. |
alerts.feed | get_alerts_feed | Ninety days of site events, newest first, paged with cursor and filterable by kind, problems_only, search text q and lang (en or nl). Needs role user or higher. |
A real uptime.status call and response
Send your API key in the Authorization header and site_id in the JSON body, and the answer comes back under data and meta.
curl -X POST https://app.marketingtracer.com/rest/v1/uptime.status \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"site_id": "YOUR_SITE_ID"}'
{
"data": {
"enabled": true,
"url": "https://example-site.nl/",
"state": "up",
"up_since": "2026-10-27T23:30:03Z",
"down_since": null,
"last_check_at": "2026-10-31T23:00:08Z",
"certificate_expires_at": "2027-01-01T13:27:24Z",
"uptime_7d_pct": 100,
"uptime_30d_pct": 100,
"response_ms_median_7d": 209,
"incidents_30d": 1
},
"meta": {
"site_id": "YOUR_SITE_ID"
}
}
A morning status board across your client sites
When you look after client sites, you want one screen in the morning. Most mornings it stays green. A small script polls alerts.summary and uptime.status across every site in your account with the same API key.
An empty open array means nothing is broken. Ongoing homepage outages, blocked checks, invalid or expiring SSL certificates, missing https redirects and weekly Core Web Vitals drops all show up in that array with the UTC time they started. Pair it with up_since and certificate_expires_at from uptime.status, plus 30-day uptime and 7-day median TTFB for each row.
{
"data": {
"days": 90,
"total": 426,
"by_kind": {
"uptime": 0,
"sitecheck": 0,
"seo": 426,
"cwv": 0
},
"open": []
},
"meta": {
"site_id": "YOUR_SITE_ID"
}
}
Rule out an outage or a firewall block after a traffic dip
A client messages on Tuesday morning because traffic dipped or pages vanished from the audit. Check the site log first. An overnight host outage drops sessions, and a strict CDN rule can block crawlers for a full day. Your AI assistant calls get_uptime_incidents and sees the exact UTC window, the duration in minutes, the HTTP status or network error, and firewall: true when a challenge stepped in. Calling get_alerts_feed with kind: "seo" right after lists every URL that changed status code, title, H1 or meta description.
Every fix and outage in your client report
The site's 90-day log in alerts.feed records every event, whatever each person chose for mail or Slack.
At the end of the month, your reporting script pages through the log with cursor to pull every fixed scan issue alongside any outages. Pass problems_only: true to skip fixes and routine edits, or filter the rows by kind and search text q. Set lang to en or nl and the one-sentence text field comes back ready for an English or Dutch report.
{
"data": [
{
"id": "6ae67516bf737c062606238a",
"at": "2026-10-31T23:00:00Z",
"kind": "seo",
"type": "seo",
"rule": "status_change",
"label": "changed",
"text": "Now returns 200 (was 403)",
"url": "https://www.example-site.nl/pregnancy/work/risk-assessment",
"open": false
},
{
"id": "6ae5fa7c532767cc8602b59b",
"at": "2026-10-30T23:00:00Z",
"kind": "seo",
"type": "seo",
"rule": "status_change",
"label": "problem",
"text": "Now returns 410 (was 403)",
"url": "https://www.example-site.nl/pregnancy/fun/spa-treatment",
"open": false
}
],
"meta": {
"site_id": "YOUR_SITE_ID",
"next_cursor": "eyJwYyI6WzE3OTM0MDEyMDAwMDAs…",
"total": 2
}
}
Endpoints, arguments and field descriptions
Every endpoint is a POST with a JSON body; reading endpoints also take a GET with the same arguments in the query string. Send your API key as Authorization: Bearer YOUR_API_KEY. Every answer is {"data": …, "meta": {…}}: meta.site_id always, meta.next_cursor and meta.total for a list, meta.period where the endpoint covers a period. An error is {"error": {"code", "message"}} with the HTTP status: 400 invalid_argument, unknown_argument or missing_argument; 401 not_authenticated; 403 no_access or tool_off; 404 not_found; 429 rate_limited. The machine-readable version is openapi.json.
uptime.status
POST /rest/v1/uptime.status · MCP tool get_uptime_status
Returns the uptime monitor of one site: whether it is on, the checked address (the homepage), the current state, since when it is up or down, the last check, when the SSL certificate expires, the share of checks that were not down over 7 and 30 days, the median response time over 7 days and the number of incidents in 30 days. Values are null while the monitor has no checks yet.
Arguments
| Argument | Type | What it does |
|---|---|---|
site_id (required) | string | The site: its id from list_sites, or the id in the app’s address. |
Example request
curl -X POST https://app.marketingtracer.com/rest/v1/uptime.status \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"site_id":"YOUR_SITE_ID"}'
Example response · brabbels.com, 1 November 2026: up since the firewall rule was fixed on 28 October.
{
"data": {
"enabled": true,
"url": "https://example-site.nl/",
"state": "up",
"up_since": "2026-10-27T23:30:03Z",
"down_since": null,
"last_check_at": "2026-10-31T23:00:08Z",
"certificate_expires_at": "2027-01-01T13:27:24Z",
"uptime_7d_pct": 100,
"uptime_30d_pct": 100,
"response_ms_median_7d": 209,
"incidents_30d": 1
},
"meta": {"site_id": "YOUR_SITE_ID"}
}
Response fields · in data:
| Field | Type | What it is |
|---|---|---|
enabled | boolean | Whether the monitor is on. When false, the numbers are from before it was switched off, or null. |
url | string | The address that is checked: the homepage of the site. Redirects are followed. |
state | string | pending (no checks yet), up, failing (one failed round; down only after two in a row), down, blocked (our check is refused by a firewall) or warn. |
up_since | string or null | Since when the site is up without a break, ISO 8601 UTC; null when it is not up or not known. |
down_since | string or null | Since when the site is down, ISO 8601 UTC; null when it is not down. |
last_check_at | string or null | The last check, ISO 8601 UTC; null before the first. |
certificate_expires_at | string or null | When the SSL certificate of the address expires, ISO 8601 UTC; null when not known. |
uptime_7d_pct | number or null | Share of the checks in the last 7 days that were not down, 0-100 with two decimals; null without checks. |
uptime_30d_pct | number or null | The same over the last 30 days. |
response_ms_median_7d | integer or null | Median time to first byte of the checks in the last 7 days that answered, in milliseconds; null without one. |
incidents_30d | integer | Incidents in the last 30 days (see uptime.incidents). |
uptime.incidents
POST /rest/v1/uptime.incidents · MCP tool get_uptime_incidents
Returns the incidents of the last 30 days, newest first: each run of checks in a row that were not up, with when it started and ended, how long it took, the worst outcome and the HTTP status or error of that check. One failed round already counts here; the site is only marked down (and alerts are sent) after two in a row. An ongoing incident has no end.
Arguments
| Argument | Type | What it does |
|---|---|---|
site_id (required) | string | The site: its id from list_sites, or the id in the app’s address. |
Example request
curl -X POST https://app.marketingtracer.com/rest/v1/uptime.incidents \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"site_id":"YOUR_SITE_ID"}'
Example response · The firewall challenge of 26-27 October (403, blocked), before the Skip rule moved to the top of the Cloudflare rules.
{
"data": [
{
"started_at": "2026-10-26T21:22:37Z",
"ended_at": "2026-10-27T23:30:03Z",
"ongoing": false,
"minutes": 1567,
"outcome": "blocked",
"rounds": 54,
"http_status": 403,
"error": null,
"firewall": true
}
],
"meta": {"site_id": "YOUR_SITE_ID", "next_cursor": null, "total": 1}
}
Response fields · data is a list; each item has:
| Field | Type | What it is |
|---|---|---|
started_at | string | The first check that was not up, ISO 8601 UTC. |
ended_at | string or null | The first check that was up again, ISO 8601 UTC; null while it is ongoing. |
ongoing | boolean | Whether the incident is still going on. |
minutes | integer or null | From started_at to ended_at in minutes; null while it is ongoing. |
outcome | string | The worst outcome during the incident: up (answered 200), warn (answered with another status, or the address is invalid), blocked (403, 429 or a firewall challenge: our check is refused) or down (no answer, a timeout or a 5xx). |
rounds | integer | How many checks in a row were not up. |
http_status | integer or null | The HTTP status of the check with the worst outcome; null when there was no answer. |
error | string or null | Why that check got no answer: dns, connect, connect_timeout, timeout, tls, redirects (more than 5), invalid_url, invalid_ip or network; null when it answered. |
firewall | boolean | Whether a firewall or CDN challenge refused a check during the incident. |
uptime.checks
POST /rest/v1/uptime.checks · MCP tool get_uptime_checks
Returns every check of the last 7 days, newest first, with its outcome and response time (time to first byte). The response time is null when the check got no answer.
Arguments
| Argument | Type | What it does |
|---|---|---|
site_id (required) | string | The site: its id from list_sites, or the id in the app’s address. |
Example request
curl -X POST https://app.marketingtracer.com/rest/v1/uptime.checks \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"site_id":"YOUR_SITE_ID"}'
Example response · Shortened to two checks; the real answer had 246.
{
"data": [
{"at": "2026-10-31T22:30:06Z", "outcome": "up", "response_ms": 220},
{"at": "2026-10-31T22:00:07Z", "outcome": "up", "response_ms": 273}
],
"meta": {"site_id": "YOUR_SITE_ID", "next_cursor": null, "total": 246}
}
Response fields · data is a list; each item has:
| Field | Type | What it is |
|---|---|---|
at | string | When the check ran, ISO 8601 UTC. |
outcome | string | up (answered 200), warn (answered with another status, or the address is invalid), blocked (403, 429 or a firewall challenge: our check is refused) or down (no answer, a timeout or a 5xx). |
response_ms | integer or null | Time to first byte in milliseconds; null without an answer. |
alerts.feed
POST /rest/v1/alerts.feed · MCP tool get_alerts_feed
Returns everything that happened on one site in the last 90 days, newest first, one row per event: outages, SSL and https problems, Core Web Vitals that got worse, and every change the SEO scan found on a page (a new problem, a fixed one, a changed title, H1, meta description or status). The same rows as the Meldingen page, independent of who gets which alert by mail or Slack. Page through with cursor.
Arguments
| Argument | Type | What it does |
|---|---|---|
site_id (required) | string | The site: its id from list_sites, or the id in the app’s address. |
kind | one of uptime, sitecheck, seo, cwv | Only this kind: uptime, sitecheck, seo or cwv. Omit for all. |
problems_only | boolean, default | Only rows labelled problem, down or worse. |
q | string | Only rows whose page address (seo) or text (the other kinds) contains this. |
lang | one of en, nl | Language of text: en or nl. Defaults to en. |
limit | integer, 1 to 100, default 50 | Rows per page, 1-100. Defaults to 50. |
cursor | string | meta.next_cursor of the previous call, for the next page. |
Example request
curl -X POST https://app.marketingtracer.com/rest/v1/alerts.feed \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"site_id":"YOUR_SITE_ID","kind":"seo","limit":2}'
Example response · Two SEO rows; pages that came back after the firewall fix.
{
"data": [
{
"id": "6ae67516bf737c062606238a",
"at": "2026-10-31T23:00:00Z",
"kind": "seo",
"type": "seo",
"rule": "status_change",
"label": "changed",
"text": "Now returns 200 (was 403)",
"url": "https://www.example-site.nl/pregnancy/work/risk-assessment",
"open": false
},
{
"id": "6ae5fa7c532767cc8602b59b",
"at": "2026-10-30T23:00:00Z",
"kind": "seo",
"type": "seo",
"rule": "status_change",
"label": "problem",
"text": "Now returns 410 (was 403)",
"url": "https://www.example-site.nl/pregnancy/fun/spa-treatment",
"open": false
}
],
"meta": {
"site_id": "YOUR_SITE_ID",
"next_cursor": "eyJwYyI6WzE3OTM0MDEyMDAwMDAsIjZhZTVmYTdjNTMyNzY3Y2M4NjAyYjU5YiJdfQ==",
"total": 2
}
}
Response fields · data is a list; each item has:
| Field | Type | What it is |
|---|---|---|
id | string | The id of the event. |
at | string | When it happened, ISO 8601 UTC. For seo: when the scan saw it. |
kind | string | uptime (site down or our check blocked), sitecheck (SSL certificate invalid or expiring, http not redirecting to https), seo (a change or problem the SEO scan found on a page) or cwv (a Core Web Vital of the site got a worse rating than the week before). |
type | string | What happened: uptime_down, uptime_blocked, ssl_invalid, ssl_expiry, https_redirect, cwv_worse, or seo for a change from the SEO scan. |
rule | string or null | For seo: the scan rule or change (for example indexable, title_change, status_change); null for the other kinds. |
label | string | down (outage), problem, worse, fixed or changed. |
text | string | The event in one sentence, in lang. |
url | string or null | For seo: the page; null for the other kinds (they are about the whole site). |
open | boolean | Whether it is still going on (an outage that has not ended, a certificate that is still invalid). Always false for seo. |
alerts.summary
POST /rest/v1/alerts.summary · MCP tool get_alerts_summary
Returns how many events the site had per kind in the last 90 days (the rows of alerts.feed) and what is still going on now: an outage, a blocked check, an SSL or https problem, at most 5, newest first.
Arguments
| Argument | Type | What it does |
|---|---|---|
site_id (required) | string | The site: its id from list_sites, or the id in the app’s address. |
lang | one of en, nl | Language of text: en or nl. Defaults to en. |
Example request
curl -X POST https://app.marketingtracer.com/rest/v1/alerts.summary \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"site_id":"YOUR_SITE_ID"}'
Example response · Nothing open; 426 SEO changes in 90 days.
{
"data": {
"days": 90,
"total": 426,
"by_kind": {"uptime": 0, "sitecheck": 0, "seo": 426, "cwv": 0},
"open": []
},
"meta": {"site_id": "YOUR_SITE_ID"}
}
Response fields · in data:
| Field | Type | What it is |
|---|---|---|
days | integer | The period counted, in days (90). |
total | integer | Events of all kinds together. |
by_kind | object | Events per kind. |
by_kind.uptime | integer | Outages and blocked checks. |
by_kind.sitecheck | integer | SSL and https problems. |
by_kind.seo | integer | Changes the SEO scan found. |
by_kind.cwv | integer | Core Web Vitals that got worse. |
open | array | What is still going on, newest first; empty when nothing is. |
open[].kind | string | uptime, sitecheck or cwv. |
open[].type | string | uptime_down, uptime_blocked, ssl_invalid, ssl_expiry, https_redirect or cwv_worse. |
open[].text | string | In one sentence, in lang. |
open[].since | string | When it started, ISO 8601 UTC. |
White-label website monitoring API. On your own domain, one key for every client site.
The whole dashboard is white label, so the REST API and the MCP server answer on your custom domain under your agency's name. One personal API key works across every client site in your account. You decide whether your clients also get the API and the MCP.
Free 14-day trial
MarketingTracer smart A.I. tool shows you what you need to rank. Then we'll help you get it done.
- No credit card required
- No installation needed
- No strings attached
FAQ
Something else? Ask us.
How often does the uptime monitor check a site, and when is it marked down?
Two servers check the site's homepage every 30 minutes in turn and follow redirects. A single failed round sets state to failing in uptime.status and opens a row in uptime.incidents. MarketingTracer marks the site down and logs an outage in alerts.feed only after two failed checks in a row. You can read 7 days of checks in uptime.checks and 30 days of incidents in uptime.incidents.
Why does an uptime check or incident show blocked?
A firewall or CDN challenge refused our check, for example with HTTP 403 or 429. On uptime.incidents, that sets outcome to blocked and firewall to true. Every uptime check and SEO scan identifies itself with the MarketingTracer user agent and sends a per-site secret in the X-SEO-Crawler header. Team members with role user or higher can copy that secret and ready-made Cloudflare Skip or AWS WAF Allow rules under Site settings in the app. Guests cannot open those settings.
Who can read uptime and alerts through the API and MCP?
Your personal API key inherits your role on each site in your account. Any member on a site, including a guest, can call the three uptime endpoints when Uptime is on for their role. Uptime is on by default, and admins can switch it off per role. Calling alerts.summary or alerts.feed needs role user or higher on that site, so guests get HTTP 403 (no_access).
Does alerts.feed depend on my email or Slack notification settings?
No. Both alerts.feed and alerts.summary read the site's 90-day event log directly, so muting Slack or turning email alerts off changes nothing in the API. Each alerts.feed request returns up to 100 events (50 by default), newest first, with meta.next_cursor to fetch the next page.
Which site events go into the alerts feed?
The feed records four kinds of events. An uptime row logs a homepage outage after two failed checks, or a blocked check. A sitecheck row flags an invalid or expiring SSL certificate or a missing https redirect, and cwv flags a Core Web Vital that dropped a weekly rating. Each seo row records a new or fixed scan issue or a changed title, H1, meta description or HTTP status, along with the page url. Outages and other site-wide problems keep open: true while they are still going on, and open is always false for seo. Search Console or GA4 traffic drops do not create rows in alerts, and neither do rank changes or lost links.
Can I turn the uptime monitor on or edit alert settings through the API?
No. Every public endpoint and MCP tool is read-only. Someone with edit rights switches the monitor on once under Uptime in the app, and email or Slack delivery stays in the app as well. Before the monitor is switched on for a site, uptime.status returns enabled: false. Right after you turn it on, state shows pending until the first 30-minute check finishes.
What is the rate limit, and does the API cost extra?
Each personal API key allows 60 calls per minute across the REST API and the MCP server together. Both come in every MarketingTracer plan at no extra cost. See pricing for the plans, or download the OpenAPI schema to generate a client.