Webhooks are HTTP requests from our servers to your servers to let you know about a particular event that just happened. For some users, having UtilityAPI push events to an endpoint of their choosing is easier than polling our API to monitor for changes. Using webhooks is optional! We only send events to users who opt-in to receive them in their user settings.
ping
event for each of your endpoints.
Here is an example of a webhook request you will typically get when a customer submits an authorization form.
POST /webhook-receiver HTTP/1.1 Host: yourserver.com X-UtilityAPI-Webhook-Salt: 0934ujsd... X-UtilityAPI-Webhook-Signature: 310723b64b26a72ab9... Content-Length: 519 Content-Type: application/json { "events": [ { "uid": "0b346106", "type": "authorization_created", "ts": "2019-01-01T12:32:42.347321+00:00", "delivery_method": "webhook", "delivery_target": "https://yourserver.com/webhook-receiver", "is_delivered": false, "authorization_uid": "12345-678" }, { "uid": "f18bb97d", "type": "authorization_update_started", "ts": "2019-01-01T12:32:42.347321+00:00", "delivery_method": "webhook", "delivery_target": "https://yourserver.com/webhook-receiver", "is_delivered": false, "authorization_uid": "12345-678" } ], "next": null }
Below are the types of events we can push to your server via webhook request. These types are part of the Event object.
Type | Description | Additional Attributes |
---|---|---|
Testing / Debugging Events | ||
ping |
This is a test event notification that you can trigger manually from your settings. | No additional attributes |
Form Events | ||
form_created |
Triggered when a new Form is created. |
form_uid
- UID String
- The uid of the Form that was created.
|
Authorization Events | ||
authorization_created |
Triggered when a new Authorization is submitted by a customer (i.e. utility account holder). |
authorization_uid
- UID String
- The uid of the Authorization that was created.
|
authorization_declined |
Triggered when a customer declines an Authorization. |
authorization_uid
- UID String
- The uid of the declined Authorization that was created.
|
authorization_renewed |
Triggered when an existing Authorization has been re-submitted or renewed by the customer. This typically happens when a customer extends the expiration for an authorization. |
authorization_uid
- UID String
- The uid of the Authorization that was updated.
|
authorization_update_started |
Triggered when we start verifying an Authorization, which includes updating the meter list associated with the Authorization. |
authorization_uid
- UID String
- The uid of the Authorization that is being updated.
|
authorization_update_delayed |
Triggered when updating an Authorization has been delayed. This usually happens when we are waiting on something from the utility (e.g. they need to push us the meter list) or customer (e.g. they need to submit a code for two-factor-authentication). |
authorization_uid
- UID String
- The uid of the Authorization that is being updated.
|
authorization_update_retrying |
Triggered when we encountered an error, and will be automatically retrying in a moment. This usually happens when the utility times out or is down for maintenance. Check the Authorization's retrying note for an estimated time of retry. |
authorization_uid
- UID String
- The uid of the Authorization that is being updated.
|
authorization_update_progress |
Triggered when significant progress has been made updating an Authorization, but the task is not yet complete. This usually happens when authorization forms have multiple steps and one of the steps is completed. |
authorization_uid
- UID String
- The uid of the Authorization that is being updated.
|
authorization_update_finished_successful |
Triggered when the task updating an Authorization
has completed, and the Authorization's status
is updated .
|
authorization_uid
- UID String
- The uid of the Authorization that was updated.
|
authorization_update_finished_errored |
Triggered when task updating an Authorization
has completed, but we encountered errors from the utility during collection.
Check the Authorization's notes
for what happened.
|
authorization_uid
- UID String
- The uid of the Authorization that was updated.
|
authorization_expired |
Triggered when an existing Authorization has expired. We delete access credentials when a authorization expires, so we will not be able to collect any additional utility data. If you want to continue to be able to collect data for this Authorization or its Meters, you need to send the customer a re-authorization form. |
authorization_uid
- UID String
- The uid of the Authorization that was updated.
|
authorization_revoked |
Triggered when an existing Authorization has been revoked. We delete all collected data (including bill and interval data) and access credentials when a authorization is revoked. If you want to get access again for this Authorization or its Meters, you need to send the customer a new authorization form. |
authorization_uid
- UID String
- The uid of the Authorization that was updated.
|
Meter Events | ||
meter_created |
Triggered when we find a new Meter. You will usually see this during Authorization updates (e.g. when we build the meter list). You may also see this event when we perform historical collection tasks and happen to find new meters associated with the Authorization. |
|
meter_bills_added |
Triggered when we find new Bills
associated with a Meter. You will usually see this event during
historical collections
tasks. Check the Meter's
bill_count and
bill_coverage
to see what bills were added.
|
|
meter_intervals_added |
Triggered when we find new Intervals
associated with a Meter. You will usually see this event during
historical collections
tasks. Check the Meter's
interval_count and
interval_coverage
to see what intervals were added.
|
|
meter_historical_collection_started |
Triggered when we start collecting historical data for a Meter. |
|
meter_historical_collection_delayed |
Triggered when a historical collection for a Meter has been delayed. This usually happens when we are waiting on something from the utility (e.g. they need to push us the data) or customer (e.g. they need to submit a code for two-factor-authentication). |
|
meter_historical_collection_retrying |
Triggered when we encountered an error, and will be automatically retrying in a moment. This usually happens when the utility times out or is down for maintenance. Check the Meter's retrying note for an estimated time of retry. |
|
meter_historical_collection_progress |
Triggered during the process of collecting historical data for a meter. Currently this event is only fired once at the beginning of each collection. |
|
meter_historical_collection_finished_successful |
Triggered when historical collection for a Meter
has completed, and the Meter's status
is updated .
|
|
meter_historical_collection_finished_errored |
Triggered when historical collection for a Meter
has completed, but we encountered errors from the utility during collection.
Check the Meter's notes
for what happened.
|
|
Extras | ||
Extensible: We may add variants to this enumeration type in the future, so be able to handle unknown values gracefully. |
When an Event object is created,
is_delivered
is false
. Here's our logic for successfully delivering events:
POST ...
)
to the endpoint on your server that you configured during setup.
200 OK
HTTP response code back from your server, we
mark is_delivered=true
for all the events in the webhook request.
4xx
, 5xx
, etc.),
we start retrying to send the webhook request every hour for 72 hours.
200 OK
response, you may receive newer events before you receive older events
(e.g. if the older event failed, and is waiting to retry).
If your server goes down and you want to see what events you missed, you can look them up on our /events API endpoints. These API endpoints have the same Event formats as what we POST to your server. You can also manually update the delivery status of undelivered events so we will stop retrying to push them to you.
We cryptographically sign every webhook request made to your server using SHA-256 . We hash the webhook endpoint secret from your settings plus a salt and the webhook request body, joined with periods (".").
SHA256("<secret>.<salt>.<body>")
For example, say you receive the following request to your webhook endpoint:
POST /notify-me HTTP/1.1 Host: localhost:8888 Connection: keep-alive Accept-Encoding: gzip, deflate Accept: */* User-Agent: UtilityAPI Bot X-UtilityAPI-Webhook-Signature: 285783a12faafd0c991f131ccb08514481f2c728a303e309955b6f474012bb37 X-UtilityAPI-Webhook-Salt: E7EB2SFcv8JSDbaH Content-Type: application/json Content-Length: 320 { "events": [ { "delivery_method": "webhook", "delivery_target": "http://localhost:8888/notify-me", "is_delivered": false, "ts": "2018-03-03T01:05:28.119646+00:00", "type": "ping", "uid": "2229" } ], "next": null }
Here's how you can verify the X-UtilityAPI-Webhook-Signature header in Python 3.
$ python3 >>> from hashlib import sha256 >>> secret_from_settings = "vWU36X4C6Y9gm7wkrw7RUdATmGejHpNs" # Get this from your settings >>> salt_from_header = "E7EB2SFcv8JSDbaH" >>> webhook_body = """{ ... "events": [ ... { ... "delivery_method": "webhook", ... "delivery_target": "http://localhost:8888/notify-me", ... "is_delivered": false, ... "ts": "2018-03-03T01:05:28.119646+00:00", ... "type": "ping", ... "uid": "2229" ... } ... ], ... "next": null ... }""" >>> combined_string = "{}.{}.{}".format(secret_from_settings, salt_from_header, webhook_body) >>> sha256(combined_string.encode("utf-8")).hexdigest() '285783a12faafd0c991f131ccb08514481f2c728a303e309955b6f474012bb37' # ^ This is the same as the X-UtilityAPI-Webhook-Signature above