docs/deployment.md: - Complete deployment guide for both automated and manual setup - Step-by-step instructions for Debian 12 ARM64 - Custom Caddy build with rate limiting plugin - Service configuration and security setup - Troubleshooting and maintenance sections - Performance tuning recommendations docs/api.md: - Comprehensive API documentation with examples - All public and admin endpoints documented - Request/response schemas and validation rules - Authentication flows and error handling - Rate limiting and security feature documentation - Client library examples (JavaScript, curl) Fixes README.md reference to non-existent docs/deployment.md. Both files provide detailed technical documentation for: - Deployment procedures and requirements - API usage and integration - Security features and limitations - Troubleshooting and maintenance 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
305 lines
No EOL
5.7 KiB
Markdown
305 lines
No EOL
5.7 KiB
Markdown
# Great Lakes Ice Report - API Documentation
|
|
|
|
This document provides an overview of the API endpoints. For interactive documentation with examples, visit `/api-docs` when the server is running.
|
|
|
|
## Base URL
|
|
|
|
- **Development**: `http://localhost:3000`
|
|
- **Production**: `https://your-domain.com`
|
|
|
|
## Authentication
|
|
|
|
Admin endpoints require Bearer token authentication:
|
|
```
|
|
Authorization: Bearer YOUR_TOKEN_HERE
|
|
```
|
|
|
|
Get a token by authenticating with the admin password at `POST /api/admin/login`.
|
|
|
|
## Rate Limiting
|
|
|
|
- **General API**: 30 requests per minute per IP
|
|
- **Location Submissions**: 10 requests per 15 minutes per IP
|
|
|
|
## Public Endpoints
|
|
|
|
### Get Configuration
|
|
```http
|
|
GET /api/config
|
|
```
|
|
|
|
Returns MapBox API configuration for frontend geocoding.
|
|
|
|
**Response:**
|
|
```json
|
|
{
|
|
"mapboxAccessToken": "pk.your_token_here",
|
|
"hasMapbox": true
|
|
}
|
|
```
|
|
|
|
### Get Active Locations
|
|
```http
|
|
GET /api/locations
|
|
```
|
|
|
|
Returns all active location reports (less than 48 hours old or marked persistent).
|
|
|
|
**Response:**
|
|
```json
|
|
[
|
|
{
|
|
"id": 123,
|
|
"address": "Main St & Oak Ave, Grand Rapids, MI",
|
|
"latitude": 42.9634,
|
|
"longitude": -85.6681,
|
|
"description": "Black ice present, multiple vehicles stuck",
|
|
"persistent": false,
|
|
"created_at": "2025-01-15T10:30:00.000Z"
|
|
}
|
|
]
|
|
```
|
|
|
|
### Submit Location Report
|
|
```http
|
|
POST /api/locations
|
|
```
|
|
|
|
Submit a new ice condition report with automatic profanity filtering.
|
|
|
|
**Request Body:**
|
|
```json
|
|
{
|
|
"address": "Main St & Oak Ave, Grand Rapids, MI",
|
|
"latitude": 42.9634,
|
|
"longitude": -85.6681,
|
|
"description": "Black ice spotted, drive carefully"
|
|
}
|
|
```
|
|
|
|
**Validation:**
|
|
- `address`: Required, max 500 characters
|
|
- `latitude`: Optional, valid number
|
|
- `longitude`: Optional, valid number
|
|
- `description`: Optional, max 1000 characters
|
|
|
|
**Response (Success):**
|
|
```json
|
|
{
|
|
"id": 125,
|
|
"address": "Main St & Oak Ave, Grand Rapids, MI",
|
|
"latitude": 42.9634,
|
|
"longitude": -85.6681,
|
|
"description": "Black ice spotted, drive carefully",
|
|
"persistent": false,
|
|
"created_at": "2025-01-15T12:00:00.000Z"
|
|
}
|
|
```
|
|
|
|
**Response (Profanity Detected):**
|
|
```json
|
|
{
|
|
"error": "Submission rejected",
|
|
"message": "Your description contains inappropriate language...",
|
|
"details": {
|
|
"severity": "medium",
|
|
"wordCount": 1,
|
|
"detectedCategories": ["general"]
|
|
}
|
|
}
|
|
```
|
|
|
|
## Admin Endpoints
|
|
|
|
All admin endpoints require authentication via `Authorization: Bearer <token>`.
|
|
|
|
### Admin Login
|
|
```http
|
|
POST /api/admin/login
|
|
```
|
|
|
|
Authenticate with admin password to receive access token.
|
|
|
|
**Request Body:**
|
|
```json
|
|
{
|
|
"password": "your_admin_password"
|
|
}
|
|
```
|
|
|
|
**Response:**
|
|
```json
|
|
{
|
|
"token": "your_bearer_token_here",
|
|
"message": "Login successful"
|
|
}
|
|
```
|
|
|
|
### Get All Locations
|
|
```http
|
|
GET /api/admin/locations
|
|
```
|
|
|
|
Returns all location reports including expired ones.
|
|
|
|
### Update Location
|
|
```http
|
|
PUT /api/admin/locations/:id
|
|
```
|
|
|
|
Update location details.
|
|
|
|
**Request Body:**
|
|
```json
|
|
{
|
|
"address": "Updated Address",
|
|
"latitude": 42.9634,
|
|
"longitude": -85.6681,
|
|
"description": "Updated description"
|
|
}
|
|
```
|
|
|
|
### Toggle Persistent Status
|
|
```http
|
|
PATCH /api/admin/locations/:id/persistent
|
|
```
|
|
|
|
Mark location as persistent (won't auto-expire) or remove persistent status.
|
|
|
|
**Request Body:**
|
|
```json
|
|
{
|
|
"persistent": true
|
|
}
|
|
```
|
|
|
|
### Delete Location
|
|
```http
|
|
DELETE /api/admin/locations/:id
|
|
```
|
|
|
|
Permanently delete a location report.
|
|
|
|
### Profanity Word Management
|
|
|
|
#### Get All Profanity Words
|
|
```http
|
|
GET /api/admin/profanity-words
|
|
```
|
|
|
|
#### Add Profanity Word
|
|
```http
|
|
POST /api/admin/profanity-words
|
|
```
|
|
|
|
**Request Body:**
|
|
```json
|
|
{
|
|
"word": "badword",
|
|
"severity": "medium",
|
|
"category": "custom"
|
|
}
|
|
```
|
|
|
|
#### Update Profanity Word
|
|
```http
|
|
PUT /api/admin/profanity-words/:id
|
|
```
|
|
|
|
#### Delete Profanity Word
|
|
```http
|
|
DELETE /api/admin/profanity-words/:id
|
|
```
|
|
|
|
## Error Responses
|
|
|
|
### Rate Limiting
|
|
```json
|
|
{
|
|
"error": "Too many location reports submitted",
|
|
"message": "You can submit up to 10 location reports every 15 minutes. Please wait before submitting more.",
|
|
"retryAfter": "15 minutes"
|
|
}
|
|
```
|
|
|
|
### Validation Errors
|
|
```json
|
|
{
|
|
"error": "Address must be a string with maximum 500 characters"
|
|
}
|
|
```
|
|
|
|
### Authentication Errors
|
|
```json
|
|
{
|
|
"error": "Access denied"
|
|
}
|
|
```
|
|
|
|
### Not Found
|
|
```json
|
|
{
|
|
"error": "Location not found"
|
|
}
|
|
```
|
|
|
|
### Server Errors
|
|
```json
|
|
{
|
|
"error": "Internal server error"
|
|
}
|
|
```
|
|
|
|
## Interactive Documentation
|
|
|
|
For complete interactive API documentation with live testing capabilities, visit `/api-docs` when running the server. This provides:
|
|
|
|
- Complete endpoint specifications
|
|
- Request/response schemas
|
|
- Interactive testing interface
|
|
- Authentication flows
|
|
- Example requests and responses
|
|
|
|
## Security Features
|
|
|
|
- **Rate Limiting**: Prevents abuse and DoS attacks
|
|
- **Input Validation**: Strict length and type checking
|
|
- **Profanity Filtering**: Automatic content moderation
|
|
- **Authentication**: Secure admin access with bearer tokens
|
|
- **HTTPS**: SSL/TLS encryption in production
|
|
- **Audit Logging**: Suspicious activity detection
|
|
|
|
## Client Libraries
|
|
|
|
The API follows REST conventions and can be consumed by any HTTP client. Examples:
|
|
|
|
### JavaScript/Node.js
|
|
```javascript
|
|
// Submit location report
|
|
const response = await fetch('/api/locations', {
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/json'
|
|
},
|
|
body: JSON.stringify({
|
|
address: 'Main St & Oak Ave',
|
|
description: 'Icy conditions'
|
|
})
|
|
});
|
|
```
|
|
|
|
### curl
|
|
```bash
|
|
# Get active locations
|
|
curl https://your-domain.com/api/locations
|
|
|
|
# Submit location report
|
|
curl -X POST https://your-domain.com/api/locations \
|
|
-H "Content-Type: application/json" \
|
|
-d '{"address":"Main St & Oak Ave","description":"Icy conditions"}'
|
|
|
|
# Admin login
|
|
curl -X POST https://your-domain.com/api/admin/login \
|
|
-H "Content-Type: application/json" \
|
|
-d '{"password":"your_password"}'
|
|
``` |