```
public class LendingTIDOutboundIntegrationHelper {
    IntegrationBase iBase;
    public Map<String, Integration_Credential__mdt> creds;
    public LendingTIDOutboundIntegrationHelper() {
        iBase = new IntegrationBase();
        creds = new Map<String, Integration_Credential__mdt>();
        for(Integration_Credential__mdt cred : [SELECT ID, Http_Method__c, DeveloperName, Endpoint__c, HeaderMap__c, Password__c, Integration_Type__c, Username__c FROM Integration_Credential__mdt WHERE Integration_Type__c = 'Lending System']) {
            creds.put(cred.DeveloperName, cred);
        }
    }

    public LendingTIDOutboundIntegrationHelper(IntegrationBase iBase, Map<String, Integration_Credential__mdt> creds) {
        this.iBase = iBase;
        this.creds = creds;
    }

    public HttpResponse authenticateLendingSystem(Integration_Message__c im, Access_Tokens__c tokens) {
        AccessTokenWrapper wrapper = getAccessToken(im);
        if(wrapper.accessToken != null) {
            tokens.Lending_System_Access_Token__c = wrapper.accessToken;
            // call the actual service again
            im.Error_Description__c = null;
            im.Error_Code__c = null;
            Integration_Credential__mdt cred = creds.get(im.Parent_Template_Name__c);
            Map<String, Object> header = (Map<String, Object>) JSON.deserializeUntyped(cred.HeaderMap__c);
            header.put('access-token', tokens.Lending_System_Access_Token__c); //changed lending as per doc 1.2
            HttpResponse res = iBase.makeCalloutWithHeaderV2(im.Request_Envelope__c, cred.Http_Method__c, cred.Endpoint__c, header);
            return res;
        }
        return wrapper.resp;
    }

    @TestVisible private AccessTokenWrapper getAccessToken(Integration_Message__c im) {
        AccessTokenWrapper toReturn = new AccessTokenWrapper();
        // 1. get the credentials
        Integration_Credential__mdt cred = creds.get('Lending_Get_Access_Token');
        Map<String, Object> header = (Map<String, Object>) JSON.deserializeUntyped(cred.HeaderMap__c);
        
        // 2. call the access token api
        HttpResponse res = iBase.makeCalloutWithHeaderV2(null, cred.Http_Method__c, cred.Endpoint__c, header);
        toReturn.resp = res;
        System.debug(Logginglevel.DEBUG, 'response : ' + res.getBody() + ' Code : ' + res.getStatusCode());
        im.Login_Response_Envelope__c = res.getBody();
        
        // 3. parse the response and return access token
        Map<String, Object> response = (Map<String, Object>)JSON.deserializeUntyped(res.getBody());
        if(res.getStatusCode() == 200) {
            toReturn.accessToken = (String)response.get('token'); //changed lending as per doc 1.2
            return toReturn;
        } else {
            im.Error_Description__c = (String)response.get('error_description');
            im.Error_Code__c = res.getStatusCode() + ' ' + (String)response.get('error');
        }
        return toReturn;
    }

    public class AccessTokenWrapper {
        public String accessToken;
        public HttpResponse resp;
    }

    public class TIDStatusResponseWrapper {
        public List<TIDStatus> tIdStatus;
    }

    public class TIDStatus {
        public String tId, posId, status, remark, processingStatus;
    }
    
    public class Stage2KYCResponseWrapper {
        public List<DocStatus> docStatus;
    }

    public class DocStatus {
        public String docType, docId, status, remark, processingStatus;
    }
    
    public class BankReviewResponseWrapper{
        public String  processingRemarks, processingStatus, reqId;
    }
}
```