> Índice completo de la documentación: https://trackerintl.com/devs/llms.txt
> Esta página en HTML: https://trackerintl.com/devs/guias/erp-y-crm
> Estado: Parcial, revisada el 2026-10-05. Usa operaciones verificadas por diff contra producción. El script se ejecutó contra un servidor simulado con 95 eventos ficticios; no se ha ejecutado contra una cuenta real.

# Sincronizar con un ERP o CRM

Mantén tu ERP o CRM al día con tus vehículos y los eventos de alertas mediante lectura periódica de la API, con un script de ejemplo con cursor.

Esta guía sincroniza dos cosas con un sistema externo: el **inventario de vehículos** (cada cierto tiempo) y los **eventos de alertas** (de forma incremental). La API entrega los datos; el modelo de tu ERP o CRM y su lógica los defines tú.

## Plan

1. **Inventario**: llama a `get_devices` con `limit` y `page` hasta que la lista llegue vacía. Relaciona cada `id` con tu activo; los datos del equipo (IMEI, placa) están en `device_data`.
2. **Eventos**: llama a `get_events` sin `page`. La respuesta trae `items.data` y `items.next_cursor`; envía `next_cursor` como `cursor` hasta que sea `null`.
3. **Incremental**: en las ejecuciones siguientes usa `date_from` con la fecha del último evento que procesaste, para no recorrer todo. Las fechas se interpretan en la zona horaria de la cuenta.
4. **Idempotencia**: usa el `id` del evento como clave única en tu sistema. Si una ejecución se repite, no duplicarás registros.
5. **Frecuencia**: no hay una frecuencia oficial. Respeta los [límites](/devs/limites) y reintenta con espera creciente si recibes un `429` o un `5xx`.

## Inventario de vehículos

**Listar vehículos**

cURL:

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

JavaScript:

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

const params = new URLSearchParams({
  limit: "50",
  page: "1",
});
const respuesta = await fetch(`${BASE_URL}/api/get_devices?${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_devices",
    headers={"user-api-hash": API_HASH},
    params={"limit": "50", "page": "1"},
    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_devices?" . http_build_query(["limit" => "50", "page" => "1"]);
$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";
```

## Eventos con cursor

**Eventos recientes**

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";
```

## Script de ejemplo

Este script lee todos los eventos disponibles siguiendo el cursor y muestra cuántos leyó. Sustituye la parte final por la escritura en tu sistema.

**Leer eventos con cursor**

cURL:

```bash
#!/usr/bin/env bash
# Requiere curl y jq.
BASE_URL="https://plataforma.trackerintl.com"
API_HASH="TU_API_HASH"

CURSOR=""
TOTAL=0

while true; do
  RESPUESTA=$(curl -sS -G "$BASE_URL/api/get_events" \
    -H "user-api-hash: $API_HASH" \
    --data-urlencode "limit=50" \
    --data-urlencode "cursor=$CURSOR")
  # Aquí guardas los eventos en tu sistema, usando .id como clave única.
  TOTAL=$((TOTAL + $(echo "$RESPUESTA" | jq '.items.data | length')))
  CURSOR=$(echo "$RESPUESTA" | jq -r '.items.next_cursor // empty')
  [ -z "$CURSOR" ] && break
done

echo "Eventos leídos: $TOTAL"
```

JavaScript:

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

let cursor = null;
let total = 0;

do {
  const params = new URLSearchParams({ limit: "50" });
  if (cursor) params.set("cursor", cursor);

  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}`);
  const { items } = await respuesta.json();

  for (const evento of items.data) {
    // Aquí guardas el evento en tu sistema, usando evento.id como clave única.
    total += 1;
  }
  cursor = items.next_cursor;
} while (cursor);

console.log(`Eventos leídos: ${total}`);
```

Python:

```python
import requests

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

cursor = None
total = 0

while True:
    params = {"limit": "50"}
    if cursor:
        params["cursor"] = cursor
    respuesta = requests.get(
        f"{BASE_URL}/api/get_events",
        headers={"user-api-hash": API_HASH},
        params=params,
        timeout=30,
    )
    respuesta.raise_for_status()
    items = respuesta.json()["items"]

    for evento in items["data"]:
        # Aquí guardas el evento en tu sistema, usando evento["id"] como clave única.
        total += 1

    cursor = items["next_cursor"]
    if not cursor:
        break

print(f"Eventos leídos: {total}")
```

PHP:

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

$cursor = null;
$total = 0;

do {
    $params = ["limit" => "50"];
    if ($cursor) {
        $params["cursor"] = $cursor;
    }
    $ch = curl_init($baseUrl . "/api/get_events?" . http_build_query($params));
    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);
    }
    $items = json_decode($cuerpo, true)["items"];

    foreach ($items["data"] as $evento) {
        // Aquí guardas el evento en tu sistema, usando $evento["id"] como clave única.
        $total++;
    }
    $cursor = $items["next_cursor"];
} while ($cursor);

echo "Eventos leídos: $total\n";
```

> **Sobre los datos.**
>
> El script del ejemplo no guarda estado entre ejecuciones. En tu integración, guarda la fecha del último evento procesado y el `id` para la idempotencia.
