Xero Contacts API Integration With Working Example.

This blog was written on 24 Nov 2021 and the example uses ASP.NET MVC, you can download the working example at GitHub.

The example site uses Xero.API.SDK version 2.2.9, Xero.NetStandards.OAuth2 version 3.20.0 and Xero.NetStandards.OAuth2Client version 1.5.1.

This blog is the second of three parts that will show you how to do the following:

If you are following along with this blog, you will have seen how to create an access token in part one. This blog carries on from that and I will show you how to create a new contact using the AccountingApi. These examples are designed to be simple so that beginners can easily follow along, so let's get started.

Contacts API

First let's create the view model of the data we want to add Xero contacts, the code for the view model is below.

namespace XeroIntergration.Models.Customer
{
    public class CustomerViewModel
    {
        public string EmployeeName              { get; set; }
        public string EmployeeEmail             { get; set; }
        public string CompanyName               { get; set; }
        public string CompanyAddress            { get; set; }
        public string CompanyCity               { get; set; }
        public string CompanyCounty             { get; set; }
        public string CompanyPostCode           { get; set; }
        public string CompanyCountry            { get; set; }
        public string CompanyPhoneCountryCode   { get; set; }
        public string CompanyPhoneAreaCode      { get; set; }
        public string CompanyPhoneNumber        { get; set; }
        public string CompanyFaxNumber          { get; set; }
        public string CompanyMobileNumber       { get; set; }
    }
}

You can see from the view model above that I'm only using a handful of the fields that can be used, for a full list you can view the xero api contacts documentation

The code for creating the new Xero API contact can be seen below.

public bool CreateNewCustomer(CustomerViewModel model)
        {
            bool doesXeroTokenFileExist = XeroConfigurationHelper.DoesXeroTokenFileExist();
            XeroClient client;

            if (doesXeroTokenFileExist)
            {
                try
                {
                    var token = XeroConfigurationHelper.RetrieveToken();

                    if (token == null) return false;

                    var xeroTokenExpires = token.ExpiresAtUtc;

                    if (DateTime.Now.ToUniversalTime() > xeroTokenExpires)
                    {
                        client              = new XeroClient(XeroConfigurationHelper.XeroConfiguration());
                        var refreshToken    = token;
                        token               = (XeroOAuth2Token)Task.Run(() => client.RefreshAccessTokenAsync(refreshToken)).Result;

                        XeroConfigurationHelper.StoreToken(token);
                    }

                    Guid customerId = Guid.NewGuid();

                    Address address = new Address
                    {
                        AddressLine1        = model.CompanyAddress,
                        City                = model.CompanyCity,
                        Region              = model.CompanyCounty,
                        PostalCode          = model.CompanyPostCode,
                        Country             = model.CompanyCountry,
                        AddressType         = Address.AddressTypeEnum.POBOX
                    };

                    List<Address> customerAddress = new List<Address> { address };

                    Phone phone = new Phone
                    {
                        PhoneCountryCode    = model.CompanyPhoneCountryCode,
                        PhoneAreaCode       = model.CompanyPhoneAreaCode,
                        PhoneNumber         = model.CompanyPhoneNumber,
                        PhoneType           = Phone.PhoneTypeEnum.DEFAULT
                    };

                    Phone fax = new Phone
                    {
                        PhoneCountryCode    = model.CompanyPhoneCountryCode,
                        PhoneAreaCode       = model.CompanyPhoneAreaCode,
                        PhoneNumber         = model.CompanyFaxNumber,
                        PhoneType           = Phone.PhoneTypeEnum.FAX
                    };

                    Phone mobile = new Phone
                    {
                        PhoneCountryCode    = model.CompanyPhoneCountryCode,
                        PhoneAreaCode       = model.CompanyPhoneAreaCode,
                        PhoneNumber         = model.CompanyMobileNumber,
                        PhoneType           = Phone.PhoneTypeEnum.MOBILE
                    };

                    List<Phone> phones = new List<Phone> { phone, fax, mobile };

                    var newCustomer = new Contact
                    {
                        ContactID       = customerId,
                        AccountNumber   = customerId.ToString(),
                        FirstName       = model.EmployeeName,
                        Name            = model.CompanyName,
                        EmailAddress    = model.EmployeeEmail,
                        Addresses       = customerAddress,
                        Phones          = phones,
                        IsCustomer      = true
                    };

                    var insertCustomer = new Contacts
                    {
                        _Contacts = new List<Contact>
                    {
                        newCustomer
                    }
                    };


                    var accountingApi = new AccountingApi();
                    var xeroResponse = Task.Run(() => accountingApi.CreateContactsAsync(token.AccessToken, token.Tenants[0].TenantId.ToString(), insertCustomer)).Result;

                    return true;
                }
                catch (Exception)
                {
                    return false;
                }

            }
            return false;
        }

As you can see from the code above, I'm checking if the access token exists, if it does I then check to see if its expiry date is greater than the current date-time.

I then create the address, phone types and then create the new contact via the Xero API accountingApi.CreateContactsAsync. If no errors are thrown, I return true, or false. The return value could be whatever you want to return.

Finally, in the controller, I have the following which just returns the message shown below.

[HttpPost]
        public ActionResult CreateCustomer(CustomerViewModel model)
        {
            IXeroBearerToken token = new XeroBearerToken();
            var xeroToken = token.CreateNewCustomer(model);

            ViewBag.Status = xeroToken ? "Customer Created Successfully" : "Failed to create customer";


            return View();
        }

Upon creating the new contact, you can log in to your Xero account and see the new contact created by the Xero API as the image below shows.

Xero Contacts

Display all Xero Contacts

So now that we have created the contact, how can we display all contacts on the website.

Again to achieve this, let's create a new view model.

namespace XeroIntergration.Models.Customer
{
    public class ListOfCustomers
    {
        public ListOfCustomers(string customerName, string customerId)
        {
            CustomerName    = customerName;
            CustomerId      = customerId;
        }

        public string CustomerName  { get; }
        public string CustomerId    { get; }
    }
}

Now add a new method with the following code:

public List GetCompanyNameAndId()
        {
            bool doesXeroTokenFileExist = XeroConfigurationHelper.DoesXeroTokenFileExist();
            XeroClient client;

            if (doesXeroTokenFileExist)
            {
                var token = XeroConfigurationHelper.RetrieveToken();

                if (token == null) return null;

                var xeroTokenExpires = token.ExpiresAtUtc;

                if (DateTime.Now.ToUniversalTime() > xeroTokenExpires)
                {
                    client              = new XeroClient(XeroConfigurationHelper.XeroConfiguration());
                    var refreshToken    = token;
                    token               = (XeroOAuth2Token)Task.Run(() => client.RefreshAccessTokenAsync(refreshToken)).Result;

                    XeroConfigurationHelper.StoreToken(token);
                }

                string accessToken  = token.AccessToken;
                string tenantId     = token.Tenants[0].TenantId.ToString();

                List customerList  = new List();
                AccountingApi accountingApi         = new AccountingApi();

                var xeroResponse = Task.Run(() => accountingApi.GetContactsAsync(accessToken: accessToken, xeroTenantId: tenantId, ifModifiedSince: null, where: null, order: null, iDs: null, page: 1, includeArchived: false, summaryOnly: false, searchTerm: null)).Result;

                foreach (var customer in xeroResponse._Contacts)
                {
                    customerList.Add(new ListOfCustomers(customer.Name, customer.ContactID.ToString()));
                }

                return customerList;
            }
            return null;
        }

And in the controller

[HttpGet]
        public ActionResult ListOfCustomers()
        {
            IXeroBearerToken token = new XeroBearerToken();
            var listOfCustomer = token.GetCompanyNameAndId();
            return View("~/Views/Contacts/ListOfCustomers.cshtml", listOfCustomer);
        }

Finally the view

@model List<XeroIntergration.Models.Customer.ListOfCustomers>
@{
    Layout = "~/Views/Shared/_Layout.cshtml";
}


<div class="container">
    <div class="row">
        <div class="col-md-8 mt-5">
            <h4>List Of Customers</h4>
            <p class="small">You would not really populate the list this way but its quick and easy</p>
            <select name="customers" id="customer" class="form-control">
                @foreach (var customer in Model)
                {
                    <option value="@customer.CustomerId">@customer.CustomerName</option>
                }
            </select>
        </div>
    </div>
</div>

And the end results will be a list of contacts as the image below shows.

Xero Contacts API Integration With Working Example

I hope you found this blog helpful, and don't forget you can download the full code from GitHub