Integrate Xero with C# applications

Xero Accounting Software wallpaper

Often companies ask me to integrate Xero with C# applications because Xero is a quite popular accounting application. Xero’s secure online accounting software lets you work from anywhere, share with your employees and collaborate with your advisors. Just add apps to create a complete solution for your business. Unfortunately, the documentation is not really great. In a digital transformation scenario, I want to integrate as many applications as possible.

Create a new app

First, you have to create an account on Xero. You can use a trial to start. Then go to the developer portal and create your account as a developer.

Xero Developer Portal - My Apps
Xero Developer Portal – My Apps

Create a New app with the button on the top right. You see a popup windows where you have to insert:

  • App name: the name of your app
  • OAuth 2.0: select Auth code (Web app)
  • Company or application URL: I’m testing this application locally and apparently in production doesn’t really matter. I use https://localhost:7071
  • OAuth 2.0 redirect URI: I use https://developer.xero.com/
Xero Developer Portal - Add a new app
Xero Developer Portal – Add a new app

Press Create App. Apparently, the first authorization token must be created manually with Postman for example. Xero has a Postman’s collection with 3 functions and you can download this collection on this link. Unfortunately, the documentation is not really precise. Let me explain.

So, in your App details, you have the ClientId and Client secret. You have to use these values in the Postman collection. Also, it is required another value called xero-tenant-id: this value is not in this screen. You find in later and it is the Tenant Id of your organization in Xero.

Generate a new Access Token with Postman

In Postman you have to generate a new Access Token. For that, you have first to set up your environment. The following image is an example of the values you have to use (red box). I changed scopes because I want to have access to invoices: my scope is

offline_access accounting.transactions accounting.contacts

You can have the complete list of scopes on the Xero Developer Site.

Xero environment in Postman

Now, I’m ready to generate the Access Token. In the Postman collection, click on Get started and then select Authorization.

Get started in Postman

Click on Get new access token and you have a new popup.

Generate new access token for Xero with Postman

Verify the values because for same reasons not always are correct. If so, you have to verify the environment and save again. Also, check these 3 values:

  • Auth URL: https://login.xero.com/identity/connect/authorize
  • Access Token URL: https://identity.xero.com/connect/token
  • Client Authentication: Send client credential in body

Click on Request Token. A new Postman window is open and you have to insert your developer credentials.

Xero Login in Postman
Xero Login in Postman

Then you have to select your organization or more than one to associate to your token. I select the Demo Company. Press Continue.

Xero User Consent in Postman
Xero User Consent in Postman

This window is closed now and in Postman you have another one with the token details:

  • Access Token
  • Token Type
  • Expired in
  • Refresh Token
  • Scope
Token Details
Token Details
Token Details
Token Details

Click on Use token. Remember this token is valid for 30 minutes. After that, you have to generate another token. Another way is to refresh your token before it expired with the refresh token. I show later how to use a refresh token because it is crucial when you want to integrate Xero with C# applications.

PS: if you have more than one token saved, delete the old one. Sometimes Postman doesn’t save the token. Check the environment and, if it is the case, rewrite the token (I became made to understand that!).

Delete old token
Delete old token

Test your token

Just to be sure the token is working, I’m trying to have the list of organizations in my account. In the Postman collection you fine Connections: this call returns the list of organizations. Try to execute it. If it is working you can have a json with your organizations like that.

Call Xero Connections
Call Xero Connections
[
    {
        "id": "dd69c6a4-12e2-43fb-9578-87ee27f12887",
        "authEventId": null,
        "tenantId": "1c0611b5-8fd4-4c1d-a300-04d7b1eaf89d",
        "tenantType": "ORGANISATION",
        "tenantName": "Demo Company (Global)",
        "createdDateUtc": "2020-05-12T15:24:36.1047450",
        "updatedDateUtc": "2020-05-12T15:24:36.1069920"
    }
]

If you receive an unauthorized error, the values are wrong and probably Postman didn’t save your token: create a new one.

{
    "Type": null,
    "Title": "Unauthorized",
    "Status": 401,
    "Detail": "TokenExpired: token expired at 05/19/2020 11:19:36",
    "Instance": "d53db1ca-d6fa-4898-af05-3cac9c3ffbf2",
    "Extensions": {}
}

In this json you have tenandId! It is what I need for the next step.

Create the call in C# with Xero

It is time to create a C# application to use Xero. I’ll give you show function: so, you can use them where you want. First, save the token details in your settings. I implement this solution with RestSharp.

For example, I created an Azure Function and in my local settings I have:

{
  "IsEncrypted": false,
  "Values": {
    "AzureWebJobsStorage": "UseDevelopmentStorage=true",
    "FUNCTIONS_WORKER_RUNTIME": "dotnet",
    "AccountingServiceBusConnection": ""
  },
  "logLevel": {
    "PiP.Accounting.GetTokenRefreshTimer": "Debug"
  },
  "ExternalAccountingSettings": {
    "ClientId": "88566237BC...",
    "ClientSecret": "MUcD12TcGmN6...",
    "RefreshToken": "0a1e531da39d391dcd9f8c96d8245a...",
    "AccessToken": "eyJhbGc...",
    "TenandId": "1c0611b5-8fd4-4c1d-a300-04d7b1ea",
    "Url": "https://api.xero.com/"
  }
}

In the ExternalAccountingSettings I have all details about the token. From now on, I refer to this these settings as _settings.

So, I’m ready to read from Xero the list of organization for my token. Ready?

/// <summary>
/// Gets the organizations.
/// </summary>
/// <returns>OrganizationResponse.</returns>
public OrganizationResponse GetOrganizations()
{
    OrganizationResponse rtn = new OrganizationResponse();

    _client = new RestClient($"{_settings.Url}/connections");
    _client.Timeout = -1;

    var request = new RestRequest(Method.GET);
    request.AddHeader("Authorization", "Bearer " + _settings.AccessToken);
    var response = _client.Execute<IList<Organization>>(request);

    return response;
}

The Organization class is this one:

/// <summary>
/// Class Organization.
/// </summary>
public class Organization
{
    /// <summary>
    /// Gets or sets the identifier.
    /// </summary>
    /// <value>The identifier.</value>
    [JsonProperty("id")]
    public string Id { get; set; }

    /// <summary>
    /// Gets or sets the tenant identifier.
    /// </summary>
    /// <value>The tenant identifier.</value>
    [JsonProperty("tenantId")]
    public string TenantId { get; set; }

    /// <summary>
    /// Gets or sets the type of the tenant.
    /// </summary>
    /// <value>The type of the tenant.</value>
    [JsonProperty("tenantType")]
    public string TenantType { get; set; }

    /// <summary>
    /// Gets or sets the name of the tenant.
    /// </summary>
    /// <value>The name of the tenant.</value>
    [JsonProperty("tenantName")]
    public string TenantName { get; set; }

    /// <summary>
    /// Gets or sets the created date UTC.
    /// </summary>
    /// <value>The created date UTC.</value>
    [JsonProperty("createdDateUtc")]
    public DateTime CreatedDateUtc { get; set; } = DateTime.Now;

    /// <summary>
    /// Gets or sets the updated date UTC.
    /// </summary>
    /// <value>The updated date UTC.</value>
    [JsonProperty("updatedDateUtc")]
    public DateTime? UpdatedDateUtc { get; set; }
}

This is the first integration of Xero with C# applications! More posts soon!

2 thoughts on “Integrate Xero with C# applications

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.