Authorization:
X-API-Key: <token> como header alternativo.
Registro y verificación del email
El registro usa verificación primero: nunca crea una sesión directamente. El endpoint público responde201 pending_verification tanto para un email nuevo como para uno
duplicado, por lo que no sirve para enumerar cuentas. El titular recibe un código y
completa el flujo con POST /v1/auth/register/confirm.
400 invalid_code; un código incorrecto o
vencido responde uniformemente 401 invalid_code. Si no se puede consultar el
servicio de verificación, responde 502 otp_check_failed. Una confirmación exitosa
devuelve la misma forma de sesión que login (access_token, expires_at,
refresh_token, refresh_expires_at y account).
Límites antiabuso de autenticación
Los fallos de login se cuentan por cuenta normalizada (organización/email): después de 8 fallos en 15 minutos, los intentos siguientes responden el mismo401 invalid_credentials sin ejecutar bcrypt mientras dura la ventana. Los members con
registro pendiente también reciben esa respuesta uniforme y no pueden entrar con la
clave usada en el registro.
La recuperación evita enumeración. POST /v1/auth/password/forgot mantiene el mismo
200 aunque se agote el presupuesto; permite como máximo 5 envíos reales por cuenta
por hora. POST /v1/auth/password/reset permite como máximo 8 intentos de código por
cuenta en 15 minutos. Un reset exitoso por email verifica el email y elimina
register_pending.
Los members de una cuenta empresa también pueden recibir un link de recuperación
iniciado por su admin. Canjea su token con org y new_password en
POST /v1/auth/password/reset-link; el link es de un solo uso y expira en
60 minutos. Este flujo de members es independiente del reset de admins de plataforma.
Tipos de credencial
- Sesión JWT (personas con login)
- API key (servidor a servidor)
Se obtiene con Las cuentas empresa pueden tener varios miembros con roles — ver
miembros de una empresa más abajo.
POST /v1/auth/login (el registro requiere confirmar el email primero, ver abajo) y dura
24 horas. Pensada para apps con usuarios que inician sesión. Junto al
access_token recibes un refresh token para renovar la sesión sin pedir
la contraseña de nuevo — ver renovación de sesión.Si la política de la cuenta exige OTP en el login, la respuesta trae
otp_required: true con un pending_token en vez de la sesión: el segundo
paso se completa en POST /v1/auth/login/otp con el código recibido por
SMS/WhatsApp. Flujo completo en seguridad y 2FA.También puedes ofrecer registro e inicio de sesión con Google, Apple,
Microsoft o Facebook (sin contraseña) — ver login social.
Renovación de sesión (refresh tokens)
Elaccess_token dura 24 horas; el refresh_token (rt_…) permite obtener
un par nuevo sin re-login durante 30 días, renovables en cada uso hasta
un máximo de 90 días desde el login original. Es de un solo uso: cada
canje devuelve un refresh_token nuevo y el anterior queda invalidado
(rotación).
- Rotación estricta: al canjear, el access token anterior de ese dispositivo queda revocado al instante (solo hay un access token vivo por cadena). Reemplaza siempre AMBOS tokens con los de la respuesta.
- Reúso = robo: si un refresh token ya canjeado vuelve a presentarse, la
cadena completa del dispositivo se revoca (tokens y sesiones) y queda un
evento
refresh_token_reuseenGET /v1/me/security/events. El usuario debe iniciar sesión de nuevo. - Muere con la sesión: cerrar sesión (
DELETE /v1/me/sessions/{id}),POST /v1/me/sessions/revoke-allo un cambio/reset de contraseña invalidan también los refresh tokens asociados. - Cualquier rechazo responde
401 invalid_refresh_token— ante ese error, manda al usuario al login. - Guarda el refresh token en almacenamiento seguro (Keychain/Keystore en
móvil; en web, preferir memoria + re-login o cookie httpOnly de tu
backend). Las API keys
pk_no usan refresh: no expiran.
¿Cada cuánto debo refrescar?
¿Cada cuánto debo refrescar?
Cuando el access token esté por vencer (usa
expires_at) o al recibir un
401 en una llamada normal. Evita refrescar en paralelo desde varios
lugares: si dos canjes del mismo token llegan a la vez, uno gana y el otro
recibe 401 sin castigo — pero un canje de un token YA rotado revoca la
cadena.¿Qué pasa a los 90 días?
¿Qué pasa a los 90 días?
El tope absoluto de la cadena es 90 días desde el login original: aunque
refresques a diario, al llegar al límite el refresh devuelve
401 y el
usuario debe autenticarse de nuevo (con su contraseña, passkey o login
social).¿El refresh funciona con API keys?
¿El refresh funciona con API keys?
No aplica: las API keys
pk_ no expiran ni tienen sesión. El refresh es
solo para sesiones JWT de usuarios humanos.Nivel de acceso
Tu credencial (JWT de sesión o API key) opera tu propia cuenta: saldos, payouts, payins, transferencias, crypto, KYC/KYB y webhooks propios. Si un endpoint responde403 account_required o 403 org_admin_required, esa
operación corresponde a otro nivel de credencial — contacta al equipo de
CBPay.
Tu perfil de cuenta
PATCH /v1/me acepta display_name, tax_id, phone, country y locale (envía
solo los que cambian). Un locale vacío guarda en; valores inválidos devuelven 400 invalid_locale.
El email, status y kyc_status no se autogestionan: los resuelve el administrador.
Ver Idioma y locale.
Miembros de una empresa
Las cuentas empresa pueden tener varios usuarios con login propio y distinto nivel de permiso:POST /v1/members responde 403 company_only.
Buenas prácticas
- Guarda las API keys en un gestor de secretos; nunca en el código ni en el navegador.
- Usa una key por ambiente/servicio (
labeldescriptivo) para poder rotar sin downtime.
1
Rotación sin downtime
Emite la key nueva con
POST /v1/api-keys (label nuevo).2
Despliega
Actualiza tu servicio para usar la key nueva.
3
Retira la antigua
Pide al equipo de CBPay revocar la key anterior una vez que el tráfico
migró.
- Las sesiones JWT son para front-ends; para procesos automatizados usa siempre API keys.