{"openapi":"3.0.0","paths":{"/api/v1/email/send":{"post":{"operationId":"EmailController_send","summary":"Send a transactional email","description":"Uses the SMTP transport of the specified Client App (or central SMTP as fallback). **When `clientAppId` is provided, `fromAddress` is required** — each app must declare its own sender identity. System emails sent internally by the API use the central SMTP defaults from `.env` automatically.","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SendEmailDto"}}}},"responses":{"200":{"description":"Email sent or failed with details."}},"tags":["Email as a Service"],"security":[{"bearer":[]}]}},"/api/v1/email/clients/{clientAppId}/configure-smtp":{"post":{"operationId":"EmailController_configureSmtp","summary":"Configure a custom SMTP server for a Client App (password stored encrypted)","description":"Saves the SMTP credentials for this app in the database (password encrypted AES-256-GCM). The `fromAddress` and `fromName` are **not** stored here — they must be specified in each `/email/send` request by the app.","parameters":[{"name":"clientAppId","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConfigureSmtpDto"}}}},"responses":{"201":{"description":""}},"tags":["Email as a Service"],"security":[{"bearer":[]}]}},"/api/v1/email/queue":{"get":{"operationId":"EmailController_getQueue","summary":"List email queue history (all sent/failed emails)","parameters":[{"name":"status","required":false,"in":"query","schema":{"enum":["PENDING","SENT","FAILED"],"type":"string"}},{"name":"clientAppId","required":false,"in":"query","schema":{"type":"string"}},{"name":"limit","required":false,"in":"query","schema":{"type":"number"}}],"responses":{"200":{"description":""}},"tags":["Email as a Service"],"security":[{"bearer":[]}]}},"/api/v1/auth/register":{"post":{"operationId":"AuthController_register","summary":"Register a new central user (sends verification email)","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RegisterDto"}}}},"responses":{"201":{"description":""}},"tags":["Authentication & SSO"]}},"/api/v1/auth/login":{"post":{"operationId":"AuthController_login","summary":"Login — returns access/refresh tokens. MFA code required if enabled.","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LoginDto"}}}},"responses":{"200":{"description":""}},"tags":["Authentication & SSO"]}},"/api/v1/auth/refresh":{"post":{"operationId":"AuthController_refresh","summary":"Rotate refresh token and get new access token","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RefreshTokenDto"}}}},"responses":{"200":{"description":""}},"tags":["Authentication & SSO"]}},"/api/v1/auth/verify":{"post":{"operationId":"AuthController_verify","summary":"Verify a JWT access token (for client microservices)","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/VerifyTokenDto"}}}},"responses":{"200":{"description":""}},"tags":["Authentication & SSO"]}},"/api/v1/auth/verify-email":{"get":{"operationId":"AuthController_verifyEmail","summary":"Verify email address from token sent by email","parameters":[{"name":"token","required":true,"in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"tags":["Authentication & SSO"]}},"/api/v1/auth/resend-verification":{"post":{"operationId":"AuthController_resendVerification","summary":"Resend email verification link","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ForgotPasswordDto"}}}},"responses":{"200":{"description":""}},"tags":["Authentication & SSO"]}},"/api/v1/auth/forgot-password":{"post":{"operationId":"AuthController_forgotPassword","summary":"Request password reset email","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ForgotPasswordDto"}}}},"responses":{"200":{"description":""}},"tags":["Authentication & SSO"]}},"/api/v1/auth/reset-password":{"post":{"operationId":"AuthController_resetPassword","summary":"Reset password using token from email","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResetPasswordDto"}}}},"responses":{"200":{"description":""}},"tags":["Authentication & SSO"]}},"/api/v1/auth/google":{"get":{"operationId":"AuthController_googleAuth","summary":"Redirect to Google OAuth login","parameters":[],"responses":{"200":{"description":""}},"tags":["Authentication & SSO"]}},"/api/v1/auth/google/callback":{"get":{"operationId":"AuthController_googleCallback","summary":"Google OAuth callback — issues tokens","parameters":[],"responses":{"200":{"description":""}},"tags":["Authentication & SSO"]}},"/api/v1/auth/me":{"get":{"operationId":"AuthController_getProfile","summary":"Get current authenticated user profile","parameters":[],"responses":{"200":{"description":""}},"tags":["Authentication & SSO"],"security":[{"bearer":[]}]}},"/api/v1/auth/logout":{"post":{"operationId":"AuthController_logout","summary":"Logout — blacklists current JWT and revokes all refresh tokens","parameters":[],"responses":{"200":{"description":""}},"tags":["Authentication & SSO"],"security":[{"bearer":[]}]}},"/api/v1/auth/change-password":{"post":{"operationId":"AuthController_changePassword","summary":"Change password (requires current password)","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChangePasswordDto"}}}},"responses":{"200":{"description":""}},"tags":["Authentication & SSO"],"security":[{"bearer":[]}]}},"/api/v1/auth/sessions":{"get":{"operationId":"AuthController_getSessions","summary":"List all active sessions for current user (with device & location)","parameters":[],"responses":{"200":{"description":""}},"tags":["Authentication & SSO"],"security":[{"bearer":[]}]},"delete":{"operationId":"AuthController_revokeAllSessions","summary":"Revoke ALL active sessions (logout everywhere)","parameters":[],"responses":{"200":{"description":""}},"tags":["Authentication & SSO"],"security":[{"bearer":[]}]}},"/api/v1/auth/sessions/{id}":{"delete":{"operationId":"AuthController_revokeSession","summary":"Revoke a specific session by ID","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"tags":["Authentication & SSO"],"security":[{"bearer":[]}]}},"/api/v1/auth/mfa/status":{"get":{"operationId":"MfaController_getStatus","summary":"Get MFA status for current user","parameters":[],"responses":{"200":{"description":""}},"tags":["MFA — Multi-Factor Authentication"],"security":[{"bearer":[]}]}},"/api/v1/auth/mfa/setup":{"post":{"operationId":"MfaController_setup","summary":"Step 1: Generate TOTP secret and QR code to scan with authenticator app","parameters":[],"responses":{"201":{"description":"Returns secret, otpauthUrl and QR code data URL."}},"tags":["MFA — Multi-Factor Authentication"],"security":[{"bearer":[]}]}},"/api/v1/auth/mfa/enable":{"post":{"operationId":"MfaController_enable","summary":"Step 2: Confirm TOTP code to activate MFA — returns one-time recovery codes","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TotpCodeDto"}}}},"responses":{"200":{"description":"MFA enabled. Store recovery codes safely."}},"tags":["MFA — Multi-Factor Authentication"],"security":[{"bearer":[]}]}},"/api/v1/auth/mfa/disable":{"delete":{"operationId":"MfaController_disable","summary":"Disable MFA (requires current TOTP code)","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TotpCodeDto"}}}},"responses":{"200":{"description":""}},"tags":["MFA — Multi-Factor Authentication"],"security":[{"bearer":[]}]}},"/api/v1/auth/mfa/verify-recovery":{"post":{"operationId":"MfaController_verifyRecovery","summary":"Use a recovery code instead of TOTP code","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RecoveryCodeDto"}}}},"responses":{"200":{"description":""}},"tags":["MFA — Multi-Factor Authentication"],"security":[{"bearer":[]}]}}},"info":{"title":"Api Zlp v2.0 — Central Identity & Credentials Service","description":"## 🔐 Servicio Central de Identidad y Credenciales\n\n### ⚡ Inicio Rápido\n\n**1. Registrar tu proyecto como Client App:**\n`POST /api/v1/clients` → Obtén tu `clientId` y `clientSecret`\n\n**2. Login de usuarios desde tu frontend:**\n`POST /api/v1/auth/login` → Retorna `accessToken` + `refreshToken` + geolocalización\n\n**3. Renovar el accessToken:**\n`POST /api/v1/auth/refresh` → Rotación automática del refresh token\n\n**4. Verificar un token desde tu backend:**\n`POST /api/v1/auth/verify` → Valida JWT y retorna el payload completo\n\n---\n\n### 🔑 Autenticación\nTodos los endpoints protegidos requieren: `Authorization: Bearer {accessToken}`\n\n---\n\n### 📧 Email — Regla del Sender\n- **Emails del sistema** (verificación, alertas, MFA): usan el SMTP y `from` del `.env` central.\n- **Emails de apps clientes** via `POST /email/send`: deben especificar `fromAddress` (y opcionalmente `fromName`) en cada request.\n\n---\n\n### 🌍 Geolocalización\nCada login, sesión y evento de audit incluye automáticamente:\n`ipAddress` · `country` · `city` · `region` · `latitude` · `longitude` · `deviceName` · `deviceType`","version":"2.0.0","contact":{}},"tags":[{"name":"Authentication & SSO","description":"Login, Register, Logout, Refresh, Verification, Google OAuth"},{"name":"MFA — Multi-Factor Authentication","description":"Google / Microsoft Authenticator TOTP setup & verification"},{"name":"Client Apps Management","description":"Manage client applications, origins, and IP rules"},{"name":"Users Management","description":"User profile, account status, and app-specific roles"},{"name":"API Keys (Server-to-Server M2M)","description":"Generate and manage server-to-server API keys"},{"name":"Credentials & Secrets Vault","description":"AES-256-GCM encrypted key-value vault for third-party secrets"},{"name":"Audit Logs & Security Events","description":"Security activity tracking with IP and geolocation data"},{"name":"Webhooks","description":"Real-time security event notifications with HMAC signatures"},{"name":"Email as a Service","description":"Transactional emails using custom or central SMTP"},{"name":"Admin — Dashboard & Statistics","description":"Aggregated analytics and security monitoring"},{"name":"Health & Status","description":"System health, uptime, and database latency"}],"servers":[],"components":{"securitySchemes":{"bearer":{"scheme":"bearer","bearerFormat":"JWT","type":"http"}},"schemas":{"SendEmailDto":{"type":"object","properties":{"to":{"type":"string","example":"user@example.com","description":"Recipient email address"},"toName":{"type":"string","example":"John Doe","description":"Recipient display name"},"subject":{"type":"string","example":"Welcome to our platform!"},"html":{"type":"string","example":"<h1>Hello</h1>","description":"HTML body content"},"text":{"type":"string","example":"Hello","description":"Plain-text fallback body"},"clientAppId":{"type":"string","example":"app-finance","description":"Client App ID or slug. Selects the SMTP transport for that app (falls back to central). When provided, fromAddress is required."},"fromName":{"type":"string","example":"Finance App","description":"Sender display name. Required when clientAppId is set — the system does not supply a default sender for client apps."},"fromAddress":{"type":"string","example":"noreply@finance-app.com","description":"Sender email address. Required when clientAppId is set — each app owns its own sender identity."}},"required":["to","subject","html"]},"ConfigureSmtpDto":{"type":"object","properties":{"smtpHost":{"type":"string","example":"mail.tudominio.com"},"smtpPort":{"type":"number","example":465,"description":"SMTP port. 465 = SSL, 587 = STARTTLS"},"smtpUser":{"type":"string","example":"noreply@tudominio.com"},"smtpPass":{"type":"string","example":"password_secreto","description":"Plain text SMTP password — stored AES-256-GCM encrypted in the database"}},"required":["smtpHost","smtpPort","smtpUser","smtpPass"]},"RegisterDto":{"type":"object","properties":{"email":{"type":"string","example":"user@example.com","description":"User unique email address"},"password":{"type":"string","example":"StrongPassword123!","description":"Password (minimum 8 characters)"},"fullName":{"type":"string","example":"John Doe","description":"Full name of the user"}},"required":["email","password"]},"LoginDto":{"type":"object","properties":{"email":{"type":"string","example":"user@example.com"},"password":{"type":"string","example":"StrongPassword123!"},"clientId":{"type":"string","example":"app-finance","description":"Client App ID for role/scope assignment"},"clientSlug":{"type":"string","example":"admin-portal","description":"Client App slug"},"totpCode":{"type":"string","example":"123456","description":"6-digit TOTP code (required if MFA is enabled)"},"recoveryCode":{"type":"string","example":"ABCDE-FGHIJ","description":"MFA recovery code (alternative to totpCode)"}},"required":["email","password"]},"RefreshTokenDto":{"type":"object","properties":{"refreshToken":{"type":"string","description":"Valid refresh token string"}},"required":["refreshToken"]},"VerifyTokenDto":{"type":"object","properties":{"token":{"type":"string","description":"JWT access token to verify"}},"required":["token"]},"ForgotPasswordDto":{"type":"object","properties":{"email":{"type":"string","example":"user@example.com"}},"required":["email"]},"ResetPasswordDto":{"type":"object","properties":{"token":{"type":"string","example":"token-from-email"},"newPassword":{"type":"string","example":"NewPassword456!"}},"required":["token","newPassword"]},"ChangePasswordDto":{"type":"object","properties":{"currentPassword":{"type":"string","example":"OldPassword123!"},"newPassword":{"type":"string","example":"NewPassword456!"}},"required":["currentPassword","newPassword"]},"TotpCodeDto":{"type":"object","properties":{"code":{"type":"string","example":"123456","description":"6-digit TOTP code from authenticator app"}},"required":["code"]},"RecoveryCodeDto":{"type":"object","properties":{"recoveryCode":{"type":"string","example":"ABCDE-FGHIJ","description":"One-time recovery code"}},"required":["recoveryCode"]}}}}