# Admin API Reference Admin endpoints for testing and manual operations. ## Overview The admin API allows you to trigger manual operations like crawling news and sending test emails directly through HTTP requests. **How it works**: The backend container has access to the Docker socket, allowing it to execute commands in other containers via `docker exec`. --- ## API Endpoints ### Trigger Crawler Manually trigger the news crawler to fetch new articles. ```http POST /api/admin/trigger-crawl ``` **Request Body** (optional): ```json { "max_articles": 10 } ``` **Parameters**: - `max_articles` (integer, optional): Number of articles to crawl per feed (1-100, default: 10) **Response**: ```json { "success": true, "message": "Crawler executed successfully", "max_articles": 10, "output": "... crawler output (last 1000 chars) ...", "errors": "" } ``` **Example**: ```bash # Crawl 5 articles per feed curl -X POST http://localhost:5001/api/admin/trigger-crawl \ -H "Content-Type: application/json" \ -d '{"max_articles": 5}' # Use default (10 articles) curl -X POST http://localhost:5001/api/admin/trigger-crawl ``` --- ### Send Test Email Send a test newsletter to a specific email address. ```http POST /api/admin/send-test-email ``` **Request Body**: ```json { "email": "test@example.com", "max_articles": 10 } ``` **Parameters**: - `email` (string, required): Email address to send test newsletter to - `max_articles` (integer, optional): Number of articles to include (1-50, default: 10) **Response**: ```json { "success": true, "message": "Test email sent to test@example.com", "email": "test@example.com", "output": "... sender output ...", "errors": "" } ``` **Example**: ```bash # Send test email curl -X POST http://localhost:5001/api/admin/send-test-email \ -H "Content-Type: application/json" \ -d '{"email": "your-email@example.com"}' # Send with custom article count curl -X POST http://localhost:5001/api/admin/send-test-email \ -H "Content-Type: application/json" \ -d '{"email": "your-email@example.com", "max_articles": 5}' ``` --- ### Get System Statistics Get overview statistics of the system. ```http GET /api/admin/stats ``` **Response**: ```json { "articles": { "total": 150, "with_summary": 120, "today": 15 }, "subscribers": { "total": 50, "active": 45 }, "rss_feeds": { "total": 4, "active": 4 }, "tracking": { "total_sends": 200, "total_opens": 150, "total_clicks": 75 } } ``` **Example**: ```bash curl http://localhost:5001/api/admin/stats ``` --- ## Workflow Examples ### Test Complete System ```bash # 1. Check current stats curl http://localhost:5001/api/admin/stats # 2. Trigger crawler to fetch new articles curl -X POST http://localhost:5001/api/admin/trigger-crawl \ -H "Content-Type: application/json" \ -d '{"max_articles": 5}' # 3. Wait a moment for crawler to finish, then check stats again sleep 30 curl http://localhost:5001/api/admin/stats # 4. Send test email curl -X POST http://localhost:5001/api/admin/send-test-email \ -H "Content-Type: application/json" \ -d '{"email": "your-email@example.com"}' ``` ### Quick Test Newsletter ```bash # Send test email with latest articles curl -X POST http://localhost:5001/api/admin/send-test-email \ -H "Content-Type: application/json" \ -d '{"email": "your-email@example.com", "max_articles": 3}' ``` ### Fetch Fresh Content ```bash # Crawl more articles from each feed curl -X POST http://localhost:5001/api/admin/trigger-crawl \ -H "Content-Type: application/json" \ -d '{"max_articles": 20}' ``` --- ## Error Responses All endpoints return standard error responses: ```json { "success": false, "error": "Error message here" } ``` **Common HTTP Status Codes**: - `200` - Success - `400` - Bad request (invalid parameters) - `500` - Server error --- ## Security Notes ⚠️ **Important**: These are admin endpoints and should be protected in production! Recommendations: 1. Add authentication/authorization 2. Rate limiting 3. IP whitelisting 4. API key requirement 5. Audit logging Example protection (add to routes): ```python from functools import wraps from flask import request def require_api_key(f): @wraps(f) def decorated_function(*args, **kwargs): api_key = request.headers.get('X-API-Key') if api_key != os.getenv('ADMIN_API_KEY'): return jsonify({'error': 'Unauthorized'}), 401 return f(*args, **kwargs) return decorated_function @admin_bp.route('/api/admin/trigger-crawl', methods=['POST']) @require_api_key def trigger_crawl(): # ... endpoint code ``` --- ## Related Endpoints - **[Newsletter Preview](../backend/routes/newsletter_routes.py)**: `/api/newsletter/preview` - Preview newsletter HTML - **[Analytics](API.md)**: `/api/analytics/*` - View engagement metrics - **[RSS Feeds](API.md)**: `/api/rss-feeds` - Manage RSS feeds