Vitals Clock Vitals Clock

Vitals Clock REST API

Manage watched URLs and read Core Web Vitals scores from your own scripts. JSON over HTTPS.

Authentication

Create a key in Settings. It is shown once; we store only a hash. Send it as a bearer token:

curl -H "Authorization: Bearer vcl_..." https://www.vitalsclock.com/api/v1/monitors

Revoke a key in Settings at any time. Keys act on the account they were created in.

Rate limits

Keep to 60 requests per minute per key. Every response carries X-RateLimit-Limit, X-RateLimit-Remaining and X-RateLimit-Reset. Over the limit you may get 429 with Retry-After; back off and retry.

Endpoints

MethodPathWhat it does
GET/api/v1/monitorsList URLs with the latest lab score.
POST/api/v1/monitorsAdd a URL. Body {"hostname": "https://example.com/pricing"}. Returns 201, 402 over the plan limit, or 409 if it already exists.
GET/api/v1/monitors/{id}One URL.
GET/api/v1/monitors/{id}/checksThe last 50 checks.
POST/api/v1/monitors/{id}/checkRun a check now and return the result.
DELETE/api/v1/monitors/{id}Remove a URL. Returns 204.
POST/api/vitals/checkAnonymous check. Body {"url": "https://example.com/pricing"}.
POST/api/vitals/bulkAnonymous bulk check. Body {"urls": ["https://a.example/", "https://b.example/"]}, up to five.

URL object

{
  "id": "...", "hostname": "https://example.com/pricing", "port": 443, "paused": false,
  "status": "ok" | "problem" | "pending", "error_code": null,
  "days_remaining": 92, "last_checked_at": "...",
  "created_at": "..."
}

days_remaining holds the latest mobile lab performance score from 0 to 100.

Errors

Errors return {"error": "code", "message": "..."} with codes unauthorized, invalid_json, invalid_hostname, plan_limit, duplicate, not_found and rate_limited.

Signed webhooks

Add a webhook URL in Settings to receive alerts as JSON. Each POST has X-VitalsClock-Event and X-VitalsClock-Signature: t=<unix seconds>,v1=<hex>, where v1 is HMAC-SHA256 of t + "." + raw body with your signing secret. Reject requests older than five minutes.