Monitors / WebSocket
WebSocket
Dial ws:// or wss://, complete the upgrade, then optionally exchange a text frame.
How it works
The probe TCP-connects (TLS for wss://, https://, or ssl://), sends a WebSocket upgrade, and treats a successful handshake as connected. If you set a request body, it is sent as a text frame and the next text frame is [BODY].
Default ports are 443 for secure URLs and 80 otherwise. Extra headers go on the upgrade request.
Target
ws:// or wss:// URL, including path.
wss://example.com/socketType fields
| Field | What it does |
|---|---|
request_headers | Extra headers on the upgrade request. Terraform: nested request_headers { key, value } blocks. |
request_body | Optional text frame sent after the handshake. The reply is [BODY]. |
verify_tls | For wss://. Defaults to on. |
proxy_url | HTTP or SOCKS proxy for the outbound dial. |
Placeholders
Available on this type. See conditions for operators and pat() / has() / len() / any().
[CONNECTED] [RESPONSE_TIME] [IP] [BODY] [DOMAIN_EXPIRATION]
Defaults
New monitors of this type start with:
[CONNECTED] == true[RESPONSE_TIME] < 50Example conditions
[CONNECTED] == true[BODY] == pat(*"ready"*)GraphQL
type is WebSocket. Same fields as the admin, camelCase in the input (intervalSeconds, requestBody, probeIds).
mutation {
createMonitor(input: {
name: "Live socket"
type: WebSocket
target: "wss://example.com/socket"
conditions: ["[CONNECTED] == true"]
}) { id }
}Terraform
Resource is nominal_monitor from returnearly/nominal. type is WebSocket. Shared arguments match the shared fields in snake_case (name, target, interval_seconds, probe_ids, channel_ids). Omitted conditions use the type defaults.
Type arguments: request_headers, request_body, verify_tls, proxy_url. Headers are nested request_headers blocks with key and value. proxy_url is sensitive.
resource "nominal_monitor" "live" {
name = "Live socket"
type = "WebSocket"
target = "wss://example.com/socket"
verify_tls = true
conditions = ["[CONNECTED] == true"]
}