# Alarms

Alarms from Maci Intelligence for the units' owner and for the refrigeration firm the owner has chosen as the watch. An alarm is open until someone closes it, also after its cause has cleared. Taking an alarm (`acknowledge`) stops it from going on to the next recipients, as on the unit's card. When the organisation sets a webhook address for alarms in the app, each alarm is also posted to it as `alarm.raised`, `alarm.cleared`, `alarm.acknowledged` and `alarm.closed`, with the alarm as the body's `data` and the body signed in the header `X-Maci-Signature` as `sha256=` and the HMAC-SHA256 of the body with the webhook's secret. The SMS and mail to the recipients do not depend on the webhook.

Webhook: `alarm.raised`, `alarm.cleared`, `alarm.acknowledged`, `alarm.closed` is posted to your own address as it happens. See [Webhooks](https://api.maci.energy/docs/webhooks.md).

## The alarm model

- `id` (string (uuid))
- `unit_id` (string (uuid))
- `unit_public_id` (string, nullable)
- `unit` (string, nullable): The unit's name.
- `site` (string, nullable)
- `type` (string): The alarm's type from the rule engine, e.g. `rum-for-varmt`. New types can come at any time.
- `name` (string): The type's name, in English, or in Danish with `Accept-Language: da`.
- `severity` (string): `HIGH` (SMS and mail, and on to the next recipients when nobody takes it) or `MEDIUM` (mail).
- `state` (string): `cleared` when the rule engine sees the cause gone. One of `raised`, `cleared`.
- `open` (boolean): Not yet closed by a person.
- `values` (object): The readings the rule saw.
- `raised_at` (string (date-time))
- `cleared_at` (string (date-time), nullable)
- `level` (integer): How far it has gone: 0 the watch (or the owner without a watch), 1 the owner, 2 Maci.
- `watch` (object, nullable)
- `acknowledged_at` (string (date-time), nullable)
- `acknowledged_by` (string, nullable): The person, or the key's name with (API).
- `closed_at` (string (date-time), nullable)
- `closed_by` (string, nullable)
- `result` (string, nullable) One of `real`, `false`.
- `note` (string, nullable)

## List alarms

`GET /alarms` · scope `alarms:read`

The alarms of the units the organisation owns or watches.

Raised since `since`, by default the last 30 days. The owner's key sees the alarms of its own units; a refrigeration firm's key the alarms of the units where the owner has chosen it as the watch.

### Query parameters

- `open` (boolean): `true` for only the alarms not yet closed, `false` for only the closed ones.
- `unit_id` (string (uuid))
- `since` (string (date-time))
- `limit` (integer): Records per page. At most 100, default 50.
- `cursor` (string): The value of `next_cursor` from the page before.

### Request

```bash
curl https://api.maci.energy/v1/alarms \
  -H "Authorization: Bearer $MACI_API_KEY"
```

```javascript
const response = await fetch('https://api.maci.energy/v1/alarms', {
  headers: {
    Authorization: `Bearer ${process.env.MACI_API_KEY}`,
  },
});
const data = await response.json();
```

```python
import os
import requests

response = requests.get(
    "https://api.maci.energy/v1/alarms",
    headers={"Authorization": f"Bearer {os.environ['MACI_API_KEY']}"},
)
data = response.json()
```

```php
$client = new \GuzzleHttp\Client();

$response = $client->request('GET', 'https://api.maci.energy/v1/alarms', [
    'headers' => [
        'Authorization' => 'Bearer '.getenv('MACI_API_KEY'),
    ],
]);
$data = json_decode($response->getBody(), true);
```

### Response 200

A page of alarms. The fields are those of the alarm model.

```json
{
  "data": [
    {
      "id": "7e3b1c90-2f4a-4d8e-9b61-5a0c3d7f2e18",
      "unit_id": "0b6f4c1e-5a1d-4a57-9f0e-2f6f3f0c9a11",
      "unit_public_id": "MC-0482",
      "unit": "Cold room 2",
      "site": "Main store",
      "type": "rum-for-varmt",
      "name": "Room too warm",
      "severity": "HIGH",
      "state": "raised",
      "open": true,
      "values": {
        "room_temp_c": "9.4",
        "setpoint_c": "3.0"
      },
      "raised_at": "2026-10-30T09:15:00Z",
      "cleared_at": null,
      "level": 0,
      "watch": null,
      "acknowledged_at": null,
      "acknowledged_by": null,
      "closed_at": null,
      "closed_by": null,
      "result": null,
      "note": null
    }
  ],
  "next_cursor": null
}
```

## Get alarm

`GET /alarms/{alarm}` · scope `alarms:read`

One alarm.

### Path parameters

- `alarm` (string (uuid), required): The ID of the alarm.

### Request

```bash
curl https://api.maci.energy/v1/alarms/7e3b1c90-2f4a-4d8e-9b61-5a0c3d7f2e18 \
  -H "Authorization: Bearer $MACI_API_KEY"
```

```javascript
const response = await fetch('https://api.maci.energy/v1/alarms/7e3b1c90-2f4a-4d8e-9b61-5a0c3d7f2e18', {
  headers: {
    Authorization: `Bearer ${process.env.MACI_API_KEY}`,
  },
});
const data = await response.json();
```

```python
import os
import requests

response = requests.get(
    "https://api.maci.energy/v1/alarms/7e3b1c90-2f4a-4d8e-9b61-5a0c3d7f2e18",
    headers={"Authorization": f"Bearer {os.environ['MACI_API_KEY']}"},
)
data = response.json()
```

```php
$client = new \GuzzleHttp\Client();

$response = $client->request('GET', 'https://api.maci.energy/v1/alarms/7e3b1c90-2f4a-4d8e-9b61-5a0c3d7f2e18', [
    'headers' => [
        'Authorization' => 'Bearer '.getenv('MACI_API_KEY'),
    ],
]);
$data = json_decode($response->getBody(), true);
```

### Response 200

The alarm. The fields are those of the alarm model.

```json
{
  "id": "7e3b1c90-2f4a-4d8e-9b61-5a0c3d7f2e18",
  "unit_id": "0b6f4c1e-5a1d-4a57-9f0e-2f6f3f0c9a11",
  "unit_public_id": "MC-0482",
  "unit": "Cold room 2",
  "site": "Main store",
  "type": "rum-for-varmt",
  "name": "Room too warm",
  "severity": "HIGH",
  "state": "raised",
  "open": true,
  "values": {
    "room_temp_c": "9.4",
    "setpoint_c": "3.0"
  },
  "raised_at": "2026-10-30T09:15:00Z",
  "cleared_at": null,
  "level": 0,
  "watch": null,
  "acknowledged_at": null,
  "acknowledged_by": null,
  "closed_at": null,
  "closed_by": null,
  "result": null,
  "note": null
}
```

## Acknowledge alarm

`POST /alarms/{alarm}/acknowledge` · scope `alarms:write`

Take the alarm.

Someone is on it, so the alarm does not go on to the next recipients. Taking an alarm already taken changes nothing. The card shows the key's name as who took it.

### Path parameters

- `alarm` (string (uuid), required): The ID of the alarm.

### Request

```bash
curl -X POST https://api.maci.energy/v1/alarms/7e3b1c90-2f4a-4d8e-9b61-5a0c3d7f2e18/acknowledge \
  -H "Authorization: Bearer $MACI_API_KEY"
```

```javascript
const response = await fetch('https://api.maci.energy/v1/alarms/7e3b1c90-2f4a-4d8e-9b61-5a0c3d7f2e18/acknowledge', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.MACI_API_KEY}`,
  },
});
const data = await response.json();
```

```python
import os
import requests

response = requests.post(
    "https://api.maci.energy/v1/alarms/7e3b1c90-2f4a-4d8e-9b61-5a0c3d7f2e18/acknowledge",
    headers={"Authorization": f"Bearer {os.environ['MACI_API_KEY']}"},
)
data = response.json()
```

```php
$client = new \GuzzleHttp\Client();

$response = $client->request('POST', 'https://api.maci.energy/v1/alarms/7e3b1c90-2f4a-4d8e-9b61-5a0c3d7f2e18/acknowledge', [
    'headers' => [
        'Authorization' => 'Bearer '.getenv('MACI_API_KEY'),
    ],
]);
$data = json_decode($response->getBody(), true);
```

### Response 200

The alarm, taken. The fields are those of the alarm model.

```json
{
  "id": "7e3b1c90-2f4a-4d8e-9b61-5a0c3d7f2e18",
  "unit_id": "0b6f4c1e-5a1d-4a57-9f0e-2f6f3f0c9a11",
  "unit_public_id": "MC-0482",
  "unit": "Cold room 2",
  "site": "Main store",
  "type": "rum-for-varmt",
  "name": "Room too warm",
  "severity": "HIGH",
  "state": "raised",
  "open": true,
  "values": {
    "room_temp_c": "9.4",
    "setpoint_c": "3.0"
  },
  "raised_at": "2026-10-30T09:15:00Z",
  "cleared_at": null,
  "level": 0,
  "watch": null,
  "acknowledged_at": "2026-10-30T09:17:42Z",
  "acknowledged_by": "Ops (API)",
  "closed_at": null,
  "closed_by": null,
  "result": null,
  "note": null
}
```

## Close alarm

`POST /alarms/{alarm}/close` · scope `alarms:write`

Close the alarm as real or false.

Takes it first if nobody has. What was found helps tune the alarm rules. 409 when it is closed already.

### Path parameters

- `alarm` (string (uuid), required): The ID of the alarm.

### Body (JSON)

- `result` (string, required) One of `real`, `false`.
- `note` (string): What was found on the unit. Write no names of people.

### Request

```bash
curl -X POST https://api.maci.energy/v1/alarms/7e3b1c90-2f4a-4d8e-9b61-5a0c3d7f2e18/close \
  -H "Authorization: Bearer $MACI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "result": "real",
    "note": "Door left open after a delivery."
  }'
```

```javascript
const response = await fetch('https://api.maci.energy/v1/alarms/7e3b1c90-2f4a-4d8e-9b61-5a0c3d7f2e18/close', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.MACI_API_KEY}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    "result": "real",
    "note": "Door left open after a delivery."
  }),
});
const data = await response.json();
```

```python
import os
import requests

response = requests.post(
    "https://api.maci.energy/v1/alarms/7e3b1c90-2f4a-4d8e-9b61-5a0c3d7f2e18/close",
    headers={"Authorization": f"Bearer {os.environ['MACI_API_KEY']}"},
    json={
        "result": "real",
        "note": "Door left open after a delivery."
    },
)
data = response.json()
```

```php
$client = new \GuzzleHttp\Client();

$response = $client->request('POST', 'https://api.maci.energy/v1/alarms/7e3b1c90-2f4a-4d8e-9b61-5a0c3d7f2e18/close', [
    'headers' => [
        'Authorization' => 'Bearer '.getenv('MACI_API_KEY'),
    ],
    'json' => [
        'result' => 'real',
        'note' => 'Door left open after a delivery.',
    ],
]);
$data = json_decode($response->getBody(), true);
```

### Response 200

The alarm, closed. The fields are those of the alarm model.

```json
{
  "id": "7e3b1c90-2f4a-4d8e-9b61-5a0c3d7f2e18",
  "unit_id": "0b6f4c1e-5a1d-4a57-9f0e-2f6f3f0c9a11",
  "unit_public_id": "MC-0482",
  "unit": "Cold room 2",
  "site": "Main store",
  "type": "rum-for-varmt",
  "name": "Room too warm",
  "severity": "HIGH",
  "state": "raised",
  "open": false,
  "values": {
    "room_temp_c": "9.4",
    "setpoint_c": "3.0"
  },
  "raised_at": "2026-10-30T09:15:00Z",
  "cleared_at": null,
  "level": 0,
  "watch": null,
  "acknowledged_at": "2026-10-30T09:17:42Z",
  "acknowledged_by": "Ops (API)",
  "closed_at": "2026-10-30T10:05:13Z",
  "closed_by": "Ops (API)",
  "result": "real",
  "note": "Door left open after a delivery."
}
```
