Skip to main content

Overview

The Inmobiliaria API supports traditional email and password authentication with automatic email verification and password reset functionality. All authentication flows are handled by Better Auth.

Sign Up Flow

1. Register New User

Create a new user account with email and password:
POST /api/auth/sign-up/email
curl -X POST https://api.yourdomain.com/api/auth/sign-up/email \
  -H "Content-Type: application/json" \
  -d '{
    "email": "[email protected]",
    "password": "SecurePassword123!",
    "name": "John Doe"
  }'

Request Body

email
string
required
User’s email address (must be unique)
password
string
required
User’s password (minimum 8 characters recommended)
name
string
required
User’s full name

Response

{
  "user": {
    "id": "usr_1234567890",
    "email": "[email protected]",
    "name": "John Doe",
    "emailVerified": false,
    "role": "user",
    "createdAt": "2024-03-15T10:30:00.000Z"
  },
  "session": {
    "id": "ses_abcdefghijk",
    "expiresAt": "2024-04-14T10:30:00.000Z"
  }
}
After successful registration, a session is automatically created and a verification email is sent to the user’s email address.

2. Email Verification

After registration, users receive a verification email with a link:
https://api.yourdomain.com/api/auth/verify-email?token=VERIFICATION_TOKEN&callbackURL=https://yourdomain.com

Verification Email Configuration

The system uses Resend to send verification emails:
emailVerification: {
  expiresIn: 3600, // 1 hour
  sendVerificationEmail: async ({ user, url }) => {
    await resend.emails.send({
      from: 'Ramirez Inmuebles <[email protected]>',
      to: user.email,
      subject: 'Verificación de correo electrónico',
      react: VerificationEmail({ url, userName: user.name })
    });
  },
  sendOnSignUp: true,
}
Verification tokens expire after 1 hour (3600 seconds). Users must verify their email within this timeframe.

Verify Email Endpoint

GET /api/auth/verify-email
curl "https://api.yourdomain.com/api/auth/verify-email?token=VERIFICATION_TOKEN&callbackURL=https://yourdomain.com"
token
string
required
The verification token from the email
callbackURL
string
URL to redirect to after verification (defaults to FRONTEND_URL)

Response

Successful verification redirects to the callback URL. The user’s emailVerified field is set to true.

Sign In Flow

Authenticate an existing user with email and password:
POST /api/auth/sign-in/email
curl -X POST https://api.yourdomain.com/api/auth/sign-in/email \
  -H "Content-Type: application/json" \
  -c cookies.txt \
  -d '{
    "email": "[email protected]",
    "password": "SecurePassword123!"
  }'
The -c cookies.txt flag saves the session cookie for subsequent requests.

Request Body

email
string
required
User’s email address
password
string
required
User’s password
rememberMe
boolean
Extend session duration (optional)

Response

{
  "user": {
    "id": "usr_1234567890",
    "email": "[email protected]",
    "name": "John Doe",
    "emailVerified": true,
    "role": "user",
    "image": null
  },
  "session": {
    "id": "ses_abcdefghijk",
    "expiresAt": "2024-04-14T10:30:00.000Z"
  }
}
Successful sign-in sets an HTTP-only cookie:
Set-Cookie: inmobiliaria_session=SESSION_TOKEN; HttpOnly; Secure; SameSite=None; Max-Age=2592000
{
  name: "inmobiliaria_session",
  httpOnly: true,      // Prevents JavaScript access
  secure: true,        // HTTPS only (production)
  sameSite: "none",    // Allows cross-origin requests
  maxAge: 2592000      // 30 days in seconds
}

Password Reset Flow

1. Request Password Reset

Send a password reset email:
POST /api/auth/forget-password
curl -X POST https://api.yourdomain.com/api/auth/forget-password \
  -H "Content-Type: application/json" \
  -d '{
    "email": "[email protected]",
    "redirectTo": "https://yourdomain.com/reset-password"
  }'

Request Body

email
string
required
Email address of the account to reset
redirectTo
string
URL to redirect to after clicking the reset link

Response

{
  "message": "If an account exists with that email, a password reset link has been sent",
  "status": 200
}
For security reasons, the API always returns success even if the email doesn’t exist.

Password Reset Email Configuration

emailAndPassword: {
  enabled: true,
  resetPasswordTokenExpiresIn: 3600, // 1 hour
  sendResetPassword: async ({ user, url }) => {
    await resend.emails.send({
      from: 'Ramirez Inmuebles <[email protected]>',
      to: user.email,
      subject: 'Restablecer contraseña',
      react: PasswordResetEmail({ url, userName: user.name })
    });
  },
}

2. Reset Password

Submit a new password with the reset token:
POST /api/auth/reset-password
curl -X POST https://api.yourdomain.com/api/auth/reset-password \
  -H "Content-Type: application/json" \
  -d '{
    "token": "RESET_TOKEN",
    "password": "NewSecurePassword123!"
  }'

Request Body

token
string
required
Password reset token from the email
password
string
required
New password for the account

Response

{
  "message": "Password has been reset successfully",
  "status": 200
}
Password reset tokens expire after 1 hour (3600 seconds). Users must reset their password within this timeframe.

Sign Out

Invalidate the current session:
POST /api/auth/sign-out
curl -X POST https://api.yourdomain.com/api/auth/sign-out \
  -H "Content-Type: application/json" \
  -b cookies.txt

Response

{
  "message": "Signed out successfully",
  "status": 200
}
The session cookie is cleared:
Set-Cookie: inmobiliaria_session=; HttpOnly; Secure; SameSite=None; Max-Age=0

Client Implementation Example

// Sign Up
const signUp = async (email: string, password: string, name: string) => {
  const response = await fetch('https://api.yourdomain.com/api/auth/sign-up/email', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    credentials: 'include', // Important for cookies
    body: JSON.stringify({ email, password, name })
  });
  
  return response.json();
};

// Sign In
const signIn = async (email: string, password: string) => {
  const response = await fetch('https://api.yourdomain.com/api/auth/sign-in/email', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    credentials: 'include',
    body: JSON.stringify({ email, password })
  });
  
  return response.json();
};

// Sign Out
const signOut = async () => {
  const response = await fetch('https://api.yourdomain.com/api/auth/sign-out', {
    method: 'POST',
    credentials: 'include'
  });
  
  return response.json();
};
Always include credentials: 'include' (fetch) or withCredentials: true (axios) to send cookies with requests.

Security Best Practices

While the API doesn’t enforce strict password requirements, we recommend:
  • Minimum 8 characters
  • Mix of uppercase and lowercase letters
  • At least one number
  • At least one special character
Implement these checks on the client side before sending to the API.
Implement rate limiting on your frontend to prevent:
  • Brute force attacks on sign-in
  • Spam account creation
  • Password reset abuse
Consider using libraries like express-rate-limit on the backend.
Always use HTTPS in production to protect:
  • User credentials during transmission
  • Session cookies from interception
  • API tokens and sensitive data
Enforce email verification before allowing full access:
if (!user.emailVerified) {
  return res.status(403).json({
    error: 'Please verify your email before accessing this resource'
  });
}

Troubleshooting

Ensure:
  • Frontend and backend URLs are in trustedOrigins
  • CORS is configured with credentials: true
  • Client requests include credentials: 'include'
  • SameSite=None and Secure=true for cross-origin
Check:
  • RESEND_API_KEY is set correctly
  • EMAIL_FROM domain is verified in Resend
  • Email templates are properly imported
  • Check server logs for Resend API errors
Verification and reset tokens expire after 1 hour. Users must:
  • Click the email link within 1 hour
  • Request a new verification/reset email if expired

Next Steps

Session Management

Learn how to manage and validate sessions

OAuth Authentication

Add Google sign-in to your application

Protected Routes

Implement authentication middleware

User Profile

Access and update user information

Build docs developers (and LLMs) love