Nodea — logo

Websites — API v1 and MCP | Nodea Documentation

The Websites module covers full management of monitored websites: listing, create, update, delete and operational actions (run now, pause, resume, mute, clone), plus test-run history, uptime statistics and maintenance windows. This document describes the REST API v1 layer (/api/v1) and the module's MCP tools.

Authentication and scopes

API v1 authenticates with a Passport personal access token via the Authorization: Bearer <token> header. Every route is guarded by a scope matching the operation tier:

  • monitoring:read — listing and detail (index, show, runs, uptime, maintenance-windows).
  • monitoring:write — create, update and non-destructive actions (run, pause, resume, mute, clone, maintenance-window create/delete).
  • monitoring:delete — permanently destroying the website.

The whole module is additionally gated by the Pennant flag features:websites — disabling it hides the module from both the web UI and the API. Rate limit: throttle:api-v1 = 240/min per token user.

Ownership and visibility

Row-level access is enforced by WebsitePolicy: view = owner or accepted FOREIGN share, manage = owner only. An id that exists but is not visible to the token yields 403 (policy); an unknown id yields 404 (route model binding). The run action is the exception: allowed on view (owner AND accepted share may trigger a re-check); the other state actions (pause/resume/mute/clone) require manage. Test parameters are masked — basic-auth passwords, credential-bearing headers and raw POST bodies never come back in cleartext (****+last-4 scheme), so even an accepted share never sees the owner's credentials.

API v1 — endpoints

MethodPathScopeDescription
GET/api/v1/websitesmonitoring:readList of websites (owned + accepted shares), paginated.
GET/api/v1/websites/{website}monitoring:readWebsite detail with tests; meta.can_manage.
GET/api/v1/websites/{website}/runsmonitoring:readTest-run history (TestRun), newest first.
GET/api/v1/websites/{website}/uptimemonitoring:readMonthly uptime aggregates from website_uptimes.
GET/api/v1/websites/{website}/maintenance-windowsmonitoring:readList of the website's maintenance windows.
POST/api/v1/websitesmonitoring:writeCreate a website with its test set. Returns 201.
PUT/PATCH/api/v1/websites/{website}monitoring:writeUpdate name/URL, upsert tests, sync notification groups and excluded run servers.
POST/api/v1/websites/{website}/runmonitoring:writeManually dispatch probes (HEALTH_CHECK/SSL/WHOIS). 202/422/503.
POST/api/v1/websites/{website}/pausemonitoring:writeIdempotent pause (sets paused_at).
POST/api/v1/websites/{website}/resumemonitoring:writeIdempotent resume (clears paused_at).
POST/api/v1/websites/{website}/mutemonitoring:writeToggle paused_at null↔now (silences notifications).
POST/api/v1/websites/{website}/clonemonitoring:writeClone the website for the token user. Returns 201.
POST/api/v1/websites/{website}/maintenance-windowsmonitoring:writeCreate a maintenance window. Returns 201.
DELETE/api/v1/websites/{website}/maintenance-windows/{maintenanceWindow}monitoring:writeDelete a maintenance window (scoped binding). Returns 204.
DELETE/api/v1/websites/{website}monitoring:deletePermanently delete the website (cascade). Returns 204.

GET /websites — query parameters

  • search (string, optional, max 255) — matched against name and URL.
  • status (enum: paused|healthy|unhealthy|skipped, optional).
  • sort (enum: name|url|created_at, default created_at).
  • direction (asc|desc).
  • per_page (int 1–100, default 20), page (int ≥1).

Response: a WebsiteResource collection — fields: id, name, url, status (paused→unhealthy→skipped→healthy), paused_at, ownership (owner|shared), tests[], created_at, updated_at. Each test: id, type (enum backing value), type_name, interval, state, state_name, parameters (masked), last_run.

POST/PATCH — body parameters

  • url (string, required, SafePublicUrl rule).
  • name (string, required, max 255).
  • intervals (object keyed by TestType backing value; value: seconds, 0–259200).
  • parameters (per-type object; optional — omitting a type keeps its stored config).
  • notificationGroupsId[] — must belong to the token user (otherwise 422).
  • excludedRunServersId[] — existing run_servers.id.

Test types (backing value): 1=HEALTH_CHECK, 2=SSL, 4=WHOIS, 16=TCP, 32=DNS, 64=PING, 128=SMTP, 256=POP3, 512=IMAP, 1024=UDP.

Error codes

  • 401 — missing/invalid token.
  • 403 — missing required scope or policy (existing, foreign resource without access).
  • 404 — unknown id.
  • 422 — validation (e.g. no runnable test on run, code no_runnable_test).
  • 503 — no healthy run server available to execute probes (code no_run_server_available).

Examples — API

List websites filtered by status

curl -s https://app.nodea.io/api/v1/websites?status=unhealthy&per_page=10 \
  -H "Authorization: Bearer $NODEA_TOKEN" \
  -H "Accept: application/json"

Create a website with a 60s health check

curl -s -X POST https://app.nodea.io/api/v1/websites \
  -H "Authorization: Bearer $NODEA_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Shop",
    "url": "https://shop.example.com",
    "intervals": { "1": 60 },
    "parameters": { "1": { "timeout": 10, "status_codes": "200" } }
  }'

Manually dispatch probes

curl -s -X POST https://app.nodea.io/api/v1/websites/{id}/run \
  -H "Authorization: Bearer $NODEA_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "test_id": 123 }'

MCP — tools

MCP tools share the auth and scope model with API v1 (Bearer + scope checked in ensureScope) and the features:websites flag (a tool on an inactive flag disappears from tools/list). Resource ids are UUIDs passed as strings. A missing and a foreign id raise the same error (no cross-tenant enumeration).

ToolScopeTypeDescription
websites-listmonitoring:readread-onlyList websites; filters search, status (paused/healthy/unhealthy), page, per_page (max 50).
website-getmonitoring:readread-onlyWebsite detail with tests. Param: id.
website-createmonitoring:writewriteCreate a website; name, url, tests[] (type/interval/parameters, min 1).
website-updatemonitoring:writeidempotentUpdate name/url + upsert tests[]. Owner only.
website-deletemonitoring:deletedestructivePermanent delete; requires confirm: true.
website-run-nowmonitoring:writewriteDispatch probes; optional test_type. Returns dispatched/skipped.
website-set-pausedmonitoring:writeidempotentPause/resume via paused: true|false (not a toggle).
website-runsmonitoring:readread-onlyRun history; test_type, page, per_page (max 50).
website-uptimemonitoring:readread-onlyMonthly uptime; months (default 12, max 60).
website-maintenance-windowsmonitoring:readread-onlyList maintenance windows with an active_now flag.
website-maintenance-window-createmonitoring:writewriteCreate a window; starts_at/ends_at (wall-clock in timezone), recurrence_type, weekdays.
website-maintenance-window-deletemonitoring:writedestructive (annotation)Delete a window by id. Scope stays write.

Example — MCP (JSON-RPC)

{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "website-run-now",
    "arguments": { "id": "9b1f...uuid", "test_type": 1 }
  }
}
{
  "jsonrpc": "2.0",
  "id": 2,
  "method": "tools/call",
  "params": {
    "name": "website-set-paused",
    "arguments": { "id": "9b1f...uuid", "paused": true }
  }
}