← Back to API Home

Homester Backend API

A production-ready Flask backend for Homester's AI-powered real estate platform. This API provides complete authentication, property search, and AI chat functionality for frontend applications.

🚀 For Frontend Developers

This backend provides three authentication methods and AI-powered real estate features. All endpoints return JSON and use standard HTTP status codes.

Base URL

API Documentation

🔐 Authentication Guide

Method 1: Email OTP Authentication (Recommended for MVP)

Step 1: Send OTP javascript const response = await fetch('/api/firebase-auth/otp/send', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ email: '[email protected]' }) }); // Returns: {"message": "OTP sent successfully"}

Step 2: Verify OTP ```javascript const response = await fetch('/api/firebase-auth/otp/verify', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ identifier: '[email protected]', otp: '123456' // User enters this code }) });

const { access_token, refresh_token, user } = await response.json(); // Store tokens for authenticated requests localStorage.setItem('access_token', access_token); localStorage.setItem('refresh_token', refresh_token); ```

Method 2: Google OAuth Authentication

Step 1: Get Firebase Config javascript const config = await fetch('/api/firebase-auth/config').then(r => r.json());

Step 2: Initialize Firebase & Sign In ```javascript import { initializeApp } from 'firebase/app'; import { getAuth, signInWithPopup, GoogleAuthProvider } from 'firebase/auth';

const app = initializeApp(config); const auth = getAuth(app); const provider = new GoogleAuthProvider();

// Google sign-in const result = await signInWithPopup(auth, provider); const idToken = await result.user.getIdToken(); ```

Step 3: Convert to Backend JWT ```javascript const response = await fetch('/api/firebase-auth/oauth/login', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ idToken }) });

const { access_token, refresh_token, user } = await response.json(); ```

Method 3: Phone Authentication

Step 1: Initialize Firebase Phone Auth ```javascript import { RecaptchaVerifier, signInWithPhoneNumber } from 'firebase/auth';

// Setup reCAPTCHA window.recaptchaVerifier = new RecaptchaVerifier(auth, 'recaptcha-container', { size: 'invisible' });

// Send SMS const confirmationResult = await signInWithPhoneNumber( auth, '+1234567890', window.recaptchaVerifier ); ```

Step 2: Verify SMS Code ```javascript const result = await confirmationResult.confirm('123456'); // SMS code const idToken = await result.user.getIdToken();

// Convert to backend JWT (same as OAuth step 3) const response = await fetch('/api/firebase-auth/oauth/login', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ idToken }) }); ```

🔑 Using JWT Tokens

After authentication, include the access token in all API requests:

javascript const response = await fetch('/api/properties/search?city=San Francisco', { headers: { 'Authorization': `Bearer ${access_token}`, 'Content-Type': 'application/json' } });

Token Refresh (when access token expires): ```javascript const response = await fetch('/api/auth/refresh', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ refresh_token }) });

const { access_token: newToken } = await response.json(); ```

🏠 Property Search API

Basic Search

``javascript const properties = await fetch('/api/properties/search?' + new URLSearchParams({ city: 'San Francisco', max_price: '1000000', bedrooms: '2', bathrooms: '2', property_type: 'house' }), { headers: { 'Authorization':Bearer ${access_token}` } }).then(r => r.json());

// Returns: { properties: [...], pagination: {...}, total: 150 } ```

Advanced Search with Text Query

javascript const properties = await fetch('/api/properties/search', { method: 'POST', headers: { 'Authorization': `Bearer ${access_token}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ query: "modern 3-bedroom house near good schools", city: "Austin", max_price: 800000 }) }).then(r => r.json());

Get Property Details

javascript const property = await fetch('/api/properties/123', { headers: { 'Authorization': `Bearer ${access_token}` } }).then(r => r.json());

Manage Favorites

``javascript // Add to favorites await fetch('/api/properties/123/favorite', { method: 'POST', headers: { 'Authorization':Bearer ${access_token}` } });

// Remove from favorites await fetch('/api/properties/123/favorite', { method: 'DELETE', headers: { 'Authorization': Bearer ${access_token} } });

// Get user's favorites const favorites = await fetch('/api/properties/favorites', { headers: { 'Authorization': Bearer ${access_token} } }).then(r => r.json()); ```

🤖 AI Chat Interface

Start Conversation

``javascript const response = await fetch('/api/chat/message', { method: 'POST', headers: { 'Authorization':Bearer ${access_token}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ message: "I'm looking for a family home in Austin under $500k", session_id: null // Creates new session }) }).then(r => r.json());

// Returns: { response: "AI response", properties: [...], session_id: "uuid" } ```

Continue Conversation

javascript const response = await fetch('/api/chat/message', { method: 'POST', headers: { 'Authorization': `Bearer ${access_token}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ message: "Show me houses with pools", session_id: "existing-session-id" }) }).then(r => r.json());

Get Chat History

``javascript const sessions = await fetch('/api/chat/sessions', { headers: { 'Authorization':Bearer ${access_token}` } }).then(r => r.json());

// Get specific session with messages const session = await fetch('/api/chat/sessions/session-id', { headers: { 'Authorization': Bearer ${access_token} } }).then(r => r.json()); ```

📱 Frontend Framework Examples

React Authentication Hook

```javascript import { useState, useEffect } from 'react';

export function useAuth() { const [user, setUser] = useState(null); const [loading, setLoading] = useState(true);

const login = async (email, otp) => { const response = await fetch('/api/firebase-auth/otp/verify', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ identifier: email, otp }) });

if (response.ok) {
  const { access_token, user } = await response.json();
  localStorage.setItem('access_token', access_token);
  setUser(user);
  return true;
}
return false;

};

const logout = () => { localStorage.removeItem('access_token'); localStorage.removeItem('refresh_token'); setUser(null); };

return { user, login, logout, loading }; } ```

Vue.js Property Search Component

```javascript export default { data() { return { properties: [], loading: false, filters: { city: '', max_price: '', bedrooms: '' } } }, methods: { async searchProperties() { this.loading = true; const token = localStorage.getItem('access_token');

  const response = await fetch('/api/properties/search?' + 
    new URLSearchParams(this.filters), {
    headers: { 'Authorization': `Bearer ${token}` }
  });

  const data = await response.json();
  this.properties = data.properties;
  this.loading = false;
}

} } ```

🛠️ Error Handling

All API responses follow consistent patterns:

Success Response: json { "data": {...}, "message": "Success" }

Error Response: json { "message": "Error description", "error": "ERROR_CODE", "status_code": 400 }

Common Error Codes: - 401 - Invalid or expired token - 400 - Invalid request data - 429 - Rate limit exceeded - 500 - Server error

🔒 Security & Rate Limits

🚀 Quick Setup for Frontend

  1. Start with Email OTP (simplest, no external setup required)
  2. Add Google OAuth when ready (requires Firebase setup)
  3. Implement Phone Auth for mobile apps (uses Firebase SDK)

Minimal Authentication Flow

```javascript // 1. Send OTP await fetch('/api/firebase-auth/otp/send', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ email: userEmail }) });

// 2. User enters OTP, verify it const auth = await fetch('/api/firebase-auth/otp/verify', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ identifier: userEmail, otp: userOtp }) }).then(r => r.json());

// 3. Store token and start using API localStorage.setItem('access_token', auth.access_token); ```

📋 API Endpoints Reference

Authentication

Properties

AI Chat

User Management

🎯 Production Checklist

Required for Production

Optional Enhancements

📧 Email Configuration for OTP Delivery

The system now supports professional email delivery for OTP codes:

SendGrid Configuration (Recommended):

bash export SENDGRID_API_KEY="your-sendgrid-api-key" export FROM_EMAIL="[email protected]" export FROM_NAME="Homester"

SMTP Configuration (Alternative):

bash export SMTP_SERVER="smtp.gmail.com" export SMTP_PORT="587" export SMTP_USERNAME="[email protected]" export SMTP_PASSWORD="your-app-password"

Email Features:

📞 Support


That's it! Your frontend now has access to AI-powered real estate search, user authentication, and conversational property assistance. Start with the Email OTP method for immediate testing, then add Google OAuth and Phone Auth as needed.

docker compose up -d --build api docker compose logs -f api

docker compose down -v
docker compose pull docker compose build --no-cache docker compose up -d --force-recreate docker compose logs


← Back to API Home | API Documentation