Documentation

Alerts Routes

These pages document the live alert-definition and alert-record endpoints mounted under /api/alerts.

GET /api/alerts/definitions

Lists alert definitions for the authenticated account's current organization. The stored condition JSON is validated structurally, but evaluation is still stubbed.

Request
GET /api/alerts/definitions

Response 200
{
  "alertDefinitions": [
    {
      "id": "uuid",
      "orgId": "uuid",
      "key": "low_stock_guardrail",
      "name": "Low Stock Guardrail",
      "description": "Warn when total quantity drops too low",
      "severity": "high",
      "scope": "organization",
      "condition": {
        "kind": "comparison",
        "operator": "lt",
        "left": {
          "kind": "metric",
          "source": "base",
          "key": "totalQuantity"
        },
        "right": {
          "kind": "number",
          "value": 50
        }
      },
      "isActive": true,
      "createdBy": "uuid",
      "createdAt": "2026-04-03T00:00:00.000Z",
      "updatedAt": "2026-04-03T00:00:00.000Z"
    }
  ]
}

GET /api/alerts/definitions/:alertDefinitionId

Returns a single alert definition in the authenticated account's current organization.

Request
GET /api/alerts/definitions/11111111-1111-1111-1111-111111111111

Response 200
{
  "alertDefinition": {
    "id": "uuid",
    "orgId": "uuid",
    "key": "low_stock_guardrail",
    "name": "Low Stock Guardrail",
    "description": "Warn when total quantity drops too low",
    "severity": "high",
    "scope": "organization",
    "condition": {
      "kind": "comparison",
      "operator": "lt",
      "left": {
        "kind": "metric",
        "source": "base",
        "key": "totalQuantity"
      },
      "right": {
        "kind": "number",
        "value": 50
      }
    },
    "isActive": true,
    "createdBy": "uuid",
    "createdAt": "2026-04-03T00:00:00.000Z",
    "updatedAt": "2026-04-03T00:00:00.000Z"
  }
}

POST /api/alerts/definitions

Creates an alert definition. The evaluation engine is not implemented yet, so the response returns engineStatus: "stub".

Request
POST /api/alerts/definitions
Content-Type: application/json

{
  "key": "low_stock_guardrail",
  "name": "Low Stock Guardrail",
  "description": "Warn when total quantity drops too low",
  "severity": "high",
  "scope": "organization",
  "condition": {
    "kind": "comparison",
    "operator": "lt",
    "left": {
      "kind": "metric",
      "source": "base",
      "key": "totalQuantity"
    },
    "right": {
      "kind": "number",
      "value": 50
    }
  }
}

Response 201
{
  "alertDefinition": {
    "id": "uuid",
    "orgId": "uuid",
    "key": "low_stock_guardrail",
    "name": "Low Stock Guardrail",
    "description": "Warn when total quantity drops too low",
    "severity": "high",
    "scope": "organization",
    "condition": {},
    "isActive": true,
    "createdBy": "uuid",
    "createdAt": "2026-04-03T00:00:00.000Z",
    "updatedAt": "2026-04-03T00:00:00.000Z"
  },
  "engineStatus": "stub"
}

Notes
- Condition JSON currently supports comparison and logical nodes.
- Metric references can target base metrics or custom metric definitions.

PATCH /api/alerts/definitions/:alertDefinitionId

Updates an alert definition in the current organization.

Request
PATCH /api/alerts/definitions/11111111-1111-1111-1111-111111111111
Content-Type: application/json

{
  "severity": "medium",
  "isActive": false
}

Response 200
{
  "alertDefinition": {
    "id": "uuid",
    "orgId": "uuid",
    "key": "low_stock_guardrail",
    "name": "Low Stock Guardrail",
    "description": "Warn when total quantity drops too low",
    "severity": "medium",
    "scope": "organization",
    "condition": {},
    "isActive": false,
    "createdBy": "uuid",
    "createdAt": "2026-04-03T00:00:00.000Z",
    "updatedAt": "2026-04-03T01:00:00.000Z"
  },
  "engineStatus": "stub"
}

DELETE /api/alerts/definitions/:alertDefinitionId

Deletes an alert definition from the current organization. Any linked custom alerts remain as historical alert records even after the definition link is cleared.

Request
DELETE /api/alerts/definitions/11111111-1111-1111-1111-111111111111

Response 200
{
  "alertDefinition": {
    "id": "uuid",
    "orgId": "uuid",
    "key": "low_stock_guardrail",
    "name": "Low Stock Guardrail",
    "description": "Warn when total quantity drops too low",
    "severity": "high",
    "scope": "organization",
    "condition": {},
    "isActive": true,
    "createdBy": "uuid",
    "createdAt": "2026-04-03T00:00:00.000Z",
    "updatedAt": "2026-04-03T00:00:00.000Z"
  }
}

GET /api/alerts

Lists alert records in the current organization with optional filters and pagination. Before returning results, the backend evaluates active saved alert definitions and creates or resolves linked custom alert records as needed.

Request
GET /api/alerts?status=active&type=low_stock&limit=25&offset=0

Response 200
{
  "alerts": [
    {
      "id": "uuid",
      "ownerId": "uuid",
      "productId": "uuid",
      "productName": "Widget A",
      "productSku": "WIDGET-A",
      "triggeredByMovementId": "uuid",
      "type": "low_stock",
      "status": "active",
      "thresholdQuantity": 10,
      "currentQuantity": 7,
      "message": "Stock dropped below safe threshold",
      "acknowledgedBy": null,
      "acknowledgedAt": null,
      "createdAt": "2026-04-03T00:00:00.000Z"
    }
  ],
  "pagination": {
    "limit": 25,
    "offset": 0,
    "total": 1,
    "hasMore": false
  }
}
Notes
- GET /api/alerts is the current on-demand sync point for saved alert definitions.
- Productless rows are valid for custom organization-level alerts generated from alert definitions.
- Linked custom alerts are deduped by alert definition and resolved when the condition becomes false.

GET /api/alerts/:alertId

Returns a single persisted alert record in the current organization.

Request
GET /api/alerts/11111111-1111-1111-1111-111111111111

Response 200
{
  "alert": {
    "id": "uuid",
    "ownerId": "uuid",
    "productId": "uuid",
    "productName": "Widget A",
    "productSku": "WIDGET-A",
    "triggeredByMovementId": "uuid",
    "type": "low_stock",
    "status": "active",
    "thresholdQuantity": 10,
    "currentQuantity": 7,
    "message": "Stock dropped below safe threshold",
    "acknowledgedBy": null,
    "acknowledgedAt": null,
    "createdAt": "2026-04-03T00:00:00.000Z"
  }
}

POST /api/alerts

Creates a persisted alert record.

Request
POST /api/alerts
Content-Type: application/json

{
  "productId": "uuid",
  "type": "low_stock",
  "thresholdQuantity": 10,
  "currentQuantity": 7,
  "message": "Stock dropped below safe threshold"
}

Response 201
{
  "alert": {
    "id": "uuid",
    "ownerId": "uuid",
    "productId": "uuid",
    "productName": "Widget A",
    "productSku": "WIDGET-A",
    "triggeredByMovementId": null,
    "type": "low_stock",
    "status": "active",
    "thresholdQuantity": 10,
    "currentQuantity": 7,
    "message": "Stock dropped below safe threshold",
    "acknowledgedBy": null,
    "acknowledgedAt": null,
    "createdAt": "2026-04-03T00:00:00.000Z"
  }
}
Rules
- productId is required for low_stock and critical_stock alerts.
- productId may be omitted only when:
  - type is "custom"
  - alertDefinitionId is provided
- alertDefinitionId may only be used with type "custom".

PATCH /api/alerts/:alertId

Updates an alert record. When status becomes acknowledged, the backend stamps the current user as the acknowledger.

Request
PATCH /api/alerts/11111111-1111-1111-1111-111111111111
Content-Type: application/json

{
  "status": "acknowledged"
}

Response 200
{
  "alert": {
    "id": "uuid",
    "ownerId": "uuid",
    "productId": "uuid",
    "productName": "Widget A",
    "productSku": "WIDGET-A",
    "triggeredByMovementId": null,
    "type": "low_stock",
    "status": "acknowledged",
    "thresholdQuantity": 10,
    "currentQuantity": 7,
    "message": "Stock dropped below safe threshold",
    "acknowledgedBy": {
      "id": "uuid",
      "name": "Jamie Chen",
      "username": "jamie"
    },
    "acknowledgedAt": "2026-04-03T01:00:00.000Z",
    "createdAt": "2026-04-03T00:00:00.000Z"
  }
}

DELETE /api/alerts/:alertId

Deletes a persisted alert record from the current organization.

Request
DELETE /api/alerts/11111111-1111-1111-1111-111111111111

Response 200
{
  "alert": {
    "id": "uuid",
    "ownerId": "uuid",
    "productId": "uuid",
    "productName": "Widget A",
    "productSku": "WIDGET-A",
    "triggeredByMovementId": null,
    "type": "low_stock",
    "status": "active",
    "thresholdQuantity": 10,
    "currentQuantity": 7,
    "message": "Stock dropped below safe threshold",
    "acknowledgedBy": null,
    "acknowledgedAt": null,
    "createdAt": "2026-04-03T00:00:00.000Z"
  }
}