# info.summary
Live status, incidents, and SLA data for the vendors your systems depend on.

# info.description
The PulsAPI public API exposes the same data the PulsAPI dashboard runs on: current
status, component-level detail, incident timelines, and 90-day SLA metrics for
2463+ cloud and SaaS providers.

## Authentication

Status reads are open — the endpoints tagged **Status**, **Incidents**, **Providers**,
and **Components** need no credential, and are rate limited per IP.

Account endpoints need an API key. Send it either as `X-API-Key: pb_…` or as
`Authorization: Bearer pb_…`. Keys are created in Settings → API Keys and carry an
explicit scope list; an operation refuses a key that lacks its scope with HTTP 403.
Request the narrowest set that does the job.

## Scopes

- `status:read` — Read public service, provider, and component status, uptime, and status history.
- `incidents:read` — Read incident timelines for the catalog and for individual services.
- `sla:read` — Read SLA reports, uptime percentages, MTTR, latency percentiles, and breach history.
- `monitors:read` — Read the monitors, boards, and groups configured on the account.
- `monitors:write` — Create, update, and delete monitors, boards, groups, and subscriptions.
- `alerts:read` — Read alert rules, routes, escalation policies, and delivered alert events.
- `alerts:write` — Create, update, and delete alert rules, routes, and escalation policies.
- `account:read` — Read account profile, plan, seats, and API-key metadata.
- `mcp:invoke` — Call the MCP server at /api/mcp as an AI agent tool surface.

## Conventions

- Timestamps are RFC 3339 / ISO 8601 in UTC.
- Collection endpoints return a Spring Data page envelope (`content`, `totalElements`, …).
- A status of `UNKNOWN` means PulsAPI has no trustworthy reading, not that the vendor is healthy.

## Machine-readable entry points

- OpenAPI: `https://www.pulsapi.com/openapi.json` (also served as YAML at `/openapi.yaml`)
- MCP server: `https://www.pulsapi.com/api/mcp` (JSON-RPC 2.0 over Streamable HTTP)
- API catalog: `https://www.pulsapi.com/.well-known/api-catalog` (RFC 9727)
- Site summary for LLMs: `https://www.pulsapi.com/llms.txt`

# tags[].description
Current operational status for monitored services and providers. No credential required.

# tags[].description
Incident timelines, catalog-wide or scoped to one service.

# tags[].description
Vendors PulsAPI polls, and the components each one publishes.

# tags[].description
Component-level readings — an individual product, region, or subsystem inside a vendor.

# tags[].description
Uptime, MTTR, and breach history. Requires an API key with `sla:read`.

# tags[].description
The calling account, its plan, and its API keys.

# tags[].description
Model Context Protocol server for AI agent tool use.

# paths./api/services.get.summary
List monitored services with their current status

# paths./api/services.get.description
Returns a page of monitored services with fused current status and 30-day uptime. Use `search` for name lookup and `category`/`status` to narrow the catalog. This is the entry point for discovering the slugs every other endpoint takes.

# paths./api/services.get.parameters[].description
Restrict results to one catalog category.

# paths./api/services.get.parameters[].description
Restrict results to services currently in this status.

# paths./api/services.get.parameters[].description
Case-insensitive substring match on service name or slug.

# paths./api/services.get.parameters[].description
Sort order. `name` is alphabetical; `status` surfaces impaired services first; `uptime` orders by 30-day uptime ascending.

# paths./api/services.get.responses.200.content.application/json.schema.description
A Spring Data page envelope. `content` holds the rows for this page.

# paths./api/services.get.responses.429.description
The caller exceeded its request budget. `Retry-After` carries the number of seconds to wait.

# paths./api/services/status-counts.get.description
Returns a fixed-size histogram of the whole active catalog, so a caller can report overall health without paging through every service.

# paths./api/services/status-counts.get.responses.429.description
The caller exceeded its request budget. `Retry-After` carries the number of seconds to wait.

# paths./api/services/{slug}.get.summary
Get one service with components and active incidents

# paths./api/services/{slug}.get.description
Returns the full record for a single service: fused current status, per-component readings, any unresolved incidents, 30-day uptime, and how PulsAPI obtains the reading.

# paths./api/services/{slug}.get.parameters[].description
Service slug, as returned by `GET /api/services` (for example `github`, `aws`, `stripe`).

# paths./api/services/{slug}.get.responses.404.description
No record exists for the supplied identifier.

# paths./api/services/{slug}.get.responses.429.description
The caller exceeded its request budget. `Retry-After` carries the number of seconds to wait.

# paths./api/services/{slug}/incidents.get.description
Returns incidents recorded for a service, newest first. Pass `since` to poll for changes without re-reading the whole history.

# paths./api/services/{slug}/incidents.get.parameters[].description
Service slug, as returned by `GET /api/services` (for example `github`, `aws`, `stripe`).

# paths./api/services/{slug}/incidents.get.parameters[].description
Unix epoch seconds. Only incidents that started at or after this instant are returned.

# paths./api/services/{slug}/incidents.get.responses.200.content.application/json.schema.description
A Spring Data page envelope. `content` holds the rows for this page.

# paths./api/services/{slug}/incidents.get.responses.404.description
No record exists for the supplied identifier.

# paths./api/services/{slug}/incidents.get.responses.429.description
The caller exceeded its request budget. `Retry-After` carries the number of seconds to wait.

# paths./api/services/{slug}/history.get.summary
Get the daily status history for one service

# paths./api/services/{slug}/history.get.description
Returns one row per day with the worst status observed that day — the series behind the uptime bar on a PulsAPI service page.

# paths./api/services/{slug}/history.get.parameters[].description
Service slug, as returned by `GET /api/services` (for example `github`, `aws`, `stripe`).

# paths./api/services/{slug}/history.get.parameters[].description
How many days back to return. Clamped to the range 1–90.

# paths./api/services/{slug}/history.get.responses.404.description
No record exists for the supplied identifier.

# paths./api/services/{slug}/history.get.responses.429.description
The caller exceeded its request budget. `Retry-After` carries the number of seconds to wait.

# paths./api/services/{slug}/uptime.get.summary
Get 7/30/90-day uptime and MTTR for one service

# paths./api/services/{slug}/uptime.get.description
Returns the three rolling uptime windows PulsAPI maintains. `uptimePercentage` is null when PulsAPI has not yet observed the service for the full window — treat null as 'no data', never as 100%.

# paths./api/services/{slug}/uptime.get.parameters[].description
Service slug, as returned by `GET /api/services` (for example `github`, `aws`, `stripe`).

# paths./api/services/{slug}/uptime.get.responses.404.description
No record exists for the supplied identifier.

# paths./api/services/{slug}/uptime.get.responses.429.description
The caller exceeded its request budget. `Retry-After` carries the number of seconds to wait.

# paths./api/incidents.get.description
Returns incidents from every monitored service, newest first. Use this to build a cross-vendor incident feed.

# paths./api/incidents.get.parameters[].description
Zero-based page index (named `offset` for backwards compatibility).

# paths./api/incidents.get.responses.200.content.application/json.schema.description
A Spring Data page envelope. `content` holds the rows for this page.

# paths./api/incidents.get.responses.429.description
The caller exceeded its request budget. `Retry-After` carries the number of seconds to wait.

# paths./api/status/providers-overview.get.description
Returns the component-derived aggregate status for every provider. This is the single source of truth PulsAPI renders everywhere, so a caller mirroring the PulsAPI board should read this rather than aggregating components itself.

# paths./api/status/providers-overview.get.responses.429.description
The caller exceeded its request budget. `Retry-After` carries the number of seconds to wait.

# paths./api/status/overview.get.summary
Get the provider overview in slug/name shape

# paths./api/status/overview.get.description
The same component-derived data as `getProvidersOverview`, projected onto `serviceSlug`/`serviceName` keys for callers that index by service.

# paths./api/status/overview.get.responses.429.description
The caller exceeded its request budget. `Retry-After` carries the number of seconds to wait.

# paths./api/providers.get.description
Returns each provider with its status-page URL, how PulsAPI reads it, and whether it publishes components. Use the returned `id` with the component endpoints.

# paths./api/providers.get.responses.429.description
The caller exceeded its request budget. `Retry-After` carries the number of seconds to wait.

# paths./api/providers/{providerId}/components.get.summary
List the components a provider publishes

# paths./api/providers/{providerId}/components.get.description
Returns component-level readings for one provider — individual products, regions, or subsystems — with optional filtering by region, product, status, or free text.

# paths./api/providers/{providerId}/components.get.parameters[].description
Provider UUID from `GET /api/providers`.

# paths./api/providers/{providerId}/components.get.parameters[].description
Vendor's own region code, matched exactly (for example `us-east-1`).

# paths./api/providers/{providerId}/components.get.parameters[].description
PulsAPI canonical region code, which normalises the same geography across vendors.

# paths./api/providers/{providerId}/components.get.parameters[].description
Return only components currently in this status.

# paths./api/providers/{providerId}/components.get.parameters[].description
Free-text match across component code, product, and region.

# paths./api/providers/{providerId}/components.get.responses.200.content.application/json.schema.description
A Spring Data page envelope. `content` holds the rows for this page.

# paths./api/providers/{providerId}/components.get.responses.404.description
No record exists for the supplied identifier.

# paths./api/providers/{providerId}/components.get.responses.429.description
The caller exceeded its request budget. `Retry-After` carries the number of seconds to wait.

# paths./api/providers/{providerId}/components/regions.get.summary
List the region codes a provider reports

# paths./api/providers/{providerId}/components/regions.get.description
Returns the distinct region codes present on a provider's components, so a caller can offer a region filter without downloading every component.

# paths./api/providers/{providerId}/components/regions.get.parameters[].description
Provider UUID from `GET /api/providers`.

# paths./api/providers/{providerId}/components/regions.get.responses.404.description
No record exists for the supplied identifier.

# paths./api/providers/{providerId}/components/regions.get.responses.429.description
The caller exceeded its request budget. `Retry-After` carries the number of seconds to wait.

# paths./api/components/{code}.get.description
Returns the current reading for a single component, including the confidence PulsAPI attaches to it and when it was last probed.

# paths./api/components/{code}.get.parameters[].description
Component code, unique across the catalog. Returned in the `componentCode` field of `GET /api/providers/{providerId}/components`.

# paths./api/components/{code}.get.responses.404.description
No record exists for the supplied identifier.

# paths./api/components/{code}.get.responses.429.description
The caller exceeded its request budget. `Retry-After` carries the number of seconds to wait.

# paths./api/components/{code}/history.get.summary
Get the status timeline for one component

# paths./api/components/{code}/history.get.description
Returns captured status snapshots for a component, newest first, with the source and confidence of each reading.

# paths./api/components/{code}/history.get.parameters[].description
Component code, unique across the catalog. Returned in the `componentCode` field of `GET /api/providers/{providerId}/components`.

# paths./api/components/{code}/history.get.responses.200.content.application/json.schema.description
A Spring Data page envelope. `content` holds the rows for this page.

# paths./api/components/{code}/history.get.responses.404.description
No record exists for the supplied identifier.

# paths./api/components/{code}/history.get.responses.429.description
The caller exceeded its request budget. `Retry-After` carries the number of seconds to wait.

# paths./api/user/services/{slug}/sla.get.description
Returns uptime, MTTR, incident counts, and target compliance for a service over the requested window. Requires an API key with `sla:read` on a plan that includes SLA reporting.

# paths./api/user/services/{slug}/sla.get.parameters[].description
Service slug, as returned by `GET /api/services` (for example `github`, `aws`, `stripe`).

# paths./api/user/services/{slug}/sla.get.responses.401.description
The API key is missing, revoked, or invalid.

# paths./api/user/services/{slug}/sla.get.responses.403.description
The API key is valid but was not granted the scope this operation requires.

# paths./api/user/services/{slug}/sla.get.responses.404.description
No record exists for the supplied identifier.

# paths./api/user/sla/breaches.get.summary
List SLA breaches recorded for the account

# paths./api/user/sla/breaches.get.description
Returns the windows in which a monitored service fell below its SLA target, newest first.

# paths./api/user/sla/breaches.get.responses.401.description
The API key is missing, revoked, or invalid.

# paths./api/user/sla/breaches.get.responses.403.description
The API key is valid but was not granted the scope this operation requires.

# paths./api/user/api-keys.get.description
Returns key metadata — never the secret, which is shown only once at creation. Use this to audit which scopes each key holds.

# paths./api/user/api-keys.get.responses.401.description
The API key is missing, revoked, or invalid.

# paths./api/user/api-keys.get.responses.403.description
The API key is valid but was not granted the scope this operation requires.

# paths./api/user/api-keys/scopes.get.description
Returns the scope names the server enforces, each with a sentence on what it allows. Read this before creating a key so the request asks for least privilege rather than for everything.

# paths./api/user/api-keys/scopes.get.responses.401.description
The API key is missing, revoked, or invalid.

# paths./api/user/api-keys/scopes.get.responses.403.description
The API key is valid but was not granted the scope this operation requires.

# paths./api/mcp.post.description
The Model Context Protocol endpoint, Streamable HTTP transport. Send JSON-RPC 2.0 requests (`initialize`, `tools/list`, `tools/call`, `ping`). Unauthenticated callers get the four public status tools under a per-IP budget; a key with `mcp:invoke` on a plan that includes MCP access gets the full tool set.

# paths./api/mcp.post.requestBody.description
A JSON-RPC 2.0 request or notification object.

# paths./api/mcp.post.responses.202.description
The message was a notification; there is no response body.

# paths./api/mcp.post.responses.429.description
The caller exceeded its request budget. `Retry-After` carries the number of seconds to wait.

# paths./api/mcp/tools.get.description
A REST convenience mirror of `tools/list` for clients that do not speak JSON-RPC. Returns only the tools the caller may actually invoke.

# paths./api/mcp/tools.get.responses.429.description
The caller exceeded its request budget. `Retry-After` carries the number of seconds to wait.

# paths./api/mcp/invoke.post.description
A REST convenience mirror of `tools/call`. Prefer `POST /api/mcp` when the client speaks MCP.

# paths./api/mcp/invoke.post.responses.402.description
The tool exists but requires an authenticated plan with MCP access.

# paths./api/mcp/invoke.post.responses.429.description
The caller exceeded its request budget. `Retry-After` carries the number of seconds to wait.

# paths./api/health.get.description
A liveness probe. Never cached. Use it to tell a PulsAPI outage apart from a vendor outage before concluding anything from a failed status read.

# components.securitySchemes.ApiKeyHeader.description
A PulsAPI API key (`pb_…`), created in Settings → API Keys. The key carries an explicit scope list; see the `x-required-scopes` extension on each operation.

# components.securitySchemes.BearerApiKey.description
The same API key sent as `Authorization: Bearer pb_…`, for clients whose HTTP layer only supports bearer auth.

# components.schemas.Error.description
The error envelope every failing endpoint returns.

# components.schemas.Error.properties.requiredScope.description
On a 403, the scope the key would have needed.

# components.schemas.ServiceStatus.description
Operational status. `UNKNOWN` means no trustworthy reading is available — it is not a synonym for healthy.

# components.schemas.IncidentStatus.description
Where an incident sits in its lifecycle.

# components.schemas.IncidentImpact.description
Severity the vendor assigned to the incident.

# components.schemas.Service.description
A monitored service as it appears in a listing.

# components.schemas.Service.properties.slug.description
URL-safe identifier used by every other endpoint.

# components.schemas.Service.properties.description.description
One-paragraph description of what the vendor does.

# components.schemas.Service.properties.isActive.description
False when the service is retired from active polling.

# components.schemas.Service.properties.components.description
Always empty in a listing; use `GET /api/services/{slug}` for components.

# components.schemas.Service.properties.uptimePercent.description
30-day uptime percentage, or null when PulsAPI has no history yet.

# components.schemas.Service.properties.lastRefreshed.description
When PulsAPI last successfully read this service.

# components.schemas.ServiceDetail.allOf[].description
Fields present only on the single-service endpoint.

# components.schemas.ServiceDetail.allOf[].properties.componentStatuses.description
Live component readings keyed by component name. Empty when the vendor publishes no components.

# components.schemas.ServiceDetail.allOf[].properties.regionFilter.description
Comma-separated regions this service covers.

# components.schemas.ServiceDetail.allOf[].properties.providerType.description
How PulsAPI reads this vendor (status-page engine or probe strategy).

# components.schemas.ServiceDetail.allOf[].properties.grabMethodology.description
Plain-English note on how the reading is obtained.

# components.schemas.ServiceDetail.description
One service with components, incidents, and provenance.

# components.schemas.ServiceComponent.properties.componentCode.description
Catalog-unique code, accepted by the component endpoints.

# components.schemas.ServiceStatusCounts.description
Active-catalog histogram, one count per status.

# components.schemas.Incident.description
An incident as published by the vendor and normalised by PulsAPI.

# components.schemas.Incident.properties.externalIncidentId.description
The vendor's own identifier for this incident.

# components.schemas.Incident.properties.startedAt.description
When the vendor says the incident began.

# components.schemas.Incident.properties.resolvedAt.description
Resolution time, or null while the incident is open.

# components.schemas.HistoryDay.description
The worst status observed on one calendar day (UTC).

# components.schemas.UptimeWindow.properties.uptimePercentage.description
Uptime percentage, or null when the window has no observations.

# components.schemas.UptimeWindow.properties.mttrMinutes.description
Mean time to recovery in minutes across the window.

# components.schemas.ProviderOverviewItem.description
Component-derived aggregate status for one provider.

# components.schemas.StatusOverviewItem.description
The provider overview projected onto service keys.

# components.schemas.Provider.properties.providerType.description
Status-page engine or probe strategy PulsAPI uses for this vendor.

# components.schemas.Provider.properties.hasMicroServices.description
True when the vendor publishes component-level detail.

# components.schemas.Component.description
A component-level reading inside a provider.

# components.schemas.Component.properties.canonicalRegionCode.description
PulsAPI canonical region code, comparable across vendors.

# components.schemas.Component.properties.confidenceScore.description
How much PulsAPI trusts this reading, from 0 to 1.

# components.schemas.ComponentSnapshot.properties.source.description
Which fetcher or feed produced this reading.

# components.schemas.ComponentSnapshot.properties.confidenceScore.description
Confidence attached to this reading, from 0 to 1.

# components.schemas.SlaReport.description
Uptime and recovery metrics for one service over a window.

# components.schemas.SlaReport.properties.targetUptime.description
SLA target this service is measured against.

# components.schemas.SlaReport.properties.breached.description
True when observed uptime fell below the target.

# components.schemas.SlaBreach.description
A window in which a service fell below its SLA target.

# components.schemas.ApiKey.description
API-key metadata. The secret itself is returned only at creation.

# components.schemas.ApiKey.properties.rateLimit.description
Requests per minute this key is allowed.

# components.schemas.ApiKey.properties.lastUsedAt.description
When the key was last used, or null if never.

# components.schemas.ScopeDescription.properties.name.description
Scope name, as sent when creating a key.

# components.schemas.Health.properties.status.description
Always `ok` when the API responds at all.

# components.schemas.Health.properties.time.description
Server time when the probe was answered.

# components.schemas.JsonRpcRequest.description
A JSON-RPC 2.0 request. Omit `id` to send a notification.

# components.schemas.JsonRpcRequest.properties.params.description
Method parameters. For `tools/call`, `{ name, arguments }`.

# components.schemas.JsonRpcResponse.description
A JSON-RPC 2.0 response. Exactly one of `result` or `error` is present.

# components.schemas.McpInvokeRequest.properties.input.description
Tool arguments, matching the tool's `inputSchema`.

# components.schemas.McpToolResult.properties.data.description
Structured result, for callers that prefer fields over prose.