16 KiB
History API Endpoints Documentation
Overview
The History API provides complete access to historical changes for all major entities in the ThrillTrack system. Built on top of the django-pghistory library, this API enables:
- Historical Tracking: View complete history of changes to entities
- Event Comparison: Compare different versions of entities over time
- Field History: Track changes to specific fields
- Activity Summaries: Get statistics about entity modifications
- Rollback Capabilities: Restore entities to previous states (admin only)
Supported Entities
The History API is available for the following entities:
- Parks (
/api/v1/parks/{park_id}/history/) - Rides (
/api/v1/rides/{ride_id}/history/) - Companies (
/api/v1/companies/{company_id}/history/) - Ride Models (
/api/v1/ride-models/{model_id}/history/) - Reviews (
/api/v1/reviews/{review_id}/history/)
Additionally, generic history endpoints are available:
- Generic Event Access (
/api/v1/history/events/{event_id}) - Generic Event Comparison (
/api/v1/history/compare)
Authentication & Authorization
Access Levels
The History API implements a tiered access control system:
1. Public (Unauthenticated)
- Access Window: Last 30 days
- Permissions: Read-only access to recent history
- Use Cases: Public transparency, recent changes visibility
2. Authenticated Users
- Access Window: Last 1 year
- Permissions: Read-only access to extended history
- Use Cases: User research, tracking their contributions
3. Moderators/Admins/Superusers
- Access Window: Unlimited (entire history)
- Permissions: Full read access + rollback capabilities
- Use Cases: Moderation, auditing, data recovery
Rollback Permissions
Only users with moderator, admin, or superuser privileges can perform rollbacks:
- Check via
can_rollbackfield in responses - Requires explicit permission check
- Creates audit trail of rollback actions
Endpoint Reference
1. List Entity History
Get paginated history of changes to an entity.
Endpoint Pattern: GET /{entity-type}/{entity-id}/history/
Query Parameters:
page(integer, default: 1): Page numberpage_size(integer, default: 50, max: 100): Items per pagedate_from(string, format: YYYY-MM-DD): Filter from datedate_to(string, format: YYYY-MM-DD): Filter to date
Response: 200 OK
{
"entity_id": "uuid-string",
"entity_type": "park|ride|company|ridemodel|review",
"entity_name": "Entity Display Name",
"total_events": 150,
"accessible_events": 150,
"access_limited": false,
"access_reason": "Full access (moderator)",
"events": [
{
"id": 12345,
"timestamp": "2024-01-15T10:30:00Z",
"operation": "insert|update|delete",
"snapshot": {
"id": "uuid",
"name": "Example Park",
"status": "operating",
...
},
"changed_fields": ["name", "status"],
"change_summary": "Updated name and status",
"can_rollback": true
}
],
"pagination": {
"page": 1,
"page_size": 50,
"total_pages": 3,
"total_items": 150
}
}
Examples:
# Get park history
GET /api/v1/parks/123e4567-e89b-12d3-a456-426614174000/history/
# Get ride history with date filter
GET /api/v1/rides/987fcdeb-51a2-43f1-9876-543210fedcba/history/?date_from=2024-01-01&date_to=2024-12-31
# Get company history, page 2
GET /api/v1/companies/456e789a-b12c-34d5-e678-901234567890/history/?page=2&page_size=100
2. Get Specific History Event
Retrieve detailed information about a single historical event.
Endpoint Pattern: GET /{entity-type}/{entity-id}/history/{event-id}/
Response: 200 OK
{
"id": 12345,
"timestamp": "2024-01-15T10:30:00Z",
"operation": "update",
"entity_id": "uuid-string",
"entity_type": "park",
"entity_name": "Example Park",
"snapshot": {
"id": "uuid",
"name": "Example Park",
"status": "operating",
...
},
"changed_fields": ["name", "status"],
"metadata": {},
"can_rollback": true,
"rollback_preview": null
}
Examples:
# Get specific park event
GET /api/v1/parks/123e4567-e89b-12d3-a456-426614174000/history/12345/
# Get specific review event
GET /api/v1/reviews/67890/history/54321/
3. Compare Two History Events
Compare two historical snapshots to see what changed between them.
Endpoint Pattern: GET /{entity-type}/{entity-id}/history/compare/
Query Parameters:
event1(integer, required): First event IDevent2(integer, required): Second event ID
Response: 200 OK
{
"entity_id": "uuid-string",
"entity_type": "park",
"entity_name": "Example Park",
"event1": {
"id": 12345,
"timestamp": "2024-01-15T10:30:00Z",
"snapshot": {...}
},
"event2": {
"id": 12346,
"timestamp": "2024-01-16T14:20:00Z",
"snapshot": {...}
},
"differences": {
"name": {
"old_value": "Old Park Name",
"new_value": "New Park Name",
"changed": true
},
"status": {
"old_value": "closed",
"new_value": "operating",
"changed": true
}
},
"changed_field_count": 2,
"unchanged_field_count": 15,
"time_between": "1 day, 3:50:00"
}
Examples:
# Compare two park events
GET /api/v1/parks/123e4567-e89b-12d3-a456-426614174000/history/compare/?event1=12345&event2=12346
# Compare ride events
GET /api/v1/rides/987fcdeb-51a2-43f1-9876-543210fedcba/history/compare/?event1=100&event2=105
4. Compare Event with Current State
Compare a historical event with the entity's current state.
Endpoint Pattern: GET /{entity-type}/{entity-id}/history/{event-id}/diff-current/
Response: 200 OK
{
"entity_id": "uuid-string",
"entity_type": "park",
"entity_name": "Example Park",
"event": {
"id": 12345,
"timestamp": "2024-01-15T10:30:00Z",
"snapshot": {...}
},
"current_state": {
"name": "Current Park Name",
"status": "operating",
...
},
"differences": {
"name": {
"old_value": "Historical Name",
"new_value": "Current Park Name",
"changed": true
}
},
"changed_field_count": 3,
"time_since": "45 days, 2:15:30"
}
Examples:
# Compare historical park state with current
GET /api/v1/parks/123e4567-e89b-12d3-a456-426614174000/history/12345/diff-current/
# Compare historical company state with current
GET /api/v1/companies/456e789a-b12c-34d5-e678-901234567890/history/98765/diff-current/
5. Rollback to Historical State
Restore an entity to a previous state. Requires moderator/admin/superuser permissions.
Endpoint Pattern: POST /{entity-type}/{entity-id}/history/{event-id}/rollback/
Authentication: Required (JWT)
Request Body:
{
"fields": ["name", "status"], // Optional: specific fields to rollback
"comment": "Reverting vandalism", // Optional: reason for rollback
"create_backup": true // Optional: create backup event before rollback
}
Response: 200 OK
{
"success": true,
"message": "Successfully rolled back to event 12345",
"rolled_back_fields": ["name", "status"],
"backup_event_id": 12350,
"new_event_id": 12351
}
Error Responses:
401 Unauthorized: Authentication required403 Forbidden: Insufficient permissions404 Not Found: Event or entity not found400 Bad Request: Invalid rollback request
Examples:
# Full rollback of park
POST /api/v1/parks/123e4567-e89b-12d3-a456-426614174000/history/12345/rollback/
{
"comment": "Reverting accidental changes",
"create_backup": true
}
# Partial rollback (specific fields only)
POST /api/v1/rides/987fcdeb-51a2-43f1-9876-543210fedcba/history/54321/rollback/
{
"fields": ["name", "description"],
"comment": "Restoring original name and description",
"create_backup": true
}
6. Get Field History
Track all changes to a specific field over time.
Endpoint Pattern: GET /{entity-type}/{entity-id}/history/field/{field-name}/
Response: 200 OK
{
"entity_id": "uuid-string",
"entity_type": "park",
"entity_name": "Example Park",
"field": "status",
"field_type": "CharField",
"changes": [
{
"event_id": 12346,
"timestamp": "2024-01-16T14:20:00Z",
"old_value": "closed",
"new_value": "operating"
},
{
"event_id": 12345,
"timestamp": "2024-01-15T10:30:00Z",
"old_value": "operating",
"new_value": "closed"
}
],
"total_changes": 2,
"first_recorded": "2023-06-01T08:00:00Z",
"last_changed": "2024-01-16T14:20:00Z"
}
Examples:
# Track park status changes
GET /api/v1/parks/123e4567-e89b-12d3-a456-426614174000/history/field/status/
# Track ride height changes
GET /api/v1/rides/987fcdeb-51a2-43f1-9876-543210fedcba/history/field/height/
# Track company name changes
GET /api/v1/companies/456e789a-b12c-34d5-e678-901234567890/history/field/name/
7. Get Activity Summary
Get statistics about modifications to an entity.
Endpoint Pattern: GET /{entity-type}/{entity-id}/history/summary/
Response: 200 OK
{
"entity_id": "uuid-string",
"entity_type": "park",
"entity_name": "Example Park",
"total_events": 150,
"total_updates": 145,
"total_creates": 1,
"total_deletes": 0,
"first_event": "2023-01-01T00:00:00Z",
"last_event": "2024-03-15T16:45:00Z",
"most_active_period": "2024-01",
"average_updates_per_month": 12.5,
"most_changed_fields": [
{"field": "status", "changes": 25},
{"field": "description", "changes": 18},
{"field": "ride_count", "changes": 15}
]
}
Examples:
# Get park activity summary
GET /api/v1/parks/123e4567-e89b-12d3-a456-426614174000/history/summary/
# Get review activity summary
GET /api/v1/reviews/67890/history/summary/
Generic History Endpoints
Get Any Event by ID
Retrieve any historical event by its ID, regardless of entity type.
Endpoint: GET /api/v1/history/events/{event-id}
Response: 200 OK
{
"id": 12345,
"timestamp": "2024-01-15T10:30:00Z",
"operation": "update",
"entity_type": "park",
"entity_id": "uuid-string",
"snapshot": {...},
"changed_fields": ["name", "status"],
"can_rollback": true
}
Compare Any Two Events
Compare any two events, even across different entities.
Endpoint: GET /api/v1/history/compare
Query Parameters:
event1(integer, required): First event IDevent2(integer, required): Second event ID
Response: Similar to entity-specific comparison endpoint
Access Control Details
Time-Based Access Windows
Access windows are enforced based on user authentication level:
# Access limits
PUBLIC_WINDOW = 30 days
AUTHENTICATED_WINDOW = 1 year
PRIVILEGED_WINDOW = Unlimited
Access Reason Messages
The API provides clear feedback about access limitations:
- "Full access (moderator)": Unlimited access
- "Full access (admin)": Unlimited access
- "Full access (superuser)": Unlimited access
- "Access limited to last 365 days (authenticated user)": 1-year limit
- "Access limited to last 30 days (public)": 30-day limit
Rollback Safety Guidelines
Before Performing a Rollback
- Review the Target State: Use
diff-currentto see what will change - Check Dependencies: Consider impact on related entities
- Create Backup: Always set
create_backup: truefor safety - Add Comment: Document why the rollback is being performed
- Use Partial Rollback: When possible, rollback only specific fields
Rollback Best Practices
{
"fields": ["name", "description"], // Limit scope
"comment": "Reverting vandalism on 2024-03-15", // Document reason
"create_backup": true // Always true in production
}
Audit Trail
All rollbacks create:
- Backup Event: Snapshot before rollback (if
create_backup: true) - Rollback Event: New event with restored state
- Audit Log: Metadata tracking who performed rollback and why
Error Handling
Common Error Responses
404 Not Found
{
"error": "Entity not found"
}
400 Bad Request
{
"error": "Invalid date format. Use YYYY-MM-DD"
}
403 Forbidden
{
"error": "Only moderators and administrators can perform rollbacks"
}
401 Unauthorized
{
"error": "Authentication required"
}
Error Codes
| Status Code | Meaning |
|---|---|
| 200 | Success |
| 201 | Created |
| 400 | Bad Request (invalid parameters) |
| 401 | Unauthorized (authentication required) |
| 403 | Forbidden (insufficient permissions) |
| 404 | Not Found (entity or event not found) |
| 500 | Internal Server Error |
Rate Limiting
The History API implements standard rate limiting:
- Authenticated Users: 100 requests per minute
- Unauthenticated Users: 20 requests per minute
- Rollback Operations: 10 per minute (additional limit)
Rate limit headers:
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 95
X-RateLimit-Reset: 1617181723
Performance Considerations
Pagination
- Default page size: 50 events
- Maximum page size: 100 events
- Use pagination for large result sets
Caching
- Event data is cached for 5 minutes
- Comparison results are cached for 2 minutes
- Current state comparisons are not cached
Query Optimization
- Use date filters to reduce result sets
- Prefer field-specific history for focused queries
- Use summary endpoints for overview data
Integration Examples
Python (requests)
import requests
# Get park history
response = requests.get(
'https://api.thrilltrack.com/v1/parks/123/history/',
params={'page': 1, 'page_size': 50},
headers={'Authorization': 'Bearer YOUR_TOKEN'}
)
history = response.json()
# Compare two events
response = requests.get(
'https://api.thrilltrack.com/v1/parks/123/history/compare/',
params={'event1': 100, 'event2': 105}
)
comparison = response.json()
# Perform rollback
response = requests.post(
'https://api.thrilltrack.com/v1/parks/123/history/100/rollback/',
json={
'comment': 'Reverting vandalism',
'create_backup': True
},
headers={'Authorization': 'Bearer YOUR_TOKEN'}
)
JavaScript (fetch)
// Get ride history
const response = await fetch(
'https://api.thrilltrack.com/v1/rides/456/history/',
{
headers: {
'Authorization': `Bearer ${token}`
}
}
);
const history = await response.json();
// Compare with current state
const diffResponse = await fetch(
'https://api.thrilltrack.com/v1/rides/456/history/200/diff-current/'
);
const diff = await diffResponse.json();
cURL
# Get company history
curl -H "Authorization: Bearer TOKEN" \
"https://api.thrilltrack.com/v1/companies/789/history/"
# Rollback to previous state
curl -X POST \
-H "Authorization: Bearer TOKEN" \
-H "Content-Type: application/json" \
-d '{"comment": "Reverting changes", "create_backup": true}' \
"https://api.thrilltrack.com/v1/companies/789/history/150/rollback/"
Troubleshooting
Common Issues
Issue: "Access limited to last 30 days"
- Solution: Authenticate with valid credentials to extend access window
Issue: "Event not found or not accessible"
- Solution: Event may be outside your access window or doesn't exist
Issue: "Cannot rollback: Event not found"
- Solution: Verify event ID and ensure you have rollback permissions
Issue: Rate limit exceeded
- Solution: Implement exponential backoff or reduce request frequency
Support
For additional support:
- Documentation: https://docs.thrilltrack.com/history-api
- GitHub Issues: https://github.com/thrilltrack/api/issues
- Email: api-support@thrilltrack.com
Changelog
Version 1.0 (Current)
- Initial release of History API
- Support for Parks, Rides, Companies, Ride Models, and Reviews
- Complete CRUD history tracking
- Comparison and rollback capabilities
- Tiered access control system