Adding and Updating Nested Entities
How to use objects in payloads to add and update nested entities.
Introduction
LoanPro's API uses JSON-formatted payloads. Those payloads contain objects that represent what we call ‘entities’, and some of those entities are nested within other entities. In this article, we'll explain how to use objects in your payloads to add and update entities.
How Nested Entities Work
Before we get too far, let's talk about how nested entities work. As we mentioned above, LoanPro's API uses JSON-formatted payloads. If you're familiar with LoanPro's API, you'll also know that most of our API requests that create or edit something use endpoints such as the Loans
endpoint and the Customers
endpoint. Both the Loans
and Customers
endpoints act as the parent entity for multiple, nested entities. For example, customer address information is held within a PrimaryAddress
entity, and a loan's collateral information is held with the Collateral
entity. Each of these nested entities—like Collateral
and PrimaryAddress
—are assigned their own IDs and are associated with the parent Loans or Customers
entity.
Let's look at an example of customer information in action. When you send a GET request for customer information, you'll receive a long response that's full of objects that represent each nested entity:
GET https://loanpro.simnang.com/api/public/api/1/odata.svc/Customers(1183)
{
"d": {
"metadata": {
"uri": "http://loanpro.simnang.com/api/public/api/1/odata.svc/Customers(id=1183)",
"type": "Entity.Customer"
},
"PrimaryAddress": {
"deferred": {
"uri": "Customers(id=1183)/PrimaryAddress"
}
},
"MailAddress": {
"deferred": {
"uri": "Customers(id=1183)/MailAddress"
}
},
"Employer": {
"deferred": {
"uri": "Customers(id=1183)/Employer"
}
},
"References": {
"deferred": {
"uri": "Customers(id=1183)/References"
}
},
"PaymentAccounts": {
"deferred": {
"uri": "Customers(id=1183)/PaymentAccounts"
}
},
"Phones": {
"deferred": {
"uri": "Customers(id=1183)/Phones"
}
},
"CustomFieldValues": {
"deferred": {
"uri": "Customers(id=1183)/CustomFieldValues"
}
},
"Documents": {
"deferred": {
"uri": "Customers(id=1183)/Documents"
}
},
"CreditScore": {
"deferred": {
"uri": "Customers(id=1183)/CreditScore"
}
},
"Loans": {
"deferred": {
"uri": "Customers(id=1183)/Loans"
}
},
"LineOfCredits": {
"deferred": {
"uri": "Customers(id=1183)/LineOfCredits"
}
},
"SocialProfiles": {
"deferred": {
"uri": "Customers(id=1183)/SocialProfiles"
}
},
"Notes": {
"deferred": {
"uri": "Customers(id=1183)/Notes"
}
},
"id": 1183,
"customId": null,
"mcId": 3874462,
"customerType": "customer.type.individual",
"status": "Active",
"firstName": "John",
"lastName": "Doe",
"middleName": null,
"birthDate": "/Date(0)/",
"gender": "customer.gender.male",
"generationCode": "customer.generationCode.none",
"email": "[email protected]",
"ssn": "XXXXX1010",
"driverLicense": null,
"companyName": null,
"contactName": null,
"customerIdType": "customer.idType.ssn",
"customerId": null,
"creditLimit": 0,
"accessUserName": "JohnDoe212",
"active": 1,
"ofacMatch": 0,
"ofacTested": 0,
"saleTransferPii": 1,
"passwordChanged": 0,
"hasAvatar": 0,
"loanRole": null,
"created": "/Date(1632417901)/",
"lastUpdate": "/Date(1677534526)/",
"creditScoreId": 213
}
}
You can also pull information that's stored within objects by including an $expand
pagination filter in the URL and listing the object's name. For example, here's how you could pull a customer's PrimaryAddress
information and how the response is formatted; pay attention to how the customer has an ID and the customer's address has its own, separate ID:
GET https://loanpro.simnang.com/api/public/api/1/odata.svc/Customers(1183)?$expand=PrimaryAddress
{
"d": {
"__metadata": {
"uri": "http://loanpro.simnang.com/api/public/api/1/odata.svc/Customers(id=1183)",
"type": "Entity.Customer"
},
"PrimaryAddress": {
"__metadata": {
"uri": "http://loanpro.simnang.com/api/public/api/1/odata.svc/Address(id=2554)",
"type": "Entity.Address"
},
"id": 2554,
"address1": "3844 20th Street",
"address2": null,
"city": "San Francisco",
"state": "geo.state.CA",
"zipcode": "94114",
"country": "company.country.usa",
"geoLat": "37.758198521738",
"geoLon": "-122.42684494282",
"created": "/Date(1632417901)/",
"active": 1,
"isVerified": 0,
"isStandardized": 0
},
"MailAddress": {
"__deferred": {
"uri": "Customers(id=1183)/MailAddress"
}
},
"Employer": {
"__deferred": {
"uri": "Customers(id=1183)/Employer"
}
},
"References": {
"__deferred": {
"uri": "Customers(id=1183)/References"
}
},
"PaymentAccounts": {
"__deferred": {
"uri": "Customers(id=1183)/PaymentAccounts"
}
},
"Phones": {
"__deferred": {
"uri": "Customers(id=1183)/Phones"
}
},
"CustomFieldValues": {
"__deferred": {
"uri": "Customers(id=1183)/CustomFieldValues"
}
},
"Documents": {
"__deferred": {
"uri": "Customers(id=1183)/Documents"
}
},
"CreditScore": {
"__deferred": {
"uri": "Customers(id=1183)/CreditScore"
}
},
"Loans": {
"__deferred": {
"uri": "Customers(id=1183)/Loans"
}
},
"LineOfCredits": {
"__deferred": {
"uri": "Customers(id=1183)/LineOfCredits"
}
},
"SocialProfiles": {
"__deferred": {
"uri": "Customers(id=1183)/SocialProfiles"
}
},
"Notes": {
"__deferred": {
"uri": "Customers(id=1183)/Notes"
}
},
"id": 1183,
"customId": null,
"mcId": 3874462,
"customerType": "customer.type.individual",
"status": "Active",
"firstName": "John",
"lastName": "Doe",
"middleName": null,
"birthDate": "/Date(0)/",
"gender": "customer.gender.male",
"generationCode": "customer.generationCode.none",
"email": "[email protected]",
"ssn": "XXXXX1010",
"driverLicense": null,
"companyName": null,
"contactName": null,
"customerIdType": "customer.idType.ssn",
"customerId": null,
"creditLimit": 0,
"accessUserName": "JohnDoe212",
"active": 1,
"ofacMatch": 0,
"ofacTested": 0,
"saleTransferPii": 1,
"passwordChanged": 0,
"hasAvatar": 0,
"loanRole": null,
"created": "/Date(1632417901)/",
"lastUpdate": "/Date(1677534526)/",
"creditScoreId": 213
}
}
Adding Information Stored in Nested Entities
When adding information stored in a nested entity for the first time, the entity's object is added to the payload of the request. This is more straightforward than it sounds. For example, let's say we've created a customer (who is represented by an ID of 1183
) but we haven't added phone information quite yet. This customer exists already but a phone number for the customer does not.
To add a phone number to the customer, we send a PUT request to the Customers endpoint and add the Phones object to our payload. Here's an example:
PUT https://loanpro.simnang.com/api/public/api/1/odata.svc/Customers(1183)
{
"Phones": {
"results": [
{
"phone": "5551234567",
"isPrimary": "1",
"isSecondary": "0",
"type": "customer.phoneType.cell",
"isLandLine": 0
}
]
}
}
Sending the request above successfully will add the phone to the customer's profile and provide an ID for the new phone number.
Updating Information Stored in Nested Entities
Updating information that's stored within nested entities requires a few things: the new information, an “__update”
field, and the ID of the nested entity.
As an example, let's edit the phone number we added above. This time around, we're going to change the number itself and set it as an office phone number instead of a cell phone. To achieve this, we'll need to add that new information to the payload of our request. Additionally, we'll also need to add the "__update": true
field to notify the system we're updating a nested entity, and we'll need to add an "__id"
field to tell the system which phone number we're updating.
Here's the request in full:
PUT https://loanpro.simnang.com/api/public/api/1/odata.svc/Customers(1183)
{
"Phones": {
"results": [
{
"phone": "5551230000",
"isPrimary": "0",
"isSecondary": "1",
"type": "customer.phoneType.office",
"isLandLine": 0,
"__update": true,
"__id": 797
}
]
}
}
A request formatted like above will update the customer's phone number information. Without the "__update": true
and "__id": 797
fields, the system would create a new phone number.
Common Questions
1. Do I also need to add the "__update"
and "__id"
fields to the payload outside of the nested object?
For example, like this:
PUT https://loanpro.simnang.com/api/public/api/1/odata.svc/Customers(1183)
{
"Phones": {
"results": [
{
"phone": "5551230000",
"isPrimary": "0",
"isSecondary": "1",
"type": "customer.phoneType.office",
"isLandLine": 0,
"__update": true,
"__id": 797
}
]
},
"__update": true,
"__id": 1183
}
You can, but it's not required and won't actually make a difference.
Some users add this information to tell the system to update the parent entity—such as a customer. But the method and endpoint of the request makes this additional payload information redundant: there's no need for the "__update"
field since the system knows a PUT request is updating something, and the system knows we're updating customer 1183
because that's listed within the endpoint.
In short, you don't need to add this information when updating a nested entity. But you can if it brings you peace of mind.
2. Can I update parent entity information and nested entity information in the same request?
You can, and here's an example of that in action:
PUT https://loanpro.simnang.com/api/public/api/1/odata.svc/Customers(1183)
{
"firstName": "Jonathan",
"birthDate": "1970-07-17",
"Phones": {
"results": [
{
"phone": "5551230000",
"isPrimary": "0",
"isSecondary": "1",
"type": "customer.phoneType.cell",
"isLandLine": 0,
"__update": true,
"__id": 797
}
]
},
"References": {
"results": [
{
"name": "Tony Doe",
"relation": "customerReference.relation.brother",
"Address": {
"country": "company.country.usa",
"address1": "2608 Sheridan Road",
"zipcode": "60201",
"city": "Evanston",
"state": "geo.state.IL",
"__update": true,
"__id": 3506
},
"primaryPhone": "2024456655",
"__update":true,
"__id": 245
}
]
}
}
This payload updated the following information:
- The customer's first name and birthdate (ID= 1183)
- The customer's phone number (ID = 797)
- The customer's reference's (ID=245) name, relation, phone number, address (ID= 3506)
Since the customer is the parent entity of this request (ID = 1183), we didn't add the "__update"
and "__id"
fields to update firstName
and birthDate
information. Though, those fields are required when updating the nested entities—like phone information, reference information, and (as an example of a nested entity within a nested entity) reference address information.
Updated 6 months ago