Webhooks

EnergyCAP webhooks:

  • Send automatic HTTP requests containing EnergyCAP data to custom URLs
  • Extend the functionality of the application
  • Provide a method to integrate with other systems

Why Webhooks?

Many times, integrated systems that connect to a primary system (EnergyCAP) must determine when to act. Without a webhook feature, the integrated system must poll the primary system until some condition is met. Polling is inefficient because most of the time the trigger condition does not occur.

By contrast, webhooks represent a “don’t call us, we’ll call you” approach to trigger functionality in integrated systems. A webhook configured for an event in EnergyCAP will notify the integrated system when that event occurs.

Webhook Configuration

Create webhook

You manage EnergyCAP webhooks with the UI or with the webhook management APIs.

  1. Give each webhook a descriptive name, a description, and email addresses for failure notifications.
  2. Select an event to trigger the webhook.
  3. Each webhook requires a target URL. This URL is where the webhook request is sent and must be an accessible web address where custom code is implemented to handle the webhook when it is fired.
  4. Each webhook also requires a secret string value. This secret is used to generate the signature which is sent with every webhook request and is used to verify the webhook’s authenticity. See Signature Verification for more. Webhooks are active by default and will immediately begin sending requests when their configured events occur. They can be manually deactivated using the Edit Webhook view.
Event Name ID Type Trigger Conditions
Account Create Account ID Account created
AP Export Task ID Bills exported to AP
AP Export Reversal Task ID Bills unexported from AP
Batch Closed Batch ID Batch of bills closed by invoking the Close Batch API, as a side effect of APIs which allow closing an open batch while creating a new one, (e.g. Bill Import) or creating a “self-contained” batch which is created “closed” (e.g. import bills, process Chargebacks, process Accruals, reverse bills).
Bill Created Bill ID Bill created
Bill Edited Bill ID Bill edited
Bill Analyzed and Reportable Bill ID Post-processing completed after bill created or edited (includes calendarization, normalization, GHG factors, reporting data such as Bill/Account/Meter data and statistics)
Building Create Place ID Building created
Custom Account Action Account ID Custom account action triggered from Actions menu when viewing an account
Custom Application Action Custom application action triggered from Gear icon in the application
Custom Bill Action Bill ID Custom bill action triggered from bill list
Custom Meter Action Meter ID Custom meter action triggered from Actions menu when viewing a meter
GL Export Task ID Bills exported to GL
GL Export Reversal Task ID Bills unexported from GL
Meter Create Meter ID Meter created


Webhook Behavior

Regular Webhooks

Most of the time a configured event triggers an EnergyCAP webhook, such as a bill being created, or a building being edited.

Regular webhooks:

  • Asynchronous
  • Possibly delayed firing
  • Retry policy
  • Failure notifications

Webhooks are triggered asynchronously, meaning when an API request fires the webhook, the webhook does not add any additional time to the API request. For example, when a bill is created, if webhooks exist for the Create Bill event, the API caller does not wait any additional length of time before the API response is returned.

However, this also means that there could be a delay between receipt of the triggering API response and the firing of the webhook.

EnergyCAP uses a queueing mechanism for webhook execution, so while near-instantaneous webhook firing could occur after a triggering API call, it is not guaranteed. There may be other queued actions waiting in line in front of the webhook. If a regular webhook fails, an automatic retry policy takes effect. A failure consists of the response to the webhook request having an HTTP response code not falling within the 2XX range. For example, a 204 No Content status code is considered a success, while a 404 Not Found status code is considered a failure and is retried.

A common reason for a webhook failure is when there is a lapse in internet connectivity or unavailability of the server receiving the webhook, resulting in a 502 Bad Gateway. If the webhook encounters this scenario and the retry schedule is exhausted, EnergyCAP will write a webhook log with a status code of 0, not making any assumptions about what would have happened if the server had been online. However, if the server comes back online during the retry schedule, the failed webhook would then succeed (barring other failures).

Webhook retry schedule:

  • If a webhook request fails, it retries in 5 minutes.
  • If it fails again, it retries in 10 minutes.
  • If all 3 attempts fail, this webhook execution is considered a failure, and a failure entry is written to the webhook log. An email is sent to the webhook’s mailing list with failure details

A webhook is disabled after 10 consecutive failures and a failure notification email is sent. It must be manually reactivated.

Custom Bill Actions

Custom bill action

Custom bill action webhooks target bill custom action events and are only triggered by specific API endpoints.

  • Fire instantaneously
  • Synchronous
  • Guaranteed to have fired
  • No retry policy
  • No failure emails

Execute a custom bill action from any bill list.

  1. Select one or more bills.
  2. From the Bill List actions menu, select the webhook to fire.
  3. Confirm the action and trigger the action.
  4. A result banner is displayed.

Custom Bill Action success

A green banner displays the success message.

Custom Bill Action fail

A yellow banner displays the error message.

Custom code which returns error messages in the following format will have the contents of the message property displayed instead of the default message:

{
    "status": {
        "message": "Custom code could not process bill ID 1234"
    }
}

Custom Bill Action fail with custom message

More information on API endpoints that trigger custom bill actions:

Webhook Log

Webhook log

You review the webhook execution details using the “Webhook Log” view, visible by clicking on the success percentage of a webhook in the “API Keys and Webhooks” view.

Webhook log

The webhook log displays success and failure statuses for webhook executions.

Each log entry displays

  • the local time of the webhook call
  • the HTTP status code received from the webhook request
  • a link to view the Webhook Log Details

The webhook log is preserved for the past 3 days unless that data is less than 100 rows. Then, only 100 rows are kept.

Webhook Log Details

Webhook log details

The Webhook Log Details pane shows details from the webhook request and the response received from the target server. The HTTP status code from the target server is shown at the top.

The request shows

  • headers and their values from the EnergyCAP webhook request
  • the request body from the EnergyCAP webhook request

The response shows

  • headers and their values from the target server’s response
  • the body from the target server’s response

Webhook Request Anatomy

All EnergyCAP webhook requests have the same structure, specifically the provided request headers and body (although the contents differ). The user configures the webhook URL when it is created. Below is an example of a raw EnergyCAP webhook request, followed by an explanation of each part:

https://energycap-webhook-receiver.example.com/custom?debug=false
"Content-Length": 138
"Content-Type": "application/json; charset=utf-8"
"ECI-Signature": "4DBB070C719E66D748A972B963DB1D1BEC7C8A181DA876EF9D015A5743D25B5B",
{
    "ids": [
        1995696,
        1999706,           
        2006157
    ],
    "eventType": "Bill Custom Action",
    "meta": {
        "userId" : "1024"
    }
}

Webhook URL:

  • The webhook request URL will be exactly what is configured for the webhook itself; EnergyCAP does not modify the URL in any way.

Webhook Headers:

  • Content-Type - EnergyCAP always sends webhooks with a content type of application/json since the webhook payload is a JSON object.
  • ECI-Signature – This header contains an HMAC/SHA256 encrypted signature for optional (but recommended) verification that:
    1. the request has come from the expected webhook and
    2. the request body has not been tampered with. See Signature Verification for more.

Webhook Body:

  • ids - An array of integer ID values from EnergyCAP. The eventType property determines the IDs. There may be one or many values in this array.
  • eventType - Name of the event which triggered the webhook, such as “Bill Created” or “Building Edited”. It gives context to the contents of the ids property. For example, if the eventType is AP Export, then each ID in ids points to a bill which EnergyCAP has exported to Accounts Payable as part of the triggering event. For details about event types and their corresponding IDs, please refer to Supported Webhook Events.
  • meta - A dictionary which currently has the userId of the user who triggered the webhook.

Signature Verification

EnergyCAP provides the ECI-Signature header as part of the webhook payload. It contains an opaque string that represents an HMAC/SHA256 hash of the webhook request body with all whitespace removed. The hash of the body is computed using the secret configured with the webhook. Any dashes between bytes are removed.

It is a best practice to add signature verification to any system which receives EnergyCAP webhooks.

Using the HMAC/SHA256 strategy protects against fraudulent requests by:

  1. ensuring that the sending system (EnergyCAP) and the receiving system share the same webhook secret and
  2. ensuring that no middleman has tampered with the request body since the signature was generated.

Below is an example of C# code which verifies the signature of an EnergyCAP webhook request:

using System;
using System.Text;
using System.Security.Cryptography;

private bool VerifySignature(string webhookSecret, string rawWebhookPayload, string webhookSignature)
{
    // Remove all whitespace from request body before computing signature.
    // The receiving code should accept the webhook request verbatim, but you'll need to remove the 
    // whitespace when computing the hash value, otherwise you'll get a different hash value than 
    // what EnergyCAP generates.
    var payloadNoWhitespace = rawWebhookPayload
            .Replace(Environment.NewLine, "")
            .Replace(" ", "");

    var secretBytes = Encoding.UTF8.GetBytes(webhookSecret);
    var payloadBytes = Encoding.UTF8.GetBytes(payloadNoWhitespace);

    // Compute signature
    using (var hashFunction = new HMACSHA256(secretBytes))
    {
        var hash = hashFunction.ComputeHash(payloadBytes);
        var computedSignature =  BitConverter.ToString(hash).Replace("-", "");

        // If we computed the same value as the webhook signature, it has been verified
        return computedSignature == webhookSignature;
    }
}

Custom Development Considerations

Consider the following when developing integrations which receive and act upon EnergyCAP webhook requests.

  • Plan to verify the webhook requests according to Signature Verification. This protects your system from fraudulent requests.
  • Be intentional about responding to EnergyCAP webhook requests with success or failure messages. Remember that per Regular Webhook Behavior, any non-2XX HTTP status code will be treated as a failure and retried, except in the case of Custom Bill Actions. Consider always returning a success message to EnergyCAP and using a different mechanism to alert failures in custom code.
  • Implement handling logic for the ids array by eventType. Because the webhook payload is always the same structure, if your solution expects Account IDs but receives Place IDs, unexpected behavior could result.
  • Build for idempotency and prepare for the possibility of chain reactions, especially if using multiple webhooks tracking identical or related event types. If a webhook is configured for Bill Edit, and your custom code edits a bill, you could trigger another Bill Edit or worse, an infinite loop!
  • Remember that a webhook request could contain many IDs, especially for bulk event types such as AP Export or Custom Bill Actions. You might consider batching any handling in custom code.
  • It is possible to provide additional information to the integrated system via the webhook URL. If webhook-specific settings are required, they could be passed via query parameters set in the webhook URL. For example, the following URL provides two variables, param1 and param2, to the integrated system: https://ecap-webhook-catcher.com/custom?param1=foo&param2=bar.