After taking my first steps into integrating services with Microsoft Dynamics 365 I have learnt a thing or two about the service and feel I should share them. The first thing I'm going to go through is how to update a navigational property of an entity using the provided Web API. I am going to assume you know how to access the API and have an token as that is a whole other guide!

So, first of all, you need to find the list of properties available through the API for the entity you are working with. Head into Dynamics 365 and navigate to the Customisations screen under Settings. Here you will find a section called "Instance Web API" where there will be a link to Download OData Metadata. Once you have downloaded the OData Metadata XML file, open it up in your favourite editor and find your desired entity. I'll be working on the Quote entity in this example so I searched for; 

entityset name="quotes"

This gave me a set of NavigationPropertyBinding elements that contained the property you will be able to set in the API. I am looking to set the Customer on the Quote so I found the property in the XML;

<NavigationPropertyBinding Path="Quote_DuplicateMatchingRecord" Target="duplicaterecords"/>
<NavigationPropertyBinding Path="customerid_account" Target="accounts" />
<NavigationPropertyBinding Path="quote_activity_parties" Target="activityparties" />

Now we know what we're setting we can build a HTTP request to update an existing record. The changes are sent in the body as JSON like follows;

PATCH [Organization URI]/api/data/v8.2/quotes(00000000-0000-0000-0000-000000000001) HTTP/1.1
Content-Type: application/json
Accept: application/json
OData-MaxVersion: 4.0
OData-Version: 4.0
{ "customerid_account":"00000000-0000-0000-0000-000000000002" }

The problem is, if you were to send an update setting this property like that you would get an error. Whilst with normal data (such as name etc.) it would be fine, due to it being a value pointing to another entity you need to make a couple of modifications to your data to match a format like follows;

"customerid_account@odata.bind":"/accounts(00000000-0000-0000-0000-000000000002)"

So, let's break this down. First of all, the @odata.bind indicates that we are setting a navigational property. Then there is the entity name that we are setting (in this case, "accounts" - this can be found in the Target attribute of the NavigationPropertyBinding in the XML). Finally, the identifier ("accountid" on an Account entity) of the account in brackets is the identifier of the record you would like to set the customerid_account property to.

Assuming everything went ok, you will get back a result similar to below;

HTTP/1.1 204 No Content
OData-Version: 4.0

If there is an error with the request, you will get a different response with a body containing the error message, otherwise everything is successful. A response code 204 is used when the record is updated, if the record is created (you did a POST instead of PATCH) you will get a 201 response code.