This text focuses on implementing a forgiving approach in API integration.

As our public API evolves to meet new requirements and enhance functionality, integrators, and clients need to adapt seamlessly. A key pattern supporting resilience to such changes is the Tolerant Reader.

By adopting the Tolerant Reader pattern, integrations can better handle new information without frequent updates. This approach reduces maintenance needs and enhances resilience, creating a smoother integration experience.


What is a Tolerant Reader?


The Tolerant Reader pattern is an integration design approach where a client consuming data is built to handle potential changes—such as added fields or minor structure modifications—gracefully. This pattern promotes forward compatibility, reducing the need for immediate updates whenever the data or service evolves.


Real-world Scenario


Consider a request to GET /organizations/{organization_id}. Initially, the response might be:

{  
    "id": "cc15194a-6bc9-4ebb-b15d-43411a54ba4b",  
    "parentOrganizationId": null,  
    "legalName": "Empresa Teste Ltda",  
    "legalDocument": "86820799000188",  
    "metadata": null,  
    "status": {  
        "code": "ACTIVE",  
        "description": null  
    },  
    "createdAt": "2024-02-08T16:59:31+0300",  
    "updatedAt": "2024-02-08T16:59:31+0300",  
    "deletedAt": null  
}

Later, fields like doingBusinessAs and address may be added:

{  
    "id": "cc15194a-6bc9-4ebb-b15d-43411a54ba4b",  
    "parentOrganizationId": null,  
    "legalName": "Empresa Teste Ltda",  
    "doingBusinessAs": "Empresa Teste",  
    "legalDocument": "86820799000188",  
    "address": {  
        "line1": "Rua Botucatu, 10",  
        "line2": "Casa B",  
        "zipCode": "04023060",  
        "city": "São Paulo",  
        "state": "SP",  
        "country": "BR"  
    },  
    "metadata": null,  
    "status": {  
        "code": "ACTIVE",  
        "description": null  
    },  
    "createdAt": "2024-02-08T16:59:31+0300",  
    "updatedAt": "2024-02-08T16:59:31+0300",  
    "deletedAt": null  
}

A client that follows the Tolerant Reader pattern would handle the additional fields without issue, ensuring continued functionality.


Implementing a Tolerant Reader


Below is an example Python code snippet that processes additional fields gracefully, accounting for changes in the payload.

def fetch_organization_info(organization_id):
    response = requests.get(f"{host}/organization/{organization_id}")
    org_info = response.json()
    
    # Fetch required fields
    legal_name = org_info.get("legalName", "Unknown")
    legal_document = org_info.get("legalDocument", "No document provided")
    
    # Handle optional fields
    doing_business_as = org_info.get("doingBusinessAs")
    
    # Nested address structure
    address_info = org_info.get("address", {})
    line1 = address_info.get("line1", "Address not provided")
    city = address_info.get("city", "City not provided")
    state = address_info.get("state", "State not provided")
    country = address_info.get("country", "Country not provided")
    
    # Display information
    print(f"Legal Name: {legal_name}, Legal Document: {legal_document}")
    print(f"Doing Business As: {doing_business_as}")
    print(f"Address: {line1}, {city}, {state}, {country}")

# Example usage
fetch_organization_info("cc15194a-6bc9-4ebb-b15d-43411a54ba4b")

In this example, get methods are used to safely access values. This allows for flexibility if new fields, such as phoneNumber, are introduced, as the code remains functional even if a field is absent.