# API layer
Active contributors: Saksham, Ravi
The REST API layer is the primary public surface of the backend, exposing 333 endpoints across 38 endpoint modules under `/api/v1`. Endpoints are thin controllers that validate input via Pydantic schemas, enforce auth through shared dependencies, and delegate business logic to `app/services/`. Router composition lives in `app/api/api_v1/api.py`, with mount registration in `app/infrastructure/routing.py` and the app factory in `app/factory.py`.
## Directory layout
```
app/
├── api/
│ ├── api_v1/
│ │ ├── api.py # Router composition (prefix/tags per module)
│ │ ├── dependencies/
│ │ │ └── auth.py # get_current_user, get_current_agent, get_current_admin, SSE variant
│ │ └── endpoints/ # 38 endpoint modules
│ │ ├── agent_chat.py # AI agent chat (auth + public)
│ │ ├── agents.py
│ │ ├── ai.py
│ │ ├── amenities.py
│ │ ├── auth.py
│ │ ├── blog.py
│ │ ├── bookings.py
│ │ ├── core.py # Bugs, pages, app versions, FAQs
│ │ ├── custom_domains.py
│ │ ├── dashboard.py
│ │ ├── data_hub/ # Bank auctions, RERA, circle rates, etc.
│ │ ├── design_studio.py
│ │ ├── flatmates.py
│ │ ├── flatmates_admin.py
│ │ ├── floor_plans.py
│ │ ├── hotspots.py
│ │ ├── notifications.py
│ │ ├── oauth/ # MCP OAuth 2.1 endpoints
│ │ ├── payments.py
│ │ ├── pm_*.py # 12 property management modules
│ │ ├── properties.py
│ │ ├── public.py # Public tour viewing
│ │ ├── scenes.py
│ │ ├── swipes.py
│ │ ├── tours.py
│ │ ├── upload.py
│ │ ├── users.py
│ │ ├── vastu.py
│ │ ├── visits.py
│ │ ├── websocket.py
│ │ └── webhooks/
│ └── share.py # Social share preview endpoints
└── infrastructure/
└── routing.py # Mounts REST, WS, share, OAuth, MCP routes
```
## Key abstractions
| Abstraction | Location | Purpose |
|---|---|---|
| `api_router` | `app/api/api_v1/api.py` | Single `APIRouter` that all endpoint modules attach to with a prefix and tag |
| `create_app` | `app/factory.py` | App factory that builds the FastAPI instance, OpenAPI tags, lifespan, middleware, MCP apps |
| `register_routes` | `app/infrastructure/routing.py` | Mounts `api_router` at `API_V1_STR`, plus WS, share, OAuth well-known, and the two MCP apps |
| `OPENAPI_TAGS` | `app/factory.py` | Tag descriptions used by Swagger/Redoc grouping |
| Auth dependencies | `app/api/api_v1/dependencies/auth.py` | `get_current_user`, `get_current_user_optional`, `get_current_active_user`, `get_current_agent`, `get_current_admin`, `get_current_user_sse` |
## How it works
```mermaid
graph LR
Client -->|HTTP| App[FastAPI app]
App --> MW["Middleware stack
CORS, rate limit, security, request ID, logging"]
MW --> Router["api_router mounted at /api/v1"]
Router --> Endpoint["endpoint module router
prefix + tag"]
Endpoint --> Deps["Auth dependencies
get_current_user / get_current_*"]
Deps --> Service["app/services business logic"]
Endpoint --> Service
App --> MCP["/mcp, /mcp-admin mounted apps"]
App --> WS["/ws/* websocket routes"]
```
Each endpoint module defines its own `APIRouter` and is included by `api_router` with a `prefix` and `tags=[...]`. The tags mirror the entries in `OPENAPI_TAGS` so Swagger groups operations by domain (properties, bookings, pm-rent, data-hub, and so on). A `/api/v1/health` route redirects to the root `/health` endpoint with a 307.
The factory mounts `api_router` at `settings.API_V1_STR` (default `/api/v1`), then adds the websocket router, the share preview router, the OAuth well-known routers, and the two MCP sub-apps at `/mcp` and `/mcp-admin`. `redirect_slashes=False` plus a trailing-slash middleware normalizes paths.
## Integration points
- **Auth dependencies** call `app/core/auth.verify_supabase_token` and `app/services/user.get_or_create_user_from_supabase` to resolve a bearer token into a `User` row. See [core-cross-cutting](systems--core-cross-cutting.md).
- **SSE auth** (`get_current_user_sse`) uses the background DB pool (`get_bg_session_factory`) so long-lived streams do not exhaust the main pool.
- **MCP servers** share the OAuth infrastructure at `/mcp/oauth/*` and well-known endpoints. See [features/mcp-servers](features--mcp-servers.md).
- **Services** are imported lazily inside endpoints to keep the import graph lean.
## Entry points for modification
- Add a new endpoint module under `app/api/api_v1/endpoints/`, then import and include it in `app/api/api_v1/api.py` with a prefix and tag. Add the tag description to `OPENAPI_TAGS` in `app/factory.py`.
- Tighten rate limits on a sensitive route with `EndpointRateLimiter` (see `app/middleware/rate_limit.py`); the global limit is 500 req/min per IP.
- For streaming endpoints, use `get_current_user_sse` and release the main DB session before streaming.
## Key source files
| File | Role |
|---|---|
| `app/factory.py` | App factory, OpenAPI tag definitions, lifespan wiring |
| `app/api/api_v1/api.py` | Router composition, health redirect |
| `app/api/api_v1/dependencies/auth.py` | Auth dependencies (user, agent, admin, SSE, optional) |
| `app/infrastructure/routing.py` | REST, WS, share, OAuth, MCP mount registration |
| `app/api/share.py` | Social share preview endpoints |
| `app/api/api_v1/endpoints/websocket.py` | WebSocket routes for jobs and notifications |