Monitors / GraphQL
GraphQL
POST a GraphQL document. Same headers, TLS, redirects, and conditions as HTTP.
How it works
GraphQL is an HTTP check that wraps request_body as {"query": "..."} and defaults to POST with Content-Type: application/json. An existing Content-Type header is left alone. Store the GraphQL document itself, not the JSON envelope.
The response is still HTTP, so you get [STATUS] plus a decoded JSON [BODY]. has([BODY].errors) == false is the usual way to reject a 200 that still failed the query.
Target
GraphQL HTTP endpoint. HTTPS also fills [CERTIFICATE_EXPIRATION].
https://countries.trevorblades.com/Type fields
| Field | What it does |
|---|---|
method | Defaults to POST. You can still pick another HTTP method. |
request_headers | Sent with the request. Content-Type defaults to application/json if you omit it. Terraform: nested request_headers { key, value } blocks. |
request_body | The GraphQL document, e.g. { __typename }. Wrapped as {"query": "..."} at probe time. |
follow_redirects | Follow 3xx responses. Defaults to on. |
verify_tls | Verify the server certificate. Defaults to on. |
proxy_url | HTTP or SOCKS proxy. Same as HTTP monitors. |
Placeholders
Available on this type. See conditions for operators and pat() / has() / len() / any().
[STATUS] [BODY] [CONNECTED] [RESPONSE_TIME] [IP] [CERTIFICATE_EXPIRATION] [DOMAIN_EXPIRATION]
Defaults
New monitors of this type start with:
[STATUS] >= 200[STATUS] <= 299Example conditions
[STATUS] == 200has([BODY].errors) == false[BODY].data.__typename == "Query"GraphQL
type is GraphQL. Same fields as the admin, camelCase in the input (intervalSeconds, requestBody, probeIds).
mutation {
createMonitor(input: {
name: "Countries"
type: GraphQL
target: "https://countries.trevorblades.com/"
requestBody: "{ __typename }"
conditions: ["[STATUS] == 200", "has([BODY].errors) == false"]
}) { id }
}Terraform
Resource is nominal_monitor from returnearly/nominal. type is GraphQL. 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: method, request_headers, request_body, follow_redirects, verify_tls, proxy_url. Headers are nested request_headers blocks with key and value. proxy_url is sensitive.
resource "nominal_monitor" "countries" {
name = "Countries"
type = "GraphQL"
target = "https://countries.trevorblades.com/"
request_body = "{ __typename }"
conditions = ["[STATUS] == 200", "has([BODY].errors) == false"]
}