Files
igny8/docs/MIGRATION-GUIDE.md

7.5 KiB

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:

{
  "id": 1,
  "name": "Keyword",
  "status": "active"
}

Error Response:

{
  "detail": "Not found."
}

After (Unified Format v1.0)

Success Response:

{
  "success": true,
  "data": {
    "id": 1,
    "name": "Keyword",
    "status": "active"
  },
  "request_id": "550e8400-e29b-41d4-a716-446655440000"
}

Error Response:

{
  "success": false,
  "error": "Resource not found",
  "request_id": "550e8400-e29b-41d4-a716-446655440000"
}

Migration Steps

Step 1: Update Response Parsing

Before

response = requests.get(url, headers=headers)
data = response.json()

# Direct access
keyword_id = data['id']
keyword_name = data['name']

After

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

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

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

response = requests.get(url, headers=headers)
data = response.json()

results = data['results']
next_page = data['next']
count = data['count']

After

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)

const response = await fetch(url, { headers });
const data = await response.json();

// Direct access
const keywordId = data.id;
const keywordName = data.name;

After (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

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

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

# 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

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:


Last Updated: 2025-11-16
API Version: 1.0.0