degreedays.api

Core Degree Days.net API classes, including DegreeDaysApi - the starting point for all API operations.

Class summaries

AccountKey

The shorter of the two API access keys, the account key identifies a unique Degree Days.net API account.

DegreeDaysApi

The starting point for all API operations. If you're new to this API, read the docs for this class first.

DegreeDaysApiError

Superclass of all the API exceptions that you are likely to want to catch explicitly.

Failure

Contains details of a failure in the server-side processing of all or part of an API request.

FailureError

Superclass of exceptions that indicate a Failure in the API's processing of all or part of a request.

FailureResponse

A type of API Response that indicates a failure in the server-side processing of a Request.

InvalidRequestError

Indicates that the API could not process a request because it was invalid in some way (e.g. authenticated with invalid access keys).

RateLimit

A snapshot of an API account's rate limit.

RateLimitError

Indicates that the API servers did not process a request because the RateLimit for the account's plan had been reached.

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).

RequestFailureError

Superclass of exceptions that indicate that the API's processing of a request resulted in a Failure.

Response

Models the API's response to a Request (e.g. degree-day data returned in response to a request for that data).

ResponseMetadata

Extra data that comes back with every response from the Degree Days.net API.

SecurityKey

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.

ServiceError

Indicates that the API servers failed to process a request because of temporary downtime or an unexpected error (sorry!).

TransportError

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 an AccountKey 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 the fromKeys 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 called api, 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 that api object. The links below have more information and sample code for each:

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 of Request for different API operations, like LocationDataRequest 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 of Response, mirroring the different types of Request. For example, if you use a LocationDataRequest to request some degree-day data, successful processing will give you a LocationDataResponse.

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 a Response. There are different types of RequestFailureError for the different types of Request. For example, take a look at the docs for degreedays.api.data.DataApi.getLocationData to see the exceptions that can be thrown if the API servers can’t process a LocationDataRequest. 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 and SecurityKey.

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 it api 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 a SecurityKey.

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.

Inheritance diagram of degreedays.api.DegreeDaysApiError, degreedays.api.InvalidRequestError, degreedays.api.RateLimitError, degreedays.api.ServiceError, degreedays.api.data.LocationError, degreedays.api.data.SourceDataError, degreedays.api.TransportError

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 handle InvalidRequestError 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 and DataSets.get will automatically turn any failure codes into appropriate subclasses of FailureError.

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.

Inheritance diagram of degreedays.api.FailureError, degreedays.api.RequestFailureError, degreedays.api.data.SourceDataError

Apart from TransportError, all concrete subclasses of DegreeDaysApiError are subclasses of FailureError, and carry a coded Failure which originates from the server-side processing of an API request.

Most types of FailureError extend RequestFailureError, which indicates that the API servers completely failed to process an API request (sending back only a Failure 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 is SourceDataError 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 the Failure 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.

property failure: Failure

The Failure object containing details of the failure on the API servers that led to this exception on the client.

class degreedays.api.FailureResponse(metadata: ResponseMetadata, failure: Failure)

A type of API Response that indicates a failure in the server-side processing of a Request.

Inheritance diagram of FailureResponse

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, any FailureResponse objects will be turned into RequestFailureError 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).

Inheritance diagram of degreedays.api.InvalidRequestError

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 corresponding isDueToInvalidRequestXXX 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 own isDueToInvalidRequestXXX 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 are True.

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 the ResponseMetadata that is included with each API Response (accessible via Response.metadata) and with each RequestFailureError (accessible via RequestFailureError.responseMetadata).

property minutesToReset: int

The number of minutes until the rate limit is reset, at the time that this snapshot of the rate-limit state was taken.

property requestUnitsAvailable: int

The number of request units available for use before the next reset, at the time that this snapshot of the rate-limit state was taken.

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.

Inheritance diagram of degreedays.api.RateLimitError

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 the responseMetadata 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, or degreedays.api.regression.RegressionRequest.

Inheritance diagram of degreedays.api.Request, degreedays.api.data.LocationDataRequest, degreedays.api.data.LocationInfoRequest, degreedays.api.regression.RegressionRequest

Every subclass of Request has an equivalent subclass of Response. For example, degreedays.api.data.LocationDataRequest has degreedays.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.

Inheritance diagram of degreedays.api.RequestFailureError, degreedays.api.InvalidRequestError, degreedays.api.RateLimitError, degreedays.api.ServiceError, degreedays.api.data.LocationError

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 via FailureError.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 of Request you made. A degreedays.api.data.LocationDataRequest will give you a degreedays.api.data.LocationDataResponse; a degreedays.api.data.LocationInfoRequest will give you a degreedays.api.data.LocationInfoResponse; and a degreedays.api.regression.RegressionRequest will give you a degreedays.api.regression.RegressionResponse.

Inheritance diagram of degreedays.api.Response, degreedays.api.data.LocationDataResponse, degreedays.api.data.LocationInfoResponse, degreedays.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 a Response object back), or via RequestFailureError.responseMetadata (if a RequestFailureError is thrown to indicate a failure in the server’s processing of your API request).

property rateLimit: RateLimit

Details of the rate limit that is currently associated with the API account.

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 a SecurityKey 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!).

Inheritance diagram of degreedays.api.ServiceError

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.

exception degreedays.api.TransportError(message: str | None = None)

Indicates an error transporting a request to the API servers or transporting a response back. Typically some sort of network or connection issue.

Inheritance diagram of degreedays.api.TransportError