# Create a cluster monitor

## `POST /v1/clusters/{clusterId}/monitors`

Creates and provisions a cluster monitor. Requires `monitors:write` and organization admin privileges.

### Path parameters

- `clusterId` (string, required)

### Header parameters

- `Authorization` (string, required): `Bearer <token>`. [Authentication](https://spice.ai/docs/cloud/api/management#authentication) lists the tokens it accepts.
- `X-Org-Name` (string, optional): The organization to act on, by handle. Omit it to act on the organization the credential is bound to; sending it blank is a 400, not the same as omitting it. A user credential may name any organization its owner belongs to; a machine credential is pinned to its own. A portal session token is bound to none, so it must send this header on every route but `GET /v1/orgs` (400 `org_assertion_required` otherwise). Pattern: `^[A-Za-z0-9._-]{1,255}$`.

### Request body

Required.

Content type: `application/json`

- `name` (string, required): Minimum length: `1`. Maximum length: `100`.
- `description` (string): Maximum length: `500`.
- `templateId` (string, required): Allowed values: `cluster_cpu`, `cluster_memory`, `cluster_availability`.
- `spec` (object, required)
  - `op` (string, required): Allowed values: `GT`, `GEQ`, `LT`, `LEQ`, `EQ`, `NEQ`.
  - `threshold` (number, required)
  - `window` (string): Allowed values: `1m`, `5m`, `15m`, `30m`, `1h`. Default: `5m`.
  - `sustainSecs` (integer): Default: `300`. Minimum: `0`. Maximum: `86400`.
  - `severity` (string): Allowed values: `warn`, `critical`. Default: `critical`.
  - `dataset` (string): Minimum length: `1`. Maximum length: `128`. Pattern: `^(?!.*\.\.)[A-Za-z_][A-Za-z0-9_.-]*$`.
  - `column` (string): Minimum length: `1`. Maximum length: `64`. Pattern: `^[A-Za-z_][A-Za-z0-9_]*$`.
  - `value` (string | number)
  - `datasets` (array of string): Maximum items: `20`.
  - `conditions` (array of object): Maximum items: `20`.
    - `dataset` (string, required): Minimum length: `1`. Maximum length: `128`. Pattern: `^(?!.*\.\.)[A-Za-z_][A-Za-z0-9_.-]*$`.
    - `column` (string, required): Minimum length: `1`. Maximum length: `64`. Pattern: `^[A-Za-z_][A-Za-z0-9_]*$`.
    - `op` (string, required): Allowed values: `EQ`, `NEQ`, `GT`, `GEQ`, `LT`, `LEQ`, `CONTAINS`, `STARTS_WITH`, `ENDS_WITH`, `IS_NULL`, `IS_NOT_NULL`.
    - `value` (string | number)
  - `queryLanguage` (string): Allowed values: `cypher`, `gql`.
  - `returnFields` (array of object): Dataset fields returned by generated row-match queries. Include identity and all monitored fields. Maximum items: `20`.
    - `dataset` (string, required)
    - `columns` (array of string, required): Minimum items: `1`. Maximum items: `1000`.
  - `query` (string): Maximum length: `10000`.
  - `includeDetails` (boolean)
- `target` (object): Omit to email the caller, or the organization owner for a machine credential.

  One of:
  - **type: email** (object)
    - `type` (string, required): Value: `email`.
    - `recipientUserIds` (array of integer): Organization members to email, by user ID. Maximum items: `50`.
    - `emails` (array of string (email)): Maximum items: `20`.
  - **type: http** (object)
    - `type` (string, required): Value: `http`.
    - `url` (string (uri), required): The URL each notification is sent to, using `method`. Must be https and must resolve to a public address. Minimum length: `1`. Maximum length: `2048`.
    - `method` (string): A create that omits it uses POST. An update that omits it keeps the stored method. Allowed values: `POST`, `PUT`, `PATCH`.
    - `token` (string): Bearer token sent with each delivery. Stored encrypted and never returned. Minimum length: `1`. Maximum length: `512`.
  - **type: slack** (object)
    - `type` (string, required): Value: `slack`.
    - `channelId` (string, required): Slack conversation id. The organization must already have Slack connected. Minimum length: `9`. Maximum length: `32`. Pattern: `^[CGD][A-Z0-9]{8,31}$`.
    - `channelName` (string): Minimum length: `1`. Maximum length: `80`.
- `targets` (array of object): Full destination set. When present, this replaces `target`. At most one sink of each type. Minimum items: `1`. Maximum items: `3`.

  One of:
  - **type: email** (object)
    - `type` (string, required): Value: `email`.
    - `recipientUserIds` (array of integer): Organization members to email, by user ID. Maximum items: `50`.
    - `emails` (array of string (email)): Maximum items: `20`.
  - **type: http** (object)
    - `type` (string, required): Value: `http`.
    - `url` (string (uri), required): The URL each notification is sent to, using `method`. Must be https and must resolve to a public address. Minimum length: `1`. Maximum length: `2048`.
    - `method` (string): A create that omits it uses POST. An update that omits it keeps the stored method. Allowed values: `POST`, `PUT`, `PATCH`.
    - `token` (string): Bearer token sent with each delivery. Stored encrypted and never returned. Minimum length: `1`. Maximum length: `512`.
  - **type: slack** (object)
    - `type` (string, required): Value: `slack`.
    - `channelId` (string, required): Slack conversation id. The organization must already have Slack connected. Minimum length: `9`. Maximum length: `32`. Pattern: `^[CGD][A-Z0-9]{8,31}$`.
    - `channelName` (string): Minimum length: `1`. Maximum length: `80`.
- `recipientUserIds` (array of integer)

### Example request

```bash
curl -X POST "https://api.spice.ai/v1/clusters/<clusterId>/monitors" \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "string",
    "templateId": "cluster_cpu",
    "spec": {
      "op": "GT",
      "threshold": 0
    }
  }'
```

```http
POST /v1/clusters/<clusterId>/monitors HTTP/1.1
Host: api.spice.ai
Authorization: Bearer <token>
Content-Type: application/json
Content-Length: 105

{
  "name": "string",
  "templateId": "cluster_cpu",
  "spec": {
    "op": "GT",
    "threshold": 0
  }
}
```

### Responses

**201 Created**

Monitor created

**400 Bad Request**

Invalid request body or monitor configuration, or the cluster already has 20 live monitors

**401 Unauthorized**

Unauthorized

**403 Forbidden**

Insufficient scope or role

**404 Not Found**

Cluster not found

**409 Conflict**

Duplicate monitor name or monitor deleted during creation

Content type: `application/json`

- `error` (string, required)
- `code` (string, required): Allowed values: `monitor_name_conflict`, `monitor_deleted_during_creation`.

**413 Content Too Large**

Request body too large

**422 Unprocessable Content**

Destination is unavailable

**500 Internal Server Error**

Internal server error

**502 Bad Gateway**

Monitor provisioning or cleanup failed. If cleanup is pending, the response includes the monitor ID for a retry with DELETE.

## `POST /v1/orgs/{orgId}/clusters/{clusterId}/monitors`

The org is `orgId` in the path. Creates and provisions a cluster monitor. Requires `monitors:write` and organization admin privileges.

### Path parameters

- `orgId` (integer, required): The org id from GET /v1/orgs. Minimum: `1`.
- `clusterId` (string, required)

### Header parameters

- `Authorization` (string, required): `Bearer <token>`. [Authentication](https://spice.ai/docs/cloud/api/management#authentication) lists the tokens it accepts.
- `X-Org-Name` (string, optional): When present, X-Org-Name must name the same org as orgId. Otherwise the request returns org\_path\_mismatch (400). Pattern: `^[A-Za-z0-9._-]{1,255}$`.

### Request body

Required.

Content type: `application/json`

- `name` (string, required): Minimum length: `1`. Maximum length: `100`.
- `description` (string): Maximum length: `500`.
- `templateId` (string, required): Allowed values: `cluster_cpu`, `cluster_memory`, `cluster_availability`.
- `spec` (object, required)
  - `op` (string, required): Allowed values: `GT`, `GEQ`, `LT`, `LEQ`, `EQ`, `NEQ`.
  - `threshold` (number, required)
  - `window` (string): Allowed values: `1m`, `5m`, `15m`, `30m`, `1h`. Default: `5m`.
  - `sustainSecs` (integer): Default: `300`. Minimum: `0`. Maximum: `86400`.
  - `severity` (string): Allowed values: `warn`, `critical`. Default: `critical`.
  - `dataset` (string): Minimum length: `1`. Maximum length: `128`. Pattern: `^(?!.*\.\.)[A-Za-z_][A-Za-z0-9_.-]*$`.
  - `column` (string): Minimum length: `1`. Maximum length: `64`. Pattern: `^[A-Za-z_][A-Za-z0-9_]*$`.
  - `value` (string | number)
  - `datasets` (array of string): Maximum items: `20`.
  - `conditions` (array of object): Maximum items: `20`.
    - `dataset` (string, required): Minimum length: `1`. Maximum length: `128`. Pattern: `^(?!.*\.\.)[A-Za-z_][A-Za-z0-9_.-]*$`.
    - `column` (string, required): Minimum length: `1`. Maximum length: `64`. Pattern: `^[A-Za-z_][A-Za-z0-9_]*$`.
    - `op` (string, required): Allowed values: `EQ`, `NEQ`, `GT`, `GEQ`, `LT`, `LEQ`, `CONTAINS`, `STARTS_WITH`, `ENDS_WITH`, `IS_NULL`, `IS_NOT_NULL`.
    - `value` (string | number)
  - `queryLanguage` (string): Allowed values: `cypher`, `gql`.
  - `returnFields` (array of object): Dataset fields returned by generated row-match queries. Include identity and all monitored fields. Maximum items: `20`.
    - `dataset` (string, required)
    - `columns` (array of string, required): Minimum items: `1`. Maximum items: `1000`.
  - `query` (string): Maximum length: `10000`.
  - `includeDetails` (boolean)
- `target` (object): Omit to email the caller, or the organization owner for a machine credential.

  One of:
  - **type: email** (object)
    - `type` (string, required): Value: `email`.
    - `recipientUserIds` (array of integer): Organization members to email, by user ID. Maximum items: `50`.
    - `emails` (array of string (email)): Maximum items: `20`.
  - **type: http** (object)
    - `type` (string, required): Value: `http`.
    - `url` (string (uri), required): The URL each notification is sent to, using `method`. Must be https and must resolve to a public address. Minimum length: `1`. Maximum length: `2048`.
    - `method` (string): A create that omits it uses POST. An update that omits it keeps the stored method. Allowed values: `POST`, `PUT`, `PATCH`.
    - `token` (string): Bearer token sent with each delivery. Stored encrypted and never returned. Minimum length: `1`. Maximum length: `512`.
  - **type: slack** (object)
    - `type` (string, required): Value: `slack`.
    - `channelId` (string, required): Slack conversation id. The organization must already have Slack connected. Minimum length: `9`. Maximum length: `32`. Pattern: `^[CGD][A-Z0-9]{8,31}$`.
    - `channelName` (string): Minimum length: `1`. Maximum length: `80`.
- `targets` (array of object): Full destination set. When present, this replaces `target`. At most one sink of each type. Minimum items: `1`. Maximum items: `3`.

  One of:
  - **type: email** (object)
    - `type` (string, required): Value: `email`.
    - `recipientUserIds` (array of integer): Organization members to email, by user ID. Maximum items: `50`.
    - `emails` (array of string (email)): Maximum items: `20`.
  - **type: http** (object)
    - `type` (string, required): Value: `http`.
    - `url` (string (uri), required): The URL each notification is sent to, using `method`. Must be https and must resolve to a public address. Minimum length: `1`. Maximum length: `2048`.
    - `method` (string): A create that omits it uses POST. An update that omits it keeps the stored method. Allowed values: `POST`, `PUT`, `PATCH`.
    - `token` (string): Bearer token sent with each delivery. Stored encrypted and never returned. Minimum length: `1`. Maximum length: `512`.
  - **type: slack** (object)
    - `type` (string, required): Value: `slack`.
    - `channelId` (string, required): Slack conversation id. The organization must already have Slack connected. Minimum length: `9`. Maximum length: `32`. Pattern: `^[CGD][A-Z0-9]{8,31}$`.
    - `channelName` (string): Minimum length: `1`. Maximum length: `80`.
- `recipientUserIds` (array of integer)

### Example request

```bash
curl -X POST "https://api.spice.ai/v1/orgs/<orgId>/clusters/<clusterId>/monitors" \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "string",
    "templateId": "cluster_cpu",
    "spec": {
      "op": "GT",
      "threshold": 0
    }
  }'
```

```http
POST /v1/orgs/<orgId>/clusters/<clusterId>/monitors HTTP/1.1
Host: api.spice.ai
Authorization: Bearer <token>
Content-Type: application/json
Content-Length: 105

{
  "name": "string",
  "templateId": "cluster_cpu",
  "spec": {
    "op": "GT",
    "threshold": 0
  }
}
```

### Responses

**201 Created**

Monitor created

**400 Bad Request**

Invalid request body or monitor configuration, or the cluster already has 20 live monitors. orgId is not a valid org id (`invalid_org_id`), or X-Org-Name does not name that org (`org_path_mismatch`).

**401 Unauthorized**

Unauthorized

**403 Forbidden**

Insufficient scope or role. The caller is not a member of the org (`org_forbidden`). A machine credential named a different org (`org_assertion_mismatch`). The org is deleted (`org_deleted`).

**404 Not Found**

Cluster not found

**409 Conflict**

Duplicate monitor name or monitor deleted during creation

Content type: `application/json`

- `error` (string, required)
- `code` (string, required): Allowed values: `monitor_name_conflict`, `monitor_deleted_during_creation`.

**413 Content Too Large**

Request body too large

**422 Unprocessable Content**

Destination is unavailable

**500 Internal Server Error**

Internal server error

**502 Bad Gateway**

Monitor provisioning or cleanup failed. If cleanup is pending, the response includes the monitor ID for a retry with DELETE.

OpenAPI: [api.spice.ai/openapi.json](https://api.spice.ai/openapi.json)
