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 atienden a los usuarios de tu aplicación (una web, una app móvil, un portal de clientes) que tienen cuenta en tu Dinaup. Cada cuenta es una entidad de tu empresa con un identificador de acceso, su correo. Las llamadas actúan como ese usuario final, no como el empleado por defecto de la clave.
El servidor de tu empresa no envía correos. Devuelve el código de activación, de recuperación o de acceso en la respuesta, y tu backend decide cómo se lo hace llegar al usuario.
Solo desde tu backend
Un código de activación, de recuperación o de acceso que llega al navegador deja que cualquiera se quede con la cuenta. Llama a estos endpoints desde tu servidor, envía el código tú y no lo expongas nunca en una respuesta al cliente.
Antes de empezar
- El mismo token Bearer y la misma URL de tu empresa que el resto de la API: API REST: cómo funciona.
- Los límites de peticiones son los de la clave: Límites.
Campos comunes
Todos los cuerpos admiten dos campos opcionales. El servidor los guarda en la sesión y en los registros de recuperación y de acceso. Con ellos comprueba que el cambio de contraseña y el canje de un código de acceso los pide el mismo navegador que pidió el código.
| 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 del servidor de tu empresa llega con su código. En Login, LoginWithCode y Session llega como JSON, con ok a false y el motivo en error. En Register, ActivateAccount, RecoverPassword, ChangePassword y RequestLoginCode llega como texto con el motivo.
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; el registro pendiente caduca a los 2 días.
{ "Name": "Ana López", "Email": "ana@tuempresa.com", "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 real. Un código equivocado no anula la cuenta pendiente: el usuario puede reintentar hasta que caduque.
{ "PendingAccountId": "...", "ActivationCode": "..." }{ "ok": true, "error": null, "userId": "...", "loginIdentifier": "ana@tuempresa.com" }| 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, para que nadie use el endpoint para averiguar quién está registrado. Si el correo no coincide con ninguna cuenta, recoveryCode llega a null: no envíes nada y muestra al usuario el mismo mensaje de siempre.
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": "ana@tuempresa.com" }{ "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. El código vale 20 minutos y una sola vez. El servidor comprueba que la IP y el User-Agent son los mismos que pidieron el código: envía en UserIp y UserAgent exactamente los mismos valores que en RecoverPassword, o no envíes 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. |
El alta de punta a punta
Registra
Llama a Register con el nombre, el correo y la contraseña. Guarda pendingAccountId.
Envía el código
Manda activationCode al correo del usuario con tu propio servicio de correo. Tienes 2 días.
Activa
Cuando el usuario escribe el código, llama a ActivateAccount con pendingAccountId y el código. La respuesta trae el userId con el que ya puede entrar.
Inicia sesión
Llama a Login con el correo y la contraseña.
Sesiones
La sesión vive en el servidor de tu empresa. Tu backend guarda userId y sessionId, por ejemplo en una cookie httpOnly, y valida cada petición con Session.
POST /api/Login
{ "User": "ana@tuempresa.com", "Password": "...", "UserIp": "203.0.113.7", "UserAgent": "Mozilla/5.0" }{
"ok": true,
"error": null,
"sessionId": "...",
"userId": "...",
"userName": "Ana López",
"loginIdentifier": "ana@tuempresa.com",
"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": "ana@tuempresa.com", "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. La respuesta tiene la misma forma que la de Login, con pending2FA y mustChangePassword. El servidor comprueba que la IP y el User-Agent son los mismos que pidieron el código: envía en UserIp y UserAgent exactamente los mismos valores que en RequestLoginCode, o no envíes ninguno en las dos llamadas.
{ "Email": "ana@tuempresa.com", "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 se cuentan sobre todos los códigos que ese correo pidió en los últimos 10 minutos: pedir un código 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. Space es un texto libre: el reparto por usuario, por app o por lo que necesites lo decides tú al componer el espacio y la clave. Cada uno admite hasta 200 caracteres. 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 (""). Sin Key, 400. Un Space o una Key de más de 200 caracteres responden 400 con ok a false y el motivo en error.
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. Sin Key, 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ódigos de respuesta
| Código | Cuándo |
|---|---|
200 | Operación correcta, con ok a true. |
400 | Faltan campos, un GUID está mal formado o el servidor rechazó los datos: correo no válido, código desconocido o caducado, o un Space, una Key o un Value demasiado largos. |
401 | Token de la clave inválido ({"error": "..."}), o credenciales o sesión no válidas (ok: false). |
403 | Cuenta sin acceso; código ya usado, eliminado o pedido desde otro sitio; o demasiados intentos. |
409 | Conflicto con una cuenta existente. |
415 | El cuerpo no lleva Content-Type: application/json. |
429 | Ritmo agotado. Repite pasados los segundos de Retry-After. |
500 | Fallo del servidor. El rechazo del servidor de tu empresa llega siempre con su 4xx. |
Relacionado
- Referencia de la API REST: informes, documentos y escrituras con la misma clave.
- Apps multi-tenant: cómo gestiona una app .NET la sesión de cada empresa.