Files
igny8/backup-api-standard-v1/docs/MIGRATION-GUIDE.md
2025-11-16 03:28:25 +00:00

366 lines
7.5 KiB
Markdown

# API Migration Guide
**Version**: 1.0.0
**Last Updated**: 2025-11-16
Guide for migrating existing API consumers to IGNY8 API Standard v1.0.
---
## Overview
The IGNY8 API v1.0 introduces a unified response format that standardizes all API responses. This guide helps you migrate existing code to work with the new format.
---
## What Changed
### Before (Legacy Format)
**Success Response**:
```json
{
"id": 1,
"name": "Keyword",
"status": "active"
}
```
**Error Response**:
```json
{
"detail": "Not found."
}
```
### After (Unified Format v1.0)
**Success Response**:
```json
{
"success": true,
"data": {
"id": 1,
"name": "Keyword",
"status": "active"
},
"request_id": "550e8400-e29b-41d4-a716-446655440000"
}
```
**Error Response**:
```json
{
"success": false,
"error": "Resource not found",
"request_id": "550e8400-e29b-41d4-a716-446655440000"
}
```
---
## Migration Steps
### Step 1: Update Response Parsing
#### Before
```python
response = requests.get(url, headers=headers)
data = response.json()
# Direct access
keyword_id = data['id']
keyword_name = data['name']
```
#### After
```python
response = requests.get(url, headers=headers)
data = response.json()
# Check success first
if data['success']:
# Extract data from unified format
keyword_data = data['data'] # or data['results'] for lists
keyword_id = keyword_data['id']
keyword_name = keyword_data['name']
else:
# Handle error
error_message = data['error']
raise Exception(error_message)
```
### Step 2: Update Error Handling
#### Before
```python
try:
response = requests.get(url, headers=headers)
response.raise_for_status()
data = response.json()
except requests.HTTPError as e:
if e.response.status_code == 404:
print("Not found")
elif e.response.status_code == 400:
print("Bad request")
```
#### After
```python
response = requests.get(url, headers=headers)
data = response.json()
if not data['success']:
# Unified error format
error_message = data['error']
field_errors = data.get('errors', {})
if response.status_code == 404:
print(f"Not found: {error_message}")
elif response.status_code == 400:
print(f"Validation error: {error_message}")
for field, errors in field_errors.items():
print(f" {field}: {', '.join(errors)}")
```
### Step 3: Update Pagination Handling
#### Before
```python
response = requests.get(url, headers=headers)
data = response.json()
results = data['results']
next_page = data['next']
count = data['count']
```
#### After
```python
response = requests.get(url, headers=headers)
data = response.json()
if data['success']:
# Paginated response format
results = data['results'] # Same field name
next_page = data['next'] # Same field name
count = data['count'] # Same field name
else:
# Handle error
raise Exception(data['error'])
```
### Step 4: Update Frontend Code
#### Before (JavaScript)
```javascript
const response = await fetch(url, { headers });
const data = await response.json();
// Direct access
const keywordId = data.id;
const keywordName = data.name;
```
#### After (JavaScript)
```javascript
const response = await fetch(url, { headers });
const data = await response.json();
// Check success first
if (data.success) {
// Extract data from unified format
const keywordData = data.data || data.results;
const keywordId = keywordData.id;
const keywordName = keywordData.name;
} else {
// Handle error
console.error('Error:', data.error);
if (data.errors) {
// Handle field-specific errors
Object.entries(data.errors).forEach(([field, errors]) => {
console.error(`${field}: ${errors.join(', ')}`);
});
}
}
```
---
## Helper Functions
### Python Helper
```python
def parse_api_response(response):
"""Parse unified API response format"""
data = response.json()
if data.get('success'):
# Return data or results
return data.get('data') or data.get('results')
else:
# Raise exception with error details
error_msg = data.get('error', 'Unknown error')
errors = data.get('errors', {})
if errors:
error_msg += f": {errors}"
raise Exception(error_msg)
# Usage
response = requests.get(url, headers=headers)
keyword_data = parse_api_response(response)
```
### JavaScript Helper
```javascript
function parseApiResponse(data) {
if (data.success) {
return data.data || data.results;
} else {
const error = new Error(data.error);
error.errors = data.errors || {};
throw error;
}
}
// Usage
const response = await fetch(url, { headers });
const data = await response.json();
try {
const keywordData = parseApiResponse(data);
} catch (error) {
console.error('API Error:', error.message);
if (error.errors) {
// Handle field-specific errors
}
}
```
---
## Breaking Changes
### 1. Response Structure
**Breaking**: All responses now include `success` field and wrap data in `data` or `results`.
**Migration**: Update all response parsing code to check `success` and extract `data`/`results`.
### 2. Error Format
**Breaking**: Error responses now use unified format with `error` and `errors` fields.
**Migration**: Update error handling to use new format.
### 3. Request ID
**New**: All responses include `request_id` for debugging.
**Migration**: Optional - can be used for support requests.
---
## Non-Breaking Changes
### 1. Pagination
**Status**: Compatible - same field names (`count`, `next`, `previous`, `results`)
**Migration**: No changes needed, but wrap in success check.
### 2. Authentication
**Status**: Compatible - same JWT Bearer token format
**Migration**: No changes needed.
### 3. Endpoint URLs
**Status**: Compatible - same endpoint paths
**Migration**: No changes needed.
---
## Testing Migration
### 1. Update Test Code
```python
# Before
def test_get_keyword():
response = client.get('/api/v1/planner/keywords/1/')
assert response.status_code == 200
assert response.json()['id'] == 1
# After
def test_get_keyword():
response = client.get('/api/v1/planner/keywords/1/')
assert response.status_code == 200
data = response.json()
assert data['success'] == True
assert data['data']['id'] == 1
```
### 2. Test Error Handling
```python
def test_not_found():
response = client.get('/api/v1/planner/keywords/99999/')
assert response.status_code == 404
data = response.json()
assert data['success'] == False
assert data['error'] == "Resource not found"
```
---
## Migration Checklist
- [ ] Update response parsing to check `success` field
- [ ] Extract data from `data` or `results` field
- [ ] Update error handling to use unified format
- [ ] Update pagination handling (wrap in success check)
- [ ] Update frontend code (if applicable)
- [ ] Update test code
- [ ] Test all endpoints
- [ ] Update documentation
- [ ] Deploy and monitor
---
## Rollback Plan
If issues arise during migration:
1. **Temporary Compatibility Layer**: Add wrapper to convert unified format back to legacy format
2. **Feature Flag**: Use feature flag to toggle between formats
3. **Gradual Migration**: Migrate endpoints one module at a time
---
## Support
For migration support:
- Review [API Documentation](API-DOCUMENTATION.md)
- Check [Error Codes Reference](ERROR-CODES.md)
- Contact support with `request_id` from failed requests
---
**Last Updated**: 2025-11-16
**API Version**: 1.0.0