# API Endpoints Reference ## Authentication Endpoints ### 1. User Registration (Email) ``` POST /api/v1/auth/register Content-Type: application/json { "email": "user@example.com", "password": "securepass123", "first_name": "John", "last_name": "Doe" } Response (200): { "success": true, "user_id": 123, "message": "User registered successfully", "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...", "refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...", "expires_in": 900 } ``` ### 2. Get Token for Telegram User ``` POST /api/v1/auth/token/get Content-Type: application/json { "chat_id": 556399210 } Response (200): { "success": true, "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...", "expires_in": 900, "user_id": 123 } ``` ### 3. Quick Telegram Registration ``` POST /api/v1/auth/telegram/register Query Parameters: - chat_id: 556399210 - username: john_doe - first_name: John - last_name: (optional) Response (200): { "success": true, "created": true, "user_id": 123, "jwt_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...", "message": "User created successfully (user_id=123)" } ``` ### 4. Start Telegram Binding (Link Account) ``` POST /api/v1/auth/telegram/start Content-Type: application/json { "chat_id": 556399210 } Response (200): { "code": "PgmL5ZD8vK2mN3oP4qR5sT6uV7wX8yZ9", "expires_in": 600 } ``` ### 5. Confirm Telegram Binding ``` POST /api/v1/auth/telegram/confirm Content-Type: application/json Authorization: Bearer { "code": "PgmL5ZD8vK2mN3oP4qR5sT6uV7wX8yZ9", "chat_id": 556399210, "username": "john_doe", "first_name": "John", "last_name": "Doe" } Response (200): { "success": true, "user_id": 123, "jwt_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...", "expires_at": "2025-12-12T12:00:00" } ``` ### 6. User Login (Email) ``` POST /api/v1/auth/login Content-Type: application/json { "email": "user@example.com", "password": "securepass123" } Response (200): { "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...", "refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...", "user_id": 123, "expires_in": 900 } ``` ### 7. Refresh Token ``` POST /api/v1/auth/refresh Content-Type: application/json { "refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." } Response (200): { "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...", "expires_in": 900 } ``` ### 8. Refresh Token (Telegram) ``` POST /api/v1/auth/token/refresh-telegram Query Parameters: - chat_id: 556399210 Response (200): { "success": true, "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...", "expires_in": 900, "user_id": 123 } ``` ### 9. Logout ``` POST /api/v1/auth/logout Authorization: Bearer Response (200): { "message": "Logged out successfully" } ``` --- ## Bot Usage Examples ### Python (aiohttp) ```python import aiohttp import asyncio class FinanceBotAPI: def __init__(self, base_url="http://web:8000"): self.base_url = base_url self.session = None async def start(self): self.session = aiohttp.ClientSession() async def register_telegram_user(self, chat_id, username, first_name): """Quick register Telegram user""" url = f"{self.base_url}/api/v1/auth/telegram/register" async with self.session.post( url, params={ "chat_id": chat_id, "username": username, "first_name": first_name, } ) as resp: return await resp.json() async def get_token(self, chat_id): """Get fresh token for chat_id""" url = f"{self.base_url}/api/v1/auth/token/get" async with self.session.post( url, json={"chat_id": chat_id} ) as resp: return await resp.json() async def make_request(self, method, endpoint, chat_id, **kwargs): """Make authenticated request""" # Get token token_resp = await self.get_token(chat_id) token = token_resp["access_token"] # Make request headers = { "Authorization": f"Bearer {token}", "Content-Type": "application/json" } url = f"{self.base_url}{endpoint}" async with self.session.request( method, url, headers=headers, **kwargs ) as resp: return await resp.json() async def close(self): await self.session.close() # Usage async def main(): api = FinanceBotAPI() await api.start() # Register new user result = await api.register_telegram_user( chat_id=556399210, username="john_doe", first_name="John" ) print(result) # Get token token_resp = await api.get_token(556399210) print(token_resp) # Make authenticated request accounts = await api.make_request( "GET", "/api/v1/accounts", chat_id=556399210 ) print(accounts) await api.close() asyncio.run(main()) ``` ### Node.js (axios) ```javascript const axios = require('axios'); class FinanceBotAPI { constructor(baseUrl = 'http://web:8000') { this.baseUrl = baseUrl; this.client = axios.create({ baseURL: baseUrl }); } async registerTelegramUser(chatId, username, firstName) { const response = await this.client.post( '/api/v1/auth/telegram/register', {}, { params: { chat_id: chatId, username: username, first_name: firstName } } ); return response.data; } async getToken(chatId) { const response = await this.client.post( '/api/v1/auth/token/get', { chat_id: chatId } ); return response.data; } async makeRequest(method, endpoint, chatId, data = null) { // Get token const tokenResp = await this.getToken(chatId); const token = tokenResp.access_token; // Make request const headers = { 'Authorization': `Bearer ${token}`, 'Content-Type': 'application/json' }; const config = { method: method.toUpperCase(), url: endpoint, headers: headers }; if (data) { config.data = data; } const response = await this.client.request(config); return response.data; } } // Usage const api = new FinanceBotAPI(); (async () => { // Register const result = await api.registerTelegramUser( 556399210, 'john_doe', 'John' ); console.log(result); // Get token const tokenResp = await api.getToken(556399210); console.log(tokenResp); // Make request const accounts = await api.makeRequest( 'GET', '/api/v1/accounts', 556399210 ); console.log(accounts); })(); ``` --- ## Error Responses ### 400 Bad Request ```json { "detail": "Email already registered" } ``` ### 401 Unauthorized ```json { "detail": "Invalid credentials" } ``` ### 404 Not Found ```json { "detail": "User not found for this Telegram ID" } ``` ### 500 Internal Server Error ```json { "detail": "Internal server error" } ``` --- ## Token Management ### Access Token - **TTL**: 15 minutes (900 seconds) - **Usage**: Use in `Authorization: Bearer ` header - **Refresh**: Use refresh_token to get new access_token ### Refresh Token - **TTL**: 30 days (2,592,000 seconds) - **Storage**: Store securely (Redis for bot, localStorage for web) - **Usage**: Call `/api/v1/auth/refresh` to get new access_token ### Telegram Token - **TTL**: 30 days - **Storage**: Redis cache with key `chat_id:{id}:jwt` - **Auto-refresh**: Call `/api/v1/auth/token/refresh-telegram` when expired --- ## Security Headers All authenticated requests should include: ``` Authorization: Bearer X-Client-Id: telegram_bot X-Timestamp: X-Signature: Content-Type: application/json ``` --- ## Rate Limiting - **Auth endpoints**: 5 requests/minute per IP - **API endpoints**: 100 requests/minute per user - **Response headers**: - `X-RateLimit-Limit`: Total limit - `X-RateLimit-Remaining`: Remaining requests - `X-RateLimit-Reset`: Reset timestamp (Unix) --- ## Testing ### cURL Examples ```bash # Register curl -X POST http://localhost:8000/api/v1/auth/register \ -H "Content-Type: application/json" \ -d '{ "email": "test@example.com", "password": "test123", "first_name": "Test" }' # Get token for Telegram user curl -X POST http://localhost:8000/api/v1/auth/token/get \ -H "Content-Type: application/json" \ -d '{"chat_id": 556399210}' # Make authenticated request TOKEN="eyJ..." curl -X GET http://localhost:8000/api/v1/accounts \ -H "Authorization: Bearer $TOKEN" # Quick Telegram register curl -X POST "http://localhost:8000/api/v1/auth/telegram/register?chat_id=556399210&username=john_doe&first_name=John" ``` --- ## Database Schema ### users table | Column | Type | Notes | |--------|------|-------| | id | Integer | Primary key | | email | String(255) | Unique, nullable | | password_hash | String(255) | SHA256 hash, nullable | | telegram_id | Integer | Unique, nullable | | username | String(255) | Nullable | | first_name | String(255) | Nullable | | last_name | String(255) | Nullable | | is_active | Boolean | Default: true | | email_verified | Boolean | Default: false | | created_at | DateTime | Auto | | updated_at | DateTime | Auto | --- ## Migration To apply database changes: ```bash # Inside container or with Python environment alembic upgrade head # Check migration status alembic current ```