Spaces:
No application file
No application file
| # Castor Price Forecasting API - Deployment Guide | |
| ## Quick Start | |
| ### 1. Generate API Key | |
| ```bash | |
| python3 -c " | |
| import json, os, uuid, sys | |
| from datetime import datetime | |
| API_KEYS_FILE = 'api_keys.json' | |
| api_key = f'castor_{uuid.uuid4().hex[:32]}' | |
| api_keys = {} | |
| if os.path.exists(API_KEYS_FILE): | |
| with open(API_KEYS_FILE, 'r') as f: | |
| api_keys = json.load(f) | |
| api_keys[api_key] = { | |
| 'name': 'app_developer', | |
| 'created_at': datetime.now().isoformat(), | |
| 'last_used': None, | |
| 'requests_count': 0, | |
| 'active': True | |
| } | |
| with open(API_KEYS_FILE, 'w') as f: | |
| json.dump(api_keys, f, indent=2) | |
| print(f'API Key: {api_key}') | |
| print(f'Saved to {API_KEYS_FILE}') | |
| " | |
| ``` | |
| ### 2. Start the API Server | |
| ```bash | |
| # Using Python venv | |
| D:\models\arima\venv_short\Scripts\python.exe api_production.py | |
| # Or using direct Python | |
| python3 api_production.py | |
| ``` | |
| Server runs on: `http://0.0.0.0:5000` | |
| --- | |
| ## API Endpoints | |
| ### 1. Health Check | |
| **Endpoint:** `GET /api/health` | |
| **No authentication required** | |
| ```bash | |
| curl http://localhost:5000/api/health | |
| ``` | |
| **Response:** | |
| ```json | |
| { | |
| "status": "healthy", | |
| "timestamp": "2025-12-04T22:00:00", | |
| "service": "Castor Price Forecasting API" | |
| } | |
| ``` | |
| --- | |
| ### 2. Generate API Key | |
| **Endpoint:** `POST /api/generate-key` | |
| **No authentication required** | |
| ```bash | |
| curl -X POST http://localhost:5000/api/generate-key \ | |
| -H "Content-Type: application/json" \ | |
| -d '{"name":"your_app_name"}' | |
| ``` | |
| **Response:** | |
| ```json | |
| { | |
| "status": "success", | |
| "api_key": "castor_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6", | |
| "name": "your_app_name", | |
| "created_at": "2025-12-04T22:00:00", | |
| "message": "Use this API key in X-API-Key header for all requests" | |
| } | |
| ``` | |
| --- | |
| ### 3. Get Combined Forecast (ARIMA + LSTM) | |
| **Endpoint:** `POST /api/forecast` | |
| **Authentication:** Required (X-API-Key header) | |
| ```bash | |
| curl -X POST http://localhost:5000/api/forecast \ | |
| -H "Content-Type: application/json" \ | |
| -H "X-API-Key: castor_YOUR_API_KEY_HERE" \ | |
| -d '{ | |
| "product": "Castor", | |
| "start_date": "2025-12-01", | |
| "end_date": "2026-01-31" | |
| }' | |
| ``` | |
| **Response:** | |
| ```json | |
| { | |
| "status": "success", | |
| "product": "Castor", | |
| "last_known_price": 3856.50, | |
| "forecast_period": { | |
| "start": "2025-12-01", | |
| "end": "2026-01-31", | |
| "days": 62 | |
| }, | |
| "forecast": [ | |
| { | |
| "date": "2025-12-01", | |
| "arima_price": 3856.50, | |
| "lstm_price": 3856.54, | |
| "average_price": 3856.52 | |
| }, | |
| { | |
| "date": "2025-12-02", | |
| "arima_price": 3856.50, | |
| "lstm_price": 3856.89, | |
| "average_price": 3856.70 | |
| } | |
| ], | |
| "timestamp": "2025-12-04T22:00:00" | |
| } | |
| ``` | |
| --- | |
| ### 4. Get ARIMA Forecast Only | |
| **Endpoint:** `POST /api/forecast/arima` | |
| **Authentication:** Required | |
| ```bash | |
| curl -X POST http://localhost:5000/api/forecast/arima \ | |
| -H "Content-Type: application/json" \ | |
| -H "X-API-Key: castor_YOUR_API_KEY_HERE" \ | |
| -d '{ | |
| "product": "Castor", | |
| "start_date": "2025-12-01", | |
| "end_date": "2026-01-31" | |
| }' | |
| ``` | |
| **Response:** | |
| ```json | |
| { | |
| "status": "success", | |
| "model": "ARIMA", | |
| "product": "Castor", | |
| "forecast": [ | |
| { | |
| "date": "2025-12-01", | |
| "price": 3856.50 | |
| } | |
| ] | |
| } | |
| ``` | |
| --- | |
| ### 5. Get LSTM Forecast Only | |
| **Endpoint:** `POST /api/forecast/lstm` | |
| **Authentication:** Required | |
| ```bash | |
| curl -X POST http://localhost:5000/api/forecast/lstm \ | |
| -H "Content-Type: application/json" \ | |
| -H "X-API-Key: castor_YOUR_API_KEY_HERE" \ | |
| -d '{ | |
| "product": "Castor", | |
| "start_date": "2025-12-01", | |
| "end_date": "2026-01-31" | |
| }' | |
| ``` | |
| --- | |
| ## Integration Examples | |
| ### JavaScript/Node.js | |
| ```javascript | |
| const API_KEY = 'castor_your_api_key_here'; | |
| const API_URL = 'http://localhost:5000/api/forecast'; | |
| async function getForecast() { | |
| const response = await fetch(API_URL, { | |
| method: 'POST', | |
| headers: { | |
| 'Content-Type': 'application/json', | |
| 'X-API-Key': API_KEY | |
| }, | |
| body: JSON.stringify({ | |
| product: 'Castor', | |
| start_date: '2025-12-01', | |
| end_date: '2026-01-31' | |
| }) | |
| }); | |
| const data = await response.json(); | |
| console.log(data); | |
| } | |
| getForecast(); | |
| ``` | |
| ### Python | |
| ```python | |
| import requests | |
| API_KEY = 'castor_your_api_key_here' | |
| API_URL = 'http://localhost:5000/api/forecast' | |
| response = requests.post( | |
| API_URL, | |
| headers={ | |
| 'X-API-Key': API_KEY, | |
| 'Content-Type': 'application/json' | |
| }, | |
| json={ | |
| 'product': 'Castor', | |
| 'start_date': '2025-12-01', | |
| 'end_date': '2026-01-31' | |
| } | |
| ) | |
| forecast = response.json() | |
| print(forecast) | |
| ``` | |
| ### React/Frontend | |
| ```jsx | |
| import React, { useState } from 'react'; | |
| export function ForecastComponent() { | |
| const [forecast, setForecast] = useState(null); | |
| const [loading, setLoading] = useState(false); | |
| const fetchForecast = async () => { | |
| setLoading(true); | |
| try { | |
| const response = await fetch('http://localhost:5000/api/forecast', { | |
| method: 'POST', | |
| headers: { | |
| 'Content-Type': 'application/json', | |
| 'X-API-Key': process.env.REACT_APP_CASTOR_API_KEY | |
| }, | |
| body: JSON.stringify({ | |
| product: 'Castor', | |
| start_date: '2025-12-01', | |
| end_date: '2026-01-31' | |
| }) | |
| }); | |
| const data = await response.json(); | |
| setForecast(data.forecast); | |
| } catch (error) { | |
| console.error('Error:', error); | |
| } finally { | |
| setLoading(false); | |
| } | |
| }; | |
| return ( | |
| <div> | |
| <button onClick={fetchForecast} disabled={loading}> | |
| {loading ? 'Loading...' : 'Get Forecast'} | |
| </button> | |
| {forecast && ( | |
| <table> | |
| <thead> | |
| <tr> | |
| <th>Date</th> | |
| <th>ARIMA Price</th> | |
| <th>LSTM Price</th> | |
| <th>Average</th> | |
| </tr> | |
| </thead> | |
| <tbody> | |
| {forecast.map((row) => ( | |
| <tr key={row.date}> | |
| <td>{row.date}</td> | |
| <td>{row.arima_price}</td> | |
| <td>{row.lstm_price}</td> | |
| <td>{row.average_price}</td> | |
| </tr> | |
| ))} | |
| </tbody> | |
| </table> | |
| )} | |
| </div> | |
| ); | |
| } | |
| ``` | |
| --- | |
| ## Deployment Options | |
| ### 1. Docker Deployment | |
| Create `Dockerfile`: | |
| ```dockerfile | |
| FROM python:3.12-slim | |
| WORKDIR /app | |
| COPY requirements.txt . | |
| RUN pip install -r requirements.txt | |
| COPY api_production.py . | |
| COPY daily_oilseeds_full_ml_dataset_2015_01_01_2025_12_02.csv . | |
| COPY api_keys.json . | |
| EXPOSE 5000 | |
| CMD ["python", "api_production.py"] | |
| ``` | |
| ### 2. Gunicorn (Production WSGI) | |
| ```bash | |
| pip install gunicorn | |
| gunicorn -w 4 -b 0.0.0.0:5000 api_production:app | |
| ``` | |
| ### 3. Docker Compose | |
| ```yaml | |
| version: '3.8' | |
| services: | |
| castor-api: | |
| build: . | |
| ports: | |
| - "5000:5000" | |
| environment: | |
| - FLASK_ENV=production | |
| volumes: | |
| - ./api_keys.json:/app/api_keys.json | |
| ``` | |
| --- | |
| ## Error Responses | |
| ### 401 - Unauthorized | |
| ```json | |
| { | |
| "status": "error", | |
| "message": "Invalid or missing API key. Generate one using /api/generate-key" | |
| } | |
| ``` | |
| ### 404 - Product Not Found | |
| ```json | |
| { | |
| "status": "error", | |
| "message": "Product Castor not found in database" | |
| } | |
| ``` | |
| ### 400 - Bad Request | |
| ```json | |
| { | |
| "status": "error", | |
| "message": "Invalid date format: ..." | |
| } | |
| ``` | |
| --- | |
| ## Notes for App Developers | |
| 1. **Store API Key Securely**: Use environment variables, not hardcoded | |
| 2. **Rate Limiting**: Implement on your end to prevent abuse | |
| 3. **Error Handling**: Always check response status code | |
| 4. **Caching**: Cache forecast results to reduce API calls | |
| 5. **Timeout**: Set request timeout to 30 seconds | |
| --- | |
| ## API Key Management | |
| ### View All Keys | |
| Check `api_keys.json` file | |
| ### Revoke a Key | |
| Edit `api_keys.json` and set `"active": false` | |
| ### Example api_keys.json | |
| ```json | |
| { | |
| "castor_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6": { | |
| "name": "app_developer", | |
| "created_at": "2025-12-04T22:00:00", | |
| "last_used": "2025-12-04T22:30:00", | |
| "requests_count": 45, | |
| "active": true | |
| } | |
| } | |
| ``` | |
| --- | |
| **Need Help?** Email: support@castorforecasting.com | |