This guide explains the Version History API which provides version tracking for various Waldur objects using django-reversion.
The Version History API enables auditing and debugging by maintaining a complete change history for key Waldur entities. Every modification to tracked fields creates a timestamped snapshot that can be queried via the API.
Use cases:
- Audit trail for compliance requirements
- Debugging configuration issues
- Tracking changes over time
- Investigating state transitions
- Point-in-time recovery analysis
The following models have version history endpoints:
| Model | Endpoint | Description |
|---|---|---|
| Customer | /api/customers/{uuid}/history/ |
Organization accounts |
| User | /api/users/{uuid}/history/ |
User accounts |
| SSH Key | /api/keys/{uuid}/history/ |
SSH public keys |
| Offering | /api/marketplace-provider-offerings/{uuid}/history/ |
Service offerings |
| Plan | /api/marketplace-plans/{uuid}/history/ |
Pricing plans |
| Resource | /api/marketplace-resources/{uuid}/history/ |
Marketplace resources |
| Invoice | /api/invoices/{uuid}/history/ |
Billing invoices |
graph TD
A[Object Change] --> B[django-reversion]
B --> C[Version Record]
C --> D[PostgreSQL]
E[History API] --> D
E --> F[Paginated Response]
The system uses django-reversion to capture object snapshots on save operations. Each version stores:
- Serialized field data
- Timestamp of the change
- User who made the change (if authenticated)
- Revision comment describing the change
All models with version history support two endpoints:
Returns paginated version history for an object, ordered by most recent first.
GET /api/{resource}/{uuid}/history/Query Parameters:
| Parameter | Type | Description |
|---|---|---|
created_before |
ISO 8601 timestamp | Filter versions created before this time |
created_after |
ISO 8601 timestamp | Filter versions created after this time |
Example Request:
curl -H "Authorization: Token <token>" \
"https://waldur.example.com/api/customers/abc123/history/"Example Response:
[
{
"id": 42,
"revision_date": "2024-01-15T14:30:00Z",
"revision_user": {
"uuid": "user-uuid-123",
"username": "admin",
"full_name": "John Admin"
},
"revision_comment": "Updated via REST API",
"serialized_data": {
"name": "Acme Corporation",
"abbreviation": "ACME",
"contact_details": "contact@acme.com"
}
}
]Returns the object state as it existed at a specific point in time.
GET /api/{resource}/{uuid}/history/at/?timestamp=<ISO 8601>Query Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
timestamp |
ISO 8601 timestamp | Yes | Point in time to query |
Example Request:
curl -H "Authorization: Token <token>" \
"https://waldur.example.com/api/customers/abc123/history/at/?timestamp=2024-01-15T10:00:00Z"Example Response (200 OK):
{
"id": 41,
"revision_date": "2024-01-14T09:00:00Z",
"revision_user": {
"uuid": "user-uuid-456",
"username": "operator",
"full_name": "Jane Operator"
},
"revision_comment": "Customer created",
"serialized_data": {
"name": "Acme Corporation",
"abbreviation": "ACME",
"contact_details": "info@acme.com"
},
"queried_at": "2024-01-15T10:00:00Z"
}Error Responses:
| Status | Condition |
|---|---|
| 400 | Missing or invalid timestamp parameter |
| 404 | No version exists before the specified timestamp |
The VersionHistorySerializer returns these fields:
| Field | Type | Description |
|---|---|---|
id |
integer | Version record ID |
revision_date |
datetime | When the change was recorded |
revision_user |
object/null | User who made the change |
revision_comment |
string | Description of the change |
serialized_data |
object | Snapshot of object fields |
The revision_user object contains:
| Field | Type | Description |
|---|---|---|
uuid |
UUID | User identifier |
username |
string | Login username |
full_name |
string | Display name |
Access to history endpoints is restricted to:
- Staff users - Global administrators
- Support users - Global support personnel
Regular users (owners, admins, managers, members) cannot access version history.
curl -H "Authorization: Token <token>" \
"https://waldur.example.com/api/customers/abc123/history/?\
created_after=2024-01-01T00:00:00Z&created_before=2024-01-31T23:59:59Z"curl -H "Authorization: Token <token>" \
"https://waldur.example.com/api/customers/abc123/history/at/?\
timestamp=2024-01-15T08:00:00Z"# Get current state
curl -H "Authorization: Token <token>" \
"https://waldur.example.com/api/customers/abc123/"
# Get state from 30 days ago
curl -H "Authorization: Token <token>" \
"https://waldur.example.com/api/customers/abc123/history/at/?\
timestamp=$(date -v-30d +%Y-%m-%dT%H:%M:%SZ)"Resources have additional tracked fields specific to marketplace operations. See Resource History API for details on:
- Tracked resource fields (limits, attributes, cost, etc.)
- Actions that create history entries
- Django admin integration
Tracked fields include:
name,native_name,abbreviationcontact_details,emailregistration_code,agreement_numbercountry,vat_code
Tracked fields include:
username,emailfirst_name,last_name,native_nameorganization,job_titleis_active,is_staff,is_support
Tracked fields include:
name,descriptionterms_of_service,terms_of_service_linkprivacy_policy_linkstate,paused_reason
Tracked fields include:
name,descriptionunit_price,unitmax_amount,archived
Tracked fields include:
state,year,monthtax_percentcustomerreference
The version history functionality is implemented via HistoryViewSetMixin in
waldur_core.core.views. This mixin can be added to any ViewSet whose model
is registered with django-reversion.
To add history endpoints to a new ViewSet:
-
Register the model with django-reversion:
import reversion reversion.register(MyModel)
-
Add the mixin to the ViewSet:
from waldur_core.core.views import HistoryViewSetMixin class MyViewSet(HistoryViewSetMixin, ActionsViewSet): queryset = MyModel.objects.all()
-
Optionally customize the serializer:
class MyViewSet(HistoryViewSetMixin, ActionsViewSet): history_serializer_class = MyCustomVersionSerializer
- Resource History API - Resource-specific history details
- Waldur Permissions - Permission system details