Passwordless


Documentación de API - Módulo Passwordless

Introducción

El módulo Passwordless de JAAK permite implementar autenticación biométrica facial sin contraseñas. Esta documentación proporciona información detallada sobre todos los endpoints disponibles, sus parámetros, y ejemplos de uso.

Autenticación

Todos los endpoints requieren autenticación mediante API Key:

ApiKeyAuth: tu-api-key-aqui

Gestión de Usuarios

1. Buscar Lista de Usuarios

Endpoint: GET /api/v1/passwordless/client

Busca usuarios inscritos utilizando diferentes criterios de filtrado.

Parámetros Query

ParámetroTipoRequeridoDefaultDescripción
limitintegerNo10Límite de items por página
pageintegerNo1Número de página a obtener
statusstringNoactiveEstado del usuario
fullNamestringNo-Nombre completo del usuario
external-idstringNo-ID externo del cliente
min-created-atstring (date-time)No-Fecha mínima de creación
max-created-atstring (date-time)No-Fecha máxima de creación

Respuesta Exitosa (200)

{
  "docList": [
    {
      "id": "string",
      "companyId": "string",
      "fullName": "string",
      "email": "string",
      "externalId": "string",
      "status": "active",
      "images": {
        "original": "string",
        "thumbnail": "string"
      },
      "meta": {
        "extra": "string",
        "fingers": "string",
        "identifications": "string"
      },
      "createdAt": "string",
      "updatedAt": "string"
    }
  ],
  "page": 0,
  "limit": 0,
  "totalDocs": 0,
  "totalPages": 0,
  "prevPage": true,
  "nextPage": true
}

Ejemplo de uso

GET /api/v1/passwordless/client?status=active&limit=20&page=1&fullName=Juan

2. Consultar Usuario por ID

Endpoint: GET /api/v1/passwordless/client/{id}

Obtiene la información detallada de un usuario específico.

Parámetros

ParámetroTipoRequeridoDescripción
idstringID del cliente (path parameter)

Respuesta Exitosa (200)

{
  "id": "string",
  "companyId": "string",
  "fullName": "string",
  "email": "string",
  "externalId": "string",
  "status": "active",
  "images": {
    "original": "string",
    "thumbnail": "string"
  },
  "meta": {
    "extra": "string",
    "fingers": "string",
    "identifications": "string"
  },
  "createdAt": "string",
  "updatedAt": "string"
}

3. Actualizar Usuario

Endpoint: PUT /api/v1/passwordless/client/{id}

Actualiza la información de un usuario registrado.

Headers

HeaderTipoRequeridoDefaultDescripción
Request-IdstringNo-Identificador único para la solicitud
LatitudestringNo40.7128Coordenada de latitud en grados decimales
LongitudestringNo-74.0060Coordenada de longitud en grados decimales

Request Body

{
  "fullName": "string",
  "status": "active"
}

Respuesta Exitosa (200)

[
  {
    "id": "string",
    "companyId": "string",
    "fullName": "string",
    "email": "string",
    "externalId": "string",
    "status": "active",
    "images": {
      "original": "string",
      "thumbnail": "string"
    },
    "meta": {
      "extra": "string",
      "fingers": "string",
      "identifications": "string"
    },
    "createdAt": "string",
    "updatedAt": "string"
  }
]

4. Eliminar Usuario

Endpoint: DELETE /api/v1/passwordless/client/{id}

⚠️ ADVERTENCIA: Esta acción es permanente y no se puede deshacer.

Parámetros

ParámetroTipoRequeridoDescripción
idstringID del cliente

Respuesta Exitosa (200)

{}

Inscripción (Enrollment)

1. Inscribir Usuario con Video

Endpoint: POST /api/v1/passwordless/client/enroll

Inscribe un nuevo usuario utilizando un video en formato base64.

Headers

HeaderTipoRequeridoDefaultDescripción
Request-IdstringNod99fe2d2-c0c3-4396-bd97-a502b4c30fa3Identificador único para la solicitud
LatitudestringNo40.7128Coordenada de latitud
LongitudestringNo-74.0060Coordenada de longitud

Request Body

{
  "video": "string",
  "user": {
    "fullName": "string",
    "email": "string",
    "externalId": "string"
  }
}

Respuesta Exitosa (200)

{
  "eventId": "string",
  "requestId": "string",
  "processTime": 0,
  "user": {
    "id": "string",
    "companyId": "string",
    "fullName": "string",
    "email": "string",
    "externalId": "string",
    "status": "active",
    "images": {
      "original": "string",
      "thumbnail": "string"
    },
    "meta": {
      "extra": "string",
      "fingers": "string",
      "identifications": "string"
    },
    "createdAt": "string",
    "updatedAt": "string"
  }
}

Mejores Prácticas

  • Video con buena iluminación
  • Rostro centrado y visible
  • Duración: 2-5 segundos
  • Resolución mínima: 720p
  • Formato base64 válido

2. Inscribir Usuario con Imagen

Endpoint: POST /api/v1/passwordless/client/face-enroll

Inscribe un nuevo usuario utilizando una imagen en formato base64.

Headers

HeaderTipoRequeridoDefaultDescripción
Request-IdstringNod99fe2d2-c0c3-4396-bd97-a502b4c30fa3Identificador único para la solicitud
LatitudestringNo40.7128Coordenada de latitud
LongitudestringNo-74.0060Coordenada de longitud

Request Body

{
  "image": "string",
  "user": {
    "fullName": "string",
    "email": "string",
    "externalId": "string"
  }
}

Respuesta Exitosa (200)

{
  "eventId": "string",
  "requestId": "string",
  "processTime": 0,
  "user": {
    "id": "string",
    "companyId": "string",
    "fullName": "string",
    "email": "string",
    "externalId": "string",
    "status": "active",
    "images": {
      "original": "string",
      "thumbnail": "string"
    },
    "meta": {
      "extra": "string",
      "fingers": "string",
      "identifications": "string"
    },
    "createdAt": "string",
    "updatedAt": "string"
  }
}

Requisitos de Imagen

  • Formato: JPG, PNG
  • Rostro frontal y visible
  • Buena iluminación
  • Sin accesorios que obstruyan el rostro
  • Resolución mínima: 640x480

Verificación de Identidad

1. Verificar Usuario con Video

Endpoint: POST /api/v1/passwordless/client/verify

Busca y verifica un usuario previamente inscrito mediante un video.

Headers

HeaderTipoRequeridoDefaultDescripción
Request-IdstringNod99fe2d2-c0c3-4396-bd97-a502b4c30fa3Identificador único para la solicitud
LanguagestringNoenIdioma de respuesta (en/es)
LatitudestringNo40.7128Coordenada de latitud
LongitudestringNo-74.0060Coordenada de longitud

Request Body

{
  "video": "string"
}

Respuesta Exitosa (200)

{
  "eventId": "string",
  "requestId": "string",
  "processTime": 0,
  "user": {
    "id": "string",
    "companyId": "string",
    "fullName": "string",
    "email": "string",
    "externalId": "string",
    "status": "active",
    "images": {
      "original": "string",
      "thumbnail": "string"
    },
    "meta": {
      "extra": "string",
      "fingers": "string",
      "identifications": "string"
    },
    "createdAt": "string",
    "updatedAt": "string"
  }
}

2. Verificar Usuario con Imagen

Endpoint: POST /api/v1/passwordless/client/face-verify

Busca y verifica un usuario previamente inscrito mediante una imagen.

Headers

HeaderTipoRequeridoDefaultDescripción
Request-IdstringNod99fe2d2-c0c3-4396-bd97-a502b4c30fa3Identificador único para la solicitud
LatitudestringNo40.7128Coordenada de latitud
LongitudestringNo-74.0060Coordenada de longitud

Request Body

{
  "image": "string"
}

Respuesta Exitosa (200)

{
  "eventId": "string",
  "requestId": "string",
  "processTime": 0,
  "user": {
    "id": "string",
    "companyId": "string",
    "fullName": "string",
    "email": "string",
    "externalId": "string",
    "status": "active",
    "images": {
      "original": "string",
      "thumbnail": "string"
    },
    "meta": {
      "extra": "string",
      "fingers": "string",
      "identifications": "string"
    },
    "createdAt": "string",
    "updatedAt": "string"
  }
}

Búsqueda Facial

1. Búsqueda por Imagen (1:N)

Endpoint: POST /api/v1/passwordless/client/facial

Busca usuarios similares a partir de una imagen, retornando los mejores matches ordenados por similitud.

Request Body

{
  "image": "string",
  "rankingTop": 0
}

Parámetros:

  • image: Imagen en formato base64
  • rankingTop: Número de resultados a retornar (top N matches)

Respuesta Exitosa (200)

{
  "threshold": 0,
  "clientList": [
    {
      "distance": 0,
      "user": {
        "id": "string",
        "companyId": "string",
        "fullName": "string",
        "email": "string",
        "externalId": "string",
        "status": "active",
        "images": {
          "original": "string",
          "thumbnail": "string"
        },
        "meta": {
          "extra": "string",
          "fingers": "string",
          "identifications": "string"
        },
        "createdAt": "string",
        "updatedAt": "string"
      }
    }
  ]
}

Interpretación de la respuesta:

  • threshold: Umbral de confianza utilizado
  • distance: Distancia facial (mayor = más similar)
  • Los resultados están ordenados de más a menos similar

2. Búsqueda por Vectores Faciales

Endpoint: POST /api/v1/passwordless/client/faces

Búsqueda avanzada utilizando vectores de características faciales pre-calculados.

Request Body

{
  "faces": [
    {
      "id": "string",
      "vector": [0]
    }
  ]
}

Parámetros:

  • id: Identificador temporal del vector
  • vector: Array de números flotantes (feature vector)

Respuesta Exitosa (200)

[
  {
    "names": [
      {
        "id": "string",
        "name": "string"
      }
    ]
  }
]

¿Qué es un Feature Vector?

Un feature vector es una representación matemática del rostro como un array de números flotantes (típicamente 128 o 512 dimensiones). Este método es útil para:

  • Búsquedas muy rápidas
  • Procesamiento por lotes
  • Integración con sistemas propios de extracción

Eventos y Auditoría

1. Consultar Lista de Eventos

Endpoint: GET /api/v1/passwordless/event

Obtiene el historial de eventos con filtros avanzados para auditoría y análisis.

Parámetros Query

ParámetroTipoRequeridoDefaultDescripción
limitintegerNo10Límite de items por página
pageintegerNo1Número de página
actionstringNoverify-livenessAcción realizada en el evento
statusstringNosuccessEstado del evento
event-idstringNo-ID específico del evento
min-process-timenumberNo100Tiempo mínimo de procesamiento (ms)
max-process-timenumberNo200Tiempo máximo de procesamiento (ms)
min-created-atstring (date-time)No-Fecha mínima de creación
max-created-atstring (date-time)No-Fecha máxima de creación

Respuesta Exitosa (200)

{
  "docList": [
    {
      "id": "string",
      "eventId": "string",
      "action": "string",
      "status": "success",
      "message": "string",
      "processTime": 0,
      "request": {
        "id": "string",
        "ip": "string",
        "method": "get",
        "path": "string",
        "statusCode": 0,
        "meta": {
          "request": {},
          "response": {}
        }
      },
      "flow": [
        {
          "resource": "liveness",
          "status": "success",
          "message": "string",
          "meta": {
            "time": "string",
            "processTime": 0,
            "extra": {}
          }
        }
      ],
      "meta": {
        "extra": {}
      },
      "createdAt": "string",
      "updatedAt": "string"
    }
  ],
  "page": 0,
  "limit": 0,
  "totalDocs": 0,
  "totalPages": 0,
  "prevPage": true,
  "nextPage": true
}

Ejemplo de uso

GET /api/v1/passwordless/event?action=verify-liveness&status=success&limit=50

2. Consultar Evento Específico

Endpoint: GET /api/v1/passwordless/event/{id}

Obtiene el detalle completo de un evento particular.

Parámetros

ParámetroTipoRequeridoDefaultDescripción
idstring06722190-9de7-4d1b-a9ad-1559a5ab8cb9ID del evento

Respuesta Exitosa (200)

{
  "id": "string",
  "eventId": "string",
  "action": "string",
  "status": "success",
  "message": "string",
  "processTime": 0,
  "request": {
    "id": "string",
    "ip": "string",
    "method": "get",
    "path": "string",
    "statusCode": 0,
    "meta": {
      "request": {},
      "response": {}
    }
  },
  "flow": [
    {
      "resource": "liveness",
      "status": "success",
      "message": "string",
      "meta": {
        "time": "string",
        "processTime": 0,
        "extra": {}
      }
    }
  ],
  "meta": {
    "extra": {}
  },
  "createdAt": "string",
  "updatedAt": "string"
}

Estadísticas

1. Conteo de Solicitudes por Granularidad

Endpoint: GET /api/v1/passwordless/stats/request-by-granularity

Cuenta las solicitudes realizadas en un rango de tiempo con diferentes niveles de detalle.

Parámetros Query

ParámetroTipoRequeridoDefaultDescripción
start-datestring (date-time)2022-01-19T00:00:00ZFecha inicial del conteo
end-datestring (date-time)2022-01-19T00:00:00ZFecha final del conteo
granularitystringminuteNivel de detalle: minute, hour, day
api-key-idstringNo-ID de la API key que realizó la solicitud
user-idstringNo-ID del usuario que realizó la solicitud

Respuesta Exitosa (200)

{
  "total": 0,
  "timeList": [
    {
      "key": "string",
      "value": 0
    }
  ]
}

Interpretación:

  • total: Total de solicitudes en el rango
  • timeList: Lista de conteos agrupados por la granularidad especificada
    • key: Timestamp o fecha
    • value: Número de solicitudes

Ejemplo de uso

GET /api/v1/passwordless/stats/request-by-granularity?start-date=2024-01-01T00:00:00Z&end-date=2024-01-31T23:59:59Z&granularity=day

2. Conteo por Tiempo de Procesamiento

Endpoint: GET /api/v1/passwordless/stats/request-by-lapse

Analiza las solicitudes agrupadas por su tiempo de procesamiento.

Parámetros Query

ParámetroTipoRequeridoDefaultDescripción
start-datestring (date-time)2022-01-19T00:00:00ZFecha inicial del conteo
end-datestring (date-time)2022-01-19T00:00:00ZFecha final del conteo
granularitystringminuteNivel de detalle: minute, hour, day
api-key-idstringNo-ID de la API key que realizó la solicitud
user-idstringNo-ID del usuario que realizó la solicitud

Respuesta Exitosa (200)

{
  "average": 10.5,
  "mode": 5.5,
  "lapse_list": [
    {
      "key": 60,
      "value": 100
    }
  ]
}

Interpretación:

  • average: Promedio del tiempo de procesamiento en ms
  • mode: Moda (valor más frecuente) del tiempo de procesamiento
  • lapse_list: Lista de rangos de tiempo
    • key: Tiempo de procesamiento en ms
    • value: Cantidad de solicitudes en ese rango

Modelos de Datos

Cliente (User)

{
  "id": "string",
  "companyId": "string",
  "fullName": "string",
  "email": "string",
  "externalId": "string",
  "status": "active",
  "images": {
    "original": "string",
    "thumbnail": "string"
  },
  "meta": {
    "extra": "string",
    "fingers": "string",
    "identifications": "string"
  },
  "createdAt": "string",
  "updatedAt": "string"
}

Respuesta de Error

{
  "statusCode": 0,
  "errorCode": "string",
  "message": "string",
  "eventId": "string"
}

Estados Posibles

  • Usuario: active, inactive, blocked
  • Evento: success, failed, pending
  • Recurso: liveness, enroll, verify
  • Método HTTP: get, post, put, delete

Ejemplos de Uso

Ejemplo 1: Flujo Completo de Inscripción y Verificación

// 1. Inscribir nuevo usuario con imagen
const enrollResponse = await fetch('https://api.jaak.mx/api/v1/passwordless/client/face-enroll', {
  method: 'POST',
  headers: {
    'ApiKeyAuth': 'tu-api-key',
    'Content-Type': 'application/json',
    'Request-Id': crypto.randomUUID(),
    'Latitude': '19.4326',
    'Longitude': '-99.1332'
  },
  body: JSON.stringify({
    image: imageBase64,
    user: {
      fullName: 'Roberto López García',
      email: '[email protected]',
      externalId: 'EMP-001'
    }
  })
});

const enrollData = await enrollResponse.json();
console.log('Usuario inscrito:', enrollData.user.id);
console.log('Tiempo de procesamiento:', enrollData.processTime, 'ms');
console.log('Event ID:', enrollData.eventId);

// 2. Verificar usuario con imagen
const verifyResponse = await fetch('https://api.jaak.mx/api/v1/passwordless/client/face-verify', {
  method: 'POST',
  headers: {
    'ApiKeyAuth': 'tu-api-key',
    'Content-Type': 'application/json',
    'Request-Id': crypto.randomUUID()
  },
  body: JSON.stringify({
    image: verificationImageBase64
  })
});

const verifyData = await verifyResponse.json();
if (verifyData.user) {
  console.log('Usuario verificado:', verifyData.user.fullName);
  console.log('External ID:', verifyData.user.externalId);
}

Ejemplo 2: Búsqueda Facial con Top 5 Matches

import requests
import base64

API_KEY = 'tu-api-key'
BASE_URL = 'https://api.jaak.mx/api/v1/passwordless'

headers = {
    'ApiKeyAuth': API_KEY,
    'Content-Type': 'application/json'
}

# Leer y codificar imagen
with open('rostro.jpg', 'rb') as image_file:
    image_base64 = base64.b64encode(image_file.read()).decode('utf-8')

# Buscar top 5 matches
response = requests.post(
    f'{BASE_URL}/client/facial',
    headers=headers,
    json={
        'image': image_base64,
        'rankingTop': 5
    }
)

result = response.json()
print(f'Threshold: {result["threshold"]}')
print(f'Matches encontrados: {len(result["clientList"])}')

for i, match in enumerate(result['clientList'], 1):
    print(f'\nMatch {i}:')
    print(f'  Nombre: {match["user"]["fullName"]}')
    print(f'  Distancia: {match["distance"]} (mayor = más similar)')
    print(f'  External ID: {match["user"]["externalId"]}')

Ejemplo 3: Gestión y Actualización de Usuarios

import requests
import uuid

API_KEY = 'tu-api-key'
BASE_URL = 'https://api.jaak.mx/api/v1/passwordless'

headers = {
    'ApiKeyAuth': API_KEY,
    'Content-Type': 'application/json',
    'Request-Id': str(uuid.uuid4())
}

# 1. Buscar usuarios activos
response = requests.get(
    f'{BASE_URL}/client',
    headers=headers,
    params={
        'status': 'active',
        'limit': 100,
        'page': 1
    }
)

users = response.json()
print(f'Total de usuarios: {users["totalDocs"]}')
print(f'Páginas: {users["totalPages"]}')

# 2. Actualizar un usuario específico
if users['docList']:
    user_id = users['docList'][0]['id']
    
    update_response = requests.put(
        f'{BASE_URL}/client/{user_id}',
        headers=headers,
        json={
            'fullName': 'Nombre Actualizado',
            'status': 'active'
        }
    )
    
    updated_user = update_response.json()
    print(f'Usuario actualizado: {updated_user[0]["fullName"]}')

Ejemplo 4: Monitoreo de Eventos y Estadísticas

# Obtener estadísticas del último mes
curl -X GET "https://api.jaak.mx/api/v1/passwordless/stats/request-by-granularity?start-date=2024-11-01T00:00:00Z&end-date=2024-11-30T23:59:59Z&granularity=day" \
  -H "ApiKeyAuth: tu-api-key"

# Consultar eventos fallidos del último día
curl -X GET "https://api.jaak.mx/api/v1/passwordless/event?status=failed&limit=50&min-created-at=2024-11-24T00:00:00Z" \
  -H "ApiKeyAuth: tu-api-key"

# Obtener análisis de tiempos de procesamiento
curl -X GET "https://api.jaak.mx/api/v1/passwordless/stats/request-by-lapse?start-date=2024-11-24T00:00:00Z&end-date=2024-11-24T23:59:59Z&granularity=hour" \
  -H "ApiKeyAuth: tu-api-key"

Ejemplo 5: Búsqueda por Vectores Faciales

// Búsqueda usando feature vectors pre-calculados
const searchByVectorsResponse = await fetch('https://api.jaak.mx/api/v1/passwordless/client/faces', {
  method: 'POST',
  headers: {
    'ApiKeyAuth': 'tu-api-key',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    faces: [
      {
        id: 'temp-id-1',
        vector: [0.123, 0.456, 0.789, /* ... 128 o 512 valores */]
      },
      {
        id: 'temp-id-2',
        vector: [0.321, 0.654, 0.987, /* ... 128 o 512 valores */]
      }
    ]
  })
});

const vectorResults = await searchByVectorsResponse.json();
vectorResults.forEach(result => {
  result.names.forEach(match => {
    console.log(`ID: ${match.id}, Nombre: ${match.name}`);
  });
});

Códigos de Respuesta HTTP

CódigoDescripción
200Operación exitosa
400Solicitud incorrecta (Bad Request) - Verifique los parámetros enviados
401No autorizado - API Key inválida o faltante
404Recurso no encontrado
500Error interno del servidor

Mejores Prácticas

1. Autenticación y Seguridad

  • ✅ Nunca exponga su API Key en el frontend
  • ✅ Use HTTPS siempre
  • ✅ Implemente rate limiting en su lado
  • ✅ Rote sus API Keys periódicamente

2. Headers de Solicitud

  • ✅ Siempre incluya un Request-Id único (UUID v4)
  • ✅ Envíe coordenadas de geolocalización cuando estén disponibles
  • ✅ Use el header Language para respuestas localizadas

3. Manejo de Errores

  • ✅ Implemente retry logic con backoff exponencial
  • ✅ Capture y registre el eventId de las respuestas
  • ✅ Valide las respuestas antes de procesarlas

4. Calidad de Imágenes y Videos

  • ✅ Buena iluminación uniforme
  • ✅ Rostro frontal, centrado y completamente visible
  • ✅ Sin obstrucciones (lentes oscuros, gorras, máscaras)
  • ✅ Resolución mínima: 640x480 para imágenes, 720p para videos
  • ✅ Formato: JPG o PNG para imágenes

5. Performance

  • ✅ Use búsqueda por vectores para operaciones masivas
  • ✅ Implemente paginación en listados grandes
  • ✅ Cachee resultados cuando sea apropiado

6. Auditoría y Monitoreo

  • ✅ Revise eventos periódicamente
  • ✅ Configure alertas para eventos fallidos
  • ✅ Monitoree tiempos de procesamiento
  • ✅ Analice estadísticas de uso

Casos de Uso Comunes

1. Login Biométrico

  • Inscripción: POST /api/v1/passwordless/client/face-enroll
  • Verificación: POST /api/v1/passwordless/client/face-verify

2. Control de Acceso

  • Verificación en tiempo real con video
  • Registro de eventos de acceso
  • Auditoría de intentos

3. Sistema de Asistencia

  • Verificación facial al marcar entrada/salida
  • Tracking de horarios
  • Reportes de asistencia

4. Detección de Duplicados

  • Búsqueda facial antes de inscripción
  • Validación de identidad única
  • Prevención de fraude

Soporte Técnico

Canales de Contacto

Información Útil para Soporte

Al contactar soporte, incluya:

  • eventId de la transacción
  • Request-Id enviado
  • Código de error recibido
  • Timestamp de la operación
  • Descripción detallada del problema

Changelog

Versión 1.0 (Noviembre 2024)

  • Documentación inicial del módulo Passwordless
  • Endpoints de inscripción, verificación y búsqueda
  • Sistema de eventos y auditoría
  • Estadísticas y analytics

Versión del documento: 1.0
Última actualización: Noviembre 2024
API Version: v1