Endpoint Reference
Every operation in the VitalSentinel public API, grouped by module, with the scope each one requires. 336 operations across 25 groups.
336 operations across 25 groups. Every path below is relative to https://app.vitalsentinel.com/api/public/v1.
This page is a map. The OpenAPI document is the contract, and it carries the request and response schemas, the query parameters, and the per-operation notes that are too long to fit in a table.
Read the conventions first. Pagination, time ranges, and idempotency apply across the whole surface and are not repeated per endpoint.
Meta
No scope required. Both cost 0 credits.
| Method | Path | Description |
|---|---|---|
GET | /health | Service health. Unauthenticated. |
GET | /me | Describe the calling credential, its scopes, and its effective scopes |
Crawler
No scope required. Unauthenticated. Costs 0 credits.
| Method | Path | Description |
|---|---|---|
GET | /crawler | Facts about the VitalSentinel crawler, including its IP addresses and check rates |
Use it to keep your firewall allowlist up to date. See Monitoring IPs.
Workspaces and domains
Read-only. Creating or editing a workspace or a domain is a dashboard-only operation.
| Method | Path | Scope | Description |
|---|---|---|---|
GET | /workspaces | read:workspaces | List accessible workspaces |
GET | /workspaces/{workspace_id} | read:workspaces | Get a workspace |
GET | /domains | read:domains | List domains |
GET | /domains/{domain_id} | read:domains | Get a domain |
GET | /domains/{domain_id}/limits | read:domains | Get plan limits and usage |
GET | /domains/{domain_id}/verification | read:domains, read:pages, or read:site_health | Get the domain verification status. Read-only: the API cannot start a verification |
/workspaces and /domains return the page envelope but always as a single page today, and both cost 0 credits.
/workspaces reports no retention figure, because retention is not a per-workspace number: every plan keeps a given kind of data for the same length of time. To size a query window, use the fixed windows in Retention - 16 months for RUM and CrUX, 12 for Synthetic, Uptime, robots.txt and Indexing, 10 years for Search Console and Web Analytics.
Domain overview and health
The two cross-module summaries. Start here rather than fanning out across every module.
| Method | Path | Scope | Description |
|---|---|---|---|
GET | /domains/{domain_id}/overview | read:overview | Cross-module summary with period comparison |
GET | /domains/{domain_id}/health | read:domains | Cross-module health snapshot |
/overview covers eleven modules, including Page Monitoring, Site Health Monitoring and Sitemap Monitoring. /health covers nine modules, including Site Health Monitoring. A module block is null when the module is not set up for the domain. null does not mean healthy. Both use a fixed 28-day window that is not configurable. The differences that decide which you want:
/overview | /health | |
|---|---|---|
| Scope required | read:overview | read:domains |
| Window | Last 28 days | Last 28 complete UTC days versus the 28 before |
| Comparison | Three modules: CrUX, Search Console, Web Analytics | Every configured module |
| Freshness control | None. Always cached, up to an hour old | freshness=cached (default) or freshness=live |
| Reports its own staleness | No | Yes, meta.cache_age_seconds |
/health is the one to reach for during an incident. Pass freshness=live to bypass the cache and recompute every module now. It is slower, and cache_age_seconds comes back as 0 so you know you got a fresh answer.
On the default freshness=cached, check meta.cache_age_seconds before trusting uptime.is_up. A snapshot up to an hour old is fine for a dashboard and wrong for "is the site up right now".
/overview has no freshness lever at all, so do not use it for a time-sensitive question. Use /health?freshness=live, or /uptime/status, which is never cached.
URL Overview
| Method | Path | Scope | Description |
|---|---|---|---|
GET | /domains/{domain_id}/url-overview | Any module read: scope, or read:overview | Everything VitalSentinel knows about one URL, right now. Pass the full URL in url. 5 credits |
The response has one section for each module: crawl data, Search Console, URL inspection, server logs, sitemap, robots.txt, Web Analytics, RUM, CrUX, Synthetic Monitoring, uptime and open alerts. Each section shows the latest state, not the history.
Each section has a status. not_in_scope means that the credential has no scope for that module. not_connected means that the module is not available for the domain. timeout means that the section was too slow, and the other sections still come back.
A cached answer costs 0. A credential that holds only read:overview pays 0 and gets only the url section.
Credits
| Method | Path | Scope | Description |
|---|---|---|---|
GET | /credits | none | Workspace credit balance and your own cap |
GET | /credits/log | read:credits for OAuth; admin or owner role always | This cycle's spending, request by request |
GET | /credits/workspaces | none | One balance per accessible workspace, each with its own cycle |
All three cost 0 credits. /credits and /credits/log take an optional workspace_id; /credits/workspaces takes no parameters, because it already covers every workspace the credential can reach. A request is charged to the workspace whose data it read, so a connection covering several workspaces has a separate balance and a separate log for each. Omit the parameter for the connection's default workspace, which is the only one for an API key.
Workspaces do not share a billing cycle, so the balances /credits/workspaces returns each carry their own cycle_start and cycle_end. Adding their used figures together blends different date ranges into a number that describes no real cycle.
See API credits.
Uptime
Scope: read:uptime. There is no write:uptime; uptime configuration is dashboard-only.
| Method | Path | Description |
|---|---|---|
GET | /domains/{domain_id}/uptime/status | Current uptime status. Never cached, so this is the right call for "is the site up right now" |
GET | /domains/{domain_id}/uptime/availability | Uptime availability percentage |
GET | /domains/{domain_id}/uptime/timeline | Uptime check timeline, bucketed |
GET | /domains/{domain_id}/uptime/incidents | Downtime incidents |
GET | /domains/{domain_id}/uptime/response-times | DNS, connect, TLS, and total response-time breakdown |
GET | /domains/{domain_id}/uptime/slow-checks | Slow but successful checks |
GET | /domains/{domain_id}/uptime/stats-extra | Response-time percentiles, MTTR, and slow-check count |
GET | /domains/{domain_id}/uptime/config | Get uptime monitoring configuration |
SSL
Scope: read:ssl.
| Method | Path | Description |
|---|---|---|
GET | /domains/{domain_id}/ssl/summary | SSL status summary |
GET | /domains/{domain_id}/ssl/latest | Latest SSL certificate |
GET | /domains/{domain_id}/ssl | SSL certificate chain detail |
GET | /domains/{domain_id}/ssl/history | SSL certificate history |
GET | /domains/{domain_id}/ssl/events | SSL certificate change events |
GET | /domains/{domain_id}/ssl/domain-expiration | Domain registration expiration |
CrUX
Scopes: read:crux, write:crux.
| Method | Path | Scope | Description |
|---|---|---|---|
GET | /domains/{domain_id}/crux/overview | read:crux | Latest CrUX overview |
GET | /domains/{domain_id}/crux/timeline | read:crux | CrUX metrics timeline |
GET | /domains/{domain_id}/crux/compare | read:crux | Compare metrics between two periods |
GET | /domains/{domain_id}/crux/trends/{metric_name} | read:crux | Trend for one metric |
GET | /domains/{domain_id}/crux/histogram/{metric_name} | read:crux | Distribution histogram for one metric |
GET | /domains/{domain_id}/crux/urls | read:crux | List monitored URLs |
GET | /domains/{domain_id}/crux/urls/{url_id} | read:crux | Get a monitored URL |
POST | /domains/{domain_id}/crux/urls/bulk | write:crux | Add multiple URLs. 25 credits |
POST | /domains/{domain_id}/crux/urls/bulk-delete | write:crux | Remove multiple URLs |
DELETE | /domains/{domain_id}/crux/urls/{url_id} | write:crux | Remove a URL |
There is no way to trigger a CrUX refresh through the API. Collection draws from a shared platform-wide key pool, so a scripted refresh loop would degrade collection for every other customer.
Synthetic Monitoring
Scopes: read:synthetic, write:synthetic. There is no run:synthetic: a scripted "run it now" against the schedule is an unbounded test bill for data that was coming anyway.
| Method | Path | Scope | Description |
|---|---|---|---|
GET | /domains/{domain_id}/synthetic/overview | read:synthetic | Overview |
GET | /domains/{domain_id}/synthetic/timeline | read:synthetic | Test timeline |
GET | /domains/{domain_id}/synthetic/trends | read:synthetic | Metric trends over time |
GET | /domains/{domain_id}/synthetic/compare | read:synthetic | Compare performance between two periods |
GET | /domains/{domain_id}/synthetic/tests/{test_id} | read:synthetic | Full results for one test |
GET | /domains/{domain_id}/synthetic/opportunities | read:synthetic | Recurring Lighthouse opportunities, aggregated across recent runs |
GET | /domains/{domain_id}/synthetic/urls | read:synthetic | List monitored URLs |
GET | /domains/{domain_id}/synthetic/urls/{url_id} | read:synthetic | Get a monitored URL |
GET | /domains/{domain_id}/synthetic/urls/{url_id}/locations | read:synthetic | Configured locations for a URL |
GET | /domains/{domain_id}/synthetic/locations | read:synthetic | Available testing locations |
GET | /domains/{domain_id}/synthetic/locations-with-data | read:synthetic | Locations with collected data |
GET | /domains/{domain_id}/synthetic/location-limits | read:synthetic | Location limits for this workspace |
POST | /domains/{domain_id}/synthetic/urls/bulk | write:synthetic | Add multiple URLs. 25 credits |
POST | /domains/{domain_id}/synthetic/urls/bulk-delete | write:synthetic | Remove multiple URLs |
POST | /domains/{domain_id}/synthetic/urls/bulk-frequency | write:synthetic | Update frequency for multiple URLs |
PUT | /domains/{domain_id}/synthetic/urls/{url_id}/frequency | write:synthetic | Update the frequency for one URL |
PUT | /domains/{domain_id}/synthetic/urls/{url_id}/locations | write:synthetic | Set the locations for one URL |
DELETE | /domains/{domain_id}/synthetic/urls/{url_id} | write:synthetic | Remove a URL |
RUM
Scope: read:rum. Read-only, and redacted more strictly than the dashboard.
| Method | Path | Description |
|---|---|---|
GET | /domains/{domain_id}/rum/overview | RUM overview |
GET | /domains/{domain_id}/rum/has-data | Whether this domain has any RUM data at all |
GET | /workspaces/{workspace_id}/rum/has-data | Whether each domain in a workspace has any RUM data |
GET | /domains/{domain_id}/rum/vitals | Core Web Vitals, by device type |
GET | /domains/{domain_id}/rum/vitals/timeline | Core Web Vitals over time |
GET | /domains/{domain_id}/rum/vitals/distribution-timeline | Good, needs-improvement, and poor split over time |
GET | /domains/{domain_id}/rum/vitals/lcp/subparts | LCP timing breakdown |
GET | /domains/{domain_id}/rum/vitals/lcp/subparts/timeline | LCP timing breakdown, daily |
GET | /domains/{domain_id}/rum/vitals/lcp/element-types | LCP breakdown by element type |
GET | /domains/{domain_id}/rum/vitals/lcp/element-types/timeline | LCP element types, daily |
GET | /domains/{domain_id}/rum/vitals/lcp/resources | Top LCP resources |
GET | /domains/{domain_id}/rum/vitals/inp/subparts/timeline | INP timing breakdown, daily |
GET | /domains/{domain_id}/rum/vitals/inp/script-domains | Top INP script sources |
GET | /domains/{domain_id}/rum/vitals/ttfb/subparts/timeline | TTFB timing breakdown, daily. Carries a sixth, nullable field, avg_waiting_time_ms |
GET | /domains/{domain_id}/rum/pages | Page performance breakdown |
GET | /domains/{domain_id}/rum/pageviews | Aggregated page views |
GET | /domains/{domain_id}/rum/events | Individual RUM events |
GET | /domains/{domain_id}/rum/errors | Error counts by type |
GET | /domains/{domain_id}/rum/errors/groups | Distinct error kinds |
GET | /domains/{domain_id}/rum/errors/details | Detailed error records with stack traces |
GET | /domains/{domain_id}/rum/engagement | User engagement metrics |
GET | /domains/{domain_id}/rum/engagement/correlation | Performance versus engagement correlation histogram |
GET | /domains/{domain_id}/rum/geographic | Geographic distribution of RUM metrics |
/workspaces/{workspace_id}/rum/has-data is the one workspace-scoped route in this group, so it takes a workspace_id rather than a domain_id. It reports every domain in the workspace in one call, which is how to find out which of your sites are reporting RUM at all without asking domain by domain.
/rum/vitals/ttfb/subparts/timeline gained a sixth field, avg_waiting_time_ms. It is the span from navigation start to the DNS lookup - redirects, the previous page's unload, service-worker start-up and the cache lookup - and it is the phase the breakdown never measured. With it, avg_waiting_time_ms + avg_dns_time_ms + avg_connection_time_ms + avg_request_time_ms equals TTFB exactly. The TLS and response fields are context, not summands: TLS is already inside connection setup, and the response is the body download that begins after the first byte.
The field is nullable, and null means "not measured", never zero - a real reading of zero is possible, so the two cannot share a value. Do not coalesce it to 0, which turns an unmeasured phase into a published reading of zero.
The RUM days parameters cap at 496, which covers the full 16-month window RUM is kept for. A larger value returns 422 rather than an empty series.
Web Analytics
Scopes: read:analytics, write:analytics, run:analytics.
| Method | Path | Scope | Description |
|---|---|---|---|
GET | /domains/{domain_id}/analytics/overview | read:analytics | Traffic overview |
GET | /domains/{domain_id}/analytics/timeline | read:analytics | Visitors and pageviews timeline |
GET | /domains/{domain_id}/analytics/realtime | read:analytics | Live activity |
GET | /domains/{domain_id}/analytics/pages | read:analytics | Top, entry, or exit pages |
GET | /domains/{domain_id}/analytics/authors | read:analytics | Reading numbers per article author |
GET | /domains/{domain_id}/analytics/authors/articles | read:analytics | The articles one author is credited on |
GET | /domains/{domain_id}/analytics/sources | read:analytics | Traffic source breakdown |
GET | /domains/{domain_id}/analytics/devices | read:analytics | Device, browser, and OS breakdown |
GET | /domains/{domain_id}/analytics/geographic | read:analytics | Geographic breakdown |
GET | /domains/{domain_id}/analytics/events | read:analytics | Custom events |
GET | /domains/{domain_id}/analytics/search | read:analytics | Site search queries |
GET | /domains/{domain_id}/analytics/outbound | read:analytics | Outbound link clicks |
GET | /domains/{domain_id}/analytics/downloads | read:analytics | File download clicks |
GET | /domains/{domain_id}/analytics/ecommerce/overview | read:analytics | Ecommerce overview |
GET | /domains/{domain_id}/analytics/ecommerce/products | read:analytics | Ecommerce products. 25 credits, never discounted |
GET | /domains/{domain_id}/analytics/config | read:analytics | Get analytics configuration |
PUT | /domains/{domain_id}/analytics/config | write:analytics | Update analytics configuration |
GET | /domains/{domain_id}/analytics/funnels | read:analytics | List funnels |
GET | /domains/{domain_id}/analytics/funnels/{funnel_id} | read:analytics | Get a funnel |
POST | /domains/{domain_id}/analytics/funnels | write:analytics | Create a funnel |
PUT | /domains/{domain_id}/analytics/funnels/{funnel_id} | write:analytics | Update a funnel |
DELETE | /domains/{domain_id}/analytics/funnels/{funnel_id} | write:analytics | Delete a funnel |
GET | /domains/{domain_id}/analytics/experiments | read:analytics | List experiments |
GET | /domains/{domain_id}/analytics/experiments/{experiment_id} | read:analytics | Get an experiment |
GET | /domains/{domain_id}/analytics/experiments/{experiment_id}/evaluations | read:analytics | List evaluations |
GET | /domains/{domain_id}/analytics/experiments/{experiment_id}/evaluations/latest | read:analytics | Latest evaluation |
POST | /domains/{domain_id}/analytics/experiments | write:analytics | Create an experiment |
PUT | /domains/{domain_id}/analytics/experiments/{experiment_id} | write:analytics | Update an experiment |
DELETE | /domains/{domain_id}/analytics/experiments/{experiment_id} | write:analytics | Delete an experiment |
POST | /domains/{domain_id}/analytics/experiments/{experiment_id}/evaluate | run:analytics | Evaluate an experiment. 25 credits, needs Idempotency-Key |
GET | /domains/{domain_id}/analytics/reports/_registered | read:analytics | List registered report keys |
GET | /domains/{domain_id}/analytics/reports/_summary | read:analytics | Latest run per registered report |
GET | /domains/{domain_id}/analytics/reports/{key}/latest | read:analytics | Latest completed run for a report |
GET | /domains/{domain_id}/analytics/reports/runs/{run_id} | read:analytics | Get a report run |
GET | /domains/{domain_id}/analytics/reports/runs/{run_id}/rows | read:analytics | Paginated slice of a run's rows |
POST | /domains/{domain_id}/analytics/reports/{report_key}/run | run:analytics | Run an on-demand report. 25 credits, needs Idempotency-Key |
Google Search Console
Scopes: read:gsc, write:gsc, run:gsc.
| Method | Path | Scope | Description |
|---|---|---|---|
GET | /domains/{domain_id}/gsc/overview | read:gsc | Overview statistics |
GET | /domains/{domain_id}/gsc/performance | read:gsc | Performance time series. 25 credits, never discounted |
GET | /domains/{domain_id}/gsc/queries | read:gsc | Query-level performance |
GET | /domains/{domain_id}/gsc/pages | read:gsc | Page-level performance |
GET | /domains/{domain_id}/gsc/countries | read:gsc | Performance by country |
GET | /domains/{domain_id}/gsc/devices | read:gsc | Performance by device |
GET | /domains/{domain_id}/gsc/search-appearance | read:gsc | Performance by search appearance type |
GET | /domains/{domain_id}/gsc/ctr-benchmark | read:gsc | Actual versus expected CTR across this domain's own position distribution |
GET | /domains/{domain_id}/gsc/new-rankings | read:gsc | Queries or pages new to this domain's rankings |
GET | /domains/{domain_id}/gsc/known-events | read:gsc | Known events annotated on this domain's traffic |
GET | /domains/{domain_id}/gsc/brand-patterns | read:gsc | Brand-query patterns |
GET | /domains/{domain_id}/gsc/url-patterns | read:gsc | URL-template pattern overrides |
GET | /domains/{domain_id}/gsc/locale-config | read:gsc | Locale-detection configuration |
GET | /domains/{domain_id}/gsc/experiments | read:gsc | List experiments |
GET | /domains/{domain_id}/gsc/experiments/{experiment_id}/evaluations/latest | read:gsc | Latest evaluation |
POST | /domains/{domain_id}/gsc/experiments | write:gsc | Create an A/B experiment |
PUT | /domains/{domain_id}/gsc/experiments/{experiment_id} | write:gsc | Update an experiment |
DELETE | /domains/{domain_id}/gsc/experiments/{experiment_id} | write:gsc | Delete an experiment |
POST | /domains/{domain_id}/gsc/experiments/{experiment_id}/evaluate | run:gsc | Evaluate an experiment. 25 credits, needs Idempotency-Key |
GET | /domains/{domain_id}/gsc/reports/_registered | read:gsc | Reports available to run |
GET | /domains/{domain_id}/gsc/reports/_summary | read:gsc | Reports hub summary |
GET | /domains/{domain_id}/gsc/reports/{report_key}/latest | read:gsc | Latest completed run for a report |
GET | /domains/{domain_id}/gsc/reports/runs/{run_id} | read:gsc | Get a report run |
GET | /domains/{domain_id}/gsc/reports/runs/{run_id}/rows | read:gsc | Paginated slice of a run's rows |
POST | /domains/{domain_id}/gsc/reports/{report_key}/run | run:gsc | Run a report. 25 credits, needs Idempotency-Key |
Search Console data hangs off the domain its property is linked to. Connecting or disconnecting a Google account is a dashboard-only operation.
Indexing Monitoring
Scopes: read:indexing, write:indexing.
| Method | Path | Scope | Description |
|---|---|---|---|
GET | /domains/{domain_id}/indexing/timeline | read:indexing | Coverage-state timeline |
GET | /domains/{domain_id}/indexing/issue-summary | read:indexing | Aggregate issue counts |
GET | /domains/{domain_id}/indexing/inspections | read:indexing | URL Inspection results |
GET | /domains/{domain_id}/indexing/url-history | read:indexing | Every past inspection for one URL |
GET | /domains/{domain_id}/indexing/state-changes | read:indexing | Recent per-URL coverage-state transitions |
GET | /domains/{domain_id}/indexing/sitemaps | read:indexing | Search Console sitemap coverage stats |
GET | /domains/{domain_id}/indexing/diagnostics | read:indexing | Collection diagnostics |
GET | /domains/{domain_id}/indexing/groups | read:indexing | List URL groups |
GET | /domains/{domain_id}/indexing/priority-urls | read:indexing | List priority-queue URLs |
GET | /domains/{domain_id}/indexing/properties | read:indexing | List enrolled Search Console properties |
POST | /domains/{domain_id}/indexing/groups | write:indexing | Create a URL group |
PATCH | /domains/{domain_id}/indexing/groups/{group_id} | write:indexing | Update a URL group |
DELETE | /domains/{domain_id}/indexing/groups/{group_id} | write:indexing | Delete a URL group |
POST | /domains/{domain_id}/indexing/priority-urls | write:indexing | Add a URL to the priority inspection queue |
DELETE | /domains/{domain_id}/indexing/priority-urls/{priority_url_id} | write:indexing | Remove a URL from the priority queue |
POST | /domains/{domain_id}/indexing/properties/{property_id} | write:indexing | Enroll a property. 25 credits |
DELETE | /domains/{domain_id}/indexing/properties/{property_id} | write:indexing | Remove a property |
GET | /domains/{domain_id}/indexing/log-stale-crawl | read:indexing | Stale-crawl analysis from observed Googlebot fetches. Needs Server Log Monitoring |
GET | /domains/{domain_id}/indexing/log-coverage-check | read:indexing | Self-check: crawls Search Console reports the log collector never saw. Needs Server Log Monitoring |
GET | /domains/{domain_id}/indexing/inspection-candidates | read:indexing | Where to spend today's inspection quota, ranked by observed log activity. Needs Server Log Monitoring |
GET | /domains/{domain_id}/indexing/log-crawled-not-indexed | read:indexing | "Crawled - currently not indexed", re-read against real crawl frequency. Needs Server Log Monitoring |
GET | /domains/{domain_id}/indexing/log-index-latency | read:indexing | Time from a page's first observed crawl to it being indexed. Needs Server Log Monitoring |
Robots.txt Monitoring
Scopes: read:robots, write:robots. There is no run:robots; robots.txt is fetched on a schedule.
| Method | Path | Scope | Description |
|---|---|---|---|
GET | /domains/{domain_id}/robots/latest | read:robots | Latest fetched robots.txt |
GET | /domains/{domain_id}/robots/health | read:robots | Fetch health |
GET | /domains/{domain_id}/robots/timeline | read:robots | Fetched versions |
GET | /domains/{domain_id}/robots/changes | read:robots | List changes |
GET | /domains/{domain_id}/robots/diff-impacts | read:robots | Per-change before and after impact |
GET | /domains/{domain_id}/robots/crawler-access | read:robots | Per-crawler allow and disallow matrix |
GET | /domains/{domain_id}/robots/ai-bots | read:robots | AI-bot governance view |
GET | /domains/{domain_id}/robots/test-url | read:robots | Test whether a URL is allowed for one crawler |
POST | /domains/{domain_id}/robots/test-urls/query | read:robots | Test a batch of URLs. Read-only POST |
POST | /domains/{domain_id}/robots/simulate/query | read:robots | Simulate a candidate robots.txt. Read-only POST |
GET | /domains/{domain_id}/robots/overlapping-rules | read:robots | Overlapping rules in the stored file |
POST | /domains/{domain_id}/robots/overlapping-rules/query | read:robots | Overlapping rules in a candidate file. Read-only POST |
GET | /domains/{domain_id}/robots/sitemap-conflicts | read:robots | Sitemap URLs blocked by robots.txt |
GET | /domains/{domain_id}/robots/sitemap-conflicts/summary | read:robots | Conflict summary |
GET | /domains/{domain_id}/robots/top-blocked | read:robots | High-traffic URLs blocked by robots.txt |
GET | /domains/{domain_id}/robots/validation/history | read:robots | Validation results |
GET | /domains/{domain_id}/robots/annotations | read:robots | List change annotations |
POST | /domains/{domain_id}/robots/annotations | write:robots | Add a note to a change |
PATCH | /domains/{domain_id}/robots/annotations/{annotation_id} | write:robots | Update an annotation |
DELETE | /domains/{domain_id}/robots/annotations/{annotation_id} | write:robots | Delete an annotation |
POST | /domains/{domain_id}/robots/sitemap-conflicts/recompute | write:robots | Recompute the sitemap conflict check. Needs Idempotency-Key. Priced as an ordinary write |
write:robots edits VitalSentinel's own annotations on a change, and triggers the sitemap-conflict recompute. It does not, and cannot, edit the robots.txt file on your site.
The recompute re-diffs the sitemap URLs VitalSentinel has already stored against the current robots.txt. It returns straight away and does the work in the background, so poll /robots/sitemap-conflicts/summary for the result. It does not fetch a fresh sitemap, so it clears the staleness caused by the check lagging behind a stored sitemap, but not the staleness caused by an old sitemap check. Sitemap Monitoring reads the sitemaps again every 24 hours, and that clears it.
Sitemap Monitoring
Scope: read:sitemap. Read-only. VitalSentinel checks the sitemaps of each domain automatically every 24 hours. See Sitemap Monitoring.
| Method | Path | Description |
|---|---|---|
GET | /domains/{domain_id}/sitemap/summary | Sitemap Monitoring summary |
GET | /domains/{domain_id}/sitemap/stats | Check statistics: the URLs in the sitemaps now, the first and the latest check, and when the next check is due |
GET | /domains/{domain_id}/sitemap/checks | List sitemap checks |
GET | /domains/{domain_id}/sitemap/checks/{seq} | Get one sitemap check |
GET | /domains/{domain_id}/sitemap/compare | Compare two sitemap checks. 5 credits |
GET | /domains/{domain_id}/sitemap/changes | List the URL changes between checks. 5 credits |
GET | /domains/{domain_id}/sitemap/urls | Export every discovered sitemap URL. Use in_sitemap to get current, removed, or all (default) URLs. 5 credits |
GET | /domains/{domain_id}/sitemap/urls/history | The history of one sitemap URL |
GET | /domains/{domain_id}/sitemap/files | List the sitemap files and the result of each download |
GET | /domains/{domain_id}/sitemap/files/{file_id} | Get one sitemap file |
GET | /domains/{domain_id}/sitemap/hosts | List the hosts in the sitemap URLs, up to 200 |
GET | /domains/{domain_id}/sitemap/sources | Where each sitemap was found |
GET | /domains/{domain_id}/sitemap/config | Scan configuration |
GET | /domains/{domain_id}/sitemap/rate-limit | Whether a scan can be started |
Some fields need a second scope. Search Console figures, such as clicks on a removed URL, need read:gsc. Google indexing figures on a sitemap file need read:indexing. Without the second scope, these fields are null.
To find sitemap URLs blocked by robots.txt, either read the stored result at /robots/sitemap-conflicts, refreshing it first with POST /robots/sitemap-conflicts/recompute if it is stale, or export the full URL list here plus the latest robots.txt and compute the intersection yourself.
Site Health Monitoring
Scopes: read:site_health, write:site_health. There is no run:site_health, because your plan sets how often pages are checked. Every write: operation needs the owner or admin role. See Site Health Monitoring.
| Method | Path | Scope | Description |
|---|---|---|---|
GET | /domains/{domain_id}/site-health | read:site_health | Site Health Monitoring overview |
GET | /domains/{domain_id}/site-health/issues | read:site_health | List issues |
GET | /domains/{domain_id}/site-health/issues/{issue_id} | read:site_health | Get one issue with its evidence. 5 credits |
GET | /domains/{domain_id}/site-health/issues/{issue_id}/affected-urls | read:site_health | List the pages an issue affects |
POST | /domains/{domain_id}/site-health/issues/{issue_id}/{action} | write:site_health | Act on an issue: acknowledge (Mark as seen), ignore (Snooze…), accept-baseline (This is normal…) or reopen |
GET | /domains/{domain_id}/site-health/ignore-rules | read:site_health | List ignore rules |
POST | /domains/{domain_id}/site-health/ignore-rules | write:site_health | Add an ignore rule |
DELETE | /domains/{domain_id}/site-health/ignore-rules/{rule_id} | write:site_health | Remove an ignore rule |
GET | /domains/{domain_id}/site-health/sample | read:site_health | The pages that Site Health Monitoring checks |
GET | /domains/{domain_id}/site-health/sample/urls | read:site_health | List the checked URLs |
GET | /domains/{domain_id}/site-health/pins | read:site_health | List pinned URLs |
POST | /domains/{domain_id}/site-health/pins | write:site_health | Pin a URL |
DELETE | /domains/{domain_id}/site-health/pins/{pin_id} | write:site_health | Unpin a URL |
GET | /domains/{domain_id}/site-health/settings | read:site_health | Get the settings |
PATCH | /domains/{domain_id}/site-health/settings | write:site_health | Change the settings |
GET | /domains/{domain_id}/site-health/availability | read:site_health | Whether the crawler can reach the site |
GET | /domains/{domain_id}/site-health/deploys | read:site_health | Detected site changes (deploys) |
GET | /domains/{domain_id}/site-health/ai-readability | read:site_health | What AI crawlers can read. Server log figures need read:logs |
Page Monitoring
Scopes: read:pages, write:pages, run:pages. Every write: and run: operation needs the owner or admin role. See Page Monitoring.
| Method | Path | Scope | Description |
|---|---|---|---|
GET | /domains/{domain_id}/page-monitoring | read:pages | Page Monitoring overview |
GET | /domains/{domain_id}/page-monitoring/watches | read:pages | List watched pages |
GET | /domains/{domain_id}/page-monitoring/watches/migration-summary | read:pages | Migration check summary |
POST | /domains/{domain_id}/page-monitoring/watches | write:pages | Watch one page |
POST | /domains/{domain_id}/page-monitoring/watches/bulk | write:pages | Watch up to 500 pages, within your plan limit |
GET | /domains/{domain_id}/page-monitoring/watches/{watch_id} | read:pages | Get one watched page |
PATCH | /domains/{domain_id}/page-monitoring/watches/{watch_id} | write:pages | Change a watched page |
DELETE | /domains/{domain_id}/page-monitoring/watches/{watch_id} | write:pages | Stop watching a page |
POST | /domains/{domain_id}/page-monitoring/watches/{watch_id}/resume | write:pages | Resume a page that was paused for the plan limit |
POST | /domains/{domain_id}/page-monitoring/watches/{watch_id}/check | run:pages | Check a page now. 25 credits, needs Idempotency-Key |
GET | /domains/{domain_id}/page-monitoring/jobs/{job_id} | read:pages or run:pages | Get the status of a check |
GET | /domains/{domain_id}/page-monitoring/watches/{watch_id}/checks | read:pages | List the checks of a watched page |
GET | /domains/{domain_id}/page-monitoring/watches/{watch_id}/compare | read:pages | Compare two checks of a watched page. 5 credits |
GET | /domains/{domain_id}/page-monitoring/watches/{watch_id}/impact | read:pages | Search impact of the changes on a watched page. Search Console figures need read:gsc and Googlebot figures need read:logs |
GET | /domains/{domain_id}/page-monitoring/watches/{watch_id}/changes/{change_id} | read:pages | Get one change of a watched page |
GET | /domains/{domain_id}/page-monitoring/changes | read:pages | The change feed |
GET | /domains/{domain_id}/page-monitoring/change-kinds | read:pages | List the kinds of change |
GET | /domains/{domain_id}/page-monitoring/limits | read:pages | Get the plan limits |
GET | /domains/{domain_id}/page-monitoring/issues | read:pages | List issues |
GET | /domains/{domain_id}/page-monitoring/issues/{issue_id} | read:pages | Get one issue with its evidence. 5 credits |
POST | /domains/{domain_id}/page-monitoring/issues/{issue_id}/{action} | write:pages | Act on an issue: acknowledge (Mark as seen), ignore (Snooze…), accept-baseline (This is normal…) or reopen |
GET | /domains/{domain_id}/page-monitoring/custom-elements | read:pages | List custom elements |
POST | /domains/{domain_id}/page-monitoring/custom-elements/test | read:pages | Test a selector against a stored version. Read-only POST. 5 credits |
POST | /domains/{domain_id}/page-monitoring/custom-elements | write:pages | Add a custom element |
PATCH | /domains/{domain_id}/page-monitoring/custom-elements/{element_id} | write:pages | Change a custom element |
DELETE | /domains/{domain_id}/page-monitoring/custom-elements/{element_id} | write:pages | Delete a custom element |
GET | /domains/{domain_id}/page-monitoring/ignore-rules | read:pages | List ignore rules |
POST | /domains/{domain_id}/page-monitoring/ignore-rules | write:pages | Add an ignore rule |
DELETE | /domains/{domain_id}/page-monitoring/ignore-rules/{rule_id} | write:pages | Remove an ignore rule |
A check started through the API uses the same hourly allowance as the Check now button in the dashboard. When the allowance is used, the API refuses the check with a rate-limit error. A retry with the same Idempotency-Key returns the same check and costs 0.
Stored page versions
Scope: read:pages or read:site_health. Site Health Monitoring and Page Monitoring share the stored versions of a page, so either scope reads them. A 403 lists both scopes and shows that one of them is enough.
| Method | Path | Description |
|---|---|---|
GET | /domains/{domain_id}/crawl/pages | A crawled page, found by its URL. Pass the URL in url |
GET | /domains/{domain_id}/crawl/pages/{url_id} | A crawled page, found by its url_id |
GET | /domains/{domain_id}/crawl/pages/{url_id}/versions | List the stored versions of a page |
GET | /domains/{domain_id}/crawl/pages/{url_id}/versions/{version_id} | Get one stored version |
GET | /domains/{domain_id}/crawl/pages/{url_id}/versions/{version_id}/html | The stored HTML of a version, as text. 5 credits for the first part. More parts of the same version within 10 minutes cost 0 |
GET | /domains/{domain_id}/crawl/pages/{url_id}/diff | Compare two versions of a page. 5 credits |
The stored HTML comes from your site. The API returns it as text, never as a web page.
Server Log Monitoring
Scope: read:logs. Read-only: there is no write:logs or run:logs, so the API cannot connect a log source or start a collection run.
Every route costs 5 credits on the heavy-query rate-limit bucket, except /logs/sources and /logs/exclusions, which cost 1. The API never returns a visitor IP address: unverified and spoofed traffic is grouped per network (ASN). See Server Log Monitoring for what each report means.
| Method | Path | Description |
|---|---|---|
GET | /domains/{domain_id}/logs/overview | Hits overview: timeline by bot category, status mix, totals |
GET | /domains/{domain_id}/logs/bots | Per-bot activity table |
GET | /domains/{domain_id}/logs/categories | Bot activity grouped by category |
GET | /domains/{domain_id}/logs/sections | Crawl activity grouped by site section |
GET | /domains/{domain_id}/logs/pages | Crawled pages |
GET | /domains/{domain_id}/logs/pages/{url_id}/detail | One page's crawl detail |
GET | /domains/{domain_id}/logs/crawled-pages | Crawled pages: one row per URL, up to 12 months |
GET | /domains/{domain_id}/logs/urls-to-fix | Every URL crawlers got an error or a redirect for, one row per URL |
GET | /domains/{domain_id}/logs/status-codes | Bot-by-status-code matrix and the error explorer |
GET | /domains/{domain_id}/logs/status-timeline | Status codes over time, one series per exact code |
GET | /domains/{domain_id}/logs/explore | Request-level drill-down: which crawler and which pages got a given status |
GET | /domains/{domain_id}/logs/crawl-budget | Crawl budget: waste, per-section spend, waste composition, top and long-tail URL split |
GET | /domains/{domain_id}/logs/crawl-mechanics/duplicate-variants | Budget spent fetching the same page under different URLs |
GET | /domains/{domain_id}/logs/crawl-mechanics/depth | How many folders deep verified Googlebot's crawl reaches |
GET | /domains/{domain_id}/logs/tree | Site-structure crawl map: known vs crawled URLs, folder by folder |
GET | /domains/{domain_id}/logs/ai-crawlers | AI crawler activity, licensing split and robots.txt compliance |
GET | /domains/{domain_id}/logs/ai-crawlers/coverage-gap | Pages verified Googlebot crawled that no AI crawler has fetched |
GET | /domains/{domain_id}/logs/security | Spoofed bot identities, ASN clusters and scanner activity |
GET | /domains/{domain_id}/logs/sources | Log source configuration and health. 1 credit |
GET | /domains/{domain_id}/logs/exclusions | Excluded traffic: what the collection policy did not keep, and why. 1 credit |
GET | /domains/{domain_id}/logs/search-console/funnel | Crawl-to-click funnel per URL |
GET | /domains/{domain_id}/logs/search-console/crawl-roi | Share of crawl spent per section against share of clicks |
GET | /domains/{domain_id}/logs/search-console/stale-money-pages | Impressions behind pages Google stopped re-crawling |
GET | /domains/{domain_id}/logs/search-console/ctr-vs-crawl | CTR underperformance crossed with stale crawl |
GET | /domains/{domain_id}/logs/search-console/impression-collapse | Pages whose impressions fell away as crawl errors appeared |
GET | /domains/{domain_id}/logs/search-console/discovery-latency | Time from first Googlebot crawl to first search impression |
GET | /domains/{domain_id}/logs/search-console/crawl-frequency-position | Whether the most-crawled sections are the best-ranking ones |
GET | /domains/{domain_id}/logs/search-console/algorithm-events | Known search algorithm events over this site's crawl timeline |
GET | /domains/{domain_id}/logs/web-analytics/bot-share | Bot share of total traffic, with Web Analytics as the human denominator |
GET | /domains/{domain_id}/logs/web-analytics/crawl-visit-gap | Pages people visit that Googlebot hasn't crawled |
GET | /domains/{domain_id}/logs/web-analytics/ai-funnel | AI visibility funnel: crawled, cited and visited |
GET | /domains/{domain_id}/logs/rum/ttfb-bot-vs-human | Bot TTFB against human TTFB for the same URL |
GET | /domains/{domain_id}/logs/rum/cwv-crawl-priority | Poor Core Web Vitals on heavily-crawled pages |
GET | /domains/{domain_id}/logs/sitemap/orphan-pages | Crawled by Google, missing from your sitemap |
GET | /domains/{domain_id}/logs/sitemap/uncrawled-urls | Sitemap URLs Googlebot has not crawled recently |
GET | /domains/{domain_id}/logs/sitemap/crawl-lift | Whether being in the sitemap increases Googlebot crawl frequency |
GET | /domains/{domain_id}/logs/sitemap/new-urls-found | New URLs Googlebot found this week |
GET | /domains/{domain_id}/logs/robots/behaviour-delta | What crawlers did before and after a robots.txt change |
GET | /domains/{domain_id}/logs/robots/compliance | How closely each bot honors this site's robots.txt |
GET | /domains/{domain_id}/logs/robots/ineffective-disallow | Disallow rules verified crawlers are still ignoring |
GET | /domains/{domain_id}/logs/robots/ai-policy-reality | What this site tells AI bots vs what they actually did |
GET | /domains/{domain_id}/logs/robots/fetch-health | Non-200 responses to a bot's request for /robots.txt |
GET | /domains/{domain_id}/logs/uptime/seo-cost | Search and AI crawler errors during downtime |
GET | /domains/{domain_id}/logs/uptime/crawl-drop-attribution | Crawl decline explained by an incident |
GET | /domains/{domain_id}/logs/uptime/certificate-events | Crawler behavior around certificate renewals and expiries |
GET | /domains/{domain_id}/logs/indexing/crawl-drop-leading-indicator | Crawl volume next to indexing health, week by week |
The cross-module routes return a source-coverage block, so a figure that a missing source (Search Console, Web Analytics, RUM or a sitemap) cannot establish comes back as unknown rather than zero.
Alerts
Scopes: read:alerts, write:alerts. Members can create and edit alert rules, because a rule belongs to whoever created it.
Alert rules also cover Page Monitoring, Site Health Monitoring and Sitemap Monitoring. See Alert types.
| Method | Path | Scope | Description |
|---|---|---|---|
GET | /alerts/metrics | read:alerts | Available alert metrics. Costs 0 credits |
GET | /alerts/rules | read:alerts | Account-wide: rules on every accessible domain. Optional workspace_id, module, and enabled filters. Costs 0 credits |
GET | /alerts/history | read:alerts | Account-wide: fired alerts on every accessible domain, newest first. Optional workspace_id and domain_id filters. Costs 0 credits |
GET | /domains/{domain_id}/alerts/rules | read:alerts | Per domain: rules on this one domain |
GET | /domains/{domain_id}/alerts/rules/{rule_id} | read:alerts | Get a rule |
GET | /domains/{domain_id}/alerts/history | read:alerts | Per domain: fired alerts on this one domain |
POST | /domains/{domain_id}/alerts/rules | write:alerts | Create a rule |
PUT | /domains/{domain_id}/alerts/rules/{rule_id} | write:alerts | Update a rule |
DELETE | /domains/{domain_id}/alerts/rules/{rule_id} | write:alerts | Delete a rule |
The account-wide /alerts/rules and /alerts/history answer "what do I have set up" and "what has fired lately" across every workspace the credential can reach, without looping over /domains first. Every row names its own domain and workspace, so nothing has to be correlated against a second call. Both cost 0 credits, because a call that reads every accessible workspace has no single workspace to charge. Narrowing one with workspace_id or domain_id does not change that, since those are query filters rather than part of the path.
Read /alerts/metrics before building a rule. It is free and it is what tells you which metric and comparison combinations are valid.
There is no endpoint to test-fire a rule. The dashboard does not expose one either.
Notifications
Scopes: read:notifications, write:notifications. Scoped to the calling user, not to the workspace. Members keep write access here, because these are personal preferences.
Because they are user-scoped rather than workspace-scoped, every route in this group costs 0 credits. The one exception is GET /notifications/{notification_id}/trend, which recomputes a series from live data and costs 1.
| Method | Path | Scope | Description |
|---|---|---|---|
GET | /notifications | read:notifications | List notifications |
GET | /notifications/unread-count | read:notifications | Unread count |
GET | /notifications/stats | read:notifications | Notification statistics |
GET | /notifications/{notification_id}/trend | read:notifications | Live trend behind a fired alert |
GET | /notifications/preferences | read:notifications | Get preferences |
GET | /notifications/domain-subscriptions | read:notifications | Per-domain email subscriptions |
POST | /notifications/read | write:notifications | Mark notifications as read |
POST | /notifications/{notification_id}/read | write:notifications | Mark one as read |
POST | /notifications/{notification_id}/unread | write:notifications | Mark one as unread |
DELETE | /notifications/{notification_id} | write:notifications | Delete a notification |
PUT | /notifications/preferences | write:notifications | Update preferences |
PUT | /notifications/domain-subscriptions | write:notifications | Update a per-domain subscription |
Fired alerts arrive as notifications carrying the alert rule and alert history identifiers, so this is where you watch for an alert firing.
Reports
Scopes: read:reports, write:reports, run:reports.
| Method | Path | Scope | Description |
|---|---|---|---|
GET | /domains/reports/sections-catalog | read:reports | Available sections and widgets. Costs 0 credits |
GET | /domains/reports/default-config | read:reports | Default sections_config for a new template. Costs 0 credits |
GET | /domains/{domain_id}/reports/templates | read:reports | List templates |
GET | /domains/{domain_id}/reports/templates/{template_id} | read:reports | Get a template |
POST | /domains/{domain_id}/reports/data/{template_id} | read:reports | Collect report data as JSON. Read-only POST |
POST | /domains/{domain_id}/reports/templates | write:reports | Create a template |
PUT | /domains/{domain_id}/reports/templates/{template_id} | write:reports | Update a template |
POST | /domains/{domain_id}/reports/templates/{template_id}/duplicate | write:reports | Duplicate a template |
DELETE | /domains/{domain_id}/reports/templates/{template_id} | write:reports | Delete a template |
POST | /domains/{domain_id}/reports/{template_id}/generate | run:reports | Generate a PDF. 25 credits, needs Idempotency-Key |
GET | /domains/{domain_id}/reports/jobs/{job_id} | run:reports | Check a PDF job. Priced as a read |
GET | /domains/{domain_id}/reports/jobs/{job_id}/download | run:reports | Download a completed PDF. Priced as a read |
PDF generation is asynchronous. POST .../generate returns a job identifier; poll /reports/jobs/{job_id} until it completes, then download. Polling is priced as an ordinary read, so watching a report never costs more than starting one.
If you want the numbers rather than a PDF, use POST /reports/data/{template_id}. It returns the same content as JSON, needs only read:reports, and costs a read rather than 25 credits.
OAuth
The authorization server. See Authentication for the full flow.
| Method | Path | Description |
|---|---|---|
POST | /oauth/register | Register a client (RFC 7591) |
GET | /oauth/authorize | Start an authorization request |
GET | /oauth/authorize/request | Resolve an authorization request handle |
POST | /oauth/authorize/consent | Record a consent decision |
POST | /oauth/token | Exchange an authorization code or refresh token |
POST | /oauth/revoke | Revoke a token (RFC 7009) |
Two discovery documents sit at the site root rather than under the API prefix:
GET https://app.vitalsentinel.com/.well-known/oauth-authorization-server
GET https://app.vitalsentinel.com/.well-known/oauth-protected-resource