As you continue to develop the application example in JavaScript, we want to
  incorporate how to look at classes and their children. In the case of the
  fvCEp class, we can perform a class query and request the
  children of that object.
  Looking at the children of fvCEp is useful, because this is where
  the location of the endpoint in the fabric can be found. Specifically, the
  child object we're looking for is fvRsCEpToPathEp. What we need
  to do perform a class query for fvCEp and requesting its children
  objects be included in the response.
  If you remember this table from the API explanation section, we have various
  ways to query and filter the ACI fabric. In particular, we want the fvCEp
  object AND it's children. If you only use query-target=children, you
  would get the children of the object but not the object itself.
| Filter Type | Syntax | Description | 
|---|---|---|
| query-target | {self | children | subtree} | Define the scope of a query | 
| target-subtree-class | class name | Respond-only elements including the specified class | 
| query-target-filter | filter expressions | Respond-only elements matching conditions | 
| rsp-subtree | {no | children | full} | Specifies child object level included in the response | 
| rsp-subtree-class | class name | Respond only specified classes | 
| rsp-subtree-filter | filter expressions | Respond only classes matching conditions | 
| rsp-subtree-include | {faults | health :stats :…} | Request additional objects | 
| order-by | classname.property | {asc | desc} | Sort the response based on the property values | 
  Using the rsp-subtree query parameter returns the object and it's children.
  You might be asking, "What objects are the children of the fvCEp class?"
  For this, we can reference the ACI API documentation (you will see this in the lab reference section) in the APIC. Or
  if you query the
  object it will show you all that are configured.
  If you were to use POSTMAN to perform a query for the fvCEP class,
  you will notice not all these objects are returned back to you. This is because
  relationships are built as needed by the MIT based on the device types, interactions
  and other factors. For example one child of the fvCEp is fvIp,
  which only applies if this is a Layer 3 learned endpoint.
  For your code to request the children of fvCEp we have to pass
  the correct parameter in the URL request within the classQuery()function.
  Add the filter argument to the classQuery()function,
  and build a conditional statement to determine if a query string should be used
  in the request's URL. Then, expand the URL to use the value of queryString.
var creds = {
  url: 'https://10.0.226.43',
  name: 'aciproglab01',
  pwd: 'cisco.123',
  token: '',
  urlToken: ''
}
var endpoints = {};
function classQuery(classname, filter="") {
  queryString = "";
  if (filter == "children") {
    queryString = "?rsp-subtree=children";
  }
  return $.ajax({
    url: creds.url + '/api/node/class/' + classname + '.json' + queryString,
    headers: {
      'DevCookie': creds.token,
      'APIC-challenge': creds.urlToken,
      'Content-Type': 'application/json'
    }
  });
};
function login() {
  return $.ajax({
    type: 'POST',
    url: creds.url + '/api/aaaLogin.json?gui-token-request=yes',
    data: JSON.stringify({
      aaaUser: {
        attributes: {
          name: creds.name,
          pwd: creds.pwd
        }
      }
    }),
  });
};
function buildTableData(aci_endpoint_data) {
  table_data = []
  $.each(aci_endpoint_data['imdata'], function (i, endpoint) {
    row = [ endpoint.fvCEp.attributes.mac, endpoint.fvCEp.attributes.ip ];
    table_data.push(row);
  });
  return table_data;
}
$( document ).ready(function() {
  login().then(function (data) {
    var attrs = data['imdata'][0]['aaaLogin']['attributes'];
    creds.token = attrs['token'];
    creds.urlToken = attrs['urlToken'];
    classQuery('fvCEp').then(buildTableData).then(function(table_data){
      $("#endpoint-table").DataTable({
        data: table_data,
        columns: [
          {title: "MAC Address"},
          {title: "IP Address"}
        ]
      })
    });
  });
});
There are likely better ways to accomplish this, but this way allows for simplifcation and saving of time during the lab.
  The original buildTableData() function needs to be updated. We
  have to iterate through the returned child objects of the original object
  fvCEp to find a specific object which contains the location (path).
  This object is called fvRsCEpToPathEp, and is the Endpoint Path
  object associated with the endpoint.
  This is another area where optimization could be accomplished if there was
  more time in the lab. The request to the APIC could be constructed to return
  only specific children of an object chidren. Meaning the query could be constructed as
  /api/node/class/fvCEp.json?rsp-subtree=children&rsp-subtree-class=RsCEpToPathEp.
  This will cause the APIC to return only the children of fvCEp which are of
  type RsCEpToPathEp.
Below is an example of iterative code which extracts a particular class from returned object data.
var creds = {
  url: 'https://10.0.226.43',
  name: 'aciproglab01',
  pwd: 'cisco.123',
  token: '',
  urlToken: ''
}
var endpoints = {};
function classQuery(classname, filter="") {
  queryString = "";
  if (filter == "children") {
    queryString = "?rsp-subtree=children";
  }
  return $.ajax({
    url: creds.url + '/api/node/class/' + classname + '.json' + queryString,
    headers: {
      'DevCookie': creds.token,
      'APIC-challenge': creds.urlToken,
      'Content-Type': 'application/json'
    }
  });
};
function login() {
  return $.ajax({
    type: 'POST',
    url: creds.url + '/api/aaaLogin.json?gui-token-request=yes',
    data: JSON.stringify({
      aaaUser: {
        attributes: {
          name: creds.name,
          pwd: creds.pwd
        }
      }
    }),
  });
};
function buildTableData(aci_endpoint_data) {
  regex =  /tn-(\w*)\/ap-(\w*)\/epg-(\w*)\/cep-(\w*:\w*:\w*:\w*:\w*:\w*)/
  table_data = []
  $.each(aci_endpoint_data['imdata'], function (i, endpoint) {  // for each endpoint in the data
    var line_dn = regex.exec(endpoint.fvCEp.attributes.dn)
    if (line_dn) {
      var fabric_location = ""
      var ip_addr = ""
      var tenant = line_dn[1]
      var app_profile = line_dn[2]
      var epg = line_dn[3]
      $.each(endpoint.fvCEp.children, function (x, endpoint_child){
        // This JavaScript code simply takes each object of the return data from the APIC and is grabing the 
        // children objects and processing them as the variable endpoint_child
        if (endpoint_child.fvRsCEpToPathEp) {  // check if there's a path attribute
          fabric_location = endpoint_child.fvRsCEpToPathEp.attributes.tDn;  // if so, set the location
        }                                                                   // from the child object (fvRsCEpToPathEp)
        if (endpoint_child.fvIp) { // check if there is an IP address object associated to the endpoint
          ip_addr = endpoint_child.fvIp.attributes.addr;
        }
      });
      row = [ endpoint.fvCEp.attributes.mac, ip_addr, tenant, app_profile, epg, fabric_location ];  // build a row containing the endpoint's IP and MAC
      table_data.push(row);  // then add this entry to the end of the array
    };
    });
  return table_data;
}
$( document ).ready(function() {
  login().then(function (data) {
    var attrs = data['imdata'][0]['aaaLogin']['attributes'];
    creds.token = attrs['token'];
    creds.urlToken = attrs['urlToken'];
    classQuery('fvCEp').then(buildTableData).then(function(table_data){
      $("#endpoint-table").DataTable({
        data: table_data,
        columns: [
          {title: "MAC Address"},
          {title: "IP Address"}
        ]
      })
    });
  });
});
  We can't forget to modify the classQuery() call in
  document.ready() to send the children parameter and update the
  DataTable column format with our third column.
var creds = {
  url: 'https://10.0.226.43',
  name: 'aciproglab01',
  pwd: 'cisco.123',
  token: '',
  urlToken: ''
}
var endpoints = {};
function classQuery(classname, filter="") {
  queryString = "";
  if (filter == "children") {
    queryString = "?rsp-subtree=children";
  }
  return $.ajax({
    url: creds.url + '/api/node/class/' + classname + '.json' + queryString,
    headers: {
      'DevCookie': creds.token,
      'APIC-challenge': creds.urlToken,
      'Content-Type': 'application/json'
    }
  });
};
function login() {
  return $.ajax({
    type: 'POST',
    url: creds.url + '/api/aaaLogin.json?gui-token-request=yes',
    data: JSON.stringify({
      aaaUser: {
        attributes: {
          name: creds.name,
          pwd: creds.pwd
        }
      }
    }),
  });
};
function buildTableData(aci_endpoint_data) {
  regex =  /tn-(\w*)\/ap-(\w*)\/epg-(\w*)\/cep-(\w*:\w*:\w*:\w*:\w*:\w*)/
  table_data = []
  $.each(aci_endpoint_data['imdata'], function (i, endpoint) {  // for each endpoint in the data
    var line_dn = regex.exec(endpoint.fvCEp.attributes.dn)
    if (line_dn) {
      var fabric_location = ""
      var ip_addr = ""
      var tenant = line_dn[1]
      var app_profile = line_dn[2]
      var epg = line_dn[3]
      $.each(endpoint.fvCEp.children, function (x, endpoint_child){
        // This JavaScript code simply takes each object of the return data from the APIC and is grabing the 
        // children objects and processing them as the variable endpoint_child
        if (endpoint_child.fvRsCEpToPathEp) {  // check if there's a path attribute
          fabric_location = endpoint_child.fvRsCEpToPathEp.attributes.tDn;  // if so, set the location
        }                                                                   // from the child object (fvRsCEpToPathEp)
        if (endpoint_child.fvIp) { // check if there is an IP address object associated to the endpoint
          ip_addr = endpoint_child.fvIp.attributes.addr;
        }
      });
      row = [ endpoint.fvCEp.attributes.mac, ip_addr, tenant, app_profile, epg, fabric_location ];  // build a row containing the endpoint's IP and MAC
      table_data.push(row);  // then add this entry to the end of the array
    };
    });
  return table_data;
}
$( document ).ready(function() {
  login().then(function (data) {
    var attrs = data['imdata'][0]['aaaLogin']['attributes'];
    creds.token = attrs['token'];
    creds.urlToken = attrs['urlToken'];
    classQuery('fvCEp','children').then(buildTableData).then(function(table_data){
      $("#endpoint-table").DataTable({
        data: table_data,
        columns: [
          {title: "MAC Address"},
          {title: "IP Address"},
          {title: "Tenant"},
          {title: "App Profile"},
          {title: "EPG"},
          {title: "Location"}
        ]
      })
    });
  });
});
The updated table should now contain location of the endpoints.
