Usuarios finales: cuentas, sesiones y KV
Los endpoints de la API REST para los usuarios de tu propia aplicación: alta y activación de cuentas, contraseñas, inicio de sesión con contraseña o con código y almacén clave-valor.
Estos endpoints dan cuenta y sesión a los usuarios de tu propia aplicación (una web, una app móvil, un portal de clientes). Cada cuenta es una entidad de tu empresa, identificada por su correo, y las llamadas actúan como ese usuario, no como el empleado por defecto de la clave.
Dinaup no envía correos: devuelve el código de activación, de recuperación o de acceso en la respuesta y tu backend se lo hace llegar al usuario. Por eso estos endpoints se llaman desde tu servidor, nunca desde el navegador.
Usan el mismo token, la misma URL y los mismos límites que el resto de la API REST.
Campos comunes
Todos los cuerpos admiten dos campos opcionales. Con ellos el servidor comprueba que quien canjea un código de recuperación o de acceso es el mismo navegador que lo pidió.
| Campo | Qué es |
|---|---|
UserIp | La IP del usuario final, la que ve tu backend. Si lo omites, el servidor usa la IP de tu servidor. |
UserAgent | El User-Agent del usuario final. Si lo omites, el de la petición de tu servidor. |
Los nombres de los campos del cuerpo no distinguen mayúsculas. Todo cuerpo va con Content-Type: application/json; sin esa cabecera, la respuesta es 415.
Una respuesta correcta es JSON en camelCase, con ok a true y error a null. Un rechazo llega con su código: en Login, LoginWithCode y Session, como JSON con ok a false y el motivo en error; en los demás, como texto con el motivo. Un token de clave inválido responde 401 con {"error": "..."}, y un ritmo agotado, 429 con Retry-After.
Cuentas
POST /api/Register
Crea una cuenta pendiente y devuelve el código para activarla. Hasta que se activa no existe nada en tu Dinaup; la cuenta pendiente caduca a los 2 días. Tu backend envía activationCode al correo del usuario.
{ "Name": "Ana López", "Email": "[email protected]", "Password": "...", "UserIp": "203.0.113.7", "UserAgent": "Mozilla/5.0" }{ "ok": true, "error": null, "pendingAccountId": "...", "activationCode": "..." }| Código | Cuándo |
|---|---|
400 | Falta Email o Password, o el correo no es válido. |
409 | Ese correo ya tiene cuenta. |
POST /api/ActivateAccount
Activa la cuenta pendiente con su código y crea el usuario, que ya puede entrar con Login. Un código equivocado no anula la cuenta pendiente: se puede reintentar hasta que caduque.
{ "PendingAccountId": "...", "ActivationCode": "..." }{ "ok": true, "error": null, "userId": "...", "loginIdentifier": "[email protected]" }| Código | Cuándo |
|---|---|
400 | Cuenta pendiente desconocida, caducada o ya usada, o código incorrecto. |
409 | Alguien registró ese correo entre el alta y la activación. |
POST /api/RecoverPassword
Pide un código de recuperación para un correo. Responde 200 exista o no la cuenta; si el correo no coincide con ninguna, recoveryCode llega a null.
Si varias cuentas comparten el correo, el código es para la primera que puede iniciar sesión. Va antes la de empleado que la de cliente y, entre iguales, la más antigua.
{ "Email": "[email protected]" }{ "ok": true, "error": null, "recoveryCode": "...", "recoveryId": "..." }| Código | Cuándo |
|---|---|
400 | Falta el correo o está mal formado. |
403 | Ninguna de las cuentas de ese correo tiene el inicio de sesión activado. |
POST /api/ChangePassword
Cambia la contraseña con un código de recuperación, que vale 20 minutos y una sola vez. Envía en UserIp y UserAgent los mismos valores que en RecoverPassword, o ninguno en las dos llamadas.
{ "RecoveryCode": "...", "NewPassword": "...", "UserIp": "203.0.113.7", "UserAgent": "Mozilla/5.0" }{ "ok": true, "error": null }| Código | Cuándo |
|---|---|
400 | Código desconocido o caducado, o contraseña no válida. |
403 | Código ya usado, eliminado, o pedido desde otra IP u otro navegador. |
Sesiones
La sesión vive en el servidor de tu empresa: tu backend guarda userId y sessionId y valida cada petición con Session.
POST /api/Login
{ "User": "[email protected]", "Password": "...", "UserIp": "203.0.113.7", "UserAgent": "Mozilla/5.0" }{
"ok": true,
"error": null,
"sessionId": "...",
"userId": "...",
"userName": "Ana López",
"loginIdentifier": "[email protected]",
"pending2FA": false,
"mustChangePassword": false
}| Campo | Qué dice |
|---|---|
pending2FA | El usuario tiene que completar un segundo factor TOTP antes de operar. |
mustChangePassword | El usuario tiene que cambiar la contraseña. |
Con credenciales incorrectas o un usuario sin acceso, la respuesta es 401 o 403 con { "ok": false, "error": "..." }. Sin User o sin Password, 400.
POST /api/Session
Valida una sesión y devuelve sus datos, con la misma forma que Login.
{ "UserId": "...", "SessionId": "..." }Una sesión cerrada, caducada o inexistente responde 401 con { "ok": false, "error": "..." }. Si UserId o SessionId no son GUID, 400.
POST /api/Logout
Cierra la sesión en el servidor. Es idempotente: cerrar una sesión ya cerrada responde igual.
{ "UserId": "...", "SessionId": "..." }{ "ok": true }Inicio de sesión con código
El usuario entra con un código de 6 dígitos que tu backend le envía, sin contraseña. El código vale 10 minutos y una sola vez.
POST /api/RequestLoginCode
Pide un código de acceso para un correo. Responde 200 exista o no la cuenta; si el correo no coincide con ninguna, loginCode llega a null. Si varias cuentas comparten el correo, el código es para la primera que puede iniciar sesión.
{ "Email": "[email protected]", "UserIp": "203.0.113.7", "UserAgent": "Mozilla/5.0" }{ "ok": true, "error": null, "loginCode": "123456", "loginCodeId": "..." }| Código | Cuándo |
|---|---|
400 | Falta el correo o está mal formado. |
403 | Ninguna de las cuentas de ese correo tiene el inicio de sesión activado. |
POST /api/LoginWithCode
Canjea el código por una sesión, con la misma respuesta que Login. Envía en UserIp y UserAgent los mismos valores que en RequestLoginCode, o ninguno en las dos llamadas.
{ "Email": "[email protected]", "LoginCode": "123456", "UserIp": "203.0.113.7", "UserAgent": "Mozilla/5.0" }El código se gasta al canjearlo, aunque la sesión no llegue a abrirse. Los intentos fallidos cuentan sobre todos los códigos que ese correo pidió en los últimos 10 minutos: pedir uno nuevo no pone la cuenta a cero.
| Código | Cuándo |
|---|---|
400 | Falta el correo o el código, o ese correo no pidió ningún código en los últimos 10 minutos. |
401 | El servidor no pudo abrir la sesión. |
403 | Código incorrecto, caducado o ya usado, pedido desde otra IP u otro navegador, o 5 intentos fallidos. |
Almacén clave-valor
Un par se identifica por Space y Key, textos libres de hasta 200 caracteres: el reparto por usuario o por app lo decides tú. Los pares se guardan en la sección Dinaup KV de tu empresa.
POST /api/GetKV
{ "Key": "preferencias", "Space": "usuario-1234" }{ "ok": true, "error": null, "key": "preferencias", "value": "{\"tema\":\"oscuro\"}" }Si el par no existe, value llega vacío ("").
POST /api/SetKV
Guarda o sustituye el valor del par.
{ "Key": "preferencias", "Space": "usuario-1234", "Value": "{\"tema\":\"oscuro\"}" }{ "ok": true, "error": null, "key": "preferencias", "value": "" }Value admite hasta 100.000 caracteres. En GetKV y SetKV, sin Key la respuesta es 400; un Space o una Key de más de 200 caracteres, o un Value de más de 100.000, responden 400 con ok a false y el motivo en error, como El valor no puede superar los 100000 caracteres.
Cómo gestiona una app .NET la sesión de cada empresa: Apps multi-tenant.