Stats API Documentation
Fire Statistics API Documentation
Overview
The Fire Statistics API provides real-time access to wildfire statistics from the National Interagency Fire Center (NIFC). It scrapes data from official NIFC statistics pages and returns structured JSON responses containing historical fire data.
Technical Architecture
System Design Diagram
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ Client App │ │ Fire Stats API │ │ NIFC Website │
│ │ │ │ │ │
│ - Web App │───▶│ - Flask/REST │───▶│ - HTML Tables │
│ - Mobile App │ │ - Web Scraper │ │ - Statistics │
│ - Dashboard │ │ - JSON Resp. │ │ - Data Source │
└─────────────────┘ └─────────────────┘ └─────────────────┘
Component Architecture
Fire Statistics API
├── Flask Application Layer
│ ├── Blueprint: stats_api
│ ├── URL Prefix: /api/stats
│ └── Flask-RESTful Integration
├── Resource Classes
│ ├── _HumanCaused
│ └── _TotalWildfires
├── Data Processing Layer
│ ├── HTTP Requests (requests library)
│ ├── HTML Parsing (BeautifulSoup)
│ └── Data Extraction & Transformation
└── Response Layer
├── JSON Serialization
├── Error Handling
└── HTTP Status Codes
API Endpoints
Base URL
/api/stats
1. Human-Caused Fire Statistics
Endpoint: GET /api/stats/human_caused
Description: Retrieves historical data on human-caused wildfires, including number of fires and acres burned per year.
Request:
GET /api/stats/human_caused HTTP/1.1
Host: your-domain.com
Accept: application/json
Response Schema:
{
"source": "string",
"data": [
{
"year": "string",
"human_caused_fires": "string",
"acres_burned": "string"
}
]
}
Success Response (200):
{
"source": "https://www.nifc.gov/fire-information/statistics/human-caused",
"data": [
{
"year": "2023",
"human_caused_fires": "45,000",
"acres_burned": "2,100,000"
},
{
"year": "2022",
"human_caused_fires": "47,500",
"acres_burned": "1,950,000"
}
]
}
Error Response (500):
{
"error": "Failed to fetch human-caused fire data",
"message": "Connection timeout"
}
2. Total Wildfire Statistics
Endpoint: GET /api/stats/total_wildfires
Description: Retrieves comprehensive wildfire statistics including total number of fires and total acres burned per year.
Request:
GET /api/stats/total_wildfires HTTP/1.1
Host: your-domain.com
Accept: application/json
Response Schema:
{
"source": "string",
"data": [
{
"year": "string",
"total_fires": "string",
"total_acres": "string"
}
]
}
Success Response (200):
{
"source": "https://www.nifc.gov/fire-information/statistics/wildfires",
"data": [
{
"year": "2023",
"total_fires": "68,500",
"total_acres": "4,200,000"
},
{
"year": "2022",
"total_fires": "71,200",
"total_acres": "3,800,000"
}
]
}
Error Response (500):
{
"error": "Failed to fetch wildfire stats",
"message": "HTML parsing failed"
}
Technical Implementation
Dependencies
# Core Framework
from flask import Blueprint, request, jsonify
from flask_restful import Api, Resource
# HTTP Client & Web Scraping
import requests
from bs4 import BeautifulSoup # Note: Missing import in original code
Code Structure
# Blueprint Configuration
stats_api = Blueprint('stats_api', __name__, url_prefix='/api/stats')
api = Api(stats_api)
# Resource Classes
class FireStatsApi:
class _HumanCaused(Resource):
# Handles human-caused fire statistics
class _TotalWildfires(Resource):
# Handles total wildfire statistics
# Endpoint Registration
api.add_resource(FireStatsApi._HumanCaused, '/human_caused')
api.add_resource(FireStatsApi._TotalWildfires, '/total_wildfires')
Data Flow
1. Client Request
↓
2. Flask Route Handler
↓
3. HTTP Request to NIFC
↓
4. HTML Response Parsing
↓
5. Data Extraction & Processing
↓
6. JSON Response Generation
↓
7. Client Response
Error Handling
HTTP Status Codes
Code | Description | Scenario |
---|---|---|
200 | Success | Data retrieved successfully |
500 | Server Error | Web scraping failure, network issues, parsing errors |
Error Response Format
{
"error": "Brief error description",
"message": "Detailed error message"
}
Rate Limiting & Best Practices
Recommendations
- Caching: Implement Redis/Memcached for response caching
- Rate Limiting: Add request throttling to prevent NIFC server overload
- Retry Logic: Implement exponential backoff for failed requests
- Monitoring: Add logging and health checks
- Data Validation: Validate scraped data before returning
Sample Caching Implementation
from flask_caching import Cache
cache = Cache(app, config={'CACHE_TYPE': 'simple'})
@cache.cached(timeout=3600) # Cache for 1 hour
def get_human_caused_stats():
# Implementation here
pass
Frontend Integration
JavaScript/React Example
// Fetch human-caused fire data
const fetchHumanCausedStats = async () => {
try {
const response = await fetch('/api/stats/human_caused');
const data = await response.json();
if (response.ok) {
setFireStats(data.data);
} else {
console.error('API Error:', data.error);
}
} catch (error) {
console.error('Network Error:', error);
}
};
// Usage in React component
useEffect(() => {
fetchHumanCausedStats();
}, []);
Python Client Example
import requests
def get_wildfire_stats():
base_url = "http://your-api-domain.com/api/stats"
try:
# Get human-caused stats
human_response = requests.get(f"{base_url}/human_caused")
human_data = human_response.json()
# Get total wildfire stats
total_response = requests.get(f"{base_url}/total_wildfires")
total_data = total_response.json()
return {
"human_caused": human_data,
"total_wildfires": total_data
}
except requests.RequestException as e:
print(f"API request failed: {e}")
return None
Security Considerations
Input Validation
- Validate all scraped data before processing
- Sanitize HTML content to prevent XSS
Rate Limiting
- Implement per-IP rate limiting
- Monitor requests to external NIFC endpoints
Error Information
- Avoid exposing internal system details in error messages
- Log detailed errors server-side for debugging
Deployment & Infrastructure
Docker Configuration
FROM python:3.9-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY . .
EXPOSE 5000
CMD ["gunicorn", "--bind", "0.0.0.0:5000", "app:app"]
Requirements
Flask==2.3.2
Flask-RESTful==0.3.10
requests==2.31.0
beautifulsoup4==4.12.2
gunicorn==21.2.0
Testing
Unit Test Example
import unittest
from unittest.mock import patch, Mock
from your_app import FireStatsApi
class TestFireStatsApi(unittest.TestCase):
@patch('requests.get')
def test_human_caused_success(self, mock_get):
# Mock successful response
mock_response = Mock()
mock_response.content = '<table><tr><td>2023</td><td>45000</td><td>2100000</td></tr></table>'
mock_get.return_value = mock_response
# Test the endpoint
resource = FireStatsApi._HumanCaused()
result = resource.get()
self.assertIn('data', result)
self.assertEqual(len(result['data']), 1)
Monitoring & Analytics
Key Metrics
- Request volume per endpoint
- Response times
- Error rates
- Data freshness from NIFC sources
Health Check Endpoint
@app.route('/health')
def health_check():
return jsonify({
"status": "healthy",
"timestamp": datetime.utcnow().isoformat(),
"version": "1.0.0"
})
Future Enhancements
- Data Persistence: Store historical data in database
- Real-time Updates: WebSocket support for live data
- Additional Endpoints: More specific fire statistics
- Data Visualization: Built-in charting capabilities
- API Versioning: Support multiple API versions
- Authentication: API key-based access control