> ## Documentation Index
> Fetch the complete documentation index at: https://arize-ax.mintlify.site/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Managing monitors with GraphQL

> Automate Arize AX monitors with the GraphQL API: list, create, patch, trigger, and delete drift, performance, and data quality monitors, thresholds, and alerts.

Monitors track a model or project's drift, performance, and data quality metrics over time in Arize AX and alert you when something changes. The [Configure Monitors](/docs/ax/observe/production-monitoring/configure-monitors) guide covers monitor concepts (evaluation windows, baselines, thresholds) in the UI. Everything in that guide can also be done through the GraphQL API, which is the better path once you manage more than a handful of monitors: bulk threshold tuning, templated monitor creation across many features or models, and scheduled downtime.

This guide assumes you already know how to [form a GraphQL call](/docs/ax/graphql-reference/overview/how-to-use-graphql/forming-calls) with an `x-api-key` header against `https://app.arize.com/graphql`.

## Find the IDs you need

Every monitor mutation takes a monitor ID, and every create mutation takes a model ID (or a space ID plus model name). Start from `viewer` to find your space, then the space's `models` connection to find the model. See [Using global node IDs](/docs/ax/graphql-reference/overview/how-to-use-graphql/using-global-node-ids) for how these opaque IDs work.

<CodeGroup>
  ```graphql Query theme={"theme":{"light":"github-light-default","dark":"github-dark-default"}}
  query FindSpaceAndModel($spaceSearch: String, $modelSearch: String) {
    viewer {
      spaces(search: $spaceSearch, first: 5) {
        edges {
          node {
            id
            name
            models(search: $modelSearch, first: 5) {
              edges {
                node {
                  id
                  name
                }
              }
            }
          }
        }
      }
    }
  }
  ```

  ```json Variables theme={"theme":{"light":"github-light-default","dark":"github-dark-default"}}
  {
    "spaceSearch": "Production",
    "modelSearch": "fraud"
  }
  ```
</CodeGroup>

Once you have a model's or space's ID, fetch any object directly with the `node` root field, for example `node(id: "<MONITOR_ID>") { ... on Monitor { name } }`.

## List monitors for a model, filtered by status

Monitors live on both `Model` and `Space` through the same `monitors` connection, with filters for category and current status. This is the fastest way to find every triggered monitor on a model.

<CodeGroup>
  ```graphql Query theme={"theme":{"light":"github-light-default","dark":"github-dark-default"}}
  query TriggeredMonitorsForModel($modelId: ID!) {
    node(id: $modelId) {
      ... on Model {
        monitors(first: 50, currentStatus: [triggered]) {
          totalCount
          edges {
            node {
              id
              name
              monitorCategory
              status
              threshold
              latestComputedValue
            }
          }
        }
      }
    }
  }
  ```

  ```json Variables theme={"theme":{"light":"github-light-default","dark":"github-dark-default"}}
  {
    "modelId": "<MODEL_ID>"
  }
  ```
</CodeGroup>

`latestComputedValue` is the monitor's most recent computed metric value. It replaces the old `currentMetricValue` field, which no longer exists on `Monitor`.

## Create a drift monitor on a feature with a custom baseline

Drift monitors compare a primary window against a baseline. By default a monitor uses the model's primary baseline, but you can give it its own moving-window baseline instead, as shown here.

<CodeGroup>
  ```graphql Mutation theme={"theme":{"light":"github-light-default","dark":"github-dark-default"}}
  mutation CreateDriftMonitor($input: CreateDriftMonitorMutationInput!) {
    createDriftMonitor(input: $input) {
      monitor {
        id
        name
        uri
        threshold
      }
    }
  }
  ```

  ```json Variables theme={"theme":{"light":"github-light-default","dark":"github-dark-default"}}
  {
    "input": {
      "modelId": "<MODEL_ID>",
      "name": "PSI drift on home_state",
      "driftMetric": "psi",
      "operator": "greaterThan",
      "dimensionCategory": "featureLabel",
      "dimensionName": "home_state",
      "dynamicAutoThreshold": { "stdDevMultiplier": 2 },
      "baseline": {
        "useModelPrimaryBaseline": false,
        "movingWindowSeconds": 1209600,
        "movingWindowDelaySeconds": 864000
      },
      "contacts": [
        { "notificationChannelType": "email", "emailAddress": "you@arize.com" }
      ]
    }
  }
  ```
</CodeGroup>

Reference: [`createDriftMonitor`](/docs/ax/graphql-reference/mutations/monitors#createdriftmonitor).

## Create a performance monitor with contacts and a webhook

Performance monitors watch a metric like accuracy or recall and alert when it crosses a threshold. Pair an email contact with a webhook subscription so the same trigger reaches both a person and an external system. Webhooks must already exist as webhook destinations in your account; `webhookId` is that destination's ID.

<CodeGroup>
  ```graphql Mutation theme={"theme":{"light":"github-light-default","dark":"github-dark-default"}}
  mutation CreatePerformanceMonitor($input: CreatePerformanceMonitorMutationInput!) {
    createPerformanceMonitor(input: $input) {
      monitor {
        id
        name
        uri
      }
    }
  }
  ```

  ```json Variables theme={"theme":{"light":"github-light-default","dark":"github-dark-default"}}
  {
    "input": {
      "modelId": "<MODEL_ID>",
      "name": "Accuracy drop on production traffic",
      "performanceMetric": "accuracy",
      "operator": "lessThan",
      "threshold": 0.85,
      "contacts": [
        { "notificationChannelType": "email", "emailAddress": "oncall@arize.com" }
      ],
      "webhookSubscriptions": [
        {
          "webhookId": "<WEBHOOK_ID>",
          "subscribedWebhookEvents": ["MONITOR_TRIGGERED", "MONITOR_CLEARED"]
        }
      ]
    }
  }
  ```
</CodeGroup>

Reference: [`createPerformanceMonitor`](/docs/ax/graphql-reference/mutations/monitors#createperformancemonitor).

## Create a data quality monitor

Data quality monitors watch a dimension-level metric, such as the percentage of empty values on a feature.

<CodeGroup>
  ```graphql Mutation theme={"theme":{"light":"github-light-default","dark":"github-dark-default"}}
  mutation CreateDataQualityMonitor($input: CreateDataQualityMonitorMutationInput!) {
    createDataQualityMonitor(input: $input) {
      monitor {
        id
        name
        uri
      }
    }
  }
  ```

  ```json Variables theme={"theme":{"light":"github-light-default","dark":"github-dark-default"}}
  {
    "input": {
      "modelId": "<MODEL_ID>",
      "name": "Missing values on credit_score",
      "dimensionName": "credit_score",
      "dimensionCategory": "featureLabel",
      "dataQualityMetric": "percentEmpty",
      "operator": "greaterThan",
      "threshold": 0.05
    }
  }
  ```
</CodeGroup>

Reference: [`createDataQualityMonitor`](/docs/ax/graphql-reference/mutations/monitors#createdataqualitymonitor).

## Raise the threshold on every drift monitor in a space

This is the most common bulk operation: pull every drift monitor in a space, then patch each one's threshold. List first, mutate second, since `patchDriftMonitor` takes one monitor ID at a time.

<CodeGroup>
  ```graphql Query theme={"theme":{"light":"github-light-default","dark":"github-dark-default"}}
  query DriftMonitorsInSpace($spaceId: ID!, $after: String) {
    node(id: $spaceId) {
      ... on Space {
        monitors(first: 100, after: $after, monitorCategory: drift) {
          pageInfo { hasNextPage endCursor }
          edges { node { id name threshold dynamicAutoThresholdEnabled } }
        }
      }
    }
  }
  ```

  ```graphql Mutation theme={"theme":{"light":"github-light-default","dark":"github-dark-default"}}
  mutation RaiseDriftThreshold($monitorId: ID!, $threshold: Float!) {
    patchDriftMonitor(
      input: { monitorId: $monitorId, set: { threshold: $threshold, dynamicAutoThresholdEnabled: false } }
    ) {
      monitor { id threshold }
    }
  }
  ```

  ```python Python theme={"theme":{"light":"github-light-default","dark":"github-dark-default"}}
  import requests

  GRAPHQL_URL = "https://app.arize.com/graphql"
  HEADERS = {"x-api-key": "<YOUR_API_KEY>", "Content-Type": "application/json"}

  # Same documents as the Query and Mutation tabs above.
  LIST_QUERY = """
  query DriftMonitorsInSpace($spaceId: ID!, $after: String) {
    node(id: $spaceId) {
      ... on Space {
        monitors(first: 100, after: $after, monitorCategory: drift) {
          pageInfo { hasNextPage endCursor }
          edges { node { id name threshold } }
        }
      }
    }
  }
  """
  PATCH_MUTATION = """
  mutation RaiseDriftThreshold($monitorId: ID!, $threshold: Float!) {
    patchDriftMonitor(
      input: { monitorId: $monitorId, set: { threshold: $threshold, dynamicAutoThresholdEnabled: false } }
    ) {
      monitor { id threshold }
    }
  }
  """


  def run(query, variables):
      resp = requests.post(GRAPHQL_URL, headers=HEADERS, json={"query": query, "variables": variables})
      resp.raise_for_status()
      payload = resp.json()
      if payload.get("errors"):
          raise RuntimeError(payload["errors"])
      return payload["data"]

  def raise_drift_thresholds(space_id, multiplier=1.1):
      after = None
      while True:
          connection = run(LIST_QUERY, {"spaceId": space_id, "after": after})["node"]["monitors"]
          for edge in connection["edges"]:
              monitor = edge["node"]
              new_threshold = monitor["threshold"] * multiplier
              run(PATCH_MUTATION, {"monitorId": monitor["id"], "threshold": new_threshold})
              print(f"{monitor['name']}: {monitor['threshold']} -> {new_threshold}")
          if not connection["pageInfo"]["hasNextPage"]:
              break
          after = connection["pageInfo"]["endCursor"]

  raise_drift_thresholds("<SPACE_ID>")
  ```
</CodeGroup>

Setting `dynamicAutoThresholdEnabled: false` alongside the new `threshold` matters: if a monitor already has dynamic auto-thresholds on, a manual `threshold` write is otherwise overwritten the next time the monitor recalculates.

Reference: [`patchDriftMonitor`](/docs/ax/graphql-reference/mutations/monitors#patchdriftmonitor).

## Switch a monitor to dynamic auto-thresholds

Instead of a fixed `threshold`, a monitor can recompute its threshold on a schedule as `mean +/- stdDevMultiplier * stdDev`. This works on any monitor type through the generic `patchMonitor` mutation.

<CodeGroup>
  ```graphql Mutation theme={"theme":{"light":"github-light-default","dark":"github-dark-default"}}
  mutation EnableAutoThreshold($monitorId: ID!, $stdDevMultiplier: Float!) {
    patchMonitor(
      input: {
        monitorId: $monitorId
        set: {
          dynamicAutoThresholdEnabled: true
          dynamicAutoThreshold: { stdDevMultiplier: $stdDevMultiplier }
        }
      }
    ) {
      monitor {
        id
        dynamicAutoThresholdEnabled
        threshold
      }
    }
  }
  ```

  ```json Variables theme={"theme":{"light":"github-light-default","dark":"github-dark-default"}}
  {
    "monitorId": "<MONITOR_ID>",
    "stdDevMultiplier": 2
  }
  ```
</CodeGroup>

Reference: [`patchMonitor`](/docs/ax/graphql-reference/mutations/monitors#patchmonitor).

## Schedule recurring downtime for a monitor

Downtime suppresses evaluation for a window that repeats on a cadence, useful for known maintenance windows or batch jobs that temporarily skew a metric.

<CodeGroup>
  ```graphql Mutation theme={"theme":{"light":"github-light-default","dark":"github-dark-default"}}
  mutation ScheduleDowntime(
    $monitorId: ID!
    $downtimeStart: DateTime!
    $durationHrs: PositiveInt!
    $frequencyDays: PositiveInt!
  ) {
    patchMonitor(
      input: {
        monitorId: $monitorId
        set: {
          downtimeStart: $downtimeStart
          downtimeDurationHrs: $durationHrs
          downtimeFrequencyDays: $frequencyDays
        }
      }
    ) {
      monitor {
        id
        downtimeStart
        downtimeDurationHrs
        downtimeFrequencyDays
      }
    }
  }
  ```

  ```json Variables theme={"theme":{"light":"github-light-default","dark":"github-dark-default"}}
  {
    "monitorId": "<MONITOR_ID>",
    "downtimeStart": "2026-01-01T00:00:00Z",
    "durationHrs": 4,
    "frequencyDays": 7
  }
  ```
</CodeGroup>

`downtimeDurationHrs` must be between 1 and 1344 hours (56 days), and `downtimeFrequencyDays` between 1 and 56 days.

Reference: [`patchMonitor`](/docs/ax/graphql-reference/mutations/monitors#patchmonitor).

## Trigger a monitor manually, then delete it

`triggerMonitor` forces an off-schedule evaluation, which is useful after you change a threshold and want to confirm the new condition immediately rather than waiting for the next evaluation interval. `deleteMonitor` removes a monitor permanently; there is no undo.

<CodeGroup>
  ```graphql Trigger theme={"theme":{"light":"github-light-default","dark":"github-dark-default"}}
  mutation TriggerMonitor($monitorId: ID!) {
    triggerMonitor(input: { monitorId: $monitorId }) {
      success
      monitor {
        id
        isTriggered
        status
      }
    }
  }
  ```

  ```graphql Delete theme={"theme":{"light":"github-light-default","dark":"github-dark-default"}}
  mutation DeleteMonitor($monitorId: ID!) {
    deleteMonitor(input: { monitorId: $monitorId }) {
      monitor {
        id
      }
    }
  }
  ```

  ```json Variables theme={"theme":{"light":"github-light-default","dark":"github-dark-default"}}
  {
    "monitorId": "<MONITOR_ID>"
  }
  ```
</CodeGroup>

Reference: [`triggerMonitor`](/docs/ax/graphql-reference/mutations/monitors#triggermonitor), [`deleteMonitor`](/docs/ax/graphql-reference/mutations/monitors#deletemonitor).

## Gotchas and behavior notes

1. **`currentMetricValue` and a patched `autoThresholdEnabled` are not real.** Older examples query `currentMetricValue` on `Monitor`, which does not exist; use `latestComputedValue` instead. Older examples also patch `autoThresholdEnabled` inside a `set` input, but the patch inputs (`DriftMonitorPatchInput`, `PerformanceMonitorPatchInput`, `DataQualityMonitorPatchInput`, `MonitorPatchInput`) only accept `dynamicAutoThresholdEnabled`. `Monitor` exposes both `autoThresholdEnabled` and `dynamicAutoThresholdEnabled` as read fields, which is easy to confuse with the patch-only name.
2. **Patched `filters` and `modelVersions` fully replace, not merge.** On every patch input, supplying either array replaces the monitor's existing list entirely. There is no append or partial update.
3. **You cannot change a monitor's metric type or dimension with a patch.** `driftMetric`, `performanceMetric`, `dataQualityMetric`, `dimensionName`, and `dimensionCategory` are set only at creation; no patch input exposes them. Delete and recreate the monitor to change what it measures.
4. **Range thresholds need the second set of fields.** `thresholdMode` defaults to `single`. Set it to `range` and also supply `threshold2`, `operator2`, and optionally `stdDevMultiplier2` to alert on both a lower and an upper bound.
5. **Evaluation window and delay are in seconds, not hours.** `evaluationWindowLengthSeconds` and `delaySeconds` are both seconds despite their schema descriptions mentioning hours. The default evaluation window is 259200 seconds (3 days).
6. **Account-level monitor usage limits are deprecated.** `Account.monitorUsage` is marked deprecated in the schema: monitors are no longer capped per pricing tier, so `limit` is always null and `limitReached` is always false.
7. **Integration contacts need an integration key, not an email.** `MonitorContactInput.notificationChannelType` defaults to `email`. For a paging or chat integration, set it to `integration` and pass `integrationKeyId` instead of `emailAddress`. Integration keys are created separately and are not part of the monitors mutations covered here.

<CardGroup cols={3}>
  <Card title="Monitor mutations reference" icon="book" href="/docs/ax/graphql-reference/mutations/monitors">
    Full argument and field listing for all nine monitor mutations.
  </Card>

  <Card title="All GraphQL mutations" icon="list" href="/docs/ax/graphql-reference/mutations">
    Browse mutations for every other domain.
  </Card>

  <Card title="API explorer" icon="terminal" href="/docs/ax/graphql-reference/overview/api-explorer">
    Try queries and mutations interactively with autocomplete.
  </Card>
</CardGroup>
