Development: http://localhost:5000
Production: https://api.wildguard.com (when deployed)
Description: Upload an image file for real-time wildlife classification and risk assessment.
Request
POST /predict HTTP/1.1
Content-Type: multipart/form-data
file: <image_file>Query Parameters
None for file uploads.
Response (Success)
{
"success": true,
"data": {
"species": "Tiger",
"confidence": 0.94,
"human_risk": "very_high",
"crop_risk": "high",
"livestock_risk": "very_high",
"explanation": "Model confidence 94.0% for Tiger. Observed during evening.",
"recommendations": [
"Evacuate area and contact wildlife/forest authorities immediately.",
"Protect crop areas and deploy deterrents; document damage.",
"Move vulnerable livestock to secure enclosures and monitor closely."
],
"alternatives": [
{"class": "Leopard", "confidence": 0.05},
{"class": "Jaguar", "confidence": 0.01}
],
"timestamp": "2024-06-01T14:23:45Z",
"detection_id": "det_67890"
}
}Response (Error)
{
"success": false,
"error": "File must be JPEG or PNG (max 10MB)",
"error_code": "INVALID_FILE"
}HTTP Status Codes
200 OK— Prediction successful400 Bad Request— Missing file or invalid format413 Payload Too Large— File exceeds 10MB500 Internal Server Error— Model inference failed
cURL Example
curl -X POST \
-F "file=@tiger.jpg" \
http://localhost:5000/predictPython Example
import requests
with open('tiger.jpg', 'rb') as f:
files = {'file': f}
response = requests.post('http://localhost:5000/predict', files=files)
result = response.json()
print(result['data']['species'])
print(result['data']['recommendations'])Description: Get a random sample prediction without uploading an image (for testing/demo).
Request
GET /predict?sample=true HTTP/1.1Query Parameters
sample(required):truefor random sample, or species name (e.g.,Tiger,Elephant)
Response
{
"success": true,
"data": {
"species": "Tiger",
"confidence": 0.92,
"human_risk": "very_high",
"crop_risk": "high",
"livestock_risk": "very_high",
"explanation": "Model confidence 92.0% for Tiger.",
"recommendations": [...],
"alternatives": [...],
"timestamp": "2024-06-01T14:30:12Z",
"detection_id": "det_12345"
}
}cURL Example
# Random sample
curl http://localhost:5000/predict?sample=true
# Specific species
curl http://localhost:5000/predict?sample=TigerDescription: Retrieve recent detection history from the database.
Request
GET /recent HTTP/1.1Query Parameters
limit(optional): Number of records to return (default: 10, max: 100)offset(optional): Pagination offset (default: 0)
Response
{
"success": true,
"data": {
"detections": [
{
"detection_id": "det_67890",
"species": "Tiger",
"confidence": 0.94,
"human_risk": "very_high",
"crop_risk": "high",
"livestock_risk": "very_high",
"timestamp": "2024-06-01T14:23:45Z"
},
{
"detection_id": "det_67891",
"species": "Leopard",
"confidence": 0.88,
"human_risk": "high",
"crop_risk": "low",
"livestock_risk": "high",
"timestamp": "2024-06-01T14:15:32Z"
}
],
"total": 127,
"limit": 10,
"offset": 0
}
}cURL Example
# Default (10 most recent)
curl http://localhost:5000/recent
# Custom limit and offset
curl http://localhost:5000/recent?limit=20&offset=10Description: Check if the API is running and model is loaded.
Request
GET /health HTTP/1.1Response (Success)
{
"status": "ok",
"model_loaded": true,
"database_connected": true,
"timestamp": "2024-06-01T14:23:45Z"
}Response (Error)
{
"status": "error",
"model_loaded": false,
"database_connected": false,
"errors": ["Model file not found", "Database connection failed"]
}| Code | HTTP Status | Description |
|---|---|---|
INVALID_FILE |
400 | File format not supported (must be JPEG/PNG) |
FILE_TOO_LARGE |
413 | File exceeds maximum size (10MB) |
MISSING_FILE |
400 | No file provided in request |
INVALID_IMAGE |
400 | File is corrupted or not a valid image |
MODEL_ERROR |
500 | Model inference failed |
DATABASE_ERROR |
500 | Database operation failed |
INTERNAL_ERROR |
500 | Unexpected server error |
Current: No rate limiting (for MVP)
Production Recommendation:
- Per IP: 100 requests/minute
- Per user (if auth added): 1000 requests/day
Allowed Origins (configurable in .env):
Access-Control-Allow-Origin: http://localhost:5173, https://wildguard-frontend.vercel.app
Access-Control-Allow-Methods: GET, POST, OPTIONS
Access-Control-Allow-Headers: Content-Type, Authorization
Enum: low | moderate | high | very_high
{
"species": "string", // Animal class name
"confidence": 0.0–1.0, // Model confidence score
"human_risk": "low|moderate|high|very_high",
"crop_risk": "low|moderate|high|very_high",
"livestock_risk": "low|moderate|high|very_high",
"explanation": "string", // Brief AI explanation
"recommendations": ["string", ...], // Action items
"alternatives": [
{
"class": "string",
"confidence": 0.0–1.0
}
],
"timestamp": "ISO 8601 datetime",
"detection_id": "string" // Unique identifier
}- Tiger
- Elephant
- Leopard
- Crocodile
- Monkey
- Rabbit
- Cow
- Goat
- Horse
- Pig
- Deer
- Bear
- Cat
- Dog
- Crow
- Indian Bull
- Jaguar
- Neelgai
API key authentication planned for production:
GET /recent HTTP/1.1
Authorization: Bearer YOUR_API_KEYContact: team@wildguard.ai for API keys
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 95
X-RateLimit-Reset: 1717256625Planned: Send detection alerts to external webhooks
POST https://your-webhook.com/wildlife-alert
{
"event": "detection_high_risk",
"detection": {...}
}
import requests
class WildGuardClient:
def __init__(self, base_url='http://localhost:5000'):
self.base_url = base_url
def predict(self, image_path):
with open(image_path, 'rb') as f:
response = requests.post(
f'{self.base_url}/predict',
files={'file': f}
)
return response.json()
def get_recent(self, limit=10):
response = requests.get(
f'{self.base_url}/recent',
params={'limit': limit}
)
return response.json()
# Usage
client = WildGuardClient()
result = client.predict('tiger.jpg')
print(result['data']['recommendations'])async function predictImage(file) {
const formData = new FormData();
formData.append('file', file);
const response = await fetch('http://localhost:5000/predict', {
method: 'POST',
body: formData,
});
return await response.json();
}
async function getRecent(limit = 10) {
const response = await fetch(`http://localhost:5000/recent?limit=${limit}`);
return await response.json();
}- Check: Model file exists (
animal_classifier.h5) - Check: Class indices file exists (
class_indices.json) - Check: Flask logs for detailed error message
- Check: File format is JPEG or PNG
- Check: File size is under 10MB
- Check: File is not corrupted
- Cause: Model loading or CPU-bound inference
- Solution: Add GPU support or use model quantization
- Workaround: Increase instance size (Render, AWS)
| Metric | Value |
|---|---|
| Avg response time | 200–300ms |
| P99 response time | 500ms |
| Model inference | 50–150ms (depends on CPU) |
| Throughput (single instance) | ~20 req/sec |
| Concurrent connections | 50–100 |
| Version | Date | Changes |
|---|---|---|
| 1.0.0 | 2024-06-01 | Initial release |
- Issues: GitHub Issues
- Docs: ARCHITECTURE.md
- Deployment: DEPLOYMENT.md