Índice

Comprueba el código recibido y abre sesión.

Revisado el 18 de septiembre de 2026

  • Método: `POST`
  • Ruta: `/v1/auth/whatsapp/verify`
  • Autenticación: `publica`

Segundo paso. El código sirve una sola vez y caduca a los cinco minutos.
Un número sin reto en curso y uno con el reto vencido responden lo mismo, a propósito: distinguirlos diría si alguien pidió un código para ese número.

Un reto derivado con una clave que el Worker ya no tiene —rotada por compromiso— responde también como vencido, nunca como código incorrecto, y no consume intentos: la persona pide otro código (ADR-035). Con la clave anterior conservada en `OTP_HMAC_CLAVE_ANTERIOR` durante la ventana de una rotación planificada, un reto creado con ella sigue verificando.

Qué hace con el código depende de con qué llega:

  • Sin sesión: encuentra la cuenta cuya identidad `whatsapp` es

ese número, o la crea con `nombre`, y abre sesión. `cuenta_nueva`
dice cuál de las dos fue.

  • **Con sesión, y el número es una identidad de la misma

cuenta**: cuenta como reautenticación reciente. No abre otra
sesión ni manda `Set-Cookie`.

  • Con sesión, y el número es de otra cuenta o de ninguna: no

vincula, no crea cuenta ni cambia de cuenta —eso es decisión
explícita de `POST /v1/me/identities`— y responde 200 igual,

porque el código era válido; lo que no hace es tocar nada. El

cuerpo y la ausencia de `Set-Cookie` son los mismos que en el

caso anterior —`cuenta_nueva` es `false` en los dos—, para que

la respuesta no diga de quién es el número. Un OTP de WhatsApp es

prueba débil y reenviable: a

diferencia de `passkeys/login` y del `callback` federado con

`intencion=entrar` («entrar es entrar»), verificar el número de

un tercero no cambia de cuenta ni reautentica la que ya está

abierta (ADR-034).

`nombre` se ignora cuando la cuenta ya existe: cambiar de nombre es otra operación.

Respuestas

  • `200`: Código correcto. Sin sesión, abre una y manda `Set-Cookie`; con sesión de la misma cuenta, la reautentica; con sesión y número ajeno, no cambia nada. `Set-Cookie` solo viaja en el primero, y `cuenta_nueva` es `true` solo cuando ese primero creó la cuenta. En los otros dos es `false`, que es lo que los deja indistinguibles.
  • `400`: Código incorrecto, vencido o sin reto en curso.
  • `429`: Se agotaron los intentos de este código.
  • `503`: El ambiente no tiene el KV `RETOS` de retos en curso, sin el que no hay código que comprobar, o le falta la clave `OTP_HMAC_CLAVE` con la que el código se deriva del reto para compararlo (ADR-035): sin ella no se puede verificar nada, y no se verifica con una clave inventada. `OTP_HMAC_CLAVE_ANTERIOR`, la que solo verifica durante la ventana de una rotación planificada, es opcional y su ausencia nunca es un 503.
  • `default`: referencia compartida: #/components/responses/Problem