Skip to content

Register a site

POST
/v1/sites
curl --request POST \
--url https://api.overwatch.weareheavy.dev/v1/sites \
--header 'Content-Type: application/json' \
--header 'x-api-key: <x-api-key>' \
--data '{ "rootUrl": "https://example.com", "cadenceMinutes": 1440, "a11yEnabled": true }'

Register a new site to monitor. The site’s hostname (derived from rootUrl) becomes the recursion whitelist for the crawler. The first crawl is scheduled to run immediately when a scanner app is on.

Five apps are toggled at creation: Broken Links (scannerEnabled, default on), Accessibility (a11yEnabled, default off), SEO (seoEnabled, default on - rides the same crawl), and Performance

  • Uptime (default on; both are inert until there is CrUX data / a monitor).

Requires an owner/admin session or an API key. A site-scoped API key cannot register sites (it can’t widen its own scope), and registration past the included site count fails with 403 unless overage billing is enabled — see the Quotas & usage guide.

Media typeapplication/json
object
rootUrl
required

The site’s root URL. Must be an http(s) URL; its hostname is the crawl whitelist.

string format: uri
cadenceMinutes

How often the site is automatically re-crawled, in minutes. Daily (1440) is the minimum; the default is weekly.

integer
default: 10080 >= 1440
maxPages

Maximum number of pages to crawl per run. Set at creation only — afterwards it is an operator-managed limit.

integer
default: 5000
maxConcurrency

Ceiling on concurrent requests to the origin. The crawler’s adaptive window slow-starts well below this and backs off on throttling; the ceiling only bounds how far it may ramp up. Clamped to [2, 200]. Set at creation only.

integer
default: 100 >= 2 <= 200
scannerEnabled

Install the Broken Links app (the dead-link crawl).

boolean
default: true
a11yEnabled

Install the Accessibility app (the rendered axe-core scan).

boolean
seoEnabled

Install the SEO app (on-page checks during the crawl).

boolean
default: true
a11yCadenceMinutes

The accessibility scan’s own cadence, in minutes. Defaults to monthly (43200) when the app is on; the scan runs over the crawl’s persisted page set on its own clock.

integer
>= 1440
performanceEnabled

Install the Performance app (CrUX sync + regression alerts).

boolean
default: true
uptimeEnabled

Install the Uptime app (monitors can then be registered).

boolean
default: true
Example
{
"rootUrl": "https://example.com",
"cadenceMinutes": 1440,
"a11yEnabled": true
}

Site created.

Media typeapplication/json
object
site
required

A monitored site, including its per-app toggles.

object
id
required
string format: uuid
tenant_id
required

The owning organization (tenant) id.

string
hostname
required

The hostname derived from root_url; the crawl whitelist.

string
root_url
required
string format: uri
cadence_minutes
required
integer
max_pages
required
integer
max_concurrency
required
integer
enabled
required

1 if the site is actively scheduled, 0 if disabled.

integer
Allowed values: 0 1
last_run_at
required

Epoch ms of the last run, or null.

integer | null
next_run_at
required

Epoch ms of the next scheduled run, or null.

integer | null
created_at
required

Epoch ms the site was registered.

integer
scanner_enabled
required

1 when the Broken Links app is installed. The shared crawl runs when any of it, the Accessibility app, or the SEO app is on.

integer
Allowed values: 0 1
a11y_enabled
required

1 when the Accessibility app is installed.

integer
Allowed values: 0 1
a11y_cadence_minutes
required

The accessibility scan’s own cadence; null falls back to cadence_minutes.

integer | null
a11y_next_run_at
required

Epoch ms the next standalone accessibility scan is due, or null.

integer | null
performance_enabled
required

1 when the Performance app (CrUX sync + regression alerts) is installed.

integer
Allowed values: 0 1
uptime_enabled
required

1 when the Uptime app is installed; 0 stops probing but keeps monitors.

integer
Allowed values: 0 1
seo_enabled
required

1 when the SEO app is installed (on-page checks extracted during the crawl).

integer
Allowed values: 0 1
crux_status

CrUX sync state: null = never checked, ok = data, no-data = not in the dataset.

string | null
crux_checked_at

Epoch ms the CrUX sync last ran for this site.

integer | null
exclude_paths
required

JSON-encoded array of glob patterns for internal paths never crawled.

string
strip_params
required

JSON-encoded array of query-parameter names dropped before crawling.

string
Example
{
"site": {
"enabled": 0,
"scanner_enabled": 0,
"a11y_enabled": 0,
"performance_enabled": 0,
"uptime_enabled": 0,
"seo_enabled": 0,
"exclude_paths": "[\"/drafts/*\"]",
"strip_params": "[\"utm_source\"]"
}
}

rootUrl is missing, not a valid URL, or not an http(s) URL.

Media typeapplication/json
object
error
required

A human-readable error message.

string
Example
{
"error": "rootUrl is required"
}

Missing or invalid credentials.

Media typeapplication/json
object
error
required

A human-readable error message.

string
Example
{
"error": "invalid api key"
}

The caller may not register sites: restricted member role, site-scoped API key, or the included site count is used up and overage billing is off.

Media typeapplication/json
object
error
required

A human-readable error message.

string
Example
{
"error": "your 5 included sites are in use — enable overage billing on the Billing page to add more"
}