---
title: "Create an alert"
method: POST
path: "/api/v1/public/alerts"
tags: ["Alerts"]
---

# Create an alert

`POST /api/v1/public/alerts`

## Request

- Base URL: `https://app.traceroot.ai`
- URL: `https://app.traceroot.ai/api/v1/public/alerts`
- Auth: HTTP bearer

Create a threshold alert in a project the authenticated user can write to.

Requires MEMBER role or higher in the project's workspace (the write
service decides). Strict create — alerts have no unique name, so every
call inserts and ``created`` is always ``true`` on success.

Args:
    request (Request): Incoming request (rate-limit plumbing).
    response (Response): Outgoing response (rate-limit plumbing).
    auth (AccountStampedAuth): Account-scope user auth (session token or
        CLI access JWT); its resolved ``user_id`` becomes the actor.
    payload (CreateAlertRequest): The alert rule to create.
    _live (None): Write-path liveness gate (blocks a revoked JWT session).

Returns:
    CreateAlertResponse: The created alert with its full rule.

## Request body

- CreateAlertRequest: Body for creating a threshold alert in a project.
  - `aggregation` 'sum' | 'avg' | 'count' | 'max' | 'min' | 'p50' | 'p75' | 'p90' | 'p95' | 'p99' | 'uniq', required
  - `filters` AlertFilterItemRequest[]: Row predicates the measure is evaluated over
    - `field` string, required: A span field, e.g. model_name or metadata
    - `key` string: The map entry to compare; required for the metadata field
    - `op` '=' | 'contains', required
    - `value` union, required
      - string
      - number
  - `measure` string, required: A measure of the view, e.g. latency, cost, count
  - `name` string, required
  - `no_data_mode` 'HOLD' | 'ZERO' | 'NOTIFY', nullable: What a window that measured nothing means; column default when omitted
  - `project_id` string, required
  - `renotify` AlertRenotifyRequest, required: How often an alert re-notifies while it stays in the alerting state.
    - `interval_minutes` integer: Minutes between repeat notifications; required when mode is EVERY
    - `mode` 'OFF' | 'EVERY', required
  - `threshold` number, required
  - `threshold_operator` '>' | '>=' | '<' | '<=' | '=' | '!=', required
  - `view` 'SPANS', required
  - `window` '1m' | '5m' | '10m' | '30m' | '1h' | '2h', required

## Response `200`

Successful Response

- CreateAlertResponse: The created alert with its full rule (alert creation is strict, never idempotent).
  - `alert` AlertDetail, required: One alert with its full rule: the summary plus filters and gap handling.
    - `aggregation` string, required
    - `alerted_at` string, date-time, nullable, required
    - `create_time` string, date-time, required
    - `creator` string, nullable, required
    - `filters` AlertFilterItem[], required
      - `field` string, required
      - `key` string, nullable
      - `op` '=' | 'contains', required
      - `value` union, required
        - string
        - number
    - `id` string, required
    - `last_error` string, nullable, required
    - `last_error_at` string, date-time, nullable, required
    - `last_evaluated_at` string, date-time, nullable, required
    - `last_notify_at` string, date-time, nullable, required
    - `last_notify_error` string, nullable, required
    - `last_notify_status` string, nullable, required
    - `measure` string, required
    - `name` string, required
    - `no_data_mode` string, required
    - `renotify` AlertRenotify, required: How often an alert re-notifies while it stays in the alerting state. Kept a single-level object rather than a discriminated union, matching the request-side shape. The cross-field rule is enforced by a validator instead, so a contradictory stored rule fails the detail read closed rather than passing through half-typed.
      - `interval_minutes` integer, nullable
      - `mode` 'OFF' | 'EVERY', required
    - `severity` string, required
    - `severity_changed_at` string, date-time, nullable, required
    - `status` string, required
    - `threshold` number, required
    - `threshold_operator` string, required
    - `update_time` string, date-time, required
    - `view` string, required
    - `window` string, required
  - `created` boolean, required

## Other responses

- `400`: Invalid request
- `401`: Authentication failed or session revoked
- `403`: Insufficient role or wrong credential kind
- `404`: Not found
- `409`: The project has reached its alert limit
- `422`: Validation Error
- `503`: Write service unavailable

---

[API](https://skmtc.dev/traceroot/apis/traceroot-public-api.md) - [All operations](https://skmtc.dev/traceroot/apis/traceroot-public-api/llms.txt) - [OpenAPI document](https://skmtc.dev/traceroot/apis/traceroot-public-api/revisions/ce6aef96c0d6?raw)
