# Alerts

> Log and metric alert rules.

Log and metric alert rules.

| Operation | Method and path |
| --- | --- |
| [List alert rules](#list-alert-rules) | `GET /v1/projects/{project}/alerts` |
| [Create an alert rule](#create-an-alert-rule) | `POST /v1/projects/{project}/alerts` |
| [Delete an alert rule](#delete-an-alert-rule) | `DELETE /v1/projects/{project}/alerts/{alert_id}` |

## List alert rules

```http
GET /v1/projects/{project}/alerts
```

- **Operation:** `listAlertRules`
- **Scopes:** `projects:read`
- **Paginated:** `?limit=` and `?cursor=`

**Parameters**

| Name | In | Type | Description |
| --- | --- | --- | --- |
| `project` * | path | string | Project id (`prj_…`) or slug (resolved in the `Guv-Workspace` workspace, or the caller's default). |

**Responses**

| Status | Meaning | Body |
| --- | --- | --- |
| `200` OK | A page of AlertRule objects. | [AlertRuleList](/docs/api/objects/alert-rule-list/) |

**Errors:** `400`, `401`, `403`, `404`, `429`, `500`, as [problem+json](/errors/) with a stable `code`.

**Example**

```bash
curl https://api.guv.dev/v1/projects/shopfront/alerts \
  -H "Authorization: Bearer $GUV_TOKEN"
```

**Example response**

```json
{
  "data": [
    {
      "id": "alr_01jbx2m9k7q4r8t5v6w3y0z1pr",
      "name": "string",
      "environment_id": "string",
      "expression": "logs(service=api, level=error) > 20/min",
      "notify": [
        "email:ops@primecarers.co.uk"
      ],
      "enabled": false,
      "managed_by_manifest": false,
      "last_fired_at": "2026-10-22T13:05:00Z",
      "created_at": "2026-10-22T13:05:00Z"
    }
  ],
  "next_cursor": "string",
  "has_more": false
}
```

## Create an alert rule

```http
POST /v1/projects/{project}/alerts
```

- **Operation:** `createAlertRule`
- **Scopes:** `projects:write`
- **Idempotency-Key:** required; supports `?dry_run=true`

**Parameters**

| Name | In | Type | Description |
| --- | --- | --- | --- |
| `project` * | path | string | Project id (`prj_…`) or slug (resolved in the `Guv-Workspace` workspace, or the caller's default). |

**Request body** (`application/json`, required): [AlertRuleCreate](/docs/api/objects/alert-rule-create/)

| Field | Type | Description |
| --- | --- | --- |
| `name` * | string |  |
| `environment` | string |  |
| `expression` * | string |  |
| `notify` * | array of string |  |
| `enabled` | boolean | Default `true`. |

**Responses**

| Status | Meaning | Body |
| --- | --- | --- |
| `200` OK | Dry run. Nothing was changed; this is what would happen. | [Plan](/docs/api/objects/plan/) |
| `201` Created | Created. | [AlertRule](/docs/api/objects/alert-rule/) |

**Errors:** `400`, `401`, `403`, `404`, `409`, `422`, `429`, `500`, as [problem+json](/errors/) with a stable `code`.

**Example**

```bash
curl -X POST https://api.guv.dev/v1/projects/shopfront/alerts \
  -H "Authorization: Bearer $GUV_TOKEN" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
  "name": "string",
  "environment": "string",
  "expression": "string",
  "notify": [
    "string"
  ],
  "enabled": true
}'
```

**Example response**

```json
{
  "id": "alr_01jbx2m9k7q4r8t5v6w3y0z1pr",
  "name": "string",
  "environment_id": "string",
  "expression": "logs(service=api, level=error) > 20/min",
  "notify": [
    "email:ops@primecarers.co.uk"
  ],
  "enabled": false,
  "managed_by_manifest": false,
  "last_fired_at": "2026-10-22T13:05:00Z",
  "created_at": "2026-10-22T13:05:00Z"
}
```

## Delete an alert rule

```http
DELETE /v1/projects/{project}/alerts/{alert_id}
```

- **Operation:** `deleteAlertRule`
- **Scopes:** `projects:write`
- **Idempotency-Key:** required; supports `?dry_run=true`
- **Concurrency:** send the `ETag` you read as `If-Match`

**Parameters**

| Name | In | Type | Description |
| --- | --- | --- | --- |
| `project` * | path | string | Project id (`prj_…`) or slug (resolved in the `Guv-Workspace` workspace, or the caller's default). |
| `alert_id` * | path | string |  |

**Responses**

| Status | Meaning | Body |
| --- | --- | --- |
| `200` OK | Dry run. Nothing was changed; this is what would happen. | [Plan](/docs/api/objects/plan/) |
| `204` No Content | Done. No body. | none |

**Errors:** `400`, `401`, `403`, `404`, `409`, `412`, `422`, `429`, `500`, as [problem+json](/errors/) with a stable `code`.

**Example**

```bash
curl -X DELETE https://api.guv.dev/v1/projects/shopfront/alerts/ale_01jbx2m9k7q4r8t5v6w3y0z1pr \
  -H "Authorization: Bearer $GUV_TOKEN" \
  -H "Idempotency-Key: $(uuidgen)"
```
