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

# Test a rule

> Run a saved rule once and see whether its condition matches.

```http theme={null}
POST /api/v1/alerts/rules/{id}/test
```

Runs the query of a saved rule once over the window from `now - period_secs` to `now` and reports whether the condition matches. The call changes nothing. It does not touch the evaluation state, incidents, notifications, or the rule itself. The call requires `alerts.manage`, and the body is empty.

Test a rule before setting `enabled` to `true`. A rule with an invalid statement or an unknown stream is stored without an error, and only the test shows the problem.

An [APM rule](https://docs.molesignal.com/en-US/api/alerting/create-rule.md#apm-rules) reads its figure instead of running a query. Its result has the columns `value`, `service`, and `trace_id` in one row, or no row when the figure has no value in the window.

A [rule split by columns](https://docs.molesignal.com/en-US/api/alerting/create-rule.md#rules-split-by-columns) lists every group in `groups`. Its `matched` is `true` when any group matches, `value` is the value of the first group that matches, and `severity` is the highest among the groups.

A [RUM rule](https://docs.molesignal.com/en-US/api/alerting/create-rule.md#rum-rules) reads its figure the same way. Its result has the columns `value` and `application` in one row, or no row when the figure has no value in the window, and `scanned_rows` is how many rows the figure is made of.

```bash cURL theme={null}
curl -X POST http://localhost:5080/api/v1/alerts/rules/$RULE_ID/test \
  -H "authorization: Bearer $MS_JWT"
```

```json 200 theme={null}
{
  "matched": true,
  "value": 2.0,
  "severity": "critical",
  "columns": ["c"],
  "rows": [[2]],
  "scanned_rows": 2,
  "took_ms": 170
}
```

**Response**

| Field | Type | Notes |
| - | - | - |
| `matched` | boolean | Whether the condition matches now. The result ignores `for_periods`. |
| `value` | number or null | The first column of the first row. `null` when the result holds no number. |
| `severity` | string or null | The severity that an incident would get. `null` when `matched` is `false`. |
| `columns` | array | The column names of the query result. |
| `rows` | array | Up to 20 rows of the result. |
| `scanned_rows` | integer | Rows scanned by the query. |
| `took_ms` | integer | Query duration in milliseconds. |
| `anomaly` | object | Only for `anomaly` rules. Holds `baseline`, `deviation`, `score` from 0 to 1, and a `reason` text. |
| `no_data` | boolean | Only when `true`: the run had no value, and the rule does not count a missing value as `0`. |
| `groups` | array | Only for a rule split by columns, in the order of the result. Each group has `labels`, a map of the columns to its values, and its `value`, `matched`, and `severity`. |
| `groups_truncated` | boolean | Only when `true`: the result has more than 100 groups, and the rest are left out. |

**Errors**

| Status | Cause |
| - | - |
| `400` | The query cannot run, for example because of invalid SQL or an unknown field, or an `anomaly` rule has no usable history for a baseline. |
| `403` | The stream of the rule does not exist, or the token lacks `alerts.manage`. |
| `404` | The rule does not exist. |


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.