Empezar

Autenticación

Cómo obtener tu user_api_hash, cómo enviarlo en cada petición y qué permisos concede, con ejemplos en cURL, JavaScript, Python y PHP.

Estado: Parcial · Revisada el 5 de octubre de 2026

Qué se verificó y cómo: Ruta y código confirmados en producción por diff. Los errores 401 y 422 se midieron en un entorno de pruebas; la respuesta 200 del inicio de sesión se lee del código y la caducidad del hash no se midió en producción.

La API usa un único tipo de credencial: el user_api_hash de un usuario de la plataforma. Lo obtienes una vez con tu correo y tu contraseña y lo envías en cada petición.

Cómo funciona #

  1. POST /api/login con email y password devuelve el user_api_hash.
  2. En cada llamada siguiente envías ese valor en la cabecera user-api-hash.
  3. La plataforma resuelve a qué usuario pertenece el hash y aplica sus permisos.

Si tu plataforma lo tiene habilitado, el hash también puede consultarse en la ficha del cliente dentro del panel de administración.

Enviar la credencial #

Enviar la credencial
FormaCómoRecomendación
Cabecerauser-api-hash: TU_API_HASHRecomendada
Parámetro?user_api_hash=TU_API_HASH (query o cuerpo)Evítala: las URL quedan en registros de acceso

Authorization: Bearer no funciona en esta API.

Datos y permisos del usuario

cURL

cURL
curl -sS "https://plataforma.trackerintl.com/api/get_user_data" \
  -H "user-api-hash: TU_API_HASH"

JavaScript · Node.js 22

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 3 con requests

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 8 con cURL

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

Caducidad del hash #

La caducidad no está medida en producción. Según la lectura del código, el hash no caduca por tiempo y se regenera cuando el usuario cambia su contraseña; al regenerarse, el valor anterior deja de servir. Hasta tener una medición real, trátalo como un dato por confirmar y prepara tu integración para volver a iniciar sesión si recibes un 401.

Qué permisos tiene el hash #

El hash concede los mismos permisos que la contraseña del usuario: no existen claves de solo lectura, claves por cliente ni alcances por módulo. Los permisos del usuario (ver, editar y eliminar por módulo) se aplican en cada petición, y GET /api/get_user_data te devuelve la matriz completa. Por eso te recomendamos:

  • Crear un usuario dedicado a la integración, con permisos únicamente de "ver".
  • Guardar el hash en un gestor de secretos o en variables de entorno, nunca en el código ni en el navegador de tus usuarios.
  • No enviarlo en la URL.

Errores de autenticación #

Errores de autenticación
RespuestaCausa probableQué hacer
401 con {"status": 0, "message": "..."}Hash ausente o incorrecto, usuario inactivo, suscripción vencida (también la del gerente) o API deshabilitada por falta de pago del servidorVerifica el hash; si cambió la contraseña, vuelve a iniciar sesión; si todo está bien, contacta a quien administra tu cuenta
422 en el inicio de sesiónFaltan email o passwordEnvía ambos campos

Consulta el detalle en Errores y los límites de intentos en Límites.

Operación de inicio de sesión #

Obtener el hash de API (user_api_hash) #

POST /api/login Parcial

Canjea correo y contraseña por el user_api_hash, la credencial que se envía en el resto de las peticiones. Acepta cuerpo JSON o formulario. Si el usuario aún no tiene hash, la plataforma lo genera en ese momento.

Autenticación. Sin autenticación. Límite de la plataforma: 60 peticiones por minuto.

  • Según el código, el hash no caduca por tiempo y cambia cuando el usuario cambia su contraseña. No se midió en producción.
  • Límite de 60 peticiones por minuto (valor por defecto del código; el valor de producción no está confirmado).
  • El hash concede los mismos permisos que la contraseña del usuario. No existen claves de solo lectura ni por alcance.

Parámetros

Parámetros de /api/login
NombreEnTipoObligatorioDescripción
emailcuerpostringSí
passwordcuerpostringSí

Ejemplo de solicitud

cURL

cURL
curl -sS -X POST "https://plataforma.trackerintl.com/api/login" \
  -H "Content-Type: application/json" \
  -d '{"email":"demo@example.com","password":"TU_CONTRASENA"}'

JavaScript · Node.js 22

JavaScript
const BASE_URL = "https://plataforma.trackerintl.com";

const respuesta = await fetch(`${BASE_URL}/api/login`, {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({ email: "demo@example.com", password: "TU_CONTRASENA" }),
});
if (!respuesta.ok) throw new Error(`HTTP ${respuesta.status}: ${await respuesta.text()}`);
console.log(JSON.stringify(await respuesta.json(), null, 2));

Python · Python 3 con requests

Python
import json
import requests

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

respuesta = requests.post(
    f"{BASE_URL}/api/login",
    json={"email": "demo@example.com", "password": "TU_CONTRASENA"},
    timeout=30,
)
respuesta.raise_for_status()
print(json.dumps(respuesta.json(), indent=2, ensure_ascii=False))

PHP · PHP 8 con cURL

PHP
<?php
$baseUrl = "https://plataforma.trackerintl.com";

$url = $baseUrl . "/api/login";
$ch = curl_init($url);
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_TIMEOUT => 30,
    CURLOPT_POST => true,
    CURLOPT_POSTFIELDS => json_encode(["email" => "demo@example.com", "password" => "TU_CONTRASENA"]),
    CURLOPT_HTTPHEADER => ["Content-Type: application/json"],
]);
$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

Respuestas de /api/login
CódigoDescripción
200Respuesta correcta.
401Hash 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}.
422Faltan email/password. Forma {status:0,errors:{campo:[..]}} (sin statusCode).
429Límite de peticiones superado (inferido del comportamiento estándar; no medido).
Campos de primer nivel de la respuesta 200
Campo (respuesta 200)TipoDescripción
status
user_api_hashstringCredencial de la API. Larga vida: solo cambia si se cambia la contraseña del usuario.
permissionsobject
Ejemplo de respuesta 200 (datos ficticios)
JSON
{
  "status": 1,
  "user_api_hash": "TU_API_HASH",
  "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: Parcial. Revisado el 5 de octubre de 2026. Ruta confirmada en producción y código idéntico al verificado. Los errores 401 y 422 se midieron en un entorno de pruebas; la respuesta 200 se lee del código porque no se hizo un inicio de sesión real.