Degree Days

Degree Days

Weather Data for Energy Professionals

Weather Underground

Degree Days.net XML API

At its core the Degree Days.net API is an XML API. The Java, .NET, and Python client libraries are wrappers around the XML API.

The XML API is carefully designed and well tested. However, unlike the client libraries, it is not particularly easy to develop against. It is built for performance rather than ease of development.

The XML API is not a simple REST API with a static URL for each "unit" of data. You can use it to fetch many years' worth of custom-specified data in a single request, in multiple base temperatures and breakdowns. The range of options and data that can be specified and returned in XML make it difficult to program against the XML API directly.

There is also an HMAC-signature-based security scheme to negotiate.

If at all possible, we recommend that you access the API using one of our client libraries. With the client libraries the API is really easy to use - you can literally be up and running fetching data in a couple of minutes. With the client libraries, all the advanced options for data-specification are readily available without extra effort.

At present we have robust client libraries for Java (and other languages that can be run on the JVM), .NET (e.g. C# and VB.NET), and Python.

We are planning to make more client libraries, but we are finding it difficult to decide which languages and platforms to prioritize. If the above options don't cater for your project particularly well, please email us at info@degreedays.net to let us know what language/platform you are using.

Using the XML API

Each of these steps is explained below (or at least will be once we've documented everything fully):

1. Create the XML request

Below is an example XML request that shows a few of the main options. Below that are more details of the various options you can use within the XML.

If you have a specific data-fetching pattern in mind, and you're struggling to figure out what XML you'll need, please feel free to email us for help on info@degreedays.net.

<?xml version="1.0" encoding="UTF-8" ?>

<RequestEnvelope>
    
    <SecurityInfo>
        <!-- "Endpoint" is always the same.  It's the URL you send the request to. -->
        <Endpoint>http://apiv1.degreedays.net/xml</Endpoint>
        <!-- "AccountKey" comes with your API account. -->
        <AccountKey>test-test-test</AccountKey>
        <!-- "Timestamp" should be the time of the request in ISO format. -->
        <Timestamp>2013-05-19T20:01:09Z</Timestamp>
        <!-- "Random" should be a random string, generated afresh for each request.
        It can be a random number or a UUID or similar. -->
        <Random>51992f85ab2bf</Random>
    </SecurityInfo>                         
    
    <LocationDataRequest>
        <!-- Specify the "Location" you want data for (more options further below):-->
        <PostalCodeLocation>
            <PostalCode>02532</PostalCode>
            <CountryCode>US</CountryCode>
        </PostalCodeLocation>
        
        <!-- Now specify what data you want.  You can specify up to 100 "DataSpec"
        items in a single request (e.g. HDD and CDD in 50 base temperatures each).
        Give each "DataSpec" a "key" attribute so you can identify the corresponding
        "DataSet" in the response. -->
        <DataSpecs>
            <!-- The following specifies HDD with a base temperature of 65 F, broken
            down daily (a value for each day), and covering the last 7 days. -->
            <DatedDataSpec key="dailyHDD">
                <!-- The "Calculation" defines the type of degree days (e.g. heating or
                cooling) and the base temperature. -->
                <HeatingDegreeDaysCalculation>
                    <FahrenheitBaseTemperature>65</FahrenheitBaseTemperature>
                </HeatingDegreeDaysCalculation>
                <!-- There are different types of "Breakdown" (see further below). -->
                <DailyBreakdown>
                    <!-- A Breakdown has a "Period" to specify the dates that the data
                    should cover.  There's more on specifying the Period further below. -->
                    <LatestValuesPeriod>
                        <NumberOfValues>7</NumberOfValues>
                    </LatestValuesPeriod>
                </DailyBreakdown>
            </DatedDataSpec>
            
            <!-- The following specifies CDD with a base temperature of 21.5 C, broken 
            down monthly, and covering June, July, and August of 2012. -->
            <DatedDataSpec key="monthlyCDD">
                <CoolingDegreeDaysCalculation>
                    <CelsiusBaseTemperature>21.5</CelsiusBaseTemperature>
                </CoolingDegreeDaysCalculation>
                <MonthlyBreakdown>
                    <DayRangePeriod>
                        <DayRange first="2012-06-01" last="2012-08-31"/>
                    </DayRangePeriod>
                </MonthlyBreakdown>
            </DatedDataSpec>
            
            <!-- The following specifies 5-year-average HDD with a base temperature of
            15.5 C.  If you made this request today you could expect to get an average
            of data from 2008, 2009, 2010, 2011, and 2012. -->
            <AverageDataSpec key="averageHDD">
                <HeatingDegreeDaysCalculation>
                    <CelsiusBaseTemperature>15.5</CelsiusBaseTemperature>
                </HeatingDegreeDaysCalculation>
                <FullYearsAverageBreakdown>
                    <LatestValuesPeriod>
                        <NumberOfValues>5</NumberOfValues>
                    </LatestValuesPeriod>
                </FullYearsAverageBreakdown>
            </AverageDataSpec>
            
        </DataSpecs>
        
    </LocationDataRequest>
    
</RequestEnvelope>

The Location can be a station ID, or a "geographic location" for which the API will select the best weather station to use automatically:

<StationIdLocation>
    <!-- The StationId must match [-_0-9a-zA-Z]{1,60} -->
    <StationId>EGLL</StationId>
</StationIdLocation>

<LongLatLocation>
    <LongLat longitude="-135.23127" latitude="43.92135"/>
</LongLatLocation>

<PostalCodeLocation>
    <!-- The PostalCode must match [- 0-9a-zA-Z]{1,16} -->
    <PostalCode>WC2N 5DN</PostalCode>
    <!-- The CountryCode should be a 2-letter ISO country code, in upper case. -->
    <CountryCode>GB</CountryCode>
</PostalCodeLocation>

A DataSpec can be either a DatedDataSpec (for daily/weekly/monthly/yearly data), or an AverageDataSpec. Both are shown by the example request XML above.

A Calculation can specify heating or cooling degree days:

<HeatingDegreeDaysCalculation>
    <CelsiusBaseTemperature>15.5</CelsiusBaseTemperature>
</HeatingDegreeDaysCalculation>

<CoolingDegreeDaysCalculation>
    <FahrenheitBaseTemperature>65</FahrenheitBaseTemperature>
</CoolingDegreeDaysCalculation>

All temperatures must be specified as whole numbers or with one digit after the decimal point.

A DatedDataSpec can have the following kinds of breakdown:

<DailyBreakdown>
    <!-- Period goes here. -->
</DailyBreakdown>

<WeeklyBreakdown firstDayOfWeek="Monday">
    <!-- Period goes here. -->
</WeeklyBreakdown>

<!-- startOfMonth is optional, the default being ---01 for regular calendar months. -->
<MonthlyBreakdown startOfMonth="---01">
    <!-- Period goes here. -->
</MonthlyBreakdown>

<!-- startOfYear is optional, the default being --01-01 for regular calendar years.
The example below specifies years starting on May 21st. -->
<YearlyBreakdown startOfYear="--05-21">
    <!-- Period goes here. -->
</YearlyBreakdown>

An AverageDataSpec can currently only have one type of breakdown:

<!-- This specifies that data should be averaged from the full calendar years
specified by the period. -->
<FullYearsAverageBreakdown>
    <!-- Period goes here.  Typically you'd use a LatestValuesPeriod to specify
    that the average should come from the most recent x full calendar years. -->
</FullYearsAverageBreakdown>

A Period can be specified in two ways:

<!-- Get the most recent available data: -->
<LatestValuesPeriod>
    <NumberOfValues>12</NumberOfValues>
    <!-- MinimumNumberOfValues is optional - you can specify it if you would
    rather have a failure than a partial set of data with less than your specified
    minimum number of values.  (Otherwise you may get back less data than you
    asked for if there aren't enough temperature-data records to generate a full
    set for your specified location.) -->
    <MinimumNumberOfValues>12</MinimumNumberOfValues>
</LatestValuesPeriod>

<!-- Get data covering your specified dates: -->
<DayRangePeriod>
    <DayRange first="2008-01-01" last="2012-12-31"/>
    <!-- MinimumDayRange is optional - you can specify it if you would rather have
    a failure than a partial set of data covering less than your specified minimum
    range (like for MinimumNumberOfValues above). -->
    <MinimumDayRange first="2010-01-01" last="2012-12-31"/>
</DayRangePeriod>

Back to overview

2. Generate the HTTP parameters and send them to our servers

You need to send five parameters to the endpoint URL (http://apiv1.degreedays.net/xml):

HTTP POST is ideal, but, if that's difficult for you, a GET should be OK too.

The signature and base64url encoding are both explained below:

The signature

The signature has two purposes:

The signature_method will ideally be HmacSHA256. If you can't do that for whatever reason (it might not be supported by your programming language), HmacSHA1 should work instead. Of course the method you use to make the signature has to correspond with the signature_method parameter that you send with your request.

Your XML string should be fed into the HMAC function, with the key being your security key (one of the access keys that comes with your API account). If the HMAC function requires a byte array, convert the XML string into bytes first using UTF-8 encoding. The HMAC function should return the signature as a byte array. Encode that using base64url (as described below), and use the resulting string as the encoded_signature parameter.

base64url encoding

base64url encoding is required to:

base64url encoding is like regular base 64, but with a few differences:

Many libraries can do base64url encoding automatically, but if not, then hopefully you can generate a regular base-64 string and convert it using the simple rules above. Note that you might find it works OK with the = characters and line breaks left in, but to ensure future compatibility it's probably best to remove them.

If your base-64 function takes a byte array, not a string, to encode the request XML you can encode the XML string into bytes first (using UTF-8 encoding) and then feed the bytes into your base-64 function.

If, in your programming language, you're struggling to generate anything base 64, drop us an email as we should be able to set up an alternative like hex.

Sending the parameters to the server

As mentioned above, an HTTP POST is the best way, but, if that's difficult in your programming language, a GET should work too.

If you can handle a compressed response, you can set the Accept-encoding header to gzip or deflate. Then the XML response will come back in compressed format. This won't make much of a difference if you're only fetching a small amount of data with each request, but it's well worth using compression to reduce bandwidth if you're fetching daily data covering long periods or in lots of base temperatures.

Back to overview

3. Parse the XML response

TODO

(Sorry, we've not documented this yet. If you email us with details of the data you want we'll send you a sample XML request and response that you can base your code around.)

Back to overview

© 2013 BizEE Software Limited - About | Contact | Privacy Policy | FAQ | Desktop App | API