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-aquiGestió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ámetro | Tipo | Requerido | Default | Descripción |
|---|---|---|---|---|
limit | integer | No | 10 | Límite de items por página |
page | integer | No | 1 | Número de página a obtener |
status | string | No | active | Estado del usuario |
fullName | string | No | - | Nombre completo del usuario |
external-id | string | No | - | ID externo del cliente |
min-created-at | string (date-time) | No | - | Fecha mínima de creación |
max-created-at | string (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=Juan2. Consultar Usuario por ID
Endpoint: GET /api/v1/passwordless/client/{id}
Obtiene la información detallada de un usuario específico.
Parámetros
| Parámetro | Tipo | Requerido | Descripción |
|---|---|---|---|
id | string | Sí | ID 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
| Header | Tipo | Requerido | Default | Descripción |
|---|---|---|---|---|
Request-Id | string | No | - | Identificador único para la solicitud |
Latitude | string | No | 40.7128 | Coordenada de latitud en grados decimales |
Longitude | string | No | -74.0060 | Coordenada 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ámetro | Tipo | Requerido | Descripción |
|---|---|---|---|
id | string | Sí | ID 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
| Header | Tipo | Requerido | Default | Descripción |
|---|---|---|---|---|
Request-Id | string | No | d99fe2d2-c0c3-4396-bd97-a502b4c30fa3 | Identificador único para la solicitud |
Latitude | string | No | 40.7128 | Coordenada de latitud |
Longitude | string | No | -74.0060 | Coordenada 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
| Header | Tipo | Requerido | Default | Descripción |
|---|---|---|---|---|
Request-Id | string | No | d99fe2d2-c0c3-4396-bd97-a502b4c30fa3 | Identificador único para la solicitud |
Latitude | string | No | 40.7128 | Coordenada de latitud |
Longitude | string | No | -74.0060 | Coordenada 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
| Header | Tipo | Requerido | Default | Descripción |
|---|---|---|---|---|
Request-Id | string | No | d99fe2d2-c0c3-4396-bd97-a502b4c30fa3 | Identificador único para la solicitud |
Language | string | No | en | Idioma de respuesta (en/es) |
Latitude | string | No | 40.7128 | Coordenada de latitud |
Longitude | string | No | -74.0060 | Coordenada 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
| Header | Tipo | Requerido | Default | Descripción |
|---|---|---|---|---|
Request-Id | string | No | d99fe2d2-c0c3-4396-bd97-a502b4c30fa3 | Identificador único para la solicitud |
Latitude | string | No | 40.7128 | Coordenada de latitud |
Longitude | string | No | -74.0060 | Coordenada 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 base64rankingTop: 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 utilizadodistance: 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 vectorvector: 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ámetro | Tipo | Requerido | Default | Descripción |
|---|---|---|---|---|
limit | integer | No | 10 | Límite de items por página |
page | integer | No | 1 | Número de página |
action | string | No | verify-liveness | Acción realizada en el evento |
status | string | No | success | Estado del evento |
event-id | string | No | - | ID específico del evento |
min-process-time | number | No | 100 | Tiempo mínimo de procesamiento (ms) |
max-process-time | number | No | 200 | Tiempo máximo de procesamiento (ms) |
min-created-at | string (date-time) | No | - | Fecha mínima de creación |
max-created-at | string (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=502. Consultar Evento Específico
Endpoint: GET /api/v1/passwordless/event/{id}
Obtiene el detalle completo de un evento particular.
Parámetros
| Parámetro | Tipo | Requerido | Default | Descripción |
|---|---|---|---|---|
id | string | Sí | 06722190-9de7-4d1b-a9ad-1559a5ab8cb9 | ID 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ámetro | Tipo | Requerido | Default | Descripción |
|---|---|---|---|---|
start-date | string (date-time) | Sí | 2022-01-19T00:00:00Z | Fecha inicial del conteo |
end-date | string (date-time) | Sí | 2022-01-19T00:00:00Z | Fecha final del conteo |
granularity | string | Sí | minute | Nivel de detalle: minute, hour, day |
api-key-id | string | No | - | ID de la API key que realizó la solicitud |
user-id | string | No | - | 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 rangotimeList: Lista de conteos agrupados por la granularidad especificadakey: Timestamp o fechavalue: 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=day2. 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ámetro | Tipo | Requerido | Default | Descripción |
|---|---|---|---|---|
start-date | string (date-time) | Sí | 2022-01-19T00:00:00Z | Fecha inicial del conteo |
end-date | string (date-time) | Sí | 2022-01-19T00:00:00Z | Fecha final del conteo |
granularity | string | Sí | minute | Nivel de detalle: minute, hour, day |
api-key-id | string | No | - | ID de la API key que realizó la solicitud |
user-id | string | No | - | 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 msmode: Moda (valor más frecuente) del tiempo de procesamientolapse_list: Lista de rangos de tiempokey: Tiempo de procesamiento en msvalue: 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ódigo | Descripción |
|---|---|
| 200 | Operación exitosa |
| 400 | Solicitud incorrecta (Bad Request) - Verifique los parámetros enviados |
| 401 | No autorizado - API Key inválida o faltante |
| 404 | Recurso no encontrado |
| 500 | Error 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
Languagepara respuestas localizadas
3. Manejo de Errores
- ✅ Implemente retry logic con backoff exponencial
- ✅ Capture y registre el
eventIdde 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
- Email: [email protected]
- Documentación: https://docs.jaak.mx
- Portal de Desarrolladores: https://developers.jaak.mx
Información Útil para Soporte
Al contactar soporte, incluya:
eventIdde la transacciónRequest-Idenviado- 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
Updated about 8 hours ago
