Consultar Estadísticas de Intentos PIN
Endpoint para obtener información detallada sobre los intentos de verificación PIN del usuario autenticado, incluyendo intentos fallidos, estado de bloqueo y tiempo restante.
/auth/pin/attemptsObtiene estadísticas detalladas de intentos de verificación PIN
📤 Respuesta
{
"code": 1001,
"message": "PIN attempt statistics retrieved successfully",
"data": {
"hasAttempts": false,
"attempts": 0,
"maxAttempts": 5,
"remainingAttempts": 5,
"lastAttempt": null,
"isBlocked": false,
"blockedUntil": null
}
}Flujo de Consulta de Estadísticas
El proceso de consulta de estadísticas de intentos incluye varios pasos:
1. Validación de Autenticación
- Verificación del token JWT del usuario
- Confirmación de que el usuario existe y está activo
- Validación de permisos para acceder a las estadísticas
2. Recopilación de Datos
- Consulta de intentos fallidos recientes
- Cálculo de intentos restantes y estado de bloqueo
- Determinación del tiempo restante de bloqueo (si aplica)
3. Procesamiento de Respuesta
- Formateo de fechas y horas para claridad
- Preparación de respuesta estructurada con metadatos útiles
- Inclusión de información para UI y debugging
Tipos de Respuesta
Respuestas Exitosas
Sin Intentos Fallidos
Código 1001 - El usuario no tiene intentos fallidos registrados.
{
"code": 1001,
"message": "PIN attempt statistics retrieved successfully",
"data": {
"hasAttempts": false,
"attempts": 0,
"maxAttempts": 5,
"remainingAttempts": 5,
"lastAttempt": null,
"isBlocked": false,
"blockedUntil": null
}
}
Campos de respuesta:
hasAttempts: false (sin intentos fallidos)attempts: 0 (ningún intento fallido)remainingAttempts: 5 (todos los intentos disponibles)lastAttempt: null (no hay último intento)isBlocked: false (no bloqueado)blockedUntil: null (no tiempo de bloqueo)
Con Intentos Fallidos pero No Bloqueado
Código 1001 - El usuario tiene intentos fallidos pero aún puede intentar.
{
"code": 1001,
"message": "PIN attempt statistics retrieved successfully",
"data": {
"hasAttempts": true,
"attempts": 2,
"maxAttempts": 5,
"remainingAttempts": 3,
"lastAttempt": "2025-01-20T14:40:00.000Z",
"isBlocked": false,
"blockedUntil": null
}
}
Campos de respuesta:
hasAttempts: true (tiene intentos fallidos)attempts: 2 (número de intentos fallidos)remainingAttempts: 3 (intentos restantes)lastAttempt: timestamp del último falloisBlocked: false (aún puede intentar)
Usuario Bloqueado por Intentos Fallidos
Código 1001 - El usuario está bloqueado temporalmente.
{
"code": 1001,
"message": "PIN attempt statistics retrieved successfully",
"data": {
"hasAttempts": true,
"attempts": 5,
"maxAttempts": 5,
"remainingAttempts": 0,
"lastAttempt": "2025-01-20T14:42:00.000Z",
"isBlocked": true,
"blockedUntil": "2025-01-20T14:57:00.000Z"
}
}
Campos de respuesta:
hasAttempts: true (tiene intentos fallidos)attempts: 5 (máximo de intentos alcanzado)remainingAttempts: 0 (sin intentos restantes)isBlocked: true (usuario bloqueado)blockedUntil: timestamp hasta cuándo está bloqueado
Errores de Autenticación
Sin Token Válido
Código 401 - No se proporcionó un token JWT válido.
{
"statusCode": 401,
"message": "Unauthorized"
}
Ciclo de Intentos y Bloqueos
Estados de Intentos
Estado Inicial
Sin intentos fallidos:
hasAttempts: falseattempts: 0remainingAttempts: 5lastAttempt: nullisBlocked: falseblockedUntil: null
Intentos Fallidos (1-4)
Con intentos fallidos pero no bloqueado:
hasAttempts: trueattempts: 1-4 (número de fallos)remainingAttempts: 4-1 (intentos restantes)lastAttempt: timestamp del último falloisBlocked: falseblockedUntil: null
Bloqueo por Intentos Excedidos
Después de 5 intentos fallidos:
hasAttempts: trueattempts: 5remainingAttempts: 0lastAttempt: timestamp del último falloisBlocked: trueblockedUntil: timestamp + 15 minutos
Gestión del Ciclo
Reinicio de Intentos
Los intentos se resetean en los siguientes casos:
- Verificación exitosa: PIN correcto resetea inmediatamente
- Expiración del bloqueo: Después de 15 minutos se desbloquea automáticamente
- Actualización de PIN: Nuevo PIN resetea el contador
- Revocación de sesiones: Puede afectar según configuración
Duración del Bloqueo
Bloqueo temporal:
- Duración: 15 minutos desde el último intento fallido
- Desbloqueo automático: No requiere intervención manual
- Nuevo bloqueo: Si se intenta durante el bloqueo, se reinicia el contador
- Persistencia: El bloqueo se mantiene hasta expiración
Campos de Respuesta Detallados
Campos Principales
- hasAttempts:
boolean- Indica si hay intentos fallidos registrados - attempts:
number- Número actual de intentos fallidos consecutivos (0-5) - maxAttempts:
number- Siempre 5, límite máximo de intentos - remainingAttempts:
number- Intentos restantes antes del bloqueo (5-attempts)
Campos de Tiempo
- lastAttempt:
string|null- ISO timestamp del último intento fallido - isBlocked:
boolean- Estado actual de bloqueo - blockedUntil:
string|null- ISO timestamp hasta cuándo está bloqueado
Estados Especiales
- lastAttempt: null cuando no hay intentos fallidos previos
- blockedUntil: null cuando no está bloqueado
- attempts: nunca excede maxAttempts (5)
- remainingAttempts: nunca es negativo
Validaciones y Restricciones
Autenticación Requerida
- JWT Token: Obligatorio en header Authorization
- Bearer Token: Formato
Bearer <accessToken> - Usuario válido: Token debe corresponder a usuario existente y activo
Estado del Usuario
- Usuario activo: Debe estar activo en el sistema
- PIN configurado: No es estrictamente necesario para consultar estadísticas
- Acceso propio: Solo puede consultar sus propias estadísticas
Rate Limiting
- Consultas frecuentes: Permitidas para monitoreo en tiempo real
- Sin límites estrictos: Endpoint informativo, no consume intentos
- Auditoría completa: Todas las consultas quedan registradas
Ejemplos de Implementación
JavaScript/TypeScript
const getPINAttempts = async (accessToken) => {
try {
const response = await fetch('https://api.swapbits.co/auth/pin/attempts', {
method: 'GET',
headers: {
'Authorization': `Bearer ${accessToken}`
}
});
const result = await response.json();
if (result.code === 1001) {
console.log('Estadísticas obtenidas exitosamente');
console.log('Intentos fallidos:', result.data.attempts);
console.log('Intentos restantes:', result.data.remainingAttempts);
console.log('Bloqueado:', result.data.isBlocked);
if (result.data.isBlocked) {
console.log('Bloqueado hasta:', result.data.blockedUntil);
}
return {
success: true,
attempts: result.data
};
} else {
console.error('Error al obtener estadísticas:', result.message);
return { success: false, error: result.message };
}
} catch (error) {
console.error('Error de conexión:', error);
throw error;
}
};
// Uso
getPINAttempts('your-jwt-token-here');
TypeScript con tipos seguros
interface PINAttemptsResponse {
code: number;
message: string;
data: {
hasAttempts: boolean;
attempts: number;
maxAttempts: number;
remainingAttempts: number;
lastAttempt: string | null;
isBlocked: boolean;
blockedUntil: string | null;
};
}
const getPINAttempts = async (accessToken: string): Promise<PINAttemptsResponse> => {
const response = await fetch('https://api.swapbits.co/auth/pin/attempts', {
method: 'GET',
headers: {
'Authorization': `Bearer ${accessToken}`,
},
});
if (!response.ok) {
const error = await response.json();
throw new Error(error.message || 'Failed to get PIN attempts');
}
return response.json();
};
// Función de alto nivel para mostrar estado
const displayPINAttemptsStatus = async (accessToken: string) => {
try {
const result = await getPINAttempts(accessToken);
if (result.data.isBlocked) {
const blockedUntil = new Date(result.data.blockedUntil!);
const remainingMinutes = Math.ceil((blockedUntil.getTime() - Date.now()) / (1000 * 60));
return {
status: 'blocked',
message: `Cuenta bloqueada. ${remainingMinutes} minutos restantes.`,
attempts: result.data.attempts,
remainingAttempts: result.data.remainingAttempts,
blockedUntil: blockedUntil
};
} else if (result.data.hasAttempts) {
return {
status: 'warning',
message: `${result.data.remainingAttempts} intentos restantes antes del bloqueo.`,
attempts: result.data.attempts,
remainingAttempts: result.data.remainingAttempts,
lastAttempt: result.data.lastAttempt ? new Date(result.data.lastAttempt) : null
};
} else {
return {
status: 'good',
message: 'Sin intentos fallidos.',
attempts: 0,
remainingAttempts: 5,
lastAttempt: null
};
}
} catch (error) {
console.error('Error getting PIN attempts:', error);
return { status: 'error', message: error.message };
}
};
Python
import requests
from typing import Dict, Optional
from datetime import datetime
def get_pin_attempts(access_token: str) -> Dict:
"""
Consultar estadísticas de intentos PIN
Args:
access_token: Token JWT de acceso
Returns:
Diccionario con las estadísticas de intentos
"""
url = 'https://api.swapbits.co/auth/pin/attempts'
headers = {
'Authorization': f'Bearer {access_token}'
}
try:
response = requests.get(url, headers=headers, timeout=10)
result = response.json()
if result['code'] == 1001:
print("Estadísticas obtenidas exitosamente")
data = result['data']
# Procesar fechas
last_attempt = None
if data['lastAttempt']:
last_attempt = datetime.fromisoformat(data['lastAttempt'].replace('Z', '+00:00'))
blocked_until = None
if data['blockedUntil']:
blocked_until = datetime.fromisoformat(data['blockedUntil'].replace('Z', '+00:00'))
return {
'success': True,
'has_attempts': data['hasAttempts'],
'attempts': data['attempts'],
'max_attempts': data['maxAttempts'],
'remaining_attempts': data['remainingAttempts'],
'last_attempt': last_attempt,
'is_blocked': data['isBlocked'],
'blocked_until': blocked_until
}
else:
print(f"Error: {result['message']}")
return {
'success': False,
'error': result['message']
}
except requests.exceptions.RequestException as e:
print(f"Error de conexión: {e}")
return {
'success': False,
'error': str(e)
}
# Ejemplo de uso
if __name__ == '__main__':
result = get_pin_attempts('your-jwt-token-here')
if result['success']:
if result['is_blocked']:
print(f"Cuenta bloqueada hasta: {result['blocked_until']}")
else:
print(f"Intentos fallidos: {result['attempts']}")
print(f"Intentos restantes: {result['remaining_attempts']}")
else:
print(f"Error: {result['error']}")
cURL
curl -X GET 'https://api.swapbits.co/auth/pin/attempts' \
-H 'Authorization: Bearer YOUR_JWT_TOKEN'
#!/bin/bash
ACCESS_TOKEN="your-jwt-token-here"
response=$(curl -s -X GET 'https://api.swapbits.co/auth/pin/attempts' \
-H "Authorization: Bearer $ACCESS_TOKEN")
code=$(echo $response | jq -r '.code')
message=$(echo $response | jq -r '.message')
if [ "$code" = "1001" ]; then
echo "Estadísticas obtenidas exitosamente"
has_attempts=$(echo $response | jq -r '.data.hasAttempts')
attempts=$(echo $response | jq -r '.data.attempts')
remaining=$(echo $response | jq -r '.data.remainingAttempts')
is_blocked=$(echo $response | jq -r '.data.isBlocked')
echo "Intentos fallidos: $attempts"
echo "Intentos restantes: $remaining"
if [ "$is_blocked" = "true" ]; then
blocked_until=$(echo $response | jq -r '.data.blockedUntil')
echo "Cuenta bloqueada hasta: $blocked_until"
else
echo "Cuenta no bloqueada"
fi
else
echo "Error: $message"
fi
Próximos Pasos
Después de Consultar Estadísticas
Una vez obtenidas las estadísticas de intentos:
Si la cuenta no está bloqueada:
- Mostrar intentos restantes al usuario
- Advertir sobre el riesgo de bloqueo
- Permitir intentos de verificación PIN
- Actualizar UI en tiempo real
Si la cuenta está bloqueada:
- Mostrar tiempo restante de bloqueo
- Deshabilitar intentos de verificación
- Actualizar contador regresivo
- Notificar cuando se desbloquee automáticamente
Para gestionar el estado:
- Usar Verificar PIN para intentar verificación
- Consultar periódicamente para actualizar estado
- Mostrar feedback claro al usuario
- Implementar lógica de reintento inteligente
Probar esta API
API Explorer
Visita el API Explorer - Intentos PIN para hacer pruebas interactivas con este endpoint en tiempo real.
En el API Explorer podrás:
- Consultar estadísticas de intentos actuales
- Ver diferentes estados (sin intentos, con intentos, bloqueado)
- Probar respuestas para diferentes escenarios
- Simular el ciclo completo de intentos y bloqueos
- Experimentar con consultas en tiempo real
Enlaces Relacionados
- Estado del PIN
- Configurar PIN
- Verificar PIN
- Solicitar Actualización de PIN
- Confirmar Actualización de PIN
- Activar/Desactivar PIN
- Estado de Sesión PIN
Notas Importantes
Consideraciones de Seguridad
- Endpoint informativo: No consume intentos, solo consulta estado
- Auditoría completa: Todas las consultas quedan registradas
- Acceso restringido: Solo el propietario puede ver sus estadísticas
- Información sensible: Datos de intentos requieren protección
- Feedback útil: Ayuda a prevenir bloqueos y mejorar UX