> Índice completo de la documentación: https://trackerintl.com/devs/llms.txt
> Esta página en HTML: https://trackerintl.com/devs/referencia/usuario
> 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. No probado con una cuenta real.

# Usuario

Datos y permisos del usuario de la API, sus conductores y el historial de comandos enviados a los equipos.

`get_user_data` es la primera llamada que conviene hacer con un hash nuevo: confirma que la credencial funciona y muestra qué módulos puede ver, editar o eliminar el usuario. Las otras dos operaciones consultan conductores y el historial de comandos enviados; ninguna envía datos.

En `get_user_data`, `group_id` identifica el tipo de cuenta (1 administrador, 2 usuario o cliente, 3 gerente o revendedor, 4 demo, 5 operador, 6 supervisor y 7 financiero, este último solo en producción).

## Datos y permisos del usuario de la API

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

Devuelve el correo, el plan, el vencimiento de la suscripción, los días restantes, el límite de vehículos y la matriz de permisos del usuario. Úsalo para comprobar que la credencial funciona.

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_user_data" \
  -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_user_data`, {
  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_user_data",
    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_user_data";
$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 |
|---|---|---|
| `email` | string |  |
| `expiration_date` | string \| null |  |
| `days_left` | integer \| null |  |
| `plan` | string |  |
| `devices_limit` | integer |  |
| `group_id` | integer | 1 admin, 2 usuario/cliente, 3 gerente (reseller), 4 demo, 5 operador, 6 supervisor; 7 = financiero (solo en producción). |
| `role_id` | integer |  |
| `permissions` | object | Módulo -> {view,edit,remove}. Incluye claves como "devices", "history", "device.imei". |

Ejemplo de respuesta 200 (datos ficticios):

```json
{
  "email": "demo@example.invalid",
  "expiration_date": "31-12-2030 23:59:59",
  "days_left": 1547,
  "plan": "Plan de demostracion (ficticio)",
  "devices_limit": 10,
  "group_id": 2,
  "role_id": 2,
  "permissions": {
    "devices": {
      "view": true,
      "edit": false,
      "remove": false
    },
    "alerts": {
      "view": true,
      "edit": false,
      "remove": false
    },
    "events": {
      "view": true,
      "edit": false,
      "remove": false
    },
    "geofences": {
      "view": true,
      "edit": false,
      "remove": false
    },
    "routes": {
      "view": true,
      "edit": false,
      "remove": false
    },
    "reports": {
      "view": true,
      "edit": false,
      "remove": false
    },
    "history": {
      "view": true,
      "edit": false,
      "remove": false
    },
    "send_command": {
      "view": false,
      "edit": false,
      "remove": false
    }
  }
}
```

### 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.

## Conductores del usuario

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

Lista los conductores del usuario, paginados (`limit` vale 10 por defecto). Requiere permiso para ver conductores.

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

### Parámetros

| Nombre | En | Tipo | Obligatorio | Descripción |
|---|---|---|---|---|
| `limit` | query | integer | No |  |
| `search` | query | string | No |  |
| `page` | query | integer | No | Número de página. |
| `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_user_drivers" \
  -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_user_drivers`, {
  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_user_drivers",
    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_user_drivers";
$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": {
    "drivers": {
      "current_page": 1,
      "data": [
        {
          "id": 21,
          "user_id": 1,
          "device_id": null,
          "name": "Conductor de prueba",
          "rfid": "0000000001",
          "phone": "5550000000",
          "email": "conductor@example.invalid",
          "description": null,
          "created_at": "2026-01-01 00:00:00",
          "updated_at": "2026-01-01 00:00:00"
        }
      ],
      "first_page_url": "https://plataforma.example.invalid/api/get_user_drivers?page=1",
      "from": 1,
      "last_page": 1,
      "last_page_url": "https://plataforma.example.invalid/api/get_user_drivers?page=1",
      "links": [],
      "next_page_url": null,
      "path": "https://plataforma.example.invalid/api/get_user_drivers",
      "per_page": 10,
      "prev_page_url": null,
      "to": 1,
      "total": 1
    }
  }
}
```

### 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.

## Historial de comandos enviados a los equipos

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

Historial de los comandos enviados a los equipos, 15 por página. Es solo lectura: no envía ningún comando. Requiere permiso para ver comandos.

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

### Parámetros

| Nombre | En | Tipo | Obligatorio | Descripción |
|---|---|---|---|---|
| `search` | query | string | No |  |
| `page` | query | integer | No | Número de página. |
| `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/sent_commands" \
  -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/sent_commands`, {
  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/sent_commands",
    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/sent_commands";
$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 |
|---|---|---|
| `data` | array de SentCommand |  |
| `pagination` | object |  |

Ejemplo de respuesta 200 (datos ficticios):

```json
{
  "data": [
    {
      "id": 401,
      "user_id": 1,
      "imei": "999000000000001",
      "connection": "gprs",
      "command_title": "Posicion unica (ficticio)",
      "parameters": {
        "data": "WHERE#"
      },
      "response": "OK",
      "status": 1,
      "created_at": "01-10-2026 09:00:00",
      "updated_at": "01-10-2026 09:00:05"
    }
  ],
  "pagination": {
    "total": 1,
    "per_page": 15,
    "current_page": 1,
    "last_page": 1,
    "next_page_url": 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.
