Apariencia
Tracking de Servicios
Nuevo en v3
El módulo de Tracking fue introducido en API v3 y no está disponible en versiones anteriores.
Descripción
El módulo de Tracking permite al cliente final rastrear el estado de su servicio mediante un portal de seguimiento. El acceso se verifica enviando un código de 6 dígitos por SMS al teléfono registrado en el servicio.
El servicio se identifica mediante una guía de servicio con el formato:
{expediente}-{idCentral}-{idServicio}Todos los endpoints de tracking requieren validación de integridad HMAC-SHA256. Ver la sección Autenticación del Chat para ver cómo generar los headers de integridad.
Endpoints
Solicitar Código de Verificación
POST /api/v3/tracking/requestCodeGenera y envía un código de verificación de 6 dígitos por SMS al número de teléfono registrado en el servicio. El código tiene una vigencia de 60 minutos.
Autenticación
Headers de integridad HMAC-SHA256 (ver Autenticación).
Body (JSON)
| Campo | Tipo | Requerido | Descripción |
|---|---|---|---|
guide | string | Sí | Guía del servicio en formato {expediente}-{idCentral}-{idServicio} |
Ejemplo de Request
json
{
"guide": "EXP2025001234-45-789"
}Respuesta exitosa (200 OK)
json
{
"message": "Código de verificación enviado",
"status": "success",
"maskedPhone": "+57****4567",
"expiresIn": "60 minutos",
"maxAttempts": 3
}Respuesta cuando el SMS falla (200 OK)
Cuando no se puede enviar el SMS (por ejemplo, Twilio no configurado), la respuesta indica cómo obtener el código de forma manual:
json
{
"message": "No se pudo enviar el código de verificación. Por favor, solicita el código directamente a tu empresa prestadora del servicio o a tu profesional asignado.",
"status": "error",
"details": {
"smsError": "Credenciales de Twilio no configuradas para esta empresa",
"canRequestManual": true
}
}Respuestas de error
| Código | Descripción |
|---|---|
400 | Guía de servicio inválida o sin número de teléfono registrado |
404 | Central o servicio no encontrado |
500 | Error interno al guardar el código |
json
{
"message": "Servicio no encontrado",
"status": "error"
}Información del Servicio (con verificación)
POST /api/v3/tracking/trackRetorna la información completa del servicio. Requiere el código de verificación enviado por SMS para acceder a datos privados (teléfonos, ubicación del técnico, etc.).
Si no se proporciona el código (validationCode), el endpoint retorna automáticamente la información pública del servicio (equivalente a POST /api/v3/tracking/track/public).
Autenticación
Headers de integridad HMAC-SHA256 (ver Autenticación).
Body (JSON)
| Campo | Tipo | Requerido | Descripción |
|---|---|---|---|
guide | string | Sí | Guía del servicio en formato {expediente}-{idCentral}-{idServicio} |
validationCode | string | No | Código de 6 dígitos recibido por SMS. Si se omite, retorna solo información pública |
Ejemplo de Request
json
{
"guide": "EXP2025001234-45-789",
"validationCode": "482916"
}Respuesta exitosa con código válido (200 OK)
json
{
"message": "Información del servicio obtenida exitosamente",
"status": "success",
"data": {
"expediente": "EXP2025001234",
"service_status": 4,
"tipoServicio": {
"id": 1,
"name": "Grúa liviana"
},
"direccionOrigen": "Carrera 25A #1A Sur-45",
"recurso": {
"names": "Carlos",
"lastname": "Ramírez",
"latitude": "6.2400",
"longitude": "-75.5800"
},
"tareas": {
"status": 3,
"estimatedArrival": "2025-07-03T14:45:00.000Z"
},
"track_enable": true
},
"isVerified": true
}Respuesta cuando el servicio no tiene recurso asignado (200 OK)
json
{
"message": "Servicio no cuenta con recurso asignado aún",
"status": true,
"data": null,
"showSurvey": false,
"track_enable": false,
"motivo": "Servicio sin recurso asignado"
}Respuesta cuando el servicio ya no está activo (200 OK)
json
{
"message": "Servicio ya no se encuentra activo",
"status": true,
"data": null,
"showSurvey": false,
"track_enable": false,
"motivo": "Servicio se encuentra en estado: Finalizado"
}Errores de validación del código
| Código HTTP | Descripción |
|---|---|
401 | No se proporcionó código, código expirado, o código incorrecto |
json
{
"message": "El código de acceso ha expirado. Por favor, verifica nuevamente para obtener la información del servicio",
"status": "error"
}json
{
"message": "El código de acceso proporcionado es incorrecto",
"status": "error"
}Información Pública del Servicio
POST /api/v3/tracking/track/publicRetorna únicamente la información pública del servicio, sin requerir código de verificación. Los datos sensibles como teléfonos del cliente y código de verificación son eliminados de la respuesta.
Autenticación
Headers de integridad HMAC-SHA256 (ver Autenticación).
Body (JSON)
| Campo | Tipo | Requerido | Descripción |
|---|---|---|---|
guide | string | Sí | Guía del servicio en formato {expediente}-{idCentral}-{idServicio} |
Ejemplo de Request
json
{
"guide": "EXP2025001234-45-789"
}Respuesta exitosa (200 OK)
json
{
"message": "Información pública del servicio obtenida exitosamente",
"status": "success",
"data": {
"expediente": "EXP2025001234",
"service_status": 4,
"tipoServicio": {
"id": 1,
"name": "Grúa liviana"
},
"direccionOrigen": "Carrera 25A #1A Sur-45",
"recurso": {
"names": "Carlos",
"lastname": "Ramírez",
"latitude": "6.2400",
"longitude": "-75.5800"
},
"track_enable": true
}
}Datos omitidos
En la información pública se omiten: c_cellphone, c_alt_phone, verificationCode, y las evidencias de las tareas.
Errores
| Código HTTP | Descripción |
|---|---|
400 | Guía de servicio inválida |
404 | Central o servicio no encontrado |
json
{
"message": "Guía de servicio inválida, consulte con su empresa prestadora del servicio",
"status": "error"
}Enviar Respuesta de Encuesta
POST /api/v3/tracking/surveyresponsePermite al cliente enviar su calificación de satisfacción tras la finalización del servicio.
Autenticación
Headers de integridad HMAC-SHA256 (ver Autenticación).
Body (JSON)
| Campo | Tipo | Requerido | Descripción |
|---|---|---|---|
guide | string | Sí | Guía del servicio |
rating | number | Sí | Calificación (1-5) |
comment | string | No | Comentario adicional |
Respuesta exitosa (200 OK)
json
{}Flujo Completo de Tracking
mermaid
sequenceDiagram
participant Cliente as Portal del cliente
participant API as Tsalva API v3
participant SMS as Twilio SMS
Cliente->>API: POST /tracking/track/public (sin código)
API-->>Cliente: Info pública del servicio
Cliente->>API: POST /tracking/requestCode
API->>SMS: Enviar código por SMS
SMS-->>Cliente: SMS con código de 6 dígitos
API-->>Cliente: { maskedPhone, expiresIn }
Cliente->>API: POST /tracking/track (con código)
API-->>Cliente: Info completa del servicio (técnico, coordenadas, etc.)
Note over Cliente,API: Encuesta al finalizar
Cliente->>API: POST /tracking/surveyresponse
API-->>Cliente: 200 OKPaso a paso:
Mostrar info pública (
POST /api/v3/tracking/track/public)- Muestra el estado básico del servicio sin requerir verificación
Solicitar código SMS (
POST /api/v3/tracking/requestCode)- El cliente ingresa la guía del servicio
- Se envía un código de 6 dígitos al teléfono registrado
Acceder a info completa (
POST /api/v3/tracking/track)- Con el código recibido se obtiene información detallada: técnico, coordenadas, ETA
Encuesta de satisfacción (
POST /api/v3/tracking/surveyresponse)- Al finalizar el servicio, el cliente puede calificar la experiencia
Ejemplo de Integración
javascript
const crypto = require('crypto');
const SECRET_KEY = 'tu_clave_secreta';
const API_URL = '[URL_API]';
function getIntegrityHeaders(method, path, body = {}) {
const timestamp = Math.floor(Date.now() / 1000).toString();
const sortedBody = sortObjectRecursively(body);
const payload = `${method}|${path}|${timestamp}|${JSON.stringify(sortedBody)}`;
const signature = crypto.createHmac('sha256', SECRET_KEY).update(payload).digest('hex');
return {
'X-Integrity-Timestamp': timestamp,
'X-Integrity-Signature': signature,
'X-Integrity-Algorithm': 'HMAC-SHA256',
'X-Integrity-Version': '1.0',
'Content-Type': 'application/json'
};
}
function sortObjectRecursively(obj) {
if (obj === null || typeof obj !== 'object') return obj;
if (Array.isArray(obj)) return obj.map(sortObjectRecursively);
return Object.keys(obj).sort().reduce((sorted, key) => {
sorted[key] = sortObjectRecursively(obj[key]);
return sorted;
}, {});
}
const guide = 'EXP2025001234-45-789';
// 1. Solicitar código
const reqBody = { guide };
const resp1 = await fetch(`${API_URL}/api/v3/tracking/requestCode`, {
method: 'POST',
headers: getIntegrityHeaders('POST', '/requestCode', reqBody),
body: JSON.stringify(reqBody)
});
const { maskedPhone, expiresIn } = await resp1.json();
console.log(`Código enviado a ${maskedPhone}, válido por ${expiresIn}`);
// 2. Verificar código e ir a info completa
const trackBody = { guide, validationCode: '482916' };
const resp2 = await fetch(`${API_URL}/api/v3/tracking/track`, {
method: 'POST',
headers: getIntegrityHeaders('POST', '/track', trackBody),
body: JSON.stringify(trackBody)
});
const serviceInfo = await resp2.json();
console.log('Técnico:', serviceInfo.data?.recurso?.names);Seguridad del código de verificación
El código SMS tiene una vigencia de 60 minutos y se invalida automáticamente una vez verificado correctamente. Si el código expira, el cliente debe solicitar uno nuevo con POST /tracking/requestCode.
Estado de tracking activo
El campo track_enable en la respuesta indica si es posible mostrar la ubicación del técnico en tiempo real. Solo está activo cuando el servicio está en progreso (service_status = 4) y tiene un recurso asignado.