June 16, 2023
In this tutorial we will learn about What is NinjaRMM and How we can call the NinjaRMM API's.
After completing this unit, you will be able to:
1. What is NinjaRMM
2. Use NinjaRMM API to Create Salesforce Data.
1. What is NinjaRMM
NinjaRMM is a remote monitoring and management (RMM) platform designed for IT professionals to efficiently monitor and manage their clients' endpoints, such as computers, servers, and network devices. It provides features like device monitoring, patch management, antivirus, remote access, scripting, and reporting, allowing IT teams to proactively handle their infrastructure.
Integrating NinjaRMM with Salesforce can help streamline IT operations and enhance customer support. By integrating the two systems, you can consolidate information, automate workflows, and gain better visibility into your clients' IT infrastructure from within Salesforce.
2. Use NinjaRMM API to Create Salesforce Data
In this tutorial we will use "/api/v2/devices-detailed" api of NinjarRMM in salesforce. To use NinjaRMM api's with salesforce, we need to follow the steps listed below:
1. Obtain API credentials: To access the NinjaRMM API, you'll need valid API credentials, typically consisting of an API key or token. Consult the NinjaRMM API documentation or contact their support for guidance on generating API credentials.
2. Authenticate and obtain an access token: The first step is to authenticate with the NinjaRMM API to obtain an access token. This token will be used for subsequent API requests. Refer to the NinjaRMM API documentation for the authentication process and the required endpoints.
3. Prepare Salesforce data: Determine the data you want to create in Salesforce and ensure it is in the appropriate format. This may include information such as contacts, accounts, leads, opportunities, or custom objects. Prepare the data in a structured manner, adhering to the Salesforce object schema.
4. Construct the API request: Construct an HTTP request to create the desired Salesforce data. This request should include the necessary headers, including the access token obtained from the previous step, and the payload containing the data to be created.
5. Send the API request: Send the constructed API request to the Salesforce API endpoint responsible for creating the specific data object. In this blog we will create Account and Asset records in salesforce using NinjaRMM endpoint. This endpoint typically follows the format https://your-salesforce-instance.com/services/data/vXX.X/sobjects/Object_Name/, where Object_Name corresponds to the Salesforce object you want to create.
The code snippet for the call NinjaRMM API in Salesforce Batch class. Create new apex batch named NinjaRMMBatch and paste the code with below snippet:
public class NinjaRMMBatch implements Database.Batchable<String>, Database.Stateful, Database.AllowsCallouts {Integer afterIndex;Integer pageSize;Boolean hasMoreRecords;public NinjaRMMBatch(Integer index, Integer pageSize1){afterIndex = index;pageSize = pageSize1;}public Iterable<String> start(Database.BatchableContext bc){return new List<String>{'test'};}public void execute(Database.BatchableContext bc, List<String> scope){Integer index = fetchData(pageSize, afterIndex);afterIndex = index;System.debug('index = ' +index);}public void finish(Database.BatchableContext bc){System.Debug(' hasMoreRecords ' + hasMoreRecords);System.Debug(' afterIndex ' + afterIndex);System.Debug(' pageSize ' + pageSize);if(!Test.isRunningTest()){if(hasMoreRecords == true && hasMoreRecords != null && afterIndex != 0){Database.executeBatch(new NinjaRMMBatch(afterIndex, pageSize));}}}public Integer fetchData(Integer pageSize, Integer afterIndex){hasMoreRecords = false;List<Asset> assetList = new List<Asset>();List<Account> orgAccList = new List<Account>();List<Account> locAccList = new List<Account>();Map<String, Model__c> mapNameModelObj = new Map<String, Model__c>();Map<String, Id> mapupsertedorgAccId_Id = new Map<String, Id>();Map<String, Id> maplocupsertedAccExternalId_Id = new Map<String, Id>();Map<String, Id> mapupsertedModelName_Id = new Map<String, Id>();Http http = new Http();HttpRequest req = new HttpRequest();req.setMethod('GET');req.setTimeout(120000);req.setEndpoint('callout:NinjaRMM_NC/v2/devices-detailed?expand=organization,location,role&pageSize=' +pageSize+ '&after=' +afterIndex);HTTPResponse res = http.send(req);String responseBody = res.getBody();System.debug('responseBody = ' +responseBody);List<Object> str1 = (List<Object>)JSON.deserializeUntyped(responseBody);if(str1.size() > 0){hasMoreRecords = true;}else{return 0;}Map<String, Object> item = new Map<String, Object>();Set<String> uniqueAccount = new Set<String>();Set<String> uniqueLocation = new Set<String>();Set<String> uniqueModel = new Set<String>();Set<String> uniqueAsset = new Set<String>();System.debug('hasMoreRecords = ' +hasMoreRecords);for(Object itemObj : str1) {item = (Map<String, Object>) itemObj;Map<String, Object> systemValue = new Map<String, Object>();systemValue = (Map<String, Object>) item.get('system');Map<String, Object> referencesValue = new Map<String, Object>();referencesValue = (Map<String, Object>) item.get('references');Map<String, Object> locationValue = new Map<String, Object>();locationValue = (Map<String, Object>) referencesValue.get('location');Map<String, Object> organizationValue = new Map<String, Object>();organizationValue = (Map<String, Object>) referencesValue.get('organization');String modelName = systemValue != null && systemValue.size() > 0 && systemValue.get('model') != null && systemValue.get('model') != '' ? String.ValueOf(systemValue.get('model')) : null;if(modelName != null && modelName != '' && modelName.trim() != ''){if(!uniqueModel.contains(modelName.toLowerCase())){Model__c md = new Model__c(Name = modelName, Model_ID__c = modelName);mapNameModelObj.put(modelName, md);uniqueModel.add(modelName.toLowerCase());}}if(!uniqueAccount.contains(String.ValueOf(organizationValue.get('id')))){Account orgAccount = new Account(Name = String.ValueOf(organizationValue.get('name')),OrganizationId__c = String.ValueOf(organizationValue.get('id')));orgAccList.add(orgAccount);uniqueAccount.add(String.ValueOf(organizationValue.get('id')));}}String orgErrorBody = '';Database.UpsertResult[] orgAccResults = Database.upsert(orgAccList, Account.Fields.OrganizationId__c, false);System.debug('orgAccResults = ' +orgAccResults);Boolean isError = false;for(Integer i=0;i<orgAccList.size(); i++){Database.UpsertResult s = orgAccResults[i];Account accRec = orgAccList[i];if(!s.isSuccess()) {for (Database.Error exd : s.getErrors()){isError = true;System.debug('orgId = ' +accRec.Id + 'orgName = ' +accRec.Name + 'orgExternalId = ' +accRec.OrganizationId__c);orgErrorBody += '<br/> Id: ' + accRec.OrganizationId__c + ' , ' +' Name: '+accRec.Name + ' Exception ' + exd.getMessage();}}}if(isError == true){String orgHeading = '<b> Organization Account Failed : </b>';orgErrorBody = orgHeading + orgErrorBody;isError = false;}Database.UpsertResult[] modelResults = Database.upsert(mapNameModelObj.values(), Model__c.Fields.Model_ID__c, true);for(Account acc : [Select Name, OrganizationId__c from Account]){mapupsertedorgAccId_Id.put(acc.OrganizationId__c, acc.Id);}for(Model__c md : [Select Name, Model_ID__c from Model__c]){mapupsertedModelName_Id.put(md.Name, md.Id);}for(Object itemObj : str1) {item = (Map<String, Object>) itemObj;Map<String, Object> referencesValue = new Map<String, Object>();referencesValue = (Map<String, Object>) item.get('references');Map<String, Object> locationValue = new Map<String, Object>();locationValue = (Map<String, Object>) referencesValue.get('location');Map<String, Object> organizationValue = new Map<String, Object>();organizationValue = (Map<String, Object>) referencesValue.get('organization');if(!uniqueLocation.contains(String.ValueOf(locationValue.get('id')))){Account locAccount = new Account(Name = String.ValueOf(locationValue.get('name')),ParentId = mapupsertedorgAccId_Id.get(String.ValueOf(organizationValue.get('id'))),Location_Id__c = String.ValueOf(locationValue.get('id')));locAccList.add(locAccount);uniqueLocation.add(String.ValueOf(locationValue.get('id')));}}Database.UpsertResult[] locAccResults = Database.upsert(locAccList, Account.Fields.Location_Id__c, false);System.debug('locAccResults = ' +locAccResults);System.debug('locAccList = ' +locAccList);for(Integer i=0;i<locAccList.size(); i++){Database.UpsertResult s = locAccResults[i];Account accRec = locAccList[i];if(!s.isSuccess()) {for (Database.Error exd : s.getErrors()){isError = true;System.debug('locId = ' +accRec.Id + 'locName = ' +accRec.Name + 'locExternalId = ' +accRec.Location_Id__c);orgErrorBody += '<br/> Id: ' + accRec.Location_Id__c + ' , ' +' Name: '+accRec.Name + ' Exception ' +exd.getMessage();}}}if(isError == true){String locHeading = '<br/> <br/> <b> Location Account Failed : </b>';orgErrorBody = locHeading + orgErrorBody;isError = false;}for(Account acc : [Select Name, Location_Id__c from Account]){maplocupsertedAccExternalId_Id.put(acc.Location_Id__c, acc.Id);}Map<String, String> mapSerialNumberId = new Map<String, String>();for(Asset ast : [select SerialNumber, Id from Asset]){mapSerialNumberId.put(ast.SerialNumber, ast.Id);}for(Integer i=0;i< str1.size(); i++) {System.debug('str1 size : ' +str1.size());Object itemObj = str1[i];item = (Map<String, Object>) itemObj;Map<String, Object> systemValue = new Map<String, Object>();systemValue = (Map<String, Object>) item.get('system');Map<String, Object> referencesValue = new Map<String, Object>();referencesValue = (Map<String, Object>) item.get('references');Map<String, Object> roleValue = new Map<String, Object>();roleValue = (Map<String, Object>) referencesValue.get('role');Map<String, Object> organizationValue = new Map<String, Object>();organizationValue = (Map<String, Object>) referencesValue.get('organization');//organizationValue this will go into account.Map<String, Object> locationValue = new Map<String, Object>();locationValue = (Map<String, Object>) referencesValue.get('location');if(String.ValueOf(item.get('systemName')) != '' && String.ValueOf(item.get('systemName')) != null ){Asset ass = new Asset();ass.Configuration_ID__c = String.ValueOf(item.get('id'));ass.Name = String.ValueOf(item.get('systemName'));ass.Type__c = String.ValueOf(roleValue.get('name'));ass.Organization_Account__c = mapupsertedorgAccId_Id.get(String.ValueOf(organizationValue.get('id')));ass.AccountId = maplocupsertedAccExternalId_Id.get(String.ValueOf(locationValue.get('id')));if(systemValue != null && systemValue.size() > 0){String modelName = systemValue.get('model') != null && systemValue.get('model') != '' ? String.ValueOf(systemValue.get('model')) : null;if(modelName != null && modelName != '' && modelName.trim() != ''){ass.Model__c = mapupsertedModelName_Id.get(modelName);}String serialNumber = systemValue.get('serialNumber') != null && systemValue.get('serialNumber') != '' ? String.ValueOf(systemValue.get('serialNumber')) : null;if(serialNumber != null && serialNumber != '' && serialNumber.trim() != ''){ass.SerialNumber = serialNumber;if(mapSerialNumberId.get(ass.SerialNumber) != null){ass.id = mapSerialNumberId.get(ass.SerialNumber);}}}assetList.add(ass);}System.debug('str1.size()-1 = ' +(str1.size()-1));if(i==str1.size()-1){afterIndex = Integer.ValueOf(item.get('id'));System.debug('afterIndex = ' +afterIndex);}}List<Asset> assetRecord = new List<Asset>();Database.UpsertResult[] assetResults = Database.upsert(assetList, false);System.debug('assetResults = ' +assetResults);List<Asset> getAssets = [Select Id, Name, Configuration_ID__c from Asset where Id IN : assetList];System.debug('assetList = ' +assetList);System.debug('getAssets = ' +getAssets);for(Integer i=0;i<assetList.size(); i++){Database.UpsertResult s = assetResults[i];Asset ast = assetList[i];if(!s.isSuccess()) {for (Database.Error exd : s.getErrors()){isError = true;System.debug('assetd = ' +ast.Id + 'assetName = ' +ast.Name + 'assetExternalId = ' +ast.Configuration_ID__c);orgErrorBody += '<br/> Id: ' + ast.Configuration_ID__c + ' , ' +' Name: '+ast.Name + ' , Exception ' + exd.getMessage();}}}if(isError == true){String assetHeading = '<br/> <br/> <b> Asset Record Failed : </b>';orgErrorBody = assetHeading + orgErrorBody;isError = false;}System.debug('afterIndex = ' +afterIndex);if(orgErrorBody != null && orgErrorBody != ''){sendEmail('Asset Sync Process Failed', orgErrorBody);}return afterIndex;}public void sendEmail(String emailSubject, String emailBody){System.Debug('emailBody ' + emailBody);Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage();mail.setTargetObjectId( UserInfo.getUserId() );mail.setSaveAsActivity(false);mail.setSubject(emailSubject);mail.setHtmlBody(emailBody);Messaging.SendEmailResult[] results = Messaging.sendEmail( new Messaging.SingleEmailMessage[] { mail } );if (results[0].success){System.debug('The email was sent successfully.' + results);} else{System.debug('results ' + results);}}}
I hope this blog helped you!