> ## Documentation Index
> Fetch the complete documentation index at: https://docs.r3al.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Monitoring: alerts, deployments, logs

> Operator monitoring: alert rules over job history, model-serving deployments, and a log tail.

<Note>
  These are operator (admin) endpoints, scoped to the whole deployment rather than a single account. Regular accounts get `403`. Everyday usage (submitting jobs, checking your own runs and usage) is covered under [Jobs](/api/jobs); you do not need these to use the product.
</Note>

## Alert rules & alerts

Two rule types, evaluated every time an async (or sync-but-tracked) job reaches a terminal status:

| `rule_type`             | `threshold` means       | Fires when                           |
| ----------------------- | ----------------------- | ------------------------------------ |
| `consecutive_failures`  | Number of jobs in a row | That many jobs in a row have errored |
| `job_duration_exceeded` | Seconds                 | A single job's runtime exceeds this  |

```bash theme={null}
curl -X POST https://platform.r3al.ai/v1/alerts/rules \
  -H "Authorization: Bearer <admin or developer credential>" \
  -H "Content-Type: application/json" \
  -d '{"name": "3 failures in a row", "rule_type": "consecutive_failures", "threshold": 3}'
```

```json theme={null}
{
  "id": "rule_a1b2c3d4e5f6",
  "name": "3 failures in a row",
  "rule_type": "consecutive_failures",
  "threshold": 3.0,
  "enabled": true,
  "created_at": 1752600000.0
}
```

| Endpoint                       | Role required      |
| ------------------------------ | ------------------ |
| `GET /v1/alerts/rules`         | Any                |
| `POST /v1/alerts/rules`        | Admin or Developer |
| `DELETE /v1/alerts/rules/{id}` | Admin or Developer |
| `GET /v1/alerts`               | Any                |
| `POST /v1/alerts/{id}/ack`     | Admin or Developer |

A fired alert:

```json theme={null}
{
  "id": "alert_a1b2c3",
  "rule_id": "rule_a1b2c3d4e5f6",
  "rule_name": "3 failures in a row",
  "rule_type": "consecutive_failures",
  "severity": "P1",
  "title": "3 consecutive job failures",
  "message": "...",
  "job_id": "job_xyz789",
  "status": "firing",
  "created_at": 1752600000.0,
  "acked_at": null
}
```

`status` moves from `"firing"` to `"acked"` once someone acknowledges it.

## Deployments (local model serving)

Each deployment is a real subprocess (`serve_model.py`, stdlib `http.server` + `onnxruntime`) running one ONNX file, with its own port, `GET /health`, and `POST /predict`. `status` is always a live health probe against that port -- never a stored flag.

```bash theme={null}
curl -X POST https://platform.r3al.ai/v1/deployments \
  -H "Authorization: Bearer <admin or developer credential>" \
  -H "Content-Type: application/json" \
  -d '{"name": "face-detector-v1", "model_path": "/path/to/model.quantized.onnx"}'
```

```json theme={null}
{
  "id": "dep_a1b2c3d4e5f6",
  "name": "face-detector-v1",
  "model_path": "/path/to/model.quantized.onnx",
  "port": 8931,
  "url": "http://127.0.0.1:8931",
  "status": "running",
  "created_at": 1752600000.0
}
```

| Endpoint                      | Role required                                   |
| ----------------------------- | ----------------------------------------------- |
| `GET /v1/deployments`         | Any                                             |
| `POST /v1/deployments`        | Admin or Developer                              |
| `DELETE /v1/deployments/{id}` | Admin or Developer -- stops the real subprocess |

## Logs

A real tail of this server's own log file (every request, job status change, and error already logged via the standard `logging` module):

```bash theme={null}
curl "https://platform.r3al.ai/v1/logs?tail=100&job_id=job_xyz789" \
  -H "Authorization: Bearer <credential>"
```

```json theme={null}
{
  "lines": ["2026-07-16 10:02:11 INFO r3alai_api.local: ..."],
  "count": 100,
  "file": "/app/data/app.log"
}
```

Pass `job_id` to filter to lines mentioning that job. `tail` defaults to `200`.
