Use the Azure Billing API and calculate the costs

The last days, I created a .net library that allows to read data from the Azure Billing REST APIs. You can use it to read data from the usage API, the ratecard API and it also gives you the combination of the data and does a cost calculation. The library is available as NuGet package (https://www.nuget.org/packages/CodeHollow.AzureBillingApi/) and the code is published on GitHub: https://github.com/codehollow/AzureBillingApi.
But before I jump into a short description of the library, I want to write a bit about the Azure Billing APIs:

Introduction

The Azure billing API allows to get data of your usage and the money that you have to pay for your resources. There are currently two types of the billing API:

The billing API for EA customers already returns the costs – so it’s much simpler. The REST (generic) billing API returns more data. It returns the usage of the resources and the costs per unit per resources – but it does not return the effective costs. If you want to get the costs, then you have to get the usage data and combine it with the ratecard data (the costs per unit per resource). I already blogged about each of those two APIs, but not about how to connect the data of both of them:

The combination of the data of these two billing APIs sound trivial, but it’s not so easy. The ratecard data contains e.g. the “IncludedQuantity” which is the quantity that you can use for free. Additionally there are probably different rates for different usages. Let’s have a look at the pricing for the bandwidth: the first 5 GB of bandwidth are for free, from 5 GB to 10 TB the price is 0,0734€ per GB, the next 40 TB are … and so on. That’s what must be part of the calculation. Another issue is, that you have to know the billing cycle and all usage data inside of the billing cycle, because rates and the included quantity start to count at 0 at the beginning of the billing cycle (which is currently the 14th of the month).

This process of combining the data and doing the calculation is done by the NuGet package that I created. (https://www.nuget.org/packages/CodeHollow.AzureBillingApi/).

Update May 2017: Since end of April 2017, there is another API available – the Azure Invoice API which allows to download Azure invoices as PDF via an API. Please find more information about it in this blog post: Azure Invoice API – download all invoices

How to use the billing API and the NuGet package

In the following section, I will describe how to configure the Azure Active Directory so that an application is allowed to access the Azure billing API. After the configuration, I will show how to build a simple C# application that uses the NuGet package for the billing API.

Configure Azure Active Directory for the billing API application

The application in the following section must at first be registered at the Azure Active Directory and must get the right permissions so that it is allowed to read the data.

Step 1: add a new application to the active directory

Open the new portal https://portal.azure.com and navigate to the Active Directory. Go to “App registrations” and click the Add Button:

  • Name: billingapi – can be whatever you want
  • Application Type: Native – we use the API from a client application, so native is the right one. If you develop a web application – “Web App/API” is the right one for you
  • Redirect URI: http://localhost/billingapi – can be whatever we want, because the client application will not redirect to an URL after login

Remember the Redirect URI because we will need it later on.

Step 2: add permissions to the service management API

After the app creation, go to the app (in app registrations) – Settings and “Required permissions”. Press the add button and add permissions for: Windows Azure Service Management API

Select “Access Azure Service Management as organization users (preview)” and save it:

Step 3: give the user/application access to the subscription

There are two ways how to authenticate. You can sign in with your user or you can use a client id and a client secret to authenticate (application). The first is good if you want to work with a specific user, the second is good for clients that run in the background (azure function, jobs, …)

Depending on what you want to use, you have to give the user or the application “Reader”, “Contributor” or “Owner” access to the subscription.

Navigate to your subscription, select your application and go to “Access control (IAM)”.

If you want to use user authentication and your user does not already have rights, just add the user and give him at least “Reader” access:

If you use application, search for the application and give it at least “Reader” access:

If you are back in the overview of the subscription, remember the Subscription ID and the OfferID. We need both of them later on.

Step 4: copy client id (and create client secret)

Navigate back to the Azure active directory – “App registrations” and select the billingApi application that was created in step 1. Copy the Application ID – we will use it later as the Client ID.

If you use application authentication, you need to create a client secret – a key. You can skip this step if you use user authentication. The key can be created by opening keys navigating to the keys. Add a new key, give it a name, select a duration and press create. This will create a new key that we copy so that we can use it later on as the Client Secret:

Building a C# application with the Azure Billing API NuGet package

The application was registered at Azure active directory in the previous steps – so we are ready to build the C# application.
Create a new Console Application and add the CodeHollow.AzureBillingApi NuGet package:

Now let’s use the Client to read data from the different resources. If you use user authentication, initiate it via:

CodeHollow.AzureBillingApi.Client c = new CodeHollow.AzureBillingApi.Client(
    "mytenant.onmicrosoft.com", "[CLIENTID]", "[SUBSCRIPTIONID]", "http://localhost/billingapi");

If you use application authentication (which requires the ClientSecret), use:

CodeHollow.AzureBillingApi.Client c = new CodeHollow.AzureBillingApi.Client(
    "mytenant.onmicrosoft.com", "[CLIENTID]", "[CLIENTSECRET]", "[SUBSCRIPTIONID]", "http://localhost/billingapi");

Reading the resource costs (combination of usage and ratecard data)

The resource costs can be read with the methods GetResourceCosts or GetResourceCostsForPeriod.

var costs = c.GetResourceCostsForPeriod("MS-AZR-0003P", "EUR", "en-US", "AT", 2017, 1);
var costsManual = c.GetResourceCosts("MS-AZR-0003P", "EUR", "en-US", "AT",
    new DateTime(2016, 11, 14), new DateTime(2016, 12, 14),
    CodeHollow.AzureBillingApi.Usage.AggregationGranularity.Daily, true);

The costs/costsManual will contain all usage lines with the calculated costs. There is also a field with TotalCosts. The cost calculation is done in the library and also supports the billing cycles (it reads the data with the beginning of the billing cycle and filters it later on).

The whole application including printing of the result:

using CodeHollow.AzureBillingApi;
using System;
using System.Linq;
 
namespace BillingApiSample
{
    class Program
    {
        static void Main(string[] args)
        {
            Client c = new Client(
                "mytenant.onmicrosoft.com", "[CLIENTID]", "[CLIENTSECRET]", "[SUBSCRIPTIONID]", "http://localhost/billingapi");
 
            var costs = c.GetResourceCostsForPeriod("[OFFERID]", "EUR", "en-US", "AT", 2016, 11);
 
            Console.WriteLine("Total costs: " + costs.TotalCosts);
            PrintMeters(costs);
             
            Console.WriteLine("Press key to exit!");
            Console.ReadKey();
        }
 
        private static void PrintMeters(ResourceCostData resourceCosts)
        {
            var meterIds = resourceCosts.GetUsedMeterIds();
 
            foreach (var x in meterIds)
            {
                var currates = resourceCosts.Costs.GetCostsByMeterId(x);
                string metername = resourceCosts.GetMeterById(x).MeterName;
                var curcosts = currates.Sum(y => y.CalculatedCosts);
                var billable = currates.Sum(y => y.BillableUnits);
                var usage = currates.Sum(y => y.UsageValue.Properties.Quantity);
 
                var curusagevalue = currates.First().UsageValue;
 
                Console.WriteLine($"{metername.PadRight(72)} : {usage.ToString("0.################")} ({billable.ToString("0.################")}) - {curcosts.ToString("0.################")}");
            }
        }
    }
}

Reading the ratecard data

You can get access the ratecard data in two ways. The GetResourceCost methods that we used in the sample above returns an object with a property RateCardData.
But the method call still reads the whole usage data, which takes some time. If you just want to get the data from the RateCard API – use:

Client c = new Client(
    "mytenant.onmicrosoft.com", "[CLIENTID]", "[CLIENTSECRET]", "[SUBSCRIPTIONID]", "http://localhost/billingapi");
 
c.GetRateCardData("[OFFERID]", "USD", "en-US", "US");

Reading the usage data

In the same way as getting only the data from the RateCard API you can get only the data of the Usage API:

Client c = new Client(
    "mytenant.onmicrosoft.com", "[CLIENTID]", "[CLIENTSECRET]", "[SUBSCRIPTIONID]", "http://localhost/billingapi");

Additional information

Categories:

5 Responses

  1. Great Stuff!
    The data which I get from Azure RateCard API has some MeterRates in the nested format.
    e.g{
    “0”:0.061,
    “1024”:0.051,
    “102400”:0.031
    }
    can you tell me how you used this kind of MeterRates to calculate the Price?

    • Hello,

      these numbers say: from 0 – 1023 units, the price is 0,061. from 1024 – 102399 units, the price is 0,051. If higher than 102400 – the price is 0.031.
      You have to consider the billing cycle for the calculation and take all units from the beginning of the billing cycle.

  2. Hello, thank you for this! I can’t seem to get the same exact total calculated costs from this library that matches my actual invoice from Azure. It’s close, but the values aren’t identical. Should these match?

    • Hello Aaron,
      I compared the results of the usage report that you can download from Microsoft (account.windowsazure.com) and the usage report that comes from my library/the usage api by microsoft.
      It seems that there is a difference between those two. The interesting part is, that I have some resources that use the exact same amount of units each day. The usage report that I downloaded from the accounts portal shows the same data each day except on the last 2 days. The report that I get from the usage api has the correct values each day. So I think that the usage api works better than the downloaded report, at least I have no idea why there is a different value at the last 2 days. I also can’t tell you why there is different data for 2 reports that should be the same.
      If I get an answer to that, I’ll update you

  3. Hallo Armin!

    Danke dafür!
    Ich bräuchte die TotalCosts einer ResourceGroup für einen gewissen Zeitraum.
    Zum Beispiel:
    – TotalCosts of RG1 from 2020-01-01 until 2020-01-31.

    Wie mache ich das am besten?
    Denn für eine ganze Subscription dauerts schon etwas lange, wenn da viele Ressourcen drin sind.

    Danke für deine Hilfe!
    LG,
    Rich

Leave a Reply

Your email address will not be published. Required fields are marked *

About
about armin

Armin Reiter
Blockchain/Web3, IT-Security & Azure
Vienna, Austria

Reiter ITS Logo

Cryptix Logo

Legal information