# 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