Navigation
Getting Started
Guides
Integrations
Reference
REST API
Complete reference for the Yorker REST API: all endpoints, methods, request/response schemas.
REST API
The Yorker REST API provides programmatic access to monitors, alerts, SLOs, notification channels, and locations. All endpoints return JSON and validate request bodies through shared Zod schemas.
Authentication
To authenticate API requests, include your API key in the Authorization header as a Bearer token.
Authorization: Bearer sk_...
All endpoints require authentication. Unauthenticated requests return 401 Unauthorized.
To mint, list, rotate, or revoke keys, see the API Keys reference.
Base URL
https://yorkermonitoring.com
Common Response Patterns
Success
Successful responses return a 2xx status code with a JSON body.
Validation Error (400)
{
"error": "Validation failed",
"details": {
"fieldErrors": { "name": ["String must contain at least 1 character(s)"] },
"formErrors": []
}
}Not Found (404)
{ "error": "Check not found" }Conflict (409)
{ "error": "Channel is in use by alert rule \"my-alert\". Remove it from those first." }Checks
List Checks
To list all checks for your team:
GET /api/checks
Response 200
{
"checks": [
{
"id": "chk_abc123",
"teamId": "team_xyz",
"name": "Homepage",
"type": "http",
"configJson": { "url": "https://example.com", "method": "GET", "timeoutMs": 30000, "followRedirects": true, "maxRedirects": 5, "assertions": [] },
"frequencySeconds": 300,
"locations": ["loc_us_east", "loc_eu_central"],
"enabled": true,
"createdAt": "2025-01-15T10:00:00.000Z",
"updatedAt": null
}
]
}Create Check
To create a new check:
POST /api/checks
Request body -- validated through CreateCheckSchema
For HTTP checks:
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
name | string | Yes | -- | Check name (1-255 characters). |
type | "http" | Yes | -- | Check type. |
enabled | boolean | No | true | Whether the check is active. |
frequencySeconds | number | No | 300 | Check interval (10-86400). |
locations | string[] | Yes | -- | Location IDs (at least one). |
httpConfig | object | Yes | -- | HTTP configuration (see below). |
httpConfig fields:
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
url | string | Yes | -- | Target URL (must be a valid URL). |
method | string | No | "GET" | GET | POST | PUT | DELETE | PATCH | HEAD |
headers | object | No | -- | Request headers (string key-value pairs). |
body | string | No | -- | Request body. |
auth | object | No | -- | Auth config (basic, bearer, or api-key). |
followRedirects | boolean | No | true | Follow HTTP redirects. |
maxRedirects | number | No | 5 | Maximum number of redirects. |
timeoutMs | number | No | 30000 | Request timeout in milliseconds. |
assertions | array | No | [] | Assertion rules. See Assertions. |
For browser checks:
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
name | string | Yes | -- | Check name (1-255 characters). |
type | "browser" | Yes | -- | Check type. |
enabled | boolean | No | true | Whether the check is active. |
frequencySeconds | number | No | 300 | Check interval (10-86400). |
locations | string[] | Yes | -- | Location IDs (at least one). |
browserConfig | object | Yes | -- | Browser configuration (see below). |
browserConfig fields:
| Field | Type | Required | Default | Constraints | Description |
|---|---|---|---|---|---|
browserMode | string | Yes | - | "scripted" | "url" | Execution mode. |
script | string | Yes (scripted) | - | - | Playwright script content (for "scripted" mode). |
url | string | Yes (url) | - | Valid URL | Target URL (for "url" mode). |
timeoutMs | number | No | 30000 | 5000-120000 | Script timeout in milliseconds. |
viewport | object | No | { width: 1280, height: 720 } | - | Viewport dimensions. |
device | string | No | - | - | Playwright device name for emulation. |
screenshotMode | string | No | "every_step" | every_step | failure_only | disabled | Screenshot capture mode. |
videoEnabled | boolean | No | false | - | Record video. |
For MCP checks:
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
name | string | Yes | - | Check name (1-255 characters). |
type | "mcp" | Yes | - | Check type. |
enabled | boolean | No | true | Whether the check is active. |
frequencySeconds | number | No | 300 | Check interval (10-86400). |
locations | string[] | Yes | - | Location IDs (at least one). |
mcpConfig | object | Yes | - | MCP configuration (see below). |
mcpConfig fields:
| Field | Type | Required | Default | Constraints | Description |
|---|---|---|---|---|---|
endpoint | string | Yes | - | Valid URL | Streamable HTTP endpoint of the MCP server. |
timeoutMs | number | No | 30000 | 5000-120000 | Request timeout in milliseconds. |
auth | object | No | - | basic, bearer, api-key | Same auth shape as HTTP checks. |
expectedTools | string[] | No | - | - | Tool names that must be present. Missing tools fail the check. |
testCalls | array | No | - | - | Tool invocations to exercise. Each entry has toolName, optional arguments (object), and optional expectedOutputContains. |
detectSchemaDrift | boolean | No | true | - | Emit events when tool list or signatures change between runs. |
Response 201
{
"check": {
"id": "chk_abc123",
"teamId": "team_xyz",
"name": "Homepage",
"type": "http",
"configJson": { "url": "https://example.com", "method": "GET", "timeoutMs": 30000, "followRedirects": true, "maxRedirects": 5, "assertions": [] },
"frequencySeconds": 300,
"locations": ["loc_us_east"],
"enabled": true,
"createdAt": "2025-01-15T10:00:00.000Z",
"updatedAt": null
}
}Error 403 -- Plan limit exceeded.
Get Check
To get a single check with its 50 most recent results:
GET /api/checks/:id
Response 200
{
"check": { "id": "chk_abc123", "name": "Homepage", "..." : "..." },
"results": [
{
"id": "res_xyz789",
"checkId": "chk_abc123",
"runId": "run_abc",
"locationId": "loc_us_east",
"status": "success",
"responseTimeMs": 142,
"httpStatusCode": 200,
"startedAt": "2025-01-15T10:05:00.000Z",
"completedAt": "2025-01-15T10:05:00.142Z"
}
]
}Update Check
To update an existing check:
PUT /api/checks/:id
Request body -- all fields are optional (partial update):
| Field | Type | Description |
|---|---|---|
name | string | Check name. |
configJson | object | Full HTTP or browser config object (replaces existing). |
frequencySeconds | number | Check interval. |
locations | string[] | Location IDs. |
enabled | boolean | Whether the check is active. |
Response 200
{ "check": { "id": "chk_abc123", "..." : "..." } }Delete Check
To delete a check and its results:
DELETE /api/checks/:id
Response 200
{ "success": true }List Check Results
To get paginated results for a check:
GET /api/checks/:id/results
Query parameters:
| Parameter | Type | Default | Max | Description |
|---|---|---|---|---|
limit | number | 50 | 200 | Number of results to return. |
offset | number | 0 | -- | Pagination offset. |
detail | "true" | -- | -- | Include Tier B debug data (network requests, console logs, screenshots). |
Response 200
{
"results": [
{
"id": "res_xyz789",
"checkId": "chk_abc123",
"runId": "run_abc",
"locationId": "loc_us_east",
"status": "success",
"responseTimeMs": 142,
"httpStatusCode": 200,
"timing": {
"dnsLookupMs": 12,
"tcpConnectMs": 18,
"tlsHandshakeMs": 25,
"ttfbMs": 80,
"contentTransferMs": 7,
"totalMs": 142
},
"startedAt": "2025-01-15T10:05:00.000Z",
"completedAt": "2025-01-15T10:05:00.142Z"
}
],
"limit": 50,
"offset": 0
}When detail=true, browser check results also include networkRequestsJson, screenshotsJson, and consoleLogsJson fields.
Trigger Ad-Hoc Run
To trigger an immediate check run across all assigned locations:
POST /api/checks/:id/trigger
Request body: none
Response 200
{
"triggered": true,
"locations": 3
}Alerts
List Alert Rules
To list all alert rules for a check:
GET /api/checks/:id/alerts
Response 200
{
"alerts": [
{
"id": "alert_abc123",
"checkId": "chk_xyz",
"name": "downtime-alert",
"enabled": true,
"conditions": [
{ "type": "consecutive_failures", "count": 3 }
],
"channelIds": ["nch_abc"],
"channels": [
{ "type": "slack", "webhookUrl": "https://hooks.slack.com/..." }
],
"createdAt": "2025-01-15T10:00:00.000Z",
"updatedAt": null
}
]
}The channels array contains resolved channel configurations for display. The channelIds array contains the raw channel IDs.
Create Alert Rule
To create an alert rule for a check:
POST /api/checks/:id/alerts
Request body -- validated through CreateAlertRuleSchema:
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
name | string | null | No | null | Alert rule name. |
enabled | boolean | No | true | Whether the rule is active. |
conditions | array | Yes | -- | At least one condition. See Alert Conditions. |
channelIds | string[] | Yes | -- | At least one notification channel ID. |
Response 201
{ "id": "alert_abc123" }Update Alert Rule
To update an existing alert rule:
PUT /api/alerts/:alertId
Request body -- validated through UpdateAlertRuleSchema (all fields optional):
| Field | Type | Description |
|---|---|---|
name | string | null | Alert rule name. |
enabled | boolean | Whether the rule is active. |
conditions | array | At least one condition (replaces existing). |
channelIds | string[] | At least one channel ID (replaces existing). |
Response 200
{ "success": true }Delete Alert Rule
To delete an alert rule:
DELETE /api/alerts/:alertId
Response 200
{ "success": true }Alert Conditions
Each condition in the conditions array must have a type field. Available types:
| Type | Fields | Description |
|---|---|---|
consecutive_failures | count (default: 2, min: 1) | Alert after N consecutive failures. |
response_time_threshold | maxMs (required) | Alert when response time exceeds threshold. |
multi_location_failure | minLocations (default: 2, min: 2), windowSeconds (default: 300) | Alert when failures occur from multiple locations within a time window. |
ssl_expiry | daysBeforeExpiry (default: 14, min: 1), severity (optional) | Alert when SSL certificate nears expiration. |
ssl_certificate_changed | severity (optional) | Alert when the leaf certificate fingerprint changes between runs. |
ssl_self_signed | severity (optional) | Alert when a self-signed or untrusted-root certificate is detected. |
ssl_protocol_deprecated | minProtocol (default: TLSv1.2, allowed: TLSv1.2, TLSv1.3), severity (optional) | Alert when the TLS handshake negotiates a protocol older than minProtocol. |
burn_rate | sloId (required), burnRateThreshold (positive number), longWindowMinutes (min 60), shortWindowMinutes (min 5, must be less than long) | SLO burn-rate alert. Typically generated automatically from SLOs with burnRateAlertsEnabled: true. |
mcp_schema_drift | changeTypes (optional, subset of added, removed, modified; defaults to all), toolNames (optional string array; defaults to all tools), severity (default warning) | Alert when an MCP server's tool list or tool signatures change between runs. Restrict by change type and/or tool name. |
baseline_anomaly | metric (required; one of response_time, dns_lookup, tls_handshake, ttfb, content_transfer, lcp, fcp, cls), sigmaThreshold (default 3, range 2-10), consecutiveCount (default 3, integer 2-20), direction (default above; one of above, below, both), severity (default warning) | Alert when the last consecutiveCount runs are all successes and each deviates by more than sigmaThreshold·σ from its own (hour × day-of-week × location) baseline in the configured direction. Any non-success run inside the window breaks the chain. |
All SSL conditions (including ssl_expiry), mcp_schema_drift, and baseline_anomaly accept an optional severity field with value critical, warning, or info. mcp_schema_drift and baseline_anomaly default to warning; SSL conditions fall back to critical via the evaluator when unset.
Alert Instances
Alert instances represent individual occurrences of a triggered alert rule. They track state transitions through a lifecycle: active -> acknowledged -> resolved (or recovered automatically).
List Alert Instances
To list alert instances for your team:
GET /api/alerts/instances
Query parameters:
| Parameter | Type | Default | Description |
|---|---|---|---|
state | string | -- | Filter by state. Comma-separated: active, acknowledged, recovered, resolved. |
checkId | string | -- | Filter by check ID. |
limit | number | 50 | Results per page (1-200). |
offset | number | 0 | Pagination offset. |
Response 200
{
"instances": [
{
"id": "ainst_abc123",
"ruleId": "alert_xyz",
"checkId": "chk_xyz",
"state": "active",
"severity": "critical",
"startedAt": "2025-01-15T10:00:00.000Z",
"acknowledgedAt": null,
"recoveredAt": null,
"resolvedAt": null,
"durationMs": null,
"notificationCount": 2,
"contextJson": {},
"muted": false,
"ruleName": "downtime-alert",
"checkName": "Homepage"
}
],
"limit": 50,
"offset": 0
}Get Alert Instance
To get a single alert instance with its full event timeline:
GET /api/alerts/instances/:id
Response 200
{
"instance": {
"id": "ainst_abc123",
"ruleId": "alert_xyz",
"checkId": "chk_xyz",
"teamId": "team_xyz",
"state": "acknowledged",
"severity": "critical",
"triggeringResultId": "res_abc",
"triggeringTraceId": "4bf92f3577b34da6a3ce929d0e0e4736",
"recoveryResultId": null,
"startedAt": "2025-01-15T10:00:00.000Z",
"acknowledgedAt": "2025-01-15T10:05:00.000Z",
"acknowledgedBy": "user_abc",
"recoveredAt": null,
"resolvedAt": null,
"durationMs": null,
"notificationCount": 2,
"contextJson": {},
"muted": false,
"ruleName": "downtime-alert",
"checkName": "Homepage"
},
"events": [
{
"id": "aevt_abc",
"instanceId": "ainst_abc123",
"type": "triggered",
"actorId": null,
"createdAt": "2025-01-15T10:00:00.000Z"
},
{
"id": "aevt_def",
"instanceId": "ainst_abc123",
"type": "acknowledged",
"actorId": "user_abc",
"createdAt": "2025-01-15T10:05:00.000Z"
}
]
}Acknowledge Alert Instance
To acknowledge an active alert instance (transitions from active to acknowledged):
POST /api/alerts/instances/:id/acknowledge
Request body: none
Response 200
{ "success": true, "state": "acknowledged" }Error 409 -- Instance is not in active state.
Resolve Alert Instance
To manually resolve an alert instance (transitions from active or acknowledged to resolved):
POST /api/alerts/instances/:id/resolve
Request body: none
Response 200
{ "success": true, "state": "resolved", "durationMs": 300000 }Error 409 -- Instance is already recovered or resolved.
Notification Channels
List Channels
To list all notification channels for your team:
GET /api/notification-channels
Response 200
{
"channels": [
{
"id": "nch_abc123",
"name": "ops-slack",
"type": "slack",
"config": { "type": "slack", "webhookUrl": "https://hooks.slack.com/..." },
"createdAt": "2025-01-15T10:00:00.000Z",
"updatedAt": null
}
]
}Create Channel
To create a notification channel:
POST /api/notification-channels
Request body -- validated through CreateNotificationChannelSchema:
| Field | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Channel name (1-100 characters). Must be unique within the team. |
channel | object | Yes | Channel configuration. |
channel object (discriminated by type):
Slack:
| Field | Type | Required | Description |
|---|---|---|---|
type | "slack" | Yes | Channel type. |
webhookUrl | string (URL) | Yes | Slack incoming webhook URL. |
Email:
| Field | Type | Required | Description |
|---|---|---|---|
type | "email" | Yes | Channel type. |
addresses | string[] | Yes | At least one valid email address. |
Webhook:
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
type | "webhook" | Yes | -- | Channel type. |
url | string (URL) | Yes | -- | Webhook endpoint URL. |
method | "POST" | "PUT" | No | "POST" | HTTP method. |
headers | object | No | -- | Custom headers. |
Response 201
{
"channel": {
"id": "nch_abc123",
"name": "ops-slack",
"type": "slack",
"config": { "type": "slack", "webhookUrl": "https://hooks.slack.com/..." }
}
}Error 409 -- A channel with that name already exists.
Get Channel
To get a single notification channel:
GET /api/notification-channels/:id
Response 200
{
"channel": {
"id": "nch_abc123",
"name": "ops-slack",
"type": "slack",
"config": { "type": "slack", "webhookUrl": "https://hooks.slack.com/..." },
"createdAt": "2025-01-15T10:00:00.000Z",
"updatedAt": null
}
}Update Channel
To update a notification channel:
PUT /api/notification-channels/:id
Request body -- validated through UpdateNotificationChannelSchema (all fields optional):
| Field | Type | Description |
|---|---|---|
name | string | Channel name (1-100 characters). |
channel | object | Channel configuration. The type field cannot change -- delete and recreate to change type. |
Response 200
{ "success": true }Error 400 -- Channel type cannot be changed.
Error 409 -- A channel with that name already exists.
Delete Channel
To delete a notification channel:
DELETE /api/notification-channels/:id
The channel must not be referenced by any alert rules or SLOs. Remove references first.
Response 200
{ "success": true }Error 409 -- Channel is still in use by an alert rule or SLO.
SLOs
List SLOs
To list all SLO definitions for your team:
GET /api/slos
Query parameters:
| Parameter | Type | Default | Description |
|---|---|---|---|
checkId | string | -- | Filter by check ID. |
sloType | string | -- | Filter by SLO type: check or third_party. |
limit | number | 50 | Results per page (1-200). |
offset | number | 0 | Pagination offset. |
Response 200
{
"slos": [
{
"id": "slo_abc123",
"checkId": "chk_xyz",
"teamId": "team_xyz",
"name": "Homepage SLO",
"targetBasisPoints": 9990,
"windowDays": 30,
"burnRateAlertsEnabled": true,
"channelIds": ["nch_abc"],
"enabled": true,
"sloType": "check",
"patternId": null,
"sliType": "availability",
"perfThresholdMs": null,
"scope": "check",
"createdAt": "2025-01-15T10:00:00.000Z",
"updatedAt": null,
"checkName": "Homepage"
}
],
"limit": 50,
"offset": 0
}Create SLO
To create a new SLO definition:
POST /api/slos
Request body -- validated through CreateSloSchema (discriminated union on sloType):
For check-based SLOs:
| Field | Type | Required | Default | Constraints | Description |
|---|---|---|---|---|---|
sloType | "check" | Yes | -- | -- | SLO type. Defaults to "check" if omitted. |
checkId | string | Yes | -- | -- | Check ID this SLO tracks. |
name | string | Yes | -- | 1-255 characters | SLO name. |
targetBasisPoints | number | Yes | -- | Integer, 1-9999 | Availability target (e.g., 9990 = 99.90%). |
windowDays | number | Yes | -- | 7 | 14 | 30 | Rolling window in days. |
burnRateAlertsEnabled | boolean | No | true | -- | Enable burn rate alerting. |
channelIds | string[] | No | -- | -- | Notification channel IDs for alerts. |
enabled | boolean | No | true | -- | Whether the SLO is active. |
Response 201
{
"slo": {
"id": "slo_abc123",
"checkId": "chk_xyz",
"teamId": "team_xyz",
"name": "Homepage SLO",
"targetBasisPoints": 9990,
"windowDays": 30,
"burnRateAlertsEnabled": true,
"channelIds": [],
"enabled": true,
"sloType": "check",
"patternId": null,
"sliType": "availability",
"perfThresholdMs": null,
"scope": "check",
"createdAt": "2025-01-15T10:00:00.000Z",
"updatedAt": null
}
}Get SLO
To get a single SLO definition:
GET /api/slos/:id
Response 200
{
"slo": {
"id": "slo_abc123",
"checkId": "chk_xyz",
"name": "Homepage SLO",
"targetBasisPoints": 9990,
"windowDays": 30,
"burnRateAlertsEnabled": true,
"channelIds": ["nch_abc"],
"enabled": true,
"sloType": "check",
"checkName": "Homepage",
"..." : "..."
}
}Update SLO
To update an existing SLO definition:
PUT /api/slos/:id
Request body -- validated through UpdateSloSchema (all fields optional):
| Field | Type | Constraints | Description |
|---|---|---|---|
name | string | 1-255 characters | SLO name. |
checkId | string | -- | Check ID (cannot be set on team-wide SLOs). |
targetBasisPoints | number | Integer, 1-9999 | Availability target. |
windowDays | number | 7 | 14 | 30 | Rolling window. |
burnRateAlertsEnabled | boolean | -- | Enable burn rate alerting. |
channelIds | string[] | -- | Notification channel IDs. |
enabled | boolean | -- | Whether the SLO is active. |
perfThresholdMs | number | Integer, min 1. Only valid for performance SLIs. | Performance threshold. |
Note: sloType, scope, and sliType are immutable after creation. Changing them would invalidate historical data.
Response 200
{
"slo": { "id": "slo_abc123", "..." : "..." }
}Delete SLO
To delete an SLO definition:
DELETE /api/slos/:id
Response 200
{ "success": true }Get SLO Status
To get the current computed state of an SLO (availability, error budget, burn rates):
GET /api/slos/:id/status
Response 200
{
"state": {
"sloId": "slo_abc123",
"checkId": "chk_xyz",
"patternId": null,
"name": "Homepage SLO",
"sloType": "check",
"sliType": "availability",
"targetBasisPoints": 9990,
"windowDays": 30,
"availability": 0.9995,
"totalCount": 8640,
"successCount": 8636,
"avgDurationMs": null,
"perfComplianceRatio": null,
"errorBudgetTotal": 43.2,
"errorBudgetConsumed": 21.6,
"errorBudgetRemaining": 21.6,
"budgetConsumedRatio": 0.5,
"burnRate1h": 0.0,
"burnRate6h": 0.2,
"burnRate24h": 0.5
}
}| Field | Type | Description |
|---|---|---|
availability | number | Current availability ratio (0-1). |
totalCount | number | Total check runs in the window. |
successCount | number | Successful check runs. |
errorBudgetTotal | number | Total error budget in estimated minutes. |
errorBudgetConsumed | number | Error budget consumed in estimated minutes. |
errorBudgetRemaining | number | Error budget remaining in estimated minutes. |
budgetConsumedRatio | number | Fraction of budget consumed (0-1). |
burnRate1h | number | 1-hour burn rate. |
burnRate6h | number | 6-hour burn rate. |
burnRate24h | number | 24-hour burn rate. |
Locations
List Locations
To list all available monitoring locations (hosted and private):
GET /api/locations
Query parameters:
| Parameter | Type | Default | Description |
|---|---|---|---|
include_deprecated | "true" | -- | Also include deprecated locations (for migration UI). |
Response 200
{
"locations": [
{
"id": "loc_us_east",
"name": "us-east",
"region": "iad",
"displayName": "US East (Ashburn)",
"type": "hosted",
"status": "active",
"health": "active",
"latitude": 39.0438,
"longitude": -77.4874
},
{
"id": "loc_staging_eu",
"name": "staging-eu",
"region": "private",
"displayName": "Staging EU",
"type": "private",
"status": "active",
"health": "active",
"teamId": "team_xyz",
"lastHeartbeat": "2025-01-15T10:03:45.000Z"
}
]
}| Field | Type | Description |
|---|---|---|
id | string | Location ID (use this in check locations arrays). |
name | string | Short name. |
region | string | Fly region code (hosted) or "private". |
displayName | string | Human-readable name. |
type | string | "hosted" or "private". |
status | string | Lifecycle status: "active", "deprecated", or "retired". |
health | string | Runtime health: "active", "degraded", or "offline". Hosted locations are always "active"; private locations are derived from heartbeat recency. |
replacedBy | string | Successor location ID (only for deprecated/retired locations). |
teamId | string | Only set for private locations. |
lastHeartbeat | string (ISO-8601) | Only set for private locations. Most recent runner check-in. |
latitude | number | Geographic latitude (optional). |
longitude | number | Geographic longitude (optional). |
NL Generation
POST /api/checks/generate has two modes, distinguished by whether the request body includes a spec field:
- Playwright mode: default. Generates a Playwright browser script from a natural language description via Claude. Used by the dashboard's NL monitor builder.
- Spec mode: generates HTTP checks from an OpenAPI document by reusing the same pipeline as
POST /api/specs/:id/generate-checks. The spec can be referenced by ID, fetched from a URL, or matched by name against an existing spec.
Generate Playwright Script
To generate a Playwright monitoring script from a natural language description:
POST /api/checks/generate
Request body:
| Field | Type | Required | Description |
|---|---|---|---|
description | string | Yes | Natural language description of what to monitor (min 10 characters). |
targetUrl | string (URL) | No | Target URL for the script. |
previousScript | string | No | Existing script to refine. |
refinement | string | No | Refinement instructions (used with previousScript). |
Response 200
{
"mode": "playwright",
"script": "// @step: Navigate to homepage\nawait page.goto('https://example.com');\n...",
"description": "Monitor the login flow",
"model": "claude-sonnet-4-20250514"
}Error 503: NL creation not configured (server missing ANTHROPIC_API_KEY).
Generate Checks From OpenAPI Spec
To generate HTTP checks from an OpenAPI spec in a single round trip (useful when an integration knows the spec source but does not want to manage the spec entity separately):
POST /api/checks/generate
Request body:
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
spec | object | Yes | - | Discriminated by spec.source. See variants below. |
locations | string[] | Yes | - | Locations to assign to generated checks. Must contain at least one. |
frequencySeconds | integer | No | 300 | Check frequency in seconds, between 10 and 86400. |
validateHeaders | boolean | No | false | Also validate response headers against the spec (toggles validateHeaders on the generated openapi_conformance assertion). |
confirm | boolean | No | false | Required when the spec yields more than 50 new operations. |
Spec reference variants: spec.source selects how the spec is resolved:
source | Required fields | Optional fields | Behavior |
|---|---|---|---|
"id" | specId | - | Uses the spec already stored on the team. Returns 404 if not found. |
"url" | specUrl (HTTP or HTTPS URL) | name (1-255 chars) | Fetches the spec via the SSRF-guarded loader (blocks private/reserved IPs and credential-bearing URLs; plain HTTP is permitted for internal networks, redirects are rejected to prevent SSRF). If a spec with the same content hash already exists for the team, it is reused; otherwise a new spec entity is inserted. When name is omitted it is derived from info.title, falling back to api-{hostname}, with a numeric suffix appended on collision. |
"name" | specName | - | Looks up an existing spec by exact name (per-team unique). Returns 404 if not found. |
Response 200 (or 201 if at least one check was created). Same envelope as POST /api/specs/:id/generate-checks. The mode field marks this as the spec branch and spec.newlyCreated indicates whether the URL variant inserted a brand-new spec row.
{
"mode": "spec",
"spec": { "id": "spec_abc", "name": "Petstore API", "newlyCreated": true },
"created": [
{ "id": "chk_xyz", "name": "Petstore API: GET /pets", "operationKey": "GET /pets" }
],
"skipped": [
{
"operationKey": "GET /pets/{id}",
"operationId": "getPetById",
"method": "GET",
"pathTemplate": "/pets/{id}",
"reason": "already_exists"
}
],
"summary": {
"operationsInSpec": 12,
"eligible": 11,
"created": 10,
"skipped": 1,
"labelAttachmentFailures": 0
}
}Errors:
400: invalid request body ({ error: "Validation failed", details: {...} }).403: plan limit reached. Body contains{ error: "<plan limit message>" }.404: spec not found (idandnamevariants only).409: confirmation required:{ error: "This spec would create N new monitors. Confirm to create all of them.", requiresConfirmation: true, operationCount: N, threshold: 50 }. Re-submit withconfirm: true.409: (urlvariant only) a spec with the resolved name already exists with different content. Pass an explicitnameor use theidvariant.422: the loaded spec content failed to parse, OR the upstream URL fetch returned an error / non-OpenAPI body / exceeded the 10 MB cap. Body contains{ error: "<details>" }.
API Specs
API specs store OpenAPI documents that HTTP checks can validate against via the openapi_conformance assertion. See Assertions: openapi_conformance.
List Specs
GET /api/specs
Returns a summary list (no full contents; use the detail endpoint to fetch the parsed spec).
Create Spec
POST /api/specs
Request body, discriminated by sourceType:
Upload mode:
| Field | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Spec name (1-255 characters). |
sourceType | "upload" | Yes | - |
content | string | Yes | Raw OpenAPI JSON or YAML (up to 4 MB). |
URL mode:
| Field | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Spec name (1-255 characters). |
sourceType | "url" | Yes | - |
sourceUrl | string (URL) | Yes | URL Yorker fetches the spec from. |
Get Spec
GET /api/specs/:id
Returns the full parsed spec including contentJson.
Update Spec
PUT /api/specs/:id
Accepts name, content (switches to upload mode), or sourceUrl (switches to url mode). You cannot provide both content and sourceUrl in the same request, and a body with none of the three fields returns 400 No fields to update.
Delete Spec
DELETE /api/specs/:id
Returns 204 No Content on success. Generated monitors are not deleted; their openapi_conformance assertion still references the spec ID. The runner's in-memory spec cache is best-effort (5-minute TTL, 50-entry LRU cap, and specs over 2 MB are not cached at all), so the assertion may keep validating against a cached spec for up to 5 minutes after deletion. Specs that were never cached (size > 2 MB) or that have already been LRU-evicted will fail on the very next run, when the runner's getSpec call returns 404. Re-creating a spec with the same ID is not supported (IDs are unique). To clean up after a delete, either generate a new spec and re-point the affected checks' assertions at the new ID, or delete the orphaned checks.
Sync URL-mode Spec
POST /api/specs/:id/sync
Forces Yorker to re-fetch a url-mode spec immediately. Returns 400 when called on an upload-mode spec. The response is the spec summary plus a changed flag indicating whether the new SHA-256 contentHash differs from the stored one (Yorker only writes a new contentJson when the hash actually changes, avoiding write amplification on periodic syncs):
{
"spec": {
"id": "spec_abc",
"teamId": "team_xyz",
"name": "Petstore API",
"sourceType": "url",
"sourceUrl": "https://petstore3.swagger.io/api/v3/openapi.json",
"contentHash": "...",
"version": "1.0.0",
"lastSyncedAt": "2026-05-15T07:00:00.000Z",
"createdAt": "2026-05-15T06:00:00.000Z",
"updatedAt": "2026-05-15T07:00:00.000Z"
},
"changed": true
}When changed: true, runners invalidate their cached copy on the next poll. Generated checks pick up the new schema automatically; you do not need to re-run generate-checks unless the spec added new operations you want to monitor.
Generate Checks From Spec
POST /api/specs/:id/generate-checks
Generates one HTTP check per operation in the spec. Operations that already have a corresponding check are skipped, so re-running this endpoint is idempotent. Returns 201 when at least one check is created, 200 otherwise.
Request body:
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
locations | string[] | Yes | - | Locations to assign to generated checks. Must contain at least one. |
frequencySeconds | integer | No | 300 | Check frequency in seconds, between 10 and 86400. |
validateHeaders | boolean | No | false | Also validate response headers against the spec (toggles validateHeaders on the generated openapi_conformance assertion). |
confirm | boolean | No | false | Required when the spec yields more than 50 new operations. Re-submit with true to proceed. |
Response 201 / 200
{
"spec": { "id": "spec_abc", "name": "Petstore API" },
"created": [
{ "id": "chk_xyz", "name": "Petstore API: GET /pets", "operationKey": "GET /pets" }
],
"skipped": [
{
"operationKey": "GET /pets/{id}",
"operationId": "getPetById",
"method": "GET",
"pathTemplate": "/pets/{id}",
"reason": "already_exists"
}
],
"summary": {
"operationsInSpec": 12,
"eligible": 11,
"created": 10,
"skipped": 1,
"labelAttachmentFailures": 0
}
}| Field | Type | Description |
|---|---|---|
spec | object | The spec the checks were generated from (id, name). |
created | array | Checks created in this call. Each entry has id, name (always prefixed "{spec name}: ..." per buildCheckName), and operationKey ("{METHOD} {pathTemplate}"). |
skipped | array | Operations the generator skipped. Each entry has operationKey, operationId (nullable), method, pathTemplate, reason, and an optional detail string explaining the failure (always present on validation_failed). Reason vocabulary: already_exists, no_responses, no_server_url, invalid_url, deprecated, unsupported_method, validation_failed. Source of truth: GenerateChecksSkipReasonSchema. |
summary.operationsInSpec | number | Total operations the spec exposes. |
summary.eligible | number | Operations that passed the per-operation filters. |
summary.created | number | New checks created in this call. |
summary.skipped | number | Operations skipped (existing + filtered). |
summary.labelAttachmentFailures | number | Label attachments that failed mid-loop (extremely rare). |
Errors:
400: invalid request body ({ error: "Validation failed", details: {...} }).403: plan limit reached. Body contains{ error: "<plan limit message>" }.404: spec not found (or belongs to another team).409: confirmation required:{ error: "This spec would create N new monitors. Confirm to create all of them.", requiresConfirmation: true, operationCount: N, threshold: 50 }. Re-submit withconfirm: true.422: the stored spec content failed to parse ({ error: "<parser message>" }).
Events
The unified events endpoint returns check executions and alert state transitions as a single time-ordered stream. See Events concepts for the model.
List Events
GET /api/events
Query parameters:
| Parameter | Type | Default | Description |
|---|---|---|---|
type | comma-separated string | all types | Restrict to specific event types: check.completed, check.failed, check.mcp_schema_drift, alert.triggered, alert.acknowledged, alert.recovered, alert.resolved, alert.escalated, alert.notified, alert.muted. Unknown values return 400. |
checkId | string | - | Restrict to a single check. |
severity | critical | warning | info | - | Restrict alert events by severity. Has no effect on check.* events. |
range | 1h, 6h, 24h, 7d, 14d, 30d | 24h | Time window measured back from now. |
limit | integer | 50 | Page size, clamped 1-200. |
offset | integer | 0 | Pagination offset. The handler returns 400 when offset > 10000; narrow the time range instead of paging deeper. |
Response 200
{
"events": [
{
"id": "res_xyz789",
"eventType": "check.completed",
"timestamp": "2026-05-14T10:05:00.142Z",
"checkId": "chk_abc123",
"checkName": "Homepage",
"checkType": "http",
"severity": null,
"traceId": "4bf92f3577b34da6a3ce929d0e0e4736",
"summary": "142 ms",
"resourceAttributes": { "synthetics.check.id": "chk_abc123", "...": "..." },
"attributes": { "synthetics.http.response_time": 142, "synthetics.check.success": 1, "...": "..." }
}
],
"limit": 50,
"offset": 0,
"hasMore": true
}Deployment Events
Record and query deployment markers, which the dashboard correlates with check-result anomaly windows.
Record a Deployment
POST /api/events/deployments
Request body (validated through CreateDeploymentEventSchema, snake_case for CI-friendliness):
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
service | string | Yes | - | Service name (1-200 characters). |
version | string | Yes | - | Version identifier (1-200 characters). |
environment | string | No | "production" | Environment name (1-40 characters). An empty string returns 400. |
commit_sha | string | No | - | Commit SHA (max 64 characters). |
commit_message | string | No | - | Commit message (max 500 characters). |
deployed_by | string | No | - | Who triggered the deploy (max 200 characters). |
source | string | No | - | Tool that recorded the deploy (max 40 characters), e.g., github-actions. |
url | string | No | - | URL to the deploy run (must be a valid URL, max 2000 characters). |
timestamp | ISO-8601 string | No | now | Override the deploy time. Must be a valid ISO-8601 datetime; a non-datetime string returns 400. |
Response 201
{
"deployment": {
"id": "dep_abc123",
"teamId": "team_xyz",
"service": "checkout-api",
"version": "v2.18.0",
"environment": "production",
"commitSha": "a1b2c3d4",
"commitMessage": "fix: retry idempotency",
"deployedBy": "drewpost",
"source": "github-actions",
"url": null,
"deployedAt": "2026-05-14T10:00:00.000Z",
"createdAt": "2026-05-14T10:00:00.000Z"
}
}The response uses camelCase field names matching the rest of the read API. When a team OTLP endpoint is configured, a successful POST also enqueues a synthetics.deployment.created OTLP log event via the outbox; teams without an OTLP endpoint configured get the row in deployment_events only.
List Deployments
GET /api/events/deployments
Query parameters:
| Parameter | Type | Default | Description |
|---|---|---|---|
range | 1h, 6h, 24h, 7d, 14d, 30d | 24h | Time window measured back from now. Ignored when from and to together form a valid custom range. If either is missing, unparseable, or from > to, the route falls back to range. |
from | ISO-8601 string | - | Custom range start. Use with to. Both must be valid ISO-8601 datetimes with from <= to, otherwise both are ignored. |
to | ISO-8601 string | - | Custom range end. Use with from. Both must be valid ISO-8601 datetimes with from <= to, otherwise both are ignored. |
service | string | - | Restrict to a single service. |
Returns up to 50 deployments, ordered by deployedAt DESC.
Response 200
{
"deployments": [
{
"id": "dep_abc123",
"service": "checkout-api",
"version": "v2.18.0",
"environment": "production",
"commitSha": "a1b2c3d4",
"commitMessage": "fix: retry idempotency",
"deployedBy": "drewpost",
"source": "github-actions",
"url": null,
"deployedAt": "2026-05-14T10:00:00.000Z",
"createdAt": "2026-05-14T10:00:00.000Z"
}
]
}Maintenance Windows
Maintenance windows silence or pause checks during scheduled work. See Configuration: maintenanceWindows for the YAML schema.
List Maintenance Windows
GET /api/maintenance-windows
Create Maintenance Window
POST /api/maintenance-windows
Request body:
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
name | string | Yes | - | Window name (1-200 characters). |
mode | "pause" | "continue" | No | "pause" | pause stops running checks; continue runs them but silences notifications. |
checkIds | string[] | null | Yes | - | Array of check IDs to cover. Pass null to apply to all checks for the team. If provided as an array, it must contain at least one ID. |
startsAt | string (ISO-8601) | Yes | - | Start timestamp. |
endsAt | string (ISO-8601) | Yes | - | End timestamp. Must be after startsAt. |
recurring | boolean | No | false | Enable recurrence. |
recurrenceRule | string (RRULE) | Required if recurring | - | RFC 5545 recurrence rule. Supported: FREQ=DAILY, FREQ=WEEKLY (optionally with BYDAY), FREQ=MONTHLY (optionally with BYMONTHDAY). Recurring window duration cannot exceed 31 days. |
Get / Update / Delete Maintenance Window
GET /api/maintenance-windows/:id
PUT /api/maintenance-windows/:id
DELETE /api/maintenance-windows/:id