ice/docs/api.md
Claude Code 5176636f6d Add comprehensive documentation in docs/ directory
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>
2025-07-05 22:03:01 -04:00

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"}'
```