---
title: Alerts
description: Create and manage alerts for email, Slack, Discord, PagerDuty, and webhook notifications. Maximum 10 per team.
section:
  title: API Resources
  order: 7
order: 7
lastUpdated: 2026-10-24
---

Alerts notify you when monitors detect issues. Each team can have up to 10 alerts with different notification strategies: email, webhook, Slack, Discord, or PagerDuty.

Sensitive data such as webhook URLs, signing secrets and PagerDuty integration keys are never returned in API responses for security.

## Repeat Behaviour

`cooldownMinutes` controls how far apart _repeat_ notifications are spaced while a monitor stays broken. For one outage an alert notifies:

1. **Immediately** on the first failing check. The first notification of an outage ignores `cooldownMinutes` entirely, so no value you set can delay it.
2. **Again every `cooldownMinutes`** for as long as the monitor stays broken. Nothing bounds the total number of notifications one outage produces.
3. **Once on recovery**, when `notifyOnRecovery` is `true`.

Repeats are additionally floored at **five minutes**: however low `cooldownMinutes` is, repeats are never sent more often than once every five minutes. A `cooldownMinutes` of `0` therefore means "as often as allowed" (at most 12 notifications an hour), not one notification per check. The floor does not apply to the recovery notification, which is spaced only by the `cooldownMinutes` you set.

Omitting `cooldownMinutes` defaults it to `60` — one hour — matching the default an alert created in the dashboard gets. Send `0` explicitly if you want repeats as often as the floor allows.

## GET /api/v1/alerts

Returns the alerts for your team. This endpoint is paginated; see [Pagination](/docs/api/pagination) for how to walk the whole list.

**Required scope:** `alerts:read`

### Errors

| Status | Type | Description |
| --- | --- | --- |
| 400 | `bad-request` | The request is malformed |
| 401 | `unauthorized` | The API key is missing or invalid |
| 403 | `forbidden` | The API key lacks the required scope |

### Response Schema

```json
{
	"$schema": "https://json-schema.org/draft/2020-12/schema",
	"type": "object",
	"properties": {
		"data": {
			"type": "object",
			"properties": {
				"alerts": {
					"type": "array",
					"items": {
						"$ref": "#/$defs/Alert"
					}
				}
			},
			"required": [
				"alerts"
			]
		},
		"meta": {
			"type": "object",
			"properties": {
				"requestId": {
					"type": "string",
					"format": "uuid"
				},
				"timestamp": {
					"type": "string",
					"format": "date-time"
				},
				"pagination": {
					"$ref": "#/$defs/Pagination"
				}
			},
			"required": [
				"requestId",
				"timestamp",
				"pagination"
			]
		}
	},
	"required": [
		"data",
		"meta"
	],
	"$defs": {
		"Alert": {
			"type": "object",
			"properties": {
				"id": {
					"type": "string",
					"pattern": "^alt_[0-7][0-9a-hjkmnp-tv-z]{25}$"
				},
				"name": {
					"type": "string"
				},
				"notifyOnRecovery": {
					"type": "boolean"
				},
				"cooldownMinutes": {
					"type": "integer"
				},
				"config": {
					"oneOf": [
						{
							"type": "object",
							"properties": {
								"strategy": {
									"type": "string",
									"const": "email"
								},
								"to": {
									"type": "string"
								},
								"subjectPrefix": {
									"type": "string"
								}
							},
							"required": [
								"strategy",
								"to",
								"subjectPrefix"
							]
						},
						{
							"type": "object",
							"properties": {
								"strategy": {
									"type": "string",
									"const": "webhook"
								},
								"signature": {
									"type": "string",
									"enum": [
										"standard-webhooks",
										"legacy"
									],
									"description": "`standard-webhooks` signs with `webhook-id`, `webhook-timestamp` and `webhook-signature: v1,<base64>`; `legacy` with `Webhook-Signature: sha256=<hex>`"
								}
							},
							"required": [
								"strategy",
								"signature"
							]
						},
						{
							"type": "object",
							"properties": {
								"strategy": {
									"type": "string",
									"const": "slack"
								}
							},
							"required": [
								"strategy"
							]
						},
						{
							"type": "object",
							"properties": {
								"strategy": {
									"type": "string",
									"const": "discord"
								}
							},
							"required": [
								"strategy"
							]
						},
						{
							"type": "object",
							"properties": {
								"strategy": {
									"type": "string",
									"const": "pagerduty"
								}
							},
							"required": [
								"strategy"
							]
						}
					],
					"discriminator": {
						"propertyName": "strategy"
					}
				},
				"monitorType": {
					"type": [
						"string",
						"null"
					],
					"enum": [
						"http",
						"dns",
						"tcp",
						"cron",
						"flow",
						null
					],
					"description": "Monitor type the alert covers; null covers every type"
				},
				"monitorId": {
					"type": [
						"string",
						"null"
					],
					"description": "The one monitor the alert covers; null covers the whole type"
				},
				"createdAt": {
					"type": "integer",
					"description": "Epoch milliseconds"
				},
				"updatedAt": {
					"type": "integer",
					"description": "Epoch milliseconds"
				}
			},
			"required": [
				"id",
				"name",
				"notifyOnRecovery",
				"cooldownMinutes",
				"config",
				"monitorType",
				"monitorId",
				"createdAt",
				"updatedAt"
			]
		},
		"Pagination": {
			"type": "object",
			"properties": {
				"next": {
					"type": [
						"string",
						"null"
					],
					"description": "Cursor of the following page"
				},
				"prev": {
					"type": [
						"string",
						"null"
					],
					"description": "Cursor of the preceding page"
				},
				"perPage": {
					"type": "integer"
				},
				"total": {
					"type": "integer"
				}
			},
			"required": [
				"next",
				"prev",
				"perPage"
			]
		}
	}
}
```

### Query Parameters

| Parameter | Type    | Required | Description                               |
| --------- | ------- | -------- | ----------------------------------------- |
| `perPage` | integer | No       | Results per page, 1-200 (default: 50)     |
| `cursor`  | string  | No       | Page to fetch, taken from a `Link` header |

### Example Request

#### cURL

```bash
curl "https://uptime.sergiodxa.com/api/v1/alerts?perPage=25" \
  -H "Authorization: Bearer uptime_your_api_key"
```

### Response

```json
{
	"data": {
		"alerts": [
			{
				"id": "alt_abc123",
				"name": "Email Alert",
				"notifyOnRecovery": true,
				"cooldownMinutes": 5,
				"config": {
					"strategy": "email",
					"to": "ops@example.com",
					"subjectPrefix": "[Uptime]"
				},
				"monitorType": null,
				"monitorId": null,
				"createdAt": 1771070400000,
				"updatedAt": 1771070400000
			},
			{
				"id": "alt_def456",
				"name": "Slack Notifications",
				"notifyOnRecovery": true,
				"cooldownMinutes": 0,
				"config": {
					"strategy": "slack"
				},
				"monitorType": "http",
				"monitorId": "mon_abc123",
				"createdAt": 1771074000000,
				"updatedAt": 1771074000000
			}
		]
	},
	"meta": {
		"requestId": "3f2504e0-4f89-11d3-9a0c-0305e82c3301",
		"timestamp": "2026-02-14T12:00:00.000Z",
		"pagination": {
			"next": null,
			"prev": null,
			"perPage": 25,
			"total": 2
		}
	}
}
```

Webhook URLs, secrets and integration keys stay out of `config`, so a Slack, Discord or PagerDuty alert reports only its `strategy`, and a webhook alert its `strategy` and `signature` scheme.

## POST /api/v1/alerts

Creates a new alert. The request body varies based on the notification strategy.

**Required scope:** `alerts:write`

### Errors

| Status | Type | Description |
| --- | --- | --- |
| 400 | `validation-error` | The request failed validation |
| 400 | `limit-exceeded` | The team has reached its limit for this resource |
| 400 | `idempotency-key-invalid` | The Idempotency-Key header is not valid |
| 401 | `unauthorized` | The API key is missing or invalid |
| 403 | `forbidden` | The API key lacks the required scope |
| 404 | `not-found` | The resource does not exist |
| 409 | `idempotency-key-in-use` | A request with this idempotency key is still being processed |
| 422 | `idempotency-key-reused` | This idempotency key was already used for a different request |

### Request Body Schema

```json
{
	"$schema": "https://json-schema.org/draft/2020-12/schema",
	"oneOf": [
		{
			"type": "object",
			"properties": {
				"strategy": {
					"type": "string",
					"const": "email"
				},
				"email": {
					"type": "string",
					"format": "email"
				},
				"subjectPrefix": {
					"type": "string",
					"maxLength": 100
				},
				"name": {
					"type": "string",
					"minLength": 1,
					"maxLength": 255
				},
				"notifyOnRecovery": {
					"type": "boolean",
					"default": true
				},
				"cooldownMinutes": {
					"type": "number",
					"minimum": 0,
					"maximum": 1440,
					"default": 60
				},
				"monitorType": {
					"type": "string",
					"enum": [
						"http",
						"dns",
						"tcp",
						"cron",
						"flow"
					],
					"description": "Defaults to `http` beside a `monitorId`"
				},
				"monitorId": {
					"type": "string"
				}
			},
			"required": [
				"strategy",
				"email",
				"name"
			]
		},
		{
			"type": "object",
			"properties": {
				"strategy": {
					"type": "string",
					"const": "webhook"
				},
				"url": {
					"type": "string",
					"format": "uri"
				},
				"secret": {
					"type": "string",
					"maxLength": 255
				},
				"signature": {
					"type": "string",
					"enum": [
						"standard-webhooks",
						"legacy"
					],
					"description": "`standard-webhooks` signs with `webhook-id`, `webhook-timestamp` and `webhook-signature: v1,<base64>`; `legacy` with `Webhook-Signature: sha256=<hex>`",
					"default": "standard-webhooks"
				},
				"name": {
					"type": "string",
					"minLength": 1,
					"maxLength": 255
				},
				"notifyOnRecovery": {
					"type": "boolean",
					"default": true
				},
				"cooldownMinutes": {
					"type": "number",
					"minimum": 0,
					"maximum": 1440,
					"default": 60
				},
				"monitorType": {
					"type": "string",
					"enum": [
						"http",
						"dns",
						"tcp",
						"cron",
						"flow"
					],
					"description": "Defaults to `http` beside a `monitorId`"
				},
				"monitorId": {
					"type": "string"
				}
			},
			"required": [
				"strategy",
				"url",
				"name"
			]
		},
		{
			"type": "object",
			"properties": {
				"strategy": {
					"type": "string",
					"const": "slack"
				},
				"webhookUrl": {
					"type": "string",
					"format": "uri",
					"description": "A Slack incoming webhook URL on `https://hooks.slack.com/`"
				},
				"name": {
					"type": "string",
					"minLength": 1,
					"maxLength": 255
				},
				"notifyOnRecovery": {
					"type": "boolean",
					"default": true
				},
				"cooldownMinutes": {
					"type": "number",
					"minimum": 0,
					"maximum": 1440,
					"default": 60
				},
				"monitorType": {
					"type": "string",
					"enum": [
						"http",
						"dns",
						"tcp",
						"cron",
						"flow"
					],
					"description": "Defaults to `http` beside a `monitorId`"
				},
				"monitorId": {
					"type": "string"
				}
			},
			"required": [
				"strategy",
				"webhookUrl",
				"name"
			]
		},
		{
			"type": "object",
			"properties": {
				"strategy": {
					"type": "string",
					"const": "discord"
				},
				"webhookUrl": {
					"type": "string",
					"format": "uri",
					"description": "A Discord webhook URL on `https://discord.com/api/webhooks/`"
				},
				"name": {
					"type": "string",
					"minLength": 1,
					"maxLength": 255
				},
				"notifyOnRecovery": {
					"type": "boolean",
					"default": true
				},
				"cooldownMinutes": {
					"type": "number",
					"minimum": 0,
					"maximum": 1440,
					"default": 60
				},
				"monitorType": {
					"type": "string",
					"enum": [
						"http",
						"dns",
						"tcp",
						"cron",
						"flow"
					],
					"description": "Defaults to `http` beside a `monitorId`"
				},
				"monitorId": {
					"type": "string"
				}
			},
			"required": [
				"strategy",
				"webhookUrl",
				"name"
			]
		},
		{
			"type": "object",
			"properties": {
				"strategy": {
					"type": "string",
					"const": "pagerduty"
				},
				"routingKey": {
					"type": "string",
					"pattern": "\\S",
					"maxLength": 255,
					"description": "The integration key of a PagerDuty service's Events API v2 integration"
				},
				"name": {
					"type": "string",
					"minLength": 1,
					"maxLength": 255
				},
				"notifyOnRecovery": {
					"type": "boolean",
					"default": true
				},
				"cooldownMinutes": {
					"type": "number",
					"minimum": 0,
					"maximum": 1440,
					"default": 60
				},
				"monitorType": {
					"type": "string",
					"enum": [
						"http",
						"dns",
						"tcp",
						"cron",
						"flow"
					],
					"description": "Defaults to `http` beside a `monitorId`"
				},
				"monitorId": {
					"type": "string"
				}
			},
			"required": [
				"strategy",
				"routingKey",
				"name"
			]
		}
	],
	"discriminator": {
		"propertyName": "strategy"
	}
}
```

### Response Schema

```json
{
	"$schema": "https://json-schema.org/draft/2020-12/schema",
	"type": "object",
	"properties": {
		"data": {
			"type": "object",
			"properties": {
				"alert": {
					"$ref": "#/$defs/AlertSummary"
				}
			},
			"required": [
				"alert"
			]
		},
		"meta": {
			"type": "object",
			"properties": {
				"requestId": {
					"type": "string",
					"format": "uuid"
				},
				"timestamp": {
					"type": "string",
					"format": "date-time"
				}
			},
			"required": [
				"requestId",
				"timestamp"
			]
		}
	},
	"required": [
		"data",
		"meta"
	],
	"$defs": {
		"AlertSummary": {
			"type": "object",
			"properties": {
				"id": {
					"type": "string",
					"pattern": "^alt_[0-7][0-9a-hjkmnp-tv-z]{25}$"
				},
				"name": {
					"type": "string"
				},
				"notifyOnRecovery": {
					"type": "boolean"
				},
				"cooldownMinutes": {
					"type": "integer"
				},
				"monitorType": {
					"type": [
						"string",
						"null"
					],
					"enum": [
						"http",
						"dns",
						"tcp",
						"cron",
						"flow",
						null
					],
					"description": "Monitor type the alert covers; null covers every type"
				},
				"monitorId": {
					"type": [
						"string",
						"null"
					],
					"description": "The one monitor the alert covers; null covers the whole type"
				},
				"config": {
					"type": "object",
					"properties": {
						"strategy": {
							"type": "string",
							"enum": [
								"email",
								"webhook",
								"slack",
								"discord",
								"pagerduty"
							]
						}
					},
					"required": [
						"strategy"
					]
				},
				"createdAt": {
					"type": "integer",
					"description": "Epoch milliseconds"
				},
				"updatedAt": {
					"type": "integer",
					"description": "Epoch milliseconds"
				}
			},
			"required": [
				"id",
				"name",
				"notifyOnRecovery",
				"cooldownMinutes",
				"monitorType",
				"monitorId",
				"config",
				"createdAt",
				"updatedAt"
			]
		}
	}
}
```

### Common Fields

| Field              | Type    | Required | Description                                                                                                                                                                                                                                                                                      |
| ------------------ | ------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `name`             | string  | Yes      | Display name for the alert, 1-255 characters                                                                                                                                                                                                                                                     |
| `strategy`         | string  | Yes      | One of: `email`, `webhook`, `slack`, `discord`, `pagerduty`                                                                                                                                                                                                                                      |
| `notifyOnRecovery` | boolean | No       | Send notification when monitor recovers (default: `true`)                                                                                                                                                                                                                                        |
| `cooldownMinutes`  | integer | No       | Minutes between repeat notifications while a monitor stays broken, 0-1440 (default: `60`; repeats are floored at 5 minutes, and the first notification of an outage is never delayed — see [Repeat Behaviour](#repeat-behaviour))                                                                |
| `monitorType`      | string  | No       | Limit the alert to one kind of monitor: `http`, `dns`, `tcp`, `cron` or `flow`. Sent on its own, the alert covers every monitor of that kind, including ones created later.                                                                                                                      |
| `monitorId`        | string  | No       | Limit the alert to a single monitor. Sent together with `monitorType`, the id is looked up in that kind's monitors; sent on its own it is read as an HTTP monitor, which is what it has always meant. The id carries the prefix of its kind: `mon_` (HTTP), `dns_`, `tcpm_`, `cron_` or `flow_`. |

### Strategy: Email

| Field           | Type   | Required | Description                                          |
| --------------- | ------ | -------- | ---------------------------------------------------- |
| `email`         | string | Yes      | Email address to notify                              |
| `subjectPrefix` | string | No       | Prefix for email subject lines, up to 100 characters |

### Strategy: Webhook

| Field       | Type   | Required | Description                                                                                                                                |
| ----------- | ------ | -------- | ------------------------------------------------------------------------------------------------------------------------------------------ |
| `url`       | string | Yes      | Webhook URL to POST notifications to                                                                                                       |
| `secret`    | string | No       | Secret every delivery is signed with, up to 255 characters                                                                                 |
| `signature` | string | No       | `standard-webhooks` (default) or `legacy`. See [Verifying Webhook Signatures](/docs/concepts/alerts#verifying-webhook-signatures) for both |

### Strategy: Slack

| Field        | Type   | Required | Description                                                     |
| ------------ | ------ | -------- | --------------------------------------------------------------- |
| `webhookUrl` | string | Yes      | Slack incoming webhook URL, starting `https://hooks.slack.com/` |

The incoming webhook posts to the channel it was created for in Slack.

### Strategy: Discord

| Field        | Type   | Required | Description                                                       |
| ------------ | ------ | -------- | ----------------------------------------------------------------- |
| `webhookUrl` | string | Yes      | Discord webhook URL, starting `https://discord.com/api/webhooks/` |

### Strategy: PagerDuty

| Field        | Type   | Required | Description                                                                                       |
| ------------ | ------ | -------- | ------------------------------------------------------------------------------------------------- |
| `routingKey` | string | Yes      | Integration key of a PagerDuty service's Events API v2 integration, up to 255 characters, trimmed |

### Example Request (Email)

#### cURL

```bash
curl -X POST https://uptime.sergiodxa.com/api/v1/alerts \
  -H "Authorization: Bearer uptime_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Team Email Alert",
    "strategy": "email",
    "email": "alerts@example.com",
    "subjectPrefix": "[Uptime]",
    "notifyOnRecovery": true,
    "cooldownMinutes": 5
  }'
```

### Example Request (Webhook)

#### cURL

```bash
curl -X POST https://uptime.sergiodxa.com/api/v1/alerts \
  -H "Authorization: Bearer uptime_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Incident Webhook",
    "strategy": "webhook",
    "url": "https://example.com/hooks/uptime",
    "secret": "whsec_your_secret_key"
  }'
```

### Example Request (Slack)

#### cURL

```bash
curl -X POST https://uptime.sergiodxa.com/api/v1/alerts \
  -H "Authorization: Bearer uptime_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Slack #incidents",
    "strategy": "slack",
    "webhookUrl": "https://hooks.slack.com/services/T00/B00/xxx"
  }'
```

### Example Request (Discord)

#### cURL

```bash
curl -X POST https://uptime.sergiodxa.com/api/v1/alerts \
  -H "Authorization: Bearer uptime_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Discord Server Alert",
    "strategy": "discord",
    "webhookUrl": "https://discord.com/api/webhooks/123/abc"
  }'
```

### Example Request (PagerDuty)

#### cURL

```bash
curl -X POST https://uptime.sergiodxa.com/api/v1/alerts \
  -H "Authorization: Bearer uptime_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "On-call Pager",
    "strategy": "pagerduty",
    "routingKey": "0123456789abcdef0123456789abcdef"
  }'
```

### Response

Returns `201 Created`. The alert's `config` reports only its `strategy`.

```json
{
	"data": {
		"alert": {
			"id": "alt_abc123",
			"name": "Team Email Alert",
			"notifyOnRecovery": true,
			"cooldownMinutes": 5,
			"monitorType": null,
			"monitorId": null,
			"config": { "strategy": "email" },
			"createdAt": 1771070400000,
			"updatedAt": 1771070400000
		}
	},
	"meta": {
		"requestId": "3f2504e0-4f89-11d3-9a0c-0305e82c3301",
		"timestamp": "2026-02-14T12:00:00.000Z"
	}
}
```

## GET /api/v1/alerts/:id

Returns a single alert by ID.

**Required scope:** `alerts:read`

### Errors

| Status | Type | Description |
| --- | --- | --- |
| 400 | `validation-error` | The request failed validation |
| 401 | `unauthorized` | The API key is missing or invalid |
| 403 | `forbidden` | The API key lacks the required scope |
| 404 | `not-found` | The resource does not exist |

### Response Schema

```json
{
	"$schema": "https://json-schema.org/draft/2020-12/schema",
	"type": "object",
	"properties": {
		"data": {
			"type": "object",
			"properties": {
				"alert": {
					"$ref": "#/$defs/Alert"
				}
			},
			"required": [
				"alert"
			]
		},
		"meta": {
			"type": "object",
			"properties": {
				"requestId": {
					"type": "string",
					"format": "uuid"
				},
				"timestamp": {
					"type": "string",
					"format": "date-time"
				}
			},
			"required": [
				"requestId",
				"timestamp"
			]
		}
	},
	"required": [
		"data",
		"meta"
	],
	"$defs": {
		"Alert": {
			"type": "object",
			"properties": {
				"id": {
					"type": "string",
					"pattern": "^alt_[0-7][0-9a-hjkmnp-tv-z]{25}$"
				},
				"name": {
					"type": "string"
				},
				"notifyOnRecovery": {
					"type": "boolean"
				},
				"cooldownMinutes": {
					"type": "integer"
				},
				"config": {
					"oneOf": [
						{
							"type": "object",
							"properties": {
								"strategy": {
									"type": "string",
									"const": "email"
								},
								"to": {
									"type": "string"
								},
								"subjectPrefix": {
									"type": "string"
								}
							},
							"required": [
								"strategy",
								"to",
								"subjectPrefix"
							]
						},
						{
							"type": "object",
							"properties": {
								"strategy": {
									"type": "string",
									"const": "webhook"
								},
								"signature": {
									"type": "string",
									"enum": [
										"standard-webhooks",
										"legacy"
									],
									"description": "`standard-webhooks` signs with `webhook-id`, `webhook-timestamp` and `webhook-signature: v1,<base64>`; `legacy` with `Webhook-Signature: sha256=<hex>`"
								}
							},
							"required": [
								"strategy",
								"signature"
							]
						},
						{
							"type": "object",
							"properties": {
								"strategy": {
									"type": "string",
									"const": "slack"
								}
							},
							"required": [
								"strategy"
							]
						},
						{
							"type": "object",
							"properties": {
								"strategy": {
									"type": "string",
									"const": "discord"
								}
							},
							"required": [
								"strategy"
							]
						},
						{
							"type": "object",
							"properties": {
								"strategy": {
									"type": "string",
									"const": "pagerduty"
								}
							},
							"required": [
								"strategy"
							]
						}
					],
					"discriminator": {
						"propertyName": "strategy"
					}
				},
				"monitorType": {
					"type": [
						"string",
						"null"
					],
					"enum": [
						"http",
						"dns",
						"tcp",
						"cron",
						"flow",
						null
					],
					"description": "Monitor type the alert covers; null covers every type"
				},
				"monitorId": {
					"type": [
						"string",
						"null"
					],
					"description": "The one monitor the alert covers; null covers the whole type"
				},
				"createdAt": {
					"type": "integer",
					"description": "Epoch milliseconds"
				},
				"updatedAt": {
					"type": "integer",
					"description": "Epoch milliseconds"
				}
			},
			"required": [
				"id",
				"name",
				"notifyOnRecovery",
				"cooldownMinutes",
				"config",
				"monitorType",
				"monitorId",
				"createdAt",
				"updatedAt"
			]
		}
	}
}
```

### Example Request

#### cURL

```bash
curl https://uptime.sergiodxa.com/api/v1/alerts/alt_abc123 \
  -H "Authorization: Bearer uptime_your_api_key"
```

### Response

```json
{
	"data": {
		"alert": {
			"id": "alt_abc123",
			"name": "Team Email Alert",
			"notifyOnRecovery": true,
			"cooldownMinutes": 5,
			"monitorType": null,
			"monitorId": null,
			"config": {
				"strategy": "email",
				"to": "alerts@example.com",
				"subjectPrefix": "[Uptime]"
			},
			"createdAt": 1771070400000,
			"updatedAt": 1771070400000
		}
	},
	"meta": {
		"requestId": "3f2504e0-4f89-11d3-9a0c-0305e82c3301",
		"timestamp": "2026-02-14T12:00:00.000Z"
	}
}
```

Webhook URLs, secrets and integration keys stay out of `config`, so a Slack, Discord or PagerDuty alert reports only its `strategy`, and a webhook alert its `strategy` and `signature` scheme.

## PATCH /api/v1/alerts/:id

Updates an existing alert with a [JSON merge patch](/docs/api/overview#updating-resources).

**Required scope:** `alerts:write`

### Errors

| Status | Type | Description |
| --- | --- | --- |
| 400 | `validation-error` | The request failed validation |
| 401 | `unauthorized` | The API key is missing or invalid |
| 403 | `forbidden` | The API key lacks the required scope |
| 404 | `not-found` | The resource does not exist |
| 415 | `unsupported-media-type` | The request body's media type is not accepted |

### Response Schema

```json
{
	"$schema": "https://json-schema.org/draft/2020-12/schema",
	"type": "object",
	"properties": {
		"data": {
			"type": "object",
			"properties": {
				"alert": {
					"$ref": "#/$defs/AlertSummary"
				}
			},
			"required": [
				"alert"
			]
		},
		"meta": {
			"type": "object",
			"properties": {
				"requestId": {
					"type": "string",
					"format": "uuid"
				},
				"timestamp": {
					"type": "string",
					"format": "date-time"
				}
			},
			"required": [
				"requestId",
				"timestamp"
			]
		}
	},
	"required": [
		"data",
		"meta"
	],
	"$defs": {
		"AlertSummary": {
			"type": "object",
			"properties": {
				"id": {
					"type": "string",
					"pattern": "^alt_[0-7][0-9a-hjkmnp-tv-z]{25}$"
				},
				"name": {
					"type": "string"
				},
				"notifyOnRecovery": {
					"type": "boolean"
				},
				"cooldownMinutes": {
					"type": "integer"
				},
				"monitorType": {
					"type": [
						"string",
						"null"
					],
					"enum": [
						"http",
						"dns",
						"tcp",
						"cron",
						"flow",
						null
					],
					"description": "Monitor type the alert covers; null covers every type"
				},
				"monitorId": {
					"type": [
						"string",
						"null"
					],
					"description": "The one monitor the alert covers; null covers the whole type"
				},
				"config": {
					"type": "object",
					"properties": {
						"strategy": {
							"type": "string",
							"enum": [
								"email",
								"webhook",
								"slack",
								"discord",
								"pagerduty"
							]
						}
					},
					"required": [
						"strategy"
					]
				},
				"createdAt": {
					"type": "integer",
					"description": "Epoch milliseconds"
				},
				"updatedAt": {
					"type": "integer",
					"description": "Epoch milliseconds"
				}
			},
			"required": [
				"id",
				"name",
				"notifyOnRecovery",
				"cooldownMinutes",
				"monitorType",
				"monitorId",
				"config",
				"createdAt",
				"updatedAt"
			]
		}
	}
}
```

### Request Body

Every field `POST /api/v1/alerts` accepts is accepted here, with the same limits. Include only the fields you want to change:

- `null` resets `notifyOnRecovery`, `cooldownMinutes` and `signature` to their defaults, and clears `subjectPrefix` and `secret`.
- `{"signature": "standard-webhooks"}` moves a webhook alert created with the legacy signature onto Standard Webhooks.
- `name`, `strategy` and a strategy's required setting (`email`, `url`, `webhookUrl` or `routingKey`) cannot be removed.
- A channel setting changes on its own, keeping the others: `{"email": "oncall@example.com"}` keeps the alert's `subjectPrefix`.
- Switching `strategy` needs the new strategy's required setting in the same patch, `{"strategy": "discord", "webhookUrl": "..."}`, and drops the previous strategy's settings.

`monitorType` and `monitorId` are the alert's scope, and they move as a pair: change either one and both are rewritten, so narrowing an alert to a whole kind of monitor cannot leave the previous monitor's id behind it. Mention neither and the scope is left exactly as it is.

- `{"monitorType": "dns"}` — every DNS monitor
- `{"monitorType": "dns", "monitorId": "..."}` — that one DNS monitor
- `{"monitorId": null}` or `{"monitorType": null}` — back to team-wide
- `{"monitorId": "..."}` — that one HTTP monitor

A `monitorId` that does not belong to the team, or that belongs to a different kind of monitor than `monitorType` names, answers a `404` `not-found` problem.

### Example Request

#### cURL

```bash
curl -X PATCH https://uptime.sergiodxa.com/api/v1/alerts/alt_abc123 \
  -H "Authorization: Bearer uptime_your_api_key" \
  -H "Content-Type: application/merge-patch+json" \
  -d '{
    "name": "Updated Alert Name",
    "cooldownMinutes": 10,
    "notifyOnRecovery": false
  }'
```

### Response

The alert's `config` reports only its `strategy`.

```json
{
	"data": {
		"alert": {
			"id": "alt_abc123",
			"name": "Updated Alert Name",
			"notifyOnRecovery": false,
			"cooldownMinutes": 10,
			"monitorType": null,
			"monitorId": null,
			"config": { "strategy": "email" },
			"createdAt": 1771070400000,
			"updatedAt": 1771074000000
		}
	},
	"meta": {
		"requestId": "3f2504e0-4f89-11d3-9a0c-0305e82c3301",
		"timestamp": "2026-02-14T12:00:00.000Z"
	}
}
```

### Update With PUT

`PUT /api/v1/alerts/:id` updates `name`, `notifyOnRecovery`, `cooldownMinutes`, `monitorType` and `monitorId`, for integrations written before `PATCH` existed. Any other field, including `strategy` and the channel settings, is ignored, so the channel changes only through `PATCH`. A field you leave out keeps its value, and `null` is refused everywhere except `monitorId`. Sending either scope field rewrites both, as listed above: `{"monitorType": "dns"}` also clears a previous monitor id.

**Required scope:** `alerts:write`

### Errors

| Status | Type | Description |
| --- | --- | --- |
| 400 | `validation-error` | The request failed validation |
| 401 | `unauthorized` | The API key is missing or invalid |
| 403 | `forbidden` | The API key lacks the required scope |
| 404 | `not-found` | The resource does not exist |

### Request Body Schema

```json
{
	"$schema": "https://json-schema.org/draft/2020-12/schema",
	"type": "object",
	"properties": {
		"name": {
			"type": "string",
			"minLength": 1,
			"maxLength": 255
		},
		"notifyOnRecovery": {
			"type": "boolean"
		},
		"cooldownMinutes": {
			"type": "number",
			"minimum": 0,
			"maximum": 1440
		},
		"monitorType": {
			"type": "string",
			"enum": [
				"http",
				"dns",
				"tcp",
				"cron",
				"flow"
			]
		},
		"monitorId": {
			"type": [
				"string",
				"null"
			]
		}
	}
}
```

### Response Schema

```json
{
	"$schema": "https://json-schema.org/draft/2020-12/schema",
	"type": "object",
	"properties": {
		"data": {
			"type": "object",
			"properties": {
				"alert": {
					"$ref": "#/$defs/AlertSummary"
				}
			},
			"required": [
				"alert"
			]
		},
		"meta": {
			"type": "object",
			"properties": {
				"requestId": {
					"type": "string",
					"format": "uuid"
				},
				"timestamp": {
					"type": "string",
					"format": "date-time"
				}
			},
			"required": [
				"requestId",
				"timestamp"
			]
		}
	},
	"required": [
		"data",
		"meta"
	],
	"$defs": {
		"AlertSummary": {
			"type": "object",
			"properties": {
				"id": {
					"type": "string",
					"pattern": "^alt_[0-7][0-9a-hjkmnp-tv-z]{25}$"
				},
				"name": {
					"type": "string"
				},
				"notifyOnRecovery": {
					"type": "boolean"
				},
				"cooldownMinutes": {
					"type": "integer"
				},
				"monitorType": {
					"type": [
						"string",
						"null"
					],
					"enum": [
						"http",
						"dns",
						"tcp",
						"cron",
						"flow",
						null
					],
					"description": "Monitor type the alert covers; null covers every type"
				},
				"monitorId": {
					"type": [
						"string",
						"null"
					],
					"description": "The one monitor the alert covers; null covers the whole type"
				},
				"config": {
					"type": "object",
					"properties": {
						"strategy": {
							"type": "string",
							"enum": [
								"email",
								"webhook",
								"slack",
								"discord",
								"pagerduty"
							]
						}
					},
					"required": [
						"strategy"
					]
				},
				"createdAt": {
					"type": "integer",
					"description": "Epoch milliseconds"
				},
				"updatedAt": {
					"type": "integer",
					"description": "Epoch milliseconds"
				}
			},
			"required": [
				"id",
				"name",
				"notifyOnRecovery",
				"cooldownMinutes",
				"monitorType",
				"monitorId",
				"config",
				"createdAt",
				"updatedAt"
			]
		}
	}
}
```

## DELETE /api/v1/alerts/:id

Deletes an alert.

**Required scope:** `alerts:write`

### Errors

| Status | Type | Description |
| --- | --- | --- |
| 400 | `validation-error` | The request failed validation |
| 401 | `unauthorized` | The API key is missing or invalid |
| 403 | `forbidden` | The API key lacks the required scope |
| 404 | `not-found` | The resource does not exist |

### Response Schema

```json
{
	"$schema": "https://json-schema.org/draft/2020-12/schema",
	"type": "object",
	"properties": {
		"data": {
			"type": "object",
			"properties": {
				"deleted": {
					"type": "boolean",
					"const": true
				}
			},
			"required": [
				"deleted"
			]
		},
		"meta": {
			"type": "object",
			"properties": {
				"requestId": {
					"type": "string",
					"format": "uuid"
				},
				"timestamp": {
					"type": "string",
					"format": "date-time"
				}
			},
			"required": [
				"requestId",
				"timestamp"
			]
		}
	},
	"required": [
		"data",
		"meta"
	]
}
```

### Example Request

#### cURL

```bash
curl -X DELETE https://uptime.sergiodxa.com/api/v1/alerts/alt_abc123 \
  -H "Authorization: Bearer uptime_your_api_key"
```

### Response

Returns `200 OK`:

```json
{
	"data": {
		"deleted": true
	},
	"meta": {
		"requestId": "3f2504e0-4f89-11d3-9a0c-0305e82c3301",
		"timestamp": "2026-02-14T12:00:00.000Z"
	}
}
```

## GET /api/v1/alerts/:id/events

Returns the event history for an alert, newest first. The history is paginated; see [Pagination](/docs/api/pagination) for how to walk further back.

**Required scope:** `alerts:read`

### Errors

| Status | Type | Description |
| --- | --- | --- |
| 400 | `bad-request` | The request is malformed |
| 400 | `validation-error` | The request failed validation |
| 401 | `unauthorized` | The API key is missing or invalid |
| 403 | `forbidden` | The API key lacks the required scope |
| 404 | `not-found` | The resource does not exist |

### Response Schema

```json
{
	"$schema": "https://json-schema.org/draft/2020-12/schema",
	"type": "object",
	"properties": {
		"data": {
			"type": "object",
			"properties": {
				"events": {
					"type": "array",
					"items": {
						"$ref": "#/$defs/AlertEvent"
					}
				}
			},
			"required": [
				"events"
			]
		},
		"meta": {
			"type": "object",
			"properties": {
				"requestId": {
					"type": "string",
					"format": "uuid"
				},
				"timestamp": {
					"type": "string",
					"format": "date-time"
				},
				"pagination": {
					"$ref": "#/$defs/Pagination"
				}
			},
			"required": [
				"requestId",
				"timestamp",
				"pagination"
			]
		}
	},
	"required": [
		"data",
		"meta"
	],
	"$defs": {
		"AlertEvent": {
			"type": "object",
			"properties": {
				"id": {
					"type": "string",
					"pattern": "^evt_[0-7][0-9a-hjkmnp-tv-z]{25}$"
				},
				"alertId": {
					"type": "string",
					"pattern": "^alt_[0-7][0-9a-hjkmnp-tv-z]{25}$"
				},
				"monitorId": {
					"type": "string"
				},
				"eventType": {
					"type": "string",
					"enum": [
						"down",
						"up",
						"degraded"
					]
				},
				"status": {
					"type": "string",
					"enum": [
						"pending",
						"sent",
						"skipped_cooldown",
						"skipped_cap",
						"failed"
					]
				},
				"sentAt": {
					"type": "integer",
					"description": "Epoch milliseconds"
				},
				"errorMessage": {
					"type": [
						"string",
						"null"
					]
				},
				"createdAt": {
					"type": "integer",
					"description": "Epoch milliseconds"
				}
			},
			"required": [
				"id",
				"alertId",
				"monitorId",
				"eventType",
				"status",
				"sentAt",
				"errorMessage",
				"createdAt"
			]
		},
		"Pagination": {
			"type": "object",
			"properties": {
				"next": {
					"type": [
						"string",
						"null"
					],
					"description": "Cursor of the following page"
				},
				"prev": {
					"type": [
						"string",
						"null"
					],
					"description": "Cursor of the preceding page"
				},
				"perPage": {
					"type": "integer"
				},
				"total": {
					"type": "integer"
				}
			},
			"required": [
				"next",
				"prev",
				"perPage"
			]
		}
	}
}
```

### Query Parameters

| Parameter | Type    | Required | Description                               |
| --------- | ------- | -------- | ----------------------------------------- |
| `perPage` | integer | No       | Results per page, 1-200 (default: 50)     |
| `cursor`  | string  | No       | Page to fetch, taken from a `Link` header |

### Example Request

#### cURL

```bash
curl "https://uptime.sergiodxa.com/api/v1/alerts/alt_abc123/events?perPage=10" \
  -H "Authorization: Bearer uptime_your_api_key"
```

### Response

```json
{
	"data": {
		"events": [
			{
				"id": "evt_abc123",
				"alertId": "alt_abc123",
				"monitorId": "mon_def456",
				"eventType": "down",
				"status": "sent",
				"sentAt": 1771072200000,
				"errorMessage": null,
				"createdAt": 1771072200000
			},
			{
				"id": "evt_def456",
				"alertId": "alt_abc123",
				"monitorId": "mon_def456",
				"eventType": "up",
				"status": "sent",
				"sentAt": 1771072500000,
				"errorMessage": null,
				"createdAt": 1771072500000
			}
		]
	},
	"meta": {
		"requestId": "3f2504e0-4f89-11d3-9a0c-0305e82c3301",
		"timestamp": "2026-02-14T12:00:00.000Z",
		"pagination": {
			"next": "eyJkIjoiYWZ0ZXIi",
			"prev": null,
			"perPage": 10
		}
	}
}
```

### Event Fields

| Field          | Type           | Description                                                                                                        |
| -------------- | -------------- | ------------------------------------------------------------------------------------------------------------------ |
| `id`           | string         | Unique event identifier                                                                                            |
| `alertId`      | string         | The alert the event belongs to                                                                                     |
| `monitorId`    | string         | The monitor that caused the event                                                                                  |
| `eventType`    | string         | What the monitor did: `down`, `up`, or `degraded`                                                                  |
| `status`       | string         | Delivery outcome: `pending` while it waits to be sent, then `sent`, `skipped_cooldown`, `skipped_cap`, or `failed` |
| `sentAt`       | integer        | Unix timestamp in milliseconds of when the notification was sent                                                   |
| `errorMessage` | string \| null | Why delivery failed, or `null` when it succeeded                                                                   |
| `createdAt`    | integer        | Unix timestamp in milliseconds of when the event was recorded                                                      |
