> Índice completo de la documentación: https://trackerintl.com/devs/llms.txt
> Esta página en HTML: https://trackerintl.com/devs/referencia/eventos-y-alertas
> Estado: Verificado, revisada el 2026-10-05. Verificado por lectura del código y diff contra producción; las respuestas se midieron con datos ficticios en un entorno de pruebas. La forma de los horarios de una alerta (`schedules`) no se midió.

# Eventos y alertas

Reglas de alerta, eventos que dispararon y conteo por tipo. Paginación por cursor o por página, filtros y zona horaria.

Una **alerta** es una regla configurada en la plataforma (por ejemplo, exceso de velocidad o entrada a una geocerca). Un **evento** es cada vez que una regla se dispara.

| Necesitas | Usa |
|---|---|
| Las reglas de alerta del usuario | `get_alerts` |
| Los eventos que ocurrieron, del más reciente al más antiguo | `get_events` |
| Cuántos eventos hubo de cada tipo | `get_alerts_summary` |

El campo `type` de un evento identifica la regla que lo generó: por ejemplo `overspeed`, `zone_in`, `zone_out`, `sos`, `ignition_on`, `ignition_off`, `move_start`, `stop_duration`, `offline_duration` o `custom`.

## Paginación de eventos

Sin `page`, `get_events` pagina por cursor: la respuesta trae `next_cursor` y lo envías como `cursor` en la llamada siguiente, hasta que `next_cursor` sea `null`. Con `page`, la respuesta trae totales. No combines ambos. Una fecha inválida en `date_from` o `date_to` no produce error: la API devuelve los datos sin filtrar, así que valida tus fechas antes de enviarlas.

## Eventos generados por las alertas (más recientes primero)

**GET** `/api/get_events` · Estado: Verificado

Lista los eventos generados por las reglas de alerta, del más reciente al más antiguo. Sin `page` usa paginación por cursor (`items.data` y `items.next_cursor`); con `page` devuelve totales. `limit` vale 30 por defecto y 1000 como máximo. Las fechas se interpretan en la zona horaria de la cuenta; una fecha inválida no produce error y devuelve los datos sin filtrar. Requiere permiso para ver eventos.

Autenticación. Cabecera `user-api-hash` con tu `user_api_hash`.

### Parámetros

| Nombre | En | Tipo | Obligatorio | Descripción |
|---|---|---|---|---|
| `device_id` | query | integer | No |  |
| `alert_id` | query | integer | No |  |
| `type` | query | string | No | Tipo de evento (overspeed, zone_in…). |
| `date_from` | query | string | No | YYYY-MM-DD HH:MM:SS (zona de la cuenta). |
| `date_to` | query | string | No |  |
| `created_from` | query | string | No | Sobre created_at. |
| `created_to` | query | string | No |  |
| `search` | query | string | No | Mensaje o nombre del vehículo. |
| `limit` | query | integer | No |  |
| `page` | query | integer | No | Número de página. |
| `cursor` | query | string | No | next_cursor de la respuesta anterior (solo sin page). |
| `lang` | query | string | No | Idioma de los textos traducibles (SetLang). También se admite la cabecera Accept-Language. |

### Ejemplo de solicitud

cURL:

```bash
curl -sS -G "https://plataforma.trackerintl.com/api/get_events" \
  -H "user-api-hash: TU_API_HASH" \
  --data-urlencode "limit=50"
```

JavaScript:

```javascript
const BASE_URL = "https://plataforma.trackerintl.com";
const API_HASH = "TU_API_HASH";

const params = new URLSearchParams({
  limit: "50",
});
const respuesta = await fetch(`${BASE_URL}/api/get_events?${params}`, {
  headers: { "user-api-hash": API_HASH },
});
if (!respuesta.ok) throw new Error(`HTTP ${respuesta.status}: ${await respuesta.text()}`);
console.log(JSON.stringify(await respuesta.json(), null, 2));
```

Python:

```python
import json
import requests

BASE_URL = "https://plataforma.trackerintl.com"
API_HASH = "TU_API_HASH"

respuesta = requests.get(
    f"{BASE_URL}/api/get_events",
    headers={"user-api-hash": API_HASH},
    params={"limit": "50"},
    timeout=30,
)
respuesta.raise_for_status()
print(json.dumps(respuesta.json(), indent=2, ensure_ascii=False))
```

PHP:

```php
<?php
$baseUrl = "https://plataforma.trackerintl.com";
$apiHash = "TU_API_HASH";

$url = $baseUrl . "/api/get_events?" . http_build_query(["limit" => "50"]);
$ch = curl_init($url);
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_TIMEOUT => 30,
    CURLOPT_HTTPHEADER => ["user-api-hash: " . $apiHash],
]);
$cuerpo = curl_exec($ch);
$codigo = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
if ($cuerpo === false || $codigo !== 200) {
    fwrite(STDERR, "HTTP $codigo\n");
    exit(1);
}
echo json_encode(json_decode($cuerpo, true), JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE), "\n";
```

### Respuestas

| Código | Descripción |
|---|---|
| `200` | Respuesta correcta. |
| `401` | Hash ausente o incorrecto, usuario inactivo, suscripción vencida (también la del gerente) o API deshabilitada por falta de pago del servidor. HTTP 401 con `{status: 0, message}`. |
| `403` | Sin permiso del rol para el módulo, vehículo de otro usuario o cuenta restringida por facturación. Incluye `perm: 0`. |
| `500` | Error interno de la plataforma. Con la depuración apagada el texto del mensaje es genérico. |

| Campo (respuesta 200) | Tipo | Descripción |
|---|---|---|
| `status` |  |  |
| `items` | Paginator + object \| CursorPaginator + object | Con ?page= devuelve Paginator; sin page, CursorPaginator. |

Ejemplo de respuesta 200 (datos ficticios):

```json
{
  "status": 1,
  "items": {
    "data": [
      {
        "id": 5000,
        "user_id": 1,
        "device_id": 9001,
        "geofence_id": null,
        "poi_id": null,
        "position_id": 700,
        "alert_id": 12,
        "type": "overspeed",
        "message": "Exceso de velocidad (ficticio)",
        "address": null,
        "altitude": 0,
        "course": 76,
        "latitude": -17.78,
        "longitude": -63.18,
        "power": null,
        "speed": 41,
        "time": "01-10-2026 17:08:19",
        "deleted": 0,
        "created_at": "2026-10-01 21:08:21",
        "updated_at": "2026-10-01 21:08:21",
        "additional": {
          "overspeed_speed": 30
        },
        "silent": null,
        "name": "Exceso de velocidad",
        "detail": "Velocidad 41 kph, limite 30 kph",
        "geofence": null,
        "device_name": "Camioneta de prueba 01"
      }
    ],
    "path": "https://plataforma.example.invalid/api/get_events",
    "per_page": 30,
    "next_cursor": "eyJldmVudHMuaWQiOjQ5OTl9",
    "next_page_url": "https://plataforma.example.invalid/api/get_events?cursor=eyJldmVudHMuaWQiOjQ5OTl9",
    "prev_cursor": null,
    "prev_page_url": null
  }
}
```

### Verificación

Estado: Verificado. Revisado el 5 de octubre de 2026. Ruta confirmada en producción y archivos del flujo idénticos a los verificados (comparación por huella y diff). La forma de la respuesta se midió con datos ficticios en un entorno de pruebas; no se probó con una cuenta real de producción.

## Reglas de alerta del usuario

**GET** `/api/get_alerts` · Estado: Verificado

Lista las reglas de alerta del usuario (no los eventos que dispararon). Si el usuario no tiene permiso para ver alertas devuelve `items.alerts` vacío, con HTTP 200.

Autenticación. Cabecera `user-api-hash` con tu `user_api_hash`.

### Parámetros

| Nombre | En | Tipo | Obligatorio | Descripción |
|---|---|---|---|---|
| `lang` | query | string | No | Idioma de los textos traducibles (SetLang). También se admite la cabecera Accept-Language. |

### Ejemplo de solicitud

cURL:

```bash
curl -sS "https://plataforma.trackerintl.com/api/get_alerts" \
  -H "user-api-hash: TU_API_HASH"
```

JavaScript:

```javascript
const BASE_URL = "https://plataforma.trackerintl.com";
const API_HASH = "TU_API_HASH";

const respuesta = await fetch(`${BASE_URL}/api/get_alerts`, {
  headers: { "user-api-hash": API_HASH },
});
if (!respuesta.ok) throw new Error(`HTTP ${respuesta.status}: ${await respuesta.text()}`);
console.log(JSON.stringify(await respuesta.json(), null, 2));
```

Python:

```python
import json
import requests

BASE_URL = "https://plataforma.trackerintl.com"
API_HASH = "TU_API_HASH"

respuesta = requests.get(
    f"{BASE_URL}/api/get_alerts",
    headers={"user-api-hash": API_HASH},
    timeout=30,
)
respuesta.raise_for_status()
print(json.dumps(respuesta.json(), indent=2, ensure_ascii=False))
```

PHP:

```php
<?php
$baseUrl = "https://plataforma.trackerintl.com";
$apiHash = "TU_API_HASH";

$url = $baseUrl . "/api/get_alerts";
$ch = curl_init($url);
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_TIMEOUT => 30,
    CURLOPT_HTTPHEADER => ["user-api-hash: " . $apiHash],
]);
$cuerpo = curl_exec($ch);
$codigo = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
if ($cuerpo === false || $codigo !== 200) {
    fwrite(STDERR, "HTTP $codigo\n");
    exit(1);
}
echo json_encode(json_decode($cuerpo, true), JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE), "\n";
```

### Respuestas

| Código | Descripción |
|---|---|
| `200` | Respuesta correcta. |
| `401` | Hash ausente o incorrecto, usuario inactivo, suscripción vencida (también la del gerente) o API deshabilitada por falta de pago del servidor. HTTP 401 con `{status: 0, message}`. |
| `403` | Sin permiso del rol para el módulo, vehículo de otro usuario o cuenta restringida por facturación. Incluye `perm: 0`. |
| `500` | Error interno de la plataforma. Con la depuración apagada el texto del mensaje es genérico. |

| Campo (respuesta 200) | Tipo | Descripción |
|---|---|---|
| `status` |  |  |
| `items` | object |  |

Ejemplo de respuesta 200 (datos ficticios):

```json
{
  "status": 1,
  "items": {
    "alerts": [
      {
        "id": 12,
        "user_id": 1,
        "active": 1,
        "name": "Exceso de velocidad (ficticio)",
        "type": "overspeed",
        "for_all_user_devices": 0,
        "schedules": null,
        "notifications": {
          "color": {
            "active": "0"
          },
          "silent": {
            "active": "0",
            "input": "0"
          },
          "sound": {
            "active": "1",
            "input": "alarm1"
          },
          "popup": {
            "active": "1",
            "input": "10"
          },
          "push": {
            "active": "1"
          },
          "email": {
            "active": "0"
          },
          "webhook": {
            "active": "0"
          },
          "sharing_email": {
            "active": "0"
          }
        },
        "created_at": "2026-02-24 21:09:52",
        "updated_at": "2026-02-24 21:09:52",
        "zone": 0,
        "schedule": 0,
        "command": {
          "active": "0",
          "type": "custom"
        },
        "continuous_duration": 0,
        "devices": [
          9001,
          9002
        ],
        "drivers": [],
        "geofences": [],
        "events_custom": [],
        "overspeed": 30
      }
    ]
  }
}
```

### Verificación

Estado: Verificado. Revisado el 5 de octubre de 2026. Ruta confirmada en producción y archivos del flujo idénticos a los verificados (comparación por huella y diff). La forma de la respuesta se midió con datos ficticios en un entorno de pruebas; no se probó con una cuenta real de producción.

## Conteo de eventos por tipo de alerta

**GET** `/api/get_alerts_summary` · Estado: Verificado

Cuenta los eventos agrupados por tipo. `date_from` y `date_to` se comparan sin conversión de zona horaria (UTC) contra la fecha de creación del evento. Solo acepta GET y requiere permiso para ver eventos.

Autenticación. Cabecera `user-api-hash` con tu `user_api_hash`.

### Parámetros

| Nombre | En | Tipo | Obligatorio | Descripción |
|---|---|---|---|---|
| `date_from` | query | string | No | created_at >= (UTC). |
| `date_to` | query | string | No | created_at <= (UTC). |
| `lang` | query | string | No | Idioma de los textos traducibles (SetLang). También se admite la cabecera Accept-Language. |

### Ejemplo de solicitud

cURL:

```bash
curl -sS -G "https://plataforma.trackerintl.com/api/get_alerts_summary" \
  -H "user-api-hash: TU_API_HASH" \
  --data-urlencode "date_from=2026-10-01" \
  --data-urlencode "date_to=2026-10-05"
```

JavaScript:

```javascript
const BASE_URL = "https://plataforma.trackerintl.com";
const API_HASH = "TU_API_HASH";

const params = new URLSearchParams({
  date_from: "2026-10-01",
  date_to: "2026-10-05",
});
const respuesta = await fetch(`${BASE_URL}/api/get_alerts_summary?${params}`, {
  headers: { "user-api-hash": API_HASH },
});
if (!respuesta.ok) throw new Error(`HTTP ${respuesta.status}: ${await respuesta.text()}`);
console.log(JSON.stringify(await respuesta.json(), null, 2));
```

Python:

```python
import json
import requests

BASE_URL = "https://plataforma.trackerintl.com"
API_HASH = "TU_API_HASH"

respuesta = requests.get(
    f"{BASE_URL}/api/get_alerts_summary",
    headers={"user-api-hash": API_HASH},
    params={"date_from": "2026-10-01", "date_to": "2026-10-05"},
    timeout=30,
)
respuesta.raise_for_status()
print(json.dumps(respuesta.json(), indent=2, ensure_ascii=False))
```

PHP:

```php
<?php
$baseUrl = "https://plataforma.trackerintl.com";
$apiHash = "TU_API_HASH";

$url = $baseUrl . "/api/get_alerts_summary?" . http_build_query(["date_from" => "2026-10-01", "date_to" => "2026-10-05"]);
$ch = curl_init($url);
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_TIMEOUT => 30,
    CURLOPT_HTTPHEADER => ["user-api-hash: " . $apiHash],
]);
$cuerpo = curl_exec($ch);
$codigo = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
if ($cuerpo === false || $codigo !== 200) {
    fwrite(STDERR, "HTTP $codigo\n");
    exit(1);
}
echo json_encode(json_decode($cuerpo, true), JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE), "\n";
```

### Respuestas

| Código | Descripción |
|---|---|
| `200` | Respuesta correcta. |
| `401` | Hash ausente o incorrecto, usuario inactivo, suscripción vencida (también la del gerente) o API deshabilitada por falta de pago del servidor. HTTP 401 con `{status: 0, message}`. |
| `403` | Sin permiso del rol para el módulo, vehículo de otro usuario o cuenta restringida por facturación. Incluye `perm: 0`. |
| `500` | Error interno de la plataforma. Con la depuración apagada el texto del mensaje es genérico. |

| Campo (respuesta 200) | Tipo | Descripción |
|---|---|---|
| `status` |  |  |
| `items` | array de object |  |

Ejemplo de respuesta 200 (datos ficticios):

```json
{
  "status": 1,
  "items": [
    {
      "type": "overspeed",
      "title": "Overspeed",
      "count": 18
    },
    {
      "type": "zone_in",
      "title": "Geofence in",
      "count": 4
    }
  ]
}
```

### Verificación

Estado: Verificado. Revisado el 5 de octubre de 2026. Ruta confirmada en producción y archivos del flujo idénticos a los verificados (comparación por huella y diff). La forma de la respuesta se midió con datos ficticios en un entorno de pruebas; no se probó con una cuenta real de producción.
