This document describes the security measures implemented in the Booking API.
The following endpoints are protected and require an X-API-Key header with a valid admin API key:
-
GET /api/bookings/future
- Lists all future bookings
- Returns: Array of booking objects
- Use case: Admin dashboard, reporting
-
GET /api/bookings/{booking_id}
- Retrieves a specific booking by ID
- Returns: Single booking object
- Use case: Admin viewing booking details
-
DELETE /api/bookings/{booking_id}
- Deletes a booking by ID
- Returns: 204 No Content
- Use case: Admin canceling bookings
- GET /api/surveys/{booking_id}
- Retrieves survey responses for a specific booking
- Returns: Survey object with all responses
- Use case: Admin viewing customer feedback
- Protected since: 2025-11-15
- Reason: Contains sensitive customer data (roles, goals, team information)
These endpoints are accessible to end users without authentication:
-
POST /api/bookings/
- Create or update a booking
- Public access needed for the booking form
-
GET /api/bookings/available-slots
- Get available time slots for a date
- Public access needed for the calendar picker
-
POST /api/surveys
- Submit survey responses after booking
- Public access needed for the survey form
-
GET /health
- Health check endpoint
- Public for monitoring
Protected endpoints use API key authentication via the X-API-Key header.
Configuration:
-
Generate a secure API key:
python3 -c "import secrets; print(secrets.token_urlsafe(32))" -
Add to
backend/.env:ADMIN_API_KEY=your-generated-key-here
Usage Example:
# With API key (succeeds)
curl -X GET http://localhost:8000/api/bookings/future \
-H "X-API-Key: your-admin-key"
# Without API key (fails with 401)
curl -X GET http://localhost:8000/api/bookings/futureError Responses:
// Missing API key
{
"detail": "API Key is missing"
}
// Invalid API key
{
"detail": "Invalid API Key"
}
// API key not configured on server
{
"detail": "Admin API key not configured on server"
}-
Use Strong API Keys
- Minimum 32 characters
- Use
secrets.token_urlsafe()to generate - Never commit to version control
-
Environment Variables
- Store
ADMIN_API_KEYin environment variables - Use
.envfile (excluded from git) - Different keys for dev/staging/prod
- Store
-
HTTPS Only
- Always use HTTPS in production
- API keys transmitted in plain text over HTTP are vulnerable
-
Key Rotation
- Rotate API keys periodically
- Immediately rotate if compromised
-
Access Control
- Only share admin keys with authorized personnel
- Use different keys for different admin users/services if needed
-
Local Development
- Use a test API key in local
.env - Don't use production keys locally
- Use a test API key in local
-
Testing
- See test-survey-api-protection.sh for examples
Protected endpoints use the verify_api_key dependency:
from ..dependencies import verify_api_key
@router.get("/protected-endpoint")
def protected_endpoint(
api_key: str = Depends(verify_api_key)
):
# Only executed if API key is valid
passAPI key is loaded from environment in backend/app/config.py:
class Settings(BaseSettings):
admin_api_key: Optional[str] = NoneSee backend/app/dependencies.py for the verify_api_key implementation.
# Test protected endpoint
./test-survey-api-protection.sh| Scenario | Expected Result |
|---|---|
| No API key | 401 Unauthorized |
| Invalid API key | 401 Unauthorized |
| Valid API key | 200 OK with data |
| API key not configured | 401 with config error |
-
Failed Authentication Attempts
- Monitor 401 errors on protected endpoints
- Alert on unusual patterns
-
API Key Usage
- Track which endpoints are accessed
- Monitor for abnormal usage patterns
-
Logs
- All authentication failures are logged
- Review logs regularly for security issues
Previously, GET /api/surveys/{booking_id} was unprotected. This has been changed to require admin authentication because:
- Contains sensitive customer data (roles, cloud usage, team size, goals)
- Not used by the frontend (only admin access needed)
- Consistent with other read-only admin endpoints
Impact:
- No frontend changes needed (endpoint not used)
- Admin tools must now include
X-API-Keyheader - Existing integrations may break if they don't use API keys
Q: Why isn't POST /api/bookings/ protected? A: End users need to create bookings through the public form. The endpoint has other protections (time slot uniqueness, validation).
Q: Why isn't POST /api/surveys protected? A: Users need to submit surveys after booking. The endpoint verifies the booking exists and prevents duplicate submissions.
Q: Can I use different API keys for different endpoints?
A: Currently, all protected endpoints use the same ADMIN_API_KEY. If you need granular access control, you'll need to extend the authentication system.
Q: What if I lose my API key?
A: Generate a new one and update the ADMIN_API_KEY environment variable. Restart the server for changes to take effect.
- BOOKING_LOGIC.md - Booking creation/update logic
- backend/.env.example - Configuration template
- test-survey-api-protection.sh - Security tests