Xero Create Invoice API 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 third of three parts that will show you how to do the following:

If you have been following along with the last two blogs about the Xero API, you will have learned how to create an access token and also create a contact via the API.

In the final part of this series, I will show you how to create an invoice and also send the invoice via email from Xero using the EmailInvoiceAsync method.

So as usual, let get cracking, first, we need to create our view model as shown below.

using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Web.Mvc;

namespace XeroIntergration.Models.Customer
{
    public class InvoiceCustomer
    {
        public List ListOfCustomers { get; set; }
        [Display(Name = "List Of Customers")]
        public string Customers                     { get; set; }
        [Display(Name = "Description")]
        public string Description                   { get; set; }
        [Display(Name = "Quantitys")]
        public int Quantity                         { get; set; }
        [Display(Name = "Price Per Unit")]
        public decimal UnitAmount                   { get; set; }
        [Display(Name = "Account Code")]
        public string AccountCode                   { get; set; }
        [Display(Name = "Tax Type")]
        public string TaxType                       { get; set; }
    }
    public class ListOfCustomers
    {
        public ListOfCustomers(string customerName, string customerId)
        {
            CustomerName    = customerName;
            CustomerId      = customerId;
        }

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

Next lets create the controller, again the code is below:

using System.Web.Mvc;
using XeroIntergration.Models.Customer;
using XeroIntergration.Models.XeroBearerToken;

namespace XeroIntergration.Controllers
{
    public class InvoiceController : Controller
    {
        [HttpPost]
        public ActionResult Invoice(InvoiceCustomer model)
        {
            IXeroBearerToken token = new XeroBearerToken();
            var invoice = token.CreateNewCustomerInvoice(model);

            TempData["Status"] = invoice;

            return Redirect("https://localhost:44351/Contacts/ListOfCustomers");
        }
    }
}

Next, we have the view as shown below:

@model XeroIntergration.Models.Customer.InvoiceCustomer
@{
    Layout = "~/Views/Shared/_Layout.cshtml";
}


<div class="container">
    <div class="row">
        <div class="col-md-8 mt-5">
            <h4>List Of Customers</h4>
            @if (TempData["Status"] != null)
            {
                <p class="text-info p-3">@TempData["Status"]</p>
            }
            @using (Html.BeginForm("Invoice", "Invoice", FormMethod.Post, new { enctype = "multipart/form-data", id = "frmCustomer", name = "frmCustomer" }))
            {
                @Html.LabelFor(x => x.Customers)<br />
                @Html.DropDownListFor(x => x.Customers, new SelectList(Model.ListOfCustomers, "Value", "Text"), new { @class = "form-control" })


                @Html.LabelFor(x => x.Description)
                <div class="input-group p-2">
                    @Html.TextBoxFor(x => x.Description, new { Class = "form-control", Placeholder = "Description" })
                </div>

                @Html.LabelFor(x => x.AccountCode)
                <div class="input-group p-2">
                    @Html.TextBoxFor(x => x.AccountCode, new { Class = "form-control", Value = "200" })
                </div>

                @Html.LabelFor(x => x.TaxType)
                <div class="input-group p-2">
                    @Html.TextBoxFor(x => x.TaxType, new { Class = "form-control", Value = "ZERORATEDOUTPUT" })
                </div>

                @Html.LabelFor(x => x.Quantity)
                <div class="input-group p-2">
                    @Html.TextBoxFor(x => x.Quantity, new { Class = "form-control", Placeholder = "Quantity" })
                </div>

                @Html.LabelFor(x => x.UnitAmount)
                <div class="input-group p-2">
                    @Html.TextBoxFor(x => x.UnitAmount, new { Class = "form-control", Placeholder = "Price per unit" })
                </div>
                <div class="input-group p-2">
                    <button type="submit" class="btn btn-success">Create Invoice</button>
                </div>
            }

        </div>
    </div>
</div>

Now we have the method that creates the invoice and also sends the invoice via email, note in this example, the invoice from Xero is just a link which you need to click to view the invoice, the code is below:

 public string CreateNewCustomerInvoice(InvoiceCustomer model)
        {
            bool doesXeroTokenFileExist = XeroConfigurationHelper.DoesXeroTokenFileExist();
            XeroClient client;

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

                if (token == null) return "No Token";

                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();

                var contact = new Contact
                {
                    ContactID = Guid.Parse(model.Customers)
                };

                var line = new LineItem
                {
                    Description     = model.Description,
                    Quantity        = model.Quantity,
                    UnitAmount      = model.UnitAmount,
                    AccountCode     = model.AccountCode,
                    TaxType         = model.TaxType
                };

                var lines = new List
                {
                    line
                };

                var invoice = new Invoice
                {
                    Type            = Invoice.TypeEnum.ACCREC,
                    Contact         = contact,
                    Date            = Convert.ToDateTime(DateTime.Now.ToString("yyyy-MM-dd")),
                    DueDate         = Convert.ToDateTime(DateTime.Now.AddDays(14).ToString("yyyy-MM-dd")),
                    LineItems       = lines,
                    CurrencyCode    = CurrencyCode.GBP,
                    Status          = Invoice.StatusEnum.AUTHORISED
                };

                var invoiceList = new List { invoice };

                var invoices = new Invoices
                {
                    _Invoices = invoiceList
                };


                AccountingApi accountingApi = new AccountingApi();

                var xeroResponse = Task.Run(() => accountingApi.CreateInvoicesAsync(accessToken, tenantId, invoices)).Result;
                
                Guid invoiceId              = new Guid(xeroResponse._Invoices[0].InvoiceID.ToString());
                RequestEmpty requestEmpty   = new RequestEmpty();

                var sendEmailInvoice = Task.Run(() => accountingApi.EmailInvoiceAsync(accessToken, tenantId, invoiceId, requestEmpty)).Id;

                var returnStatus = $"Invoice Number {xeroResponse._Invoices[0].InvoiceNumber} Email Sent ID {sendEmailInvoice}";
                return returnStatus;
            }

            return "No File";
        }

One thing to note when sending the email is that Invoice.TypeEnum must be ACCREC and Invoice.StatusEnum must be AUTHORISED, SUBMITTED or PAID.

If all goes well, you can log into your Xero account and you will see the invoices created as the image below shows:

Xero Create Invoice API

If when adding your contact and you created a valid email, then you should receive an email from the Xero API and clicking on the link will display something similar to the image below:

Xero sent email

I hope you found this blog about how to use the Xero API helpful, and don't forget you can download the full code from GitHub