Host Zendrive API Wrappers

When integrating Zendrive IQL APIs into your application ecosystem, allowing direct communication between your frontend or mobile applications and the Zendrive IQL server might introduce potential vulnerabilities or unintended data exposures. To mitigate these risks, it's advisable to establish a proxy backend or incorporate wrapper APIs within your existing backend infrastructure. By doing so, you can centralize and enhance the security measures. Specifically, we recommend that all API requests targeting the Zendrive IQL backend are first routed through your backend. This way, you can validate and authenticate these requests, ensuring an added layer of security and significantly reducing potential threats.

Here are the APIs that need to be integrated with the Zendrive IQL system:

Use the driverInfo API endpoint to upload or update driver information to the backend. Below is sample code for writing a wrapper for driverInfo API.

Python
IQL_DRIVER_INFO_ENDPOINT = '{}/iql/v1/driver/{}/info'
def update_driver_info(request, *args, **kwargs):
    try:
        # Extracting driver_id.
        driver_id = kwargs['driver_id']

        # Retrieving API key and endpoint specific to the driver.
        api_key, iql_endpoint = get_api_key_endpoint()

        # Authenticating the driver on your side.
        driver = User.objects.get(driver_id=driver_id)
        authenticate(driver, request)
        
        iql_response = requests.put(
            IQL_DRIVER_INFO_ENDPOINT.format(iql_endpoint, driver_id),
            json=request.data,
            headers={'Authorization': 'APIKEY {}'.format(api_key)})
        return get_response(iql_response)

    except User.DoesNotExist:
        return Response({'message': 'Provided driver_id does not exist'},
                        status=status.HTTP_400_BAD_REQUEST)
    except Exception as e:
        return Response({'message': e.detail}, status=e.status_code)

The supportedStateDetails API endpoint informs the publisher whether a user qualifies for an IQL test drive or not. The input that the Publisher receives from this endpoint helps them make an informed decision on allowing a user into the IQL test drive.

Below is sample code for writing a wrapper for supportedStateDetails API.

Python
IQL_SUPPORTED_STATE_DETAILS_ENDPOINT = '{}/iql/v1/supported_state_details'

def get_supported_state_details(request):
    api_key = settings.IQL_API_KEY
    try:
        authenticate(None, request)
        iql_response = requests.post(
            IQL_SUPPORTED_STATE_DETAILS_ENDPOINT,
            json=request.data,
            headers={'Authorization': 'APIKEY {}'.format(api_key)})

        return get_response(iql_response)

    except User.DoesNotExist:
        return Response({'message': 'Not a valid authorization token'},
                        status=status.HTTP_400_BAD_REQUEST)

Use the driverStatus endpoint to get basic user information from the selected start date to the present date. The start date has to be within 180 days from the present date.

Below is sample code for writing a wrapper for driverStatus API.

Python
IQL_STATUS_ENDPOINT = '{}/iql/v1/driver/{}/status'
def get_driver_status(request, *args, **kwargs):
    try:
        # Extracting driver_id.
        driver_id = kwargs['driver_id']

        # Retrieving API key and endpoint specific to the driver.
        api_key, iql_endpoint = get_api_key_endpoint()

        # Authenticating the driver on your side.
        driver = User.objects.get(driver_id=driver_id)
        authenticate(driver, request)

        # Making a GET request to the IQL driver status endpoint.
        iql_response = requests.get(
            IQL_STATUS_ENDPOINT.format(iql_endpoint, driver_id),
            params=request.GET,
            headers={'Authorization': 'APIKEY {}'.format(api_key)})

        # Processing the response received from the API call.
        return get_response(iql_response)

    except User.DoesNotExist:
        # Handling the case where the driver does not exist on your side.
        return Response({'message': 'This driver does not exist'},
                        status=status.HTTP_400_BAD_REQUEST)
    except Exception as e:
        # Handling other general exceptions.
        return Response({'message': e.detail}, status=e.status_code)

# Note: Functions get_api_key_endpoint and get_response defined
# in the section below called Utility Functions.

The driverTrips API is an IQL Server API, which allows customers to fetch driver trips, and trip information such as trip start location, trip end location, trip distance, trip highway distance, score, and event ratings.

Below is sample code for writing a wrapper for driverTrips API.

Python
IQL_DRIVER_TRIPS_ENDPOINT = '{}/iql/v1/driver/{}/trips'

def get_trips(request, *args, **kwargs):
    try:
        # Extracting driver_id.
        driver_id = kwargs['driver_id']

        # Retrieving API key and endpoint from settings.
        api_key, iql_endpoint = get_api_key_endpoint()

        # Authenticating the driver on your side.
        driver = User.objects.get(driver_id=driver_id)
        authenticate(driver, request)

        # Making a GET request to the IQL endpoint.
        iql_response = requests.get(
            IQL_DRIVER_TRIPS_ENDPOINT.format(iql_endpoint, driver_id),
            params=request.GET,
            headers={'Authorization': 'APIKEY {}'.format(api_key)})

        # Processing the response received from the API call.
        return get_response(iql_response)
        
    except User.DoesNotExist:
        return Response({'message': 'This driver does not exist'},
                        status=status.HTTP_400_BAD_REQUEST)
    except Exception as e:
        return Response({'message': e.detail}, status=e.status_code)

# Note: Functions get_api_key_endpoint and get_response defined
# in the section below called Utility Functions.

The tripFeedback API endpoint is used to mark the specific trip as invalid for the IQL program.

Below is sample code for writing a wrapper for tripFeedback API.

Python
# Endpoint format for updating trip feedback.
POST_TRIP_FEEDBACK_ENDPOINT = '{}/iql/v1/driver/{}/trip/{}/feedback'

def post_trip_feedback(request, *args, **kwargs):
    try:
        # Extracting driver_id and trip_id.
        driver_id = kwargs['driver_id']
        trip_id = kwargs['trip_id']

        # Retrieving API key and endpoint from settings.
        api_key, iql_endpoint = get_api_key_endpoint()
        
        # Authenticating the driver on your side.
        driver = User.objects.get(driver_id=driver_id)
        authenticate(driver, request)

        # Making a POST request to the IQL endpoint with the required data.
        iql_response = requests.post(
            POST_TRIP_FEEDBACK_ENDPOINT.format(iql_endpoint, driver_id, trip_id),
            json=request.data,
            headers={'Authorization': 'APIKEY {}'.format(api_key)})

        # Processing the response received from the API call.
        return get_response(iql_response)    
    except User.DoesNotExist:
        return Response({'message': 'This driver does not exist'},
                        status=status.HTTP_400_BAD_REQUEST)
    except Exception as e:
        return Response({'message': e.detail}, status=e.status_code)
        
# Note: Functions get_api_key_endpoint and get_response defined
# in the section below called Utility Functions.

AdUnit (GET)

Use the adUnit endpoint to fetch the insurance advertisement unit to be shown to the user.

Below is sample code for writing a wrapper for adUnit API.

Python
IQL_AD_UNIT_V2_ENDPOINT = '{}/iql/v2/ad_unit/{}'
def get_ad_unit_v2(request, *args, **kwargs):
    try:
        # Extracting driver_id and trip_id.
        driver_id = kwargs['driver_id']
        trip_id = kwargs['trip_id']

        # Retrieving API key and endpoint from settings.
        api_key, iql_endpoint = get_api_key_endpoint()
        
        # Authenticating the driver on your side.
        driver = User.objects.get(driver_id=driver_id)
        authenticate(driver, request)

        iql_response = requests.get(
            IQL_AD_UNIT_V2_ENDPOINT.format(iql_endpoint, driver_id),
            params=request.GET,
            headers={'Authorization': 'APIKEY {}'.format(api_key)})
        status.is_success(iql_response.status_code)

        return get_response(iql_response)

    except User.DoesNotExist:
        return Response({'message': 'This driver does not exist'},
                        status=status.HTTP_400_BAD_REQUEST)
    except Exception as e:
        return Response({'message': e.detail}, status=e.status_code)
# Note: Functions get_api_key_endpoint and get_response defined
# in the section below called Utility Functions.

Use the tripScore endpoint to fetch the details of the trips such as info, path, events.

Below is sample code for writing a wrapper for tripScore API.

Python
TRIP_DETAILS_ENDPOINT = '{}/iql/v1/driver/{}/trip/{}'
def get_trip_details(request, *args, **kwargs):
    try:
        # Extracting driver_id and trip_id.
        driver_id = kwargs['driver_id']
        trip_id = kwargs['trip_id']

        # Retrieving API key and endpoint from settings.
        api_key, iql_endpoint = get_api_key_endpoint()
        
        # Authenticating the driver on your side.
        driver = User.objects.get(driver_id=driver_id)
        authenticate(driver, request)
        
        # Making a GET request to the IQL to get trip details.
        response = requests.get(
            TRIP_DETAILS_ENDPOINT.format(iql_endpoint, driver_id,
                                                  trip_id),
            params=request.GET,
            headers={'Authorization': 'APIKEY {}'.format(api_key)})

        # Processing the response received from the API call.
        return get_response(response)

    except User.DoesNotExist:
        return Response({'message': 'This driver does not exist'},
                        status=status.HTTP_400_BAD_REQUEST)
    except Exception as e:
        return Response({'message': e.detail}, status=e.status_code)
        
# Note: Functions get_api_key_endpoint and get_response defined
# in the section below called Utility Functions.

Use the multi-offer endpoint to fetch multiple insurance offers to be shown to the user.

Below is sample code for writing a wrapper for multi-offer API.

Python
IQL_MULTI_OFFER_ENDPOINT = '{}/iql/v1/ads/driver_id/{}'
def get_multi_offer(request, *args, **kwargs):
    try:
        # Extracting driver_id
        driver_id = kwargs['driver_id']

        # Retrieving API key and endpoint from settings.
        api_key, iql_endpoint = get_api_key_endpoint()
        
        # Authenticating the driver on your side.
        driver = User.objects.get(driver_id=driver_id)
        authenticate(driver, request)
        
        # Making a GET request to the IQL to get multi offer.
        response = requests.get(
            IQL_MULTI_OFFER_ENDPOINT.format(iql_endpoint, driver_id),
            params=request.GET,
            headers={'Authorization': 'APIKEY {}'.format(api_key)})
        status.is_success(response.status_code)
        
        # Processing the response received from the API call.
        return get_response(response)

    except User.DoesNotExist:
        return Response({'message': 'This driver does not exist'},
                        status=status.HTTP_400_BAD_REQUEST)
    except Exception as e:
        return Response({'message': e.detail}, status=e.status_code)

# Note: Functions get_api_key_endpoint and get_response defined
# in the section below called Utility Functions.

Utility Functions

Python
def get_api_key_endpoint():
    # Returns the IQL API key and endpoint from the settings.
    return settings.IQL_API_KEY, settings.IQL_ENDPOINT

def get_response(response):
    # Checking the status code of the response to determine the next steps.
    if status.is_success(response.status_code) or status.is_client_error(response.status_code):
        # If the response indicates success or client error, return the response as is.
        return Response(response.json(), status=response.status_code)
    elif status.is_server_error(response.status_code):
        # If the response indicates server error, return a custom message.
        return Response(json={'message': "Server error"}, status=response.status_code)
    else:
        # For all other cases, return a generic HttpResponse.
        return HttpResponse(response)

Recommendations:

  • Avoid Unnecessary Modifications: Unless there's a compelling need, refrain from altering the content of requests and responses. Such changes could lead to unexpected behaviors or inconsistencies with how ZendriveIQLUIKit operates.

  • Endpoint Structure Preservation: It is advisable to mirror the endpoint structures of Zendrive IQL. This practice makes your proxy backend essentially transparent from a developmental standpoint, simplifying integration and troubleshooting.

Last updated