degreedays.api
¶
Core Degree Days.net API classes, including DegreeDaysApi
- the starting point for all API operations.
Class summaries¶
The shorter of the two API access keys, the account key identifies a unique Degree Days.net API account. |
|
The starting point for all API operations. If you're new to this API, read the docs for this class first. |
|
Superclass of all the API exceptions that you are likely to want to catch explicitly. |
|
Contains details of a failure in the server-side processing of all or part of an API request. |
|
Superclass of exceptions that indicate a |
|
A type of API |
|
Indicates that the API could not process a request because it was invalid in some way (e.g. authenticated with invalid access keys). |
|
A snapshot of an API account's rate limit. |
|
Indicates that the API servers did not process a request because the |
|
Specifies an operation that you'd like the API to do (e.g. calculating a specific type of degree-day data for a specific location). |
|
Superclass of exceptions that indicate that the API's processing of a request resulted in a |
|
Models the API's response to a |
|
Extra data that comes back with every response from the Degree Days.net API. |
|
The longer of the two API access keys that are needed to use the Degree Days.net API, the security key is a private key that should be kept secret. |
|
Indicates that the API servers failed to process a request because of temporary downtime or an unexpected error (sorry!). |
|
Indicates an error transporting a request to the API servers or transporting a response back. |
degreedays.api
¶
Core Degree Days.net API classes, including DegreeDaysApi
- the starting point for all API operations.
- class degreedays.api.AccountKey(stringAccountKey: str)¶
The shorter of the two API access keys, the account key identifies a unique Degree Days.net API account.
- Parameters:
stringAccountKey (str) – a Degree Days.net API account key.
- Raises:
TypeError – if stringAccountKey is not a str.
ValueError – if stringAccountKey cannot reasonably be parsed as a Degree Days.net API security key (see below for a description of the correct format).
Each API account has two API access keys: an account key and a security key. Sign up for a Degree Days.net API account to get your own API access keys. Or for development you can use the free test account, though it comes with heavy restrictions on the locations you can fetch data for.
The account key identifies the unique Degree Days.net API account. It is a public key in the sense that there is no need to keep it secret.
Here’s an example of an account key:
k9vs-e6a3-zh8r
Like the example above, all account keys are made up of three 4-character blocks separated by hyphens, with each non-hyphen character being one of the following:
abcdefghjkmnpqrstuvwxyz23456789
Account keys do not contain upper-case characters or any of the following easily-confused letters and digits: ‘i’, ‘l’, ‘o’, ‘0’ and ‘1’. The same is true of security keys (the other type of access key). The intention is to make these keys easy for non-technical users to handle (e.g. if entering them into software that you’ve made for them).
An
AccountKey
object is a wrapper around a string account key. It is useful for validating account keys from user input, since the constructor will only allow anAccountKey
object to be created with a string of the correct format or a string that can be manipulated into the correct format without too much ambiguity.
- class degreedays.api.DegreeDaysApi(requestProcessor)¶
The starting point for all API operations. If you’re new to this API, read the docs for this class first.
To create a
DegreeDaysApi
object, use thefromKeys
method. For example:api = DegreeDaysApi.fromKeys( AccountKey('test-test-test'), SecurityKey('test-test-test-test-test-test-test-test-test-test-test-test-test'))
The API access keys above (account key and security key) are for the free test account, which is heavily limited but usable for basic development and testing. For much more flexibility and production use, you can sign up for a full Degree Days.net API account to get your own API access keys.
Assuming you have a
DegreeDaysApi
object calledapi
, as in the example code above, then you can make three main types of request (and get three main types of response) using the objects and methods accessible through thatapi
object. The links below have more information and sample code for each:api.dataApi.getLocationData(locationDataRequest)
to fetch degree-day data and/or hourly temperature data from the API, for any specified weather station, postal/zip code, or longitude/latitude position.api.dataApi.getLocationInfo(locationInfoRequest)
to find out what weather station the API would use to represent any specified postal/zip code or longitude/latitude position.api.regressionApi.runRegressions(regressionRequest)
to send your energy data to the API so the API can test thousands of regressions against it (using HDD and CDD with a wide range of base temperatures), and return the regressions that give the best statistical fit (including base temperatures and coefficients you can use for further calculations).
More on how the API works: requests, responses, and errors¶
You create a
Request
object that specifies what you want the API to do. There are different types ofRequest
for different API operations, likeLocationDataRequest
for requesting degree-day data.Your
Request
gets processed. (Internally this library will turn your request into XML, send it to the API servers, and parse the XML response that the servers send back.)You’ll get a
Response
object back (assuming no errors). There are different types ofResponse
, mirroring the different types ofRequest
. For example, if you use aLocationDataRequest
to request some degree-day data, successful processing will give you aLocationDataResponse
.
If something goes wrong in sending your request to the API servers, or in getting your response back, you’ll get a
TransportError
. Typically that means there was a network error of some sort.If your request was transported to the API servers OK, but couldn’t be processed properly, you’ll get a
RequestFailureError
instead of aResponse
. There are different types ofRequestFailureError
for the different types ofRequest
. For example, take a look at the docs fordegreedays.api.data.DataApi.getLocationData
to see the exceptions that can be thrown if the API servers can’t process aLocationDataRequest
. The exceptions should help you determine the cause of the failure and decide what to do next.API access keys: the account key and the security key¶
Every customer’s API account is associated with two access keys: a public “account key” and a private “security key”, both of which are generated automatically on signup. These keys are used to secure each request sent to the API by the customer (or by software trusted to work on their behalf), to protect the API usage that the customer has paid to enable.
The account key is used to uniquely identify the customer account. It is a public key in the sense that there is no need to keep it secret.
Here’s an example account key:
k9vs-e6a3-zh8r
The security key is a private key that should be kept secret. In this respect it is like a password. The only entities that should have access to the security key are: Degree Days.net (systems and staff), the API account holder(s), and any trusted software systems that the API account holder(s) are using to manage their interactions with the API.
Here’s an example security key:
b79h-tmgg-dwv5-cgxq-j5k9-n34w-mvxv-b5be-kqp5-b6hb-3bey-h5gg-swwd
For more on the format of these access keys, see the notes in
AccountKey
andSecurityKey
.To get your own API access keys you can sign up for an API account here. Or, for basic development and testing, you can try out the free test account.
Using a
DegreeDaysApi
object¶You’d typically create just one
DegreeDaysApi
object for use throughout your application. It is perfectly safe for use from multiple threads. But there’s nothing to stop you creating and using as many instances as you like.For more information and code samples on how to use a
DegreeDaysApi
object that you have created (let’s call itapi
as per the example further above), please see the docs for the 3 main methods accessible through it:- property dataApi: DataApi¶
A
degreedays.api.data.DataApi
object that provides access to the API’s data-related operations.
- static fromKeys(accountKey: AccountKey, securityKey: SecurityKey) DegreeDaysApi ¶
Creates a
DegreeDaysApi
object configured with the specified API access keys.- Parameters:
accountKey (AccountKey) – a wrapper around the string account key that identifies the Degree Days.net API account.
securityKey (SecurityKey) – a wrapper around the string security key associated with the account.
- Raises:
TypeError – if either accountKey is not an
AccountKey
or securityKey is not aSecurityKey
.
- property regressionApi: RegressionApi¶
A
degreedays.api.regression.RegressionApi
object that provides access to the API’s regression-related operations.
- exception degreedays.api.DegreeDaysApiError¶
Superclass of all the API exceptions that you are likely to want to catch explicitly.
Handling the exceptions thrown by this client library¶
Subclasses of this exception are thrown by all the methods accessible through
DegreeDaysApi
to indicate problems like network failure (TransportError
), service failure (ServiceError
) i.e. our server-side processing going wrong, a rate limit being reached (RateLimitError
), invalid authentication credientials (InvalidRequestError
), and other types of exception that are specific to the API operation in question.The likelihood of many of these exceptions occurring will depend on how you are using the API. For example, if your customers install your application and then enter their own API access keys into it, you might expect the odd
InvalidRequestError
because of typos. However, such an exception would be less likely to occur if your application was a centrally-running background process that used a single API account to collect data. And consequently you might be less likely to want to handleInvalidRequestError
explicitly.So a typical approach would be to catch just those subclasses that you’re interested in (if any), catching
DegreeDaysApiError
last as a kind of catch all, or just letting any unhandled exceptions bubble up the call stack.
- class degreedays.api.Failure(code: str, message: str)¶
Contains details of a failure in the server-side processing of all or part of an API request.
Failure codes¶
Every failure has a
code
that indicates the cause of the failure.These codes are named in a hierarchical way. For example, if a failure is caused by an invalid request, its code will begin with “InvalidRequest”. The idea is that you can quickly test for broader types of failure code without having to know or itemize all the sub-types (like “InvalidRequestAccount” and “InvalidRequestSignature”).
New codes may be added into the API at any time. New codes might be sub-types of existing types (like if “InvalidRequestSomeNewCode” was added as a sub-type of “InvalidRequest”), or they might be completely new (like “SomeCompletelyNewCode”). If you’re writing logic that checks for different failure codes, make sure that it won’t blow up if it comes across a code that it doesn’t recognize. Though you are unlikely to need to deal with failure codes directly, as API methods like
DataApi.getLocationData
andDataSets.get
will automatically turn any failure codes into appropriate subclasses ofFailureError
.- property code: str¶
The string failure code associated with this failure.
- property message: str¶
The string message associated with this failure, providing explanatory information about the
code
and what went wrong.The format of messages, and any details contained within them, are unspecified and subject to change. By all means use them for logging and display purposes, but please don’t parse specific details from them. If you need programmatic access to information that is only available in a message, please let us know so we can think about how we could make that information available in another format.
- exception degreedays.api.FailureError(failure: Failure)¶
Superclass of exceptions that indicate a
Failure
in the API’s processing of all or part of a request.Apart from
TransportError
, all concrete subclasses ofDegreeDaysApiError
are subclasses ofFailureError
, and carry a codedFailure
which originates from the server-side processing of an API request.Most types of
FailureError
extendRequestFailureError
, which indicates that the API servers completely failed to process an API request (sending back only aFailure
as their response). But a failure doesn’t have to relate to a full request - it is possible for parts of a request to work and parts to fail. Right now the only example of this isSourceDataError
which indicates that the API servers failed to generate a specific set of data as part of a batch request.isDueToXXX properties on subclasses of
FailureError
¶Some of the subclasses of
FailureError
have isDueToXXX-style methods. These work by inspecting the failure code of theFailure
object that the exception carries.The isDueToXXX properties follow a simple pattern: they will always be True if the failure code starts with the XXX part of the method name. So, for example,
ServiceError.isDueToServiceTemporarilyDown
will be True if the code is “ServiceTemporarilyDown” or “ServiceTemporarilyDownForPostalCodeLookups” (a failure code that isn’t actually in use at the time of writing, but that may come into use at some point in the future).If you’re checking isDueToXXX properties, bear in mind that it’s possible for none of them to be True. This client library doesn’t expose all possible failure codes through the isDueToXXX properties, only the ones that are likely to arise through use of the client library, and only the ones that were defined at the time this version of the client library was released. New codes may be added into the API over time, and they shouldn’t cause incompaiblities with code that you’ve already written to test the existing isDueToXXX properties.
In a nutshell: when writing code that tests isDueToXXX properties (e.g. to decide what message to show in a UI), make sure that your code will work well if none of those properties are True.
- class degreedays.api.FailureResponse(metadata: ResponseMetadata, failure: Failure)¶
A type of API
Response
that indicates a failure in the server-side processing of aRequest
.You will probably only need to deal with this class directly if you are throwing subclasses of
RequestFailureError
for testing purposes (e.g. to test your code’s handling of such exceptions). In normal usage of this client library, anyFailureResponse
objects will be turned intoRequestFailureError
objects automatically.- property failure: Failure¶
The
Failure
object that contains details of the failure in the API’s server-side processing of the request.
- property metadata: ResponseMetadata¶
An object containing metadata sent back with every response from the API servers, including details of the account’s current rate limit.
- exception degreedays.api.InvalidRequestError(failureResponse: FailureResponse)¶
Indicates that the API could not process a request because it was invalid in some way (e.g. authenticated with invalid access keys).
This exception corresponds to any failure code starting with “InvalidRequest”.
The
isDueToInvalidRequestXXX
properties of this class make it easy to test for the “InvalidRequestXXX” codes that you are likely to want to test for. There are also several “InvalidRequestXXX” codes that do not have correspondingisDueToInvalidRequestXXX
convenience properties, but these codes should not arise through normal use of this Python client library. For example, there’s an “InvalidRequestXml” code that you should never receive unless you have modified the mechanism that this Python client library uses to generate the XML requests (something you’re unlikely to want to do).All “InvalidRequestXXX” codes will cause this exception to be thrown, irrespective of whether they have their own
isDueToInvalidRequestXXX
properties. If, for some reason, you need to explicitly check for an “InvalidRequestXXX” code that does not have its ownisDueToInvalidRequestXXX
property, you can always check for it by testing the failure code string directly.If you’re testing the
isDueToInvalidRequestXXX
properties, please do make sure that your code won’t blow up if none of them areTrue
.See also:
- property failure: Failure¶
The
Failure
object containing details of the failure on the API servers that led to this exception on the client.
- property isDueToInvalidRequestAccount¶
True if the request failed because the
AccountKey
was unrecognized (e.g. because of a typo) or the API account has been cancelled by the user or automatically expired after a billing failure; False otherwise.The account key would typically be set when creating
DegreeDaysApi
.
- property isDueToInvalidRequestForAccountPlan¶
True if this failure came in response to a request for data that is not available on the API account plan associated with the
AccountKey
; False otherwise.The Degree Days.net website has details of the different account plans and how to upgrade.
- property isDueToInvalidRequestSignature¶
True if this failure came in response to a request that was sent with an invalid signature, typically caused by a problem with the
SecurityKey
; False otherwise.Signatures are used as part of the key-based security mechanism that protects the usage quotas associated with customer accounts. This Python client library generates all signatures automatically, so this type of failure should only come about if a signature is generated using an erroneous security key (e.g. one that was entered with a typo).
The security key of the account is set when creating
DegreeDaysApi
.
- property isDueToInvalidRequestTimestamp¶
True if this failure came in response to a request that was sent with an invalid timestamp, typically caused by an out-of-sync clock on the client machine; False otherwise.
When a request is packaged up and sent to the API servers, a timestamp is included to indicate the time, in UTC (GMT), that the request was sent. This timestamp is checked against the server’s clock as part of a system designed to prevent unwanted replays of previous requests.
This type of failure can occur if the client’s clock is badly out of sync (like 15 minutes or more from the real time). If the computer’s clock looks right, and you’re still getting this type of failure, then it’s likely that the computer’s clock is set with the wrong time-zone. The timestamps sent to the server are UTC timestamps, and, unless the computer’s time-zone is set correctly, its concept of UTC time is likely to be out by at least an hour.
- property responseMetadata: ResponseMetadata¶
The metadata from the
FailureResponse
that brought details of this failure back from the API servers.
- class degreedays.api.RateLimit(requestUnitsAvailable: int, minutesToReset: int)¶
A snapshot of an API account’s rate limit.
The real state of an account’s rate limit changes over time and as more requests are made to the API. So a
RateLimit
object, which is a snapshot, is best checked soon after it is received. It is accessible through theResponseMetadata
that is included with each APIResponse
(accessible viaResponse.metadata
) and with eachRequestFailureError
(accessible viaRequestFailureError.responseMetadata
).
- exception degreedays.api.RateLimitError(failureResponse: FailureResponse)¶
Indicates that the API servers did not process a request because the
RateLimit
for the account’s plan had been reached.The best way to handle this exception is often to wait until the rate limit is reset. You can figure out how long that is from the
RateLimit
object, accessible through theresponseMetadata
property of this exception. Or you can upgrade your account to increase your rate limit. Choose the API plan you want and email us to let us know.This exception corresponds to any failure code starting with “RateLimit”.
You can interrogate the isDueToXXX properties of this exception to find out more about the cause. There is only one such property at the moment, but more may be added in a future version of this client library.
- property failure: Failure¶
The
Failure
object containing details of the failure on the API servers that led to this exception on the client.
- property isDueToRateLimitOnLocationChanges¶
True if this failure was caused by a rate limit on the number of times a location-limited account can change the location(s) that they access data for; False otherwise.
Location-limited accounts are low-end accounts that are used for fetching regular updates for a limited number of locations. The number of locations allowed depends on the location-limited account in question.
Allowed locations are set automatically. If a location-limited account successfully fetches data for a given location, that location is assigned to the account, and the account is able to continue fetching data for that location as time goes on (e.g. fetching daily/weekly/monthly updates).
A certain amount of location turnover is allowed. Offices and people move to new buildings, and occasionally weather stations go down and replacements need to be found (see
degreedays.api.data.LocationError.isDueToLocationNotSupported
for more on this). As new locations are added to an account’s list of allowed locations, older locations are removed on a least-recently-used basis. There are limits on the number of “location changes” that a location-limited account can make in any given period of time. These limits aren’t explicitly published, and may change over time, but the idea is that it should be very unlikely for a location-limited account to hit its limit on location changes. Location-limited accounts are built for a certain style of usage only (fetching regular updates for a mostly-fixed set of locations).From a programming perspective, dealing with a rate limit on location changes is unlikely to be any different from dealing with the usual rate limit on the number of request units. If you have a user-driven application, you might want to call this method to help you decide what message to show in the UI… But, if your program is a background task that fetches data at regular intervals, you probably won’t need to distinguish between a limit on request units (all accounts have these) and a limit on location changes (only location-limited accounts have these). If an account hits a rate limit (whether on request units or location changes), you’ll get a
RateLimitError
, and you’ll generally just want to wait the specified number of minutes (RateLimit.minutesToReset
) until the rate limit is reset:except RateLimitError as e: minutesToWait = e.responseMetadata.rateLimit.minutesToReset
- property responseMetadata: ResponseMetadata¶
The metadata from the
FailureResponse
that brought details of this failure back from the API servers.
- class degreedays.api.Request¶
Specifies an operation that you’d like the API to do (e.g. calculating a specific type of degree-day data for a specific location).
This is an abstract class. You wouldn’t create a
Request
directly, rather you would create one of its subclasses:degreedays.api.data.LocationDataRequest
,degreedays.api.data.LocationInfoRequest
, ordegreedays.api.regression.RegressionRequest
.Every subclass of
Request
has an equivalent subclass ofResponse
. For example,degreedays.api.data.LocationDataRequest
hasdegreedays.api.data.LocationDataResponse
.
- exception degreedays.api.RequestFailureError(failureResponse: FailureResponse)¶
Superclass of exceptions that indicate that the API’s processing of a request resulted in a
Failure
.The key point here is that the API servers were not able to process the request at all, and their response contained only:
Details of the failure, exposed through the subclasses of this exception type and through the
Failure
object itself (accessible viaFailureError.failure
).Response metadata, accessible via the
responseMetadata
property of this exception.
- property failure: Failure¶
The
Failure
object containing details of the failure on the API servers that led to this exception on the client.
- property responseMetadata: ResponseMetadata¶
The metadata from the
FailureResponse
that brought details of this failure back from the API servers.
- class degreedays.api.Response¶
Models the API’s response to a
Request
(e.g. degree-day data returned in response to a request for that data).This is an abstract class. Any
Response
objects you receive from the API will be a subclass of this, with the type depending on the type ofRequest
you made. Adegreedays.api.data.LocationDataRequest
will give you adegreedays.api.data.LocationDataResponse
; adegreedays.api.data.LocationInfoRequest
will give you adegreedays.api.data.LocationInfoResponse
; and adegreedays.api.regression.RegressionRequest
will give you adegreedays.api.regression.RegressionResponse
.- property metadata: ResponseMetadata¶
An object containing metadata sent back with every response from the API servers, including details of the account’s current rate limit.
- class degreedays.api.ResponseMetadata(rateLimit: RateLimit)¶
Extra data that comes back with every response from the Degree Days.net API.
The metadata for any particular response can be accessed via
Response.metadata
(if your API request succeeds and you get aResponse
object back), or viaRequestFailureError.responseMetadata
(if aRequestFailureError
is thrown to indicate a failure in the server’s processing of your API request).
- class degreedays.api.SecurityKey(stringSecurityKey: str)¶
The longer of the two API access keys that are needed to use the Degree Days.net API, the security key is a private key that should be kept secret.
- Parameters:
stringSecurityKey (str) – a Degree Days.net API security key.
- Raises:
TypeError – if stringSecurityKey is not a str.
ValueError – if stringSecurityKey cannot reasonably be parsed as a Degree Days.net API security key (see below for a description of the correct format).
Each API account has two API access keys: an account key and a security key. Sign up for a Degree Days.net API account to get your own API access keys. Or for development you can use the free test account, though it comes with heavy restrictions on the locations you can fetch data for.
The security key is a private key that should be kept secret. In this respect it is like a password. The only entities that should have access to the security key are: Degree Days.net (systems and staff), the API account holder(s), and any trusted software systems that the API account holder(s) are using to manage their interactions with the API.
Here’s an example of a security key:
b79h-tmgg-dwv5-cgxq-j5k9-n34w-mvxv-b5be-kqp5-b6hb-3bey-h5gg-swwd
Like the example above, all security keys are made up of thirteen 4-character blocks separated by hyphens, with each non-hyphen character being one of the following:
abcdefghjkmnpqrstuvwxyz23456789
Security keys do not contain upper-case characters or any of the following easily-confused letters and digits: ‘i’, ‘l’, ‘o’, ‘0’ and ‘1’. The same is true of account keys (the other type of access key). The intention is to make these keys easy for non-technical users to handle (e.g. if entering them into software that you’ve made for them).
A
SecurityKey
object is a wrapper around the characters that constitute a string security key. It is useful for validating security keys from user input, since the constructor will only allow aSecurityKey
object to be created with a string of the correct format or a string that can be manipulated into the correct format without too much ambiguity.- getBytes()¶
Returns a byte array containing the canonical security key’s characters encoded into bytes using the UTF-8 character set.
- toStringKey()¶
Returns the canonical string security key. Take care to ensure that the returned string doesn’t accidentally appear in log files or error messages.
- exception degreedays.api.ServiceError(failureResponse: FailureResponse)¶
Indicates that the API servers failed to process a request because of temporary downtime or an unexpected error (sorry!).
This exception corresponds to any failure code starting with “Service”.
You can interrogate the isDueToXXX properties of this exception to find out more about the cause. But do note that it is possible for none of those properties to be True if a relevant new failure code is added into the API. Be prepared for this in your handling.
- property failure: Failure¶
The
Failure
object containing details of the failure on the API servers that led to this exception on the client.
- property isDueToServiceTemporarilyDown¶
True if this failure was caused by a temporary problem preventing the API service from functioning properly (sorry!); False otherwise.
This might, for example, be caused by a temporary network error preventing our API servers from accessing the database of weather data that the calculation process relies upon. Or it could be caused by other essential systems being overloaded.
The best way to handle this type of failure is usually to try the request again until it works (waiting a little while between repeated submissions). If you get this type of failure for one request, it is quite likely that some or all of your requests will fail in the same way until the problem is resolved (which hopefully won’t take long).
- property isDueToServiceUnexpectedError¶
True if this failure was caused by a unexpected error in the API service (sorry!); False otherwise.
If an unexpected error in the API service should occur, it is quite likely that it would only be triggered by a specific request (e.g. a request for data from a particular weather station). This is different to the service going
temporarily down
and affecting most or all requests until the problem is resolved.If a request triggers a “ServiceUnexpectedError” failure, there probably won’t be any point in trying that particular request repeatedly. Other requests will probably continue to work OK, but the problem request, if repeatedly submitted, will probably repeatedly fail until the underlying bug in the system is addressed. This is the sort of thing that would typically take at least a day or two, or potentially much longer (some bugs are beyond our sphere of control).
If you’re getting this type of failure repeatedly, and it’s getting in the way of what you’re trying to achieve with the API, please email us to let us know. Our logging system should alert us each time an error like this occurs, but it’s always useful to hear more information. Also, if it’s not something we can fix on our end, we might well be able to suggest some sort of workaround.
- property responseMetadata: ResponseMetadata¶
The metadata from the
FailureResponse
that brought details of this failure back from the API servers.