Skip to main content

API Versioning

The Powerverse Platform API uses versioning to introduce new features while maintaining backward compatibility. This guide explains our versioning strategy and how to migrate between versions.

Versioning Strategy

We use URL path versioning for major versions and date-based headers for minor changes.

Current Version

VersionStatusEnd of Life
v1Current-
v2Beta-

Version in URL

# Version 1 (current)
https://platform.powerverse.com/v1/inventory-service/sites

# Version 2 (beta)
https://platform.powerverse.com/v2/inventory-service/sites

API Version Header

For fine-grained version control within a major version:

curl -X GET "https://platform.powerverse.com/v1/inventory-service/sites" \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "X-API-Version: 2024-01-15"

Backward Compatibility

What We Consider Breaking

These changes require a new major version:

  • ❌ Removing an endpoint
  • ❌ Removing a required field from responses
  • ❌ Changing field types
  • ❌ Changing authentication methods
  • ❌ Changing error response structure

What We Consider Non-Breaking

These changes may happen without a version bump:

  • ✅ Adding new endpoints
  • ✅ Adding optional request parameters
  • ✅ Adding new fields to responses
  • ✅ Adding new enum values
  • ✅ Relaxing validation rules
  • ✅ Adding new error codes

Defensive Coding

Handle unknown fields gracefully:

# ✅ Good: Ignore unknown fields
def parse_site(data):
return Site(
id=data['id'],
name=data['name'],
location=data.get('location') # Optional field
)

# ❌ Bad: Strict parsing that breaks on new fields
def parse_site(data):
if set(data.keys()) != {'id', 'name', 'location'}:
raise ValueError("Unexpected fields")

Version Lifecycle

┌─────────┐    ┌─────────┐    ┌────────────┐    ┌────────────┐
│ Beta │ -> │ Current │ -> │ Deprecated │ -> │ Sunset │
└─────────┘ └─────────┘ └────────────┘ └────────────┘
3-6 mo 24+ mo 12 mo Removed

Beta

  • New features for testing
  • May change based on feedback
  • Not recommended for production

Current

  • Stable and fully supported
  • Bug fixes and security updates
  • New non-breaking features added

Deprecated

  • Still functional but discouraged
  • No new features
  • Security fixes only
  • Migration warnings in responses

Sunset

  • Version is removed
  • Requests return 410 Gone

Deprecation Notices

In Response Headers

HTTP/1.1 200 OK
Deprecation: true
Sunset: Sat, 31 Dec 2025 23:59:59 GMT
Link: <https://platform.powerverse.com/v2/inventory-service/sites>; rel="successor-version"

In Response Body

{
"data": { ... },
"meta": {
"deprecation": {
"message": "This endpoint is deprecated",
"sunset_date": "2025-12-31",
"migration_guide": "https://docs.powerverse.com/migration/v1-to-v2"
}
}
}

Webhook Notifications

Subscribe to deprecation notifications:

curl -X POST "https://platform.powerverse.com/webhooks" \
-H "Authorization: Bearer YOUR_TOKEN" \
-d '{
"url": "https://yourapp.com/webhooks",
"events": ["api.deprecation", "api.sunset_warning"]
}'

Migration Guide: v1 to v2

Breaking Changes in v2

Changev1v2
Resource ID formatsit_abc123 / ast_abc123UUID 550e8400-e29b-...
PaginationOffset-basedCursor-based
Error format{ "error": "message" }{ "error": { "code": "...", "message": "..." } }
Date formatUnix timestampISO 8601

Migrating Resource IDs

# v1 response
{"id": "sit_abc123", "name": "London Charging Hub"}

# v2 response
{"id": "550e8400-e29b-41d4-a716-446655440000", "name": "London Charging Hub"}

# Migration: Store both during transition
class Site:
def __init__(self, data, api_version):
if api_version == 'v1':
self.legacy_id = data['id']
self.id = None # Fetch from mapping
else:
self.id = data['id']
self.legacy_id = data.get('legacy_id')

Migrating Pagination

# v1: Offset-based
def fetch_all_v1(api):
page = 1
while True:
response = api.get('/v1/inventory-service/sites', params={'page': page})
yield from response['data']
if not response['pagination']['has_next']:
break
page += 1

# v2: Cursor-based
def fetch_all_v2(api):
cursor = None
while True:
params = {'cursor': cursor} if cursor else {}
response = api.get('/v2/inventory-service/sites', params=params)
yield from response['data']
if not response['pagination']['has_next']:
break
cursor = response['pagination']['next_cursor']

Migrating Error Handling

# v1 error handling
try:
response = api_v1.create_site(data)
except APIError as e:
message = e.response.json().get('error', 'Unknown error')

# v2 error handling
try:
response = api_v2.create_site(data)
except APIError as e:
error = e.response.json().get('error', {})
code = error.get('code')
message = error.get('message')
details = error.get('details')

Version Detection

Check API Version Support

curl -X GET "https://platform.powerverse.com/versions" \
-H "Authorization: Bearer YOUR_TOKEN"
{
"versions": [
{
"version": "v1",
"status": "current",
"released": "2023-01-01",
"sunset": null
},
{
"version": "v2",
"status": "beta",
"released": "2024-06-01",
"sunset": null
}
],
"current": "v1",
"latest": "v2"
}

Best Practices

1. Pin to a Specific Version

API_VERSION = 'v1'
BASE_URL = f'https://platform.powerverse.com/{API_VERSION}'

2. Monitor Deprecation Headers

function checkDeprecation(response) {
if (response.headers.get('Deprecation')) {
const sunset = response.headers.get('Sunset');
console.warn(`API deprecated! Sunset date: ${sunset}`);
// Alert your team
notifyTeam('API deprecation warning', { sunset });
}
}

3. Test Against Beta Versions

# CI/CD: Test against both versions
jobs:
test:
strategy:
matrix:
api_version: [v1, v2]
steps:
- run: npm test
env:
API_VERSION: ${{ matrix.api_version }}

4. Plan Migration Early

  • Subscribe to deprecation webhooks
  • Allocate time for migration in roadmap
  • Test thoroughly before switching

Next Steps