# Deals24Togo — Backend API Production-grade FastAPI backend for the Deals24Togo marketplace. Supports listings for real estate, vehicles, electronics, furniture, jobs, and services. ## Architecture ``` backend/ ├── app/ │ ├── api/v1/endpoints/ # Route handlers (auth, users, agencies, listings, etc.) │ ├── core/ # Config, security, Supabase client, logging, exceptions │ ├── middleware/ # Auth dependencies (JWT extraction, RBAC) │ ├── schemas/ # Pydantic request/response models │ ├── services/ # Business logic layer │ └── main.py # FastAPI app factory ├── migrations/ # Supabase SQL migrations ├── scripts/ # Seed & utility scripts ├── tests/ # Pytest test suite ├── Dockerfile # Production container ├── docker-compose.yml # Local dev └── requirements.txt ``` ## Tech Stack | Layer | Technology | |---------------|--------------------------------| | Framework | FastAPI 0.115+ | | Database | Supabase (PostgreSQL) | | Auth | JWT (python-jose) + bcrypt | | File Storage | Supabase Storage | | Validation | Pydantic v2 | | Rate Limiting | SlowAPI | | Logging | structlog (JSON in prod) | | Monitoring | Sentry (optional) | | Container | Docker | ## API Endpoints ### Authentication (`/api/v1/auth`) | Method | Path | Auth | Description | |--------|-------------------------------|----------|--------------------------| | POST | `/register` | Public | Register user | | POST | `/login` | Public | Login, get tokens | | POST | `/refresh` | Public | Refresh access token | | GET | `/me` | Required | Get current user | | POST | `/change-password` | Required | Change password | | POST | `/password-reset/request` | Public | Request reset email | | POST | `/password-reset/confirm` | Public | Confirm reset with token | ### Users (`/api/v1/users`) | Method | Path | Auth | Description | |--------|---------------------|---------|----------------------| | GET | `/me` | Required| Get my profile | | PATCH | `/me` | Required| Update my profile | | GET | `/` | Admin | List all users | | GET | `/{user_id}` | Admin | Get user by ID | | POST | `/{user_id}/verify` | Admin | Verify user | | DELETE | `/{user_id}` | Owner/Admin | Delete user | ### Agencies (`/api/v1/agencies`) | Method | Path | Auth | Description | |--------|-------------------------|---------|--------------------------| | GET | `/` | Public | List agencies | | GET | `/me` | Required| Get my agency | | GET | `/{agency_id}` | Public | Get agency by ID | | POST | `/` | Required| Create agency | | PATCH | `/{agency_id}` | Owner/Admin | Update agency | | POST | `/{agency_id}/verify` | Admin | Verify agency | | POST | `/{agency_id}/revoke` | Admin | Revoke verification | | DELETE | `/{agency_id}` | Admin | Delete agency | ### Categories (`/api/v1/categories`) | Method | Path | Auth | Description | |--------|---------------------|---------|------------------------| | GET | `/` | Public | List all categories | | GET | `/{category_id}` | Public | Get category | | GET | `/slug/{slug}` | Public | Get category by slug | | POST | `/` | Admin | Create category | | PATCH | `/{category_id}` | Admin | Update category | | DELETE | `/{category_id}` | Admin | Delete category | ### Listings (`/api/v1/listings`) | Method | Path | Auth | Description | |--------|-------------------------|---------|--------------------------| | GET | `/` | Public | Search/list listings | | GET | `/featured` | Public | Top 8 popular listings | | GET | `/{listing_id}` | Public | Get listing (increments views) | | GET | `/agency/mine` | Agency | My agency's listings | | POST | `/` | Agency | Create listing | | PATCH | `/{listing_id}` | Owner/Admin | Update listing | | DELETE | `/{listing_id}` | Owner/Admin | Delete listing | | GET | `/admin/all` | Admin | List all (any status) | | PATCH | `/{listing_id}/status` | Admin | Approve/reject | | GET | `/stats/overview` | Required| Listing statistics | ### Messages (`/api/v1/messages`) | Method | Path | Auth | Description | |--------|-----------------------------|---------|------------------------| | POST | `/` | Public | Send contact message | | GET | `/` | Agency | List my messages | | GET | `/unread-count` | Agency | Unread count | | PATCH | `/{message_id}/read` | Agency | Mark read/unread | | DELETE | `/{message_id}` | Agency | Delete message | ### Favorites (`/api/v1/favorites`) | Method | Path | Auth | Description | |--------|-------------------------|---------|------------------------| | POST | `/` | Required| Add to favorites | | GET | `/` | Required| List my favorites | | GET | `/check/{listing_id}` | Required| Check if favorited | | DELETE | `/{listing_id}` | Required| Remove from favorites | ### Uploads (`/api/v1/uploads`) | Method | Path | Auth | Description | |--------|-------------|---------|--------------------------| | POST | `/image` | Required| Upload single image | | POST | `/images` | Required| Upload multiple images | | DELETE | `/` | Required| Delete image by URL | ### Health (`/health`) | Method | Path | Auth | Description | |--------|-----------|--------|--------------------| | GET | `/health` | Public | Health check | ## Setup ### 1. Supabase Project 1. Create a project at [supabase.com](https://supabase.com) 2. Go to **SQL Editor** and run `migrations/001_initial_schema.sql` 3. Go to **Storage** and create a bucket called `listings` with public access 4. Copy your project URL, anon key, and service role key ### 2. Environment ```bash cp .env.example .env # Edit .env with your Supabase credentials ``` ### 3. Run Locally **With Docker:** ```bash docker-compose up --build ``` **Without Docker:** ```bash python -m venv .venv source .venv/bin/activate pip install -r requirements.txt uvicorn app.main:create_app --factory --reload ``` ### 4. Seed Data ```bash python -m scripts.seed ``` ### 5. API Docs Visit `http://localhost:8000/docs` (Swagger UI) in development mode. ## Deployment ### Railway / Render / Fly.io 1. Push to a Git repository 2. Connect the repo to your platform 3. Set environment variables from `.env.example` 4. Deploy — the `Dockerfile` handles everything ### Production Checklist - [ ] Set `APP_ENV=production` and `DEBUG=false` - [ ] Set a strong random `SECRET_KEY` (64+ chars) - [ ] Configure `ALLOWED_ORIGINS` to your frontend domain - [ ] Set up Sentry DSN for error tracking - [ ] Configure SMTP for password reset emails - [ ] Enable Supabase RLS policies for direct client access - [ ] Set up Supabase Storage bucket with appropriate policies ## Frontend Integration The frontend should: 1. Store tokens from `/auth/login` response 2. Send `Authorization: Bearer ` on every authenticated request 3. Use `/auth/refresh` when the access token expires 4. Replace all mock data imports with API calls to the endpoints above **Base URL pattern:** `${API_BASE_URL}/api/v1/...`