Webhooks (Real-Time Events)

How use DigiFi's webhooks to receive real-time updates.

Overview of DigiFi Webhooks

DigiFi's platform offers webhooks that will push real-time notifications to your external applications when events occur. Webhooks provide a powerful way to track the state of applications and to implement automated actions from other applications.

Webhooks are particularly useful for:

  • Notifying you of asynchronous events, such as when a borrower completes an action (e.g. submitting an application, uploading a document, providing additional information, etc.).
  • Acting as triggers for event-based automation (e.g. integrations, decisioning, status changes, emails, etc.).

DigiFi uses HTTPS to send these notifications to your application as a JSON payload. You can then use these notifications to execute actions in your backend systems.


Settings Up Webhooks

To begin receiving and processing webhook events from DigiFi, follow these steps:

  1. Identify the type(s) of events you want to listen for.
  2. Create a webhook endpoint as an HTTP endpoint (i.e. URL) on your local server.
  3. Parse event objects sent by DigiFi and return 2xx response status codes.
  4. Deploy your webhook endpoint to a publicly accessible HTTPS URL.
  5. Connect your HTTPS URL to DigiFi's platform in the DigiFi Webhooks UI.

Step 1: Identify Which Events You Want To Monitor

A single webhook endpoint can listen for one or multiple types of events and DigiFi's platform emits the following types of events:

Event TypeDescription
application.createdOccurs when applications are created.
application.updatedOccurs when applications are updated.
application.deletedOccurs when applications are deleted.
applicationDecisionProcessedOccurs when decision ran for an application.
externalIntegration.processedOccurs when external integration is processed.
borrower.createdOccurs when borrowers are created.
borrower.updatedOccurs when borrowers are updated.
borrower.deletedOccurs when borrowers are deleted.
intermediary.createdOccurs when intermediaries are created.
intermediary.updatedOccurs when intermediaries are updated.
intermediary.deletedOccurs when intermediaries are deleted.
document.createdOccurs when documents are created.
document.updatedOccurs when documents are updated.
document.deletedOccurs when documents are deleted.
note.createdOccurs when notes are created.
note.updatedOccurs when notes are updated.
note.deletedOccurs when notes are deleted.
task.createdOccurs when tasks are created.
task.updatedOccurs when tasks are updated.
task.deletedOccurs when tasks are deleted.

👍

Best Practice: Only Listen For Relevant Events

Your webhook endpoints should be configured to receive only the types of events required by your integration. Listening for extra events (or all events) will put undue strain on your server and is not recommended.

You can change the events a webhook endpoint will receive by navigating to an endpoint within the DigiFi platform.


Step 2: Create A Webhook Endpoint On Your Local Server

Set up an HTTP endpoint on your local machine that can accept unauthenticated webhook requests with a POST method.

For example, this is a route written in Express (Node.js). The /webhooks route is configured to accept only POST requests and expects data to be delivered in a JSON payload.

const express = require('express');

const app = express();

app.post('/webhooks', (req, res) => {
  res.status(200).send({});
});

app.listen(3000, () => {
  console.log(`Example app listening at http://localhost:3000`)
});

Step 3: Parse Event Objects And Return 2xx Responses

Your endpoint must be configured to read event objects for the type of event notifications you want to receive. DigiFi sends events to your webhook endpoint as part of a POST request with a JSON payload.

Check Event Objects
Each event is structured as an event object with a eventId, eventType and related event data nested under the data. Your endpoint must check the event type and parse the payload of each event.

Within the data section, there are two main subsections:

  • previousObject provides the data prior to the change that triggered the event.
  • object provides the updated data (after the change that triggered the event).

These subsections only appear if relevant. For example, in a application.created event only object will appear, but in an application.updated event both previousObject and object``` will appear.

{
  "eventId": "619r70gb56df8c78wfcb0c",
  "eventType": "application.updated",
  "createdAt": "2021-11-18T12:50:41.894Z",
  "data": {
    "previousObject": {...},
    "object": {...}
}

By comparing the information within previousObject and object, you can identify which field(s) changed
as well as the information, both before and after the change.

Return A 2xx Response

Your endpoint must quickly (within 6 seconds) return a successful status code (2xx) prior to any complex logic that could cause a timeout. For example, you must return a 200 response before running another integration within the DigiFi platform.

const express = require('express');

const app = express();

app.post('/webhooks', (req, res) => {
  switch (req.body.eventType) {
    case 'application.created': {
      handleApplicationCreate();
    }
    case 'application.updated': {
      handleApplicationUpdate();
    }
  }

  res.status(200).send({});
});

app.listen(3000, () => {
  console.log(`Example app listening at http://localhost:3000`)
});

Built-In Retries

DigiFi webhooks have built-in retry methods for failed requests:

Retry NumberTiming
15 minutes after the actual request
215 minutes after the prior retry
330 minutes after the prior retry
41 hour after the prior retry
52 hours after the prior retry
64 hours after the prior retry
78 hours after the prior retry

After 24 hours if there are no successful events, we will:

  • Email all users with the permission level of the Owner, as well as the users that created and most recently updated the endpoint in DigiFi’s platform informing them that the endpoint has experienced continuous failures and that the issue needs to be addressed within the next 24 hours.
  • Automatically disable the endpoint (if you haven’t addressed the issue and the issue persists beyond the 48-hour period).

Handling Duplicate Events

Your webhook endpoints might occasionally receive the same event more than once. You can guard against duplicate events by logging the eventId of events you’ve processed, and then checking future events against this.


Step 4: Deploy Your Endpoint To A Public HTTPS URL

To begin receiving events from DigiFi, you must deploy your endpoint to a publicly accessible HTTPS URL.

👍

Receive Events With An HTTPS Server

If you use an HTTPS URL for your webhook endpoint, DigiFi validates that the connection to your server is secure before sending your webhook data. For this to work, your server must be correctly configured to support HTTPS with a valid SSL certificate.


Step 5: Register Your Public URL In DigiFi's Webhooks Dashboard

Once you've deployed your endpoint to a public HTTPS URL, you can add the endpoint to DigiFi's platform through our webhooks dashboard.

To add an endpoint to DigiFi's platform:

  • Navigate to General Settings > Developers > DigiFi Webooks
  • Click the Add Endpoint button

This will open a form with the following information:

FieldDescription
URLThe public HTTPS URL your endpoint was deployed to.
DescriptionA brief description of your webhook.
Listening ForThe event(s) that your endpoint will listen for.
Data SourceThe environment in which webhooks should be configured to receive the event (Production Mode and/or Testing Mode)
StatusA toggle to decide whether your endpoint should immediately be activated (if not, you can activated it later).

Once you have completed the form, click Add Endpoint. Your endpoint will be created and you'll begin receiving events immediately if your endpoint was activated.

You will be able to see all events related to this endpoint in the "Events" tab, and the "Integration" tab provides your Webhook Secret Key, which you can use to further secure your endpoint (suggested).


Secure Your Webhooks Endpoint

To let you verify that events were sent by DigiFi (not by a third party), DigiFi can optionally sign the webhook events it sends to your endpoints by including a signature in each event’s x-digifi-signature header.

You can verify signatures either using DigiFi's Official Node.js library, or using your own solution.

Before you can verify signatures, you need to retrieve your endpoint’s secret from within the DigiFi platform by navigating to this specific webhook and clicking on the "Integration" tab.

DigiFi generates a unique secret key for each endpoint. Additionally, if you use multiple endpoints, you must obtain a secret for each one you want to verify signatures on.

👍

Highly Recommended To Increase Security!

Security your endpoint provides increased security for your overall application. It is highly recommended that all organizations who implement DigiFi Webhooks secure their endpoints.


Verify Signatures Using DigiFi's Node.js Library

When using DigiFi's library to verify signatures, you perform the verification by providing:

  • the event payload,
  • the x-digifi-signature header,
  • the x-digifi-event-timestamp, and
  • the endpoint’s secret.

If verification fails, DigiFi returns an error.

const express = require('express');
const digifi = require('digifi-node-js');
const bodyParser = require('body-parser');

const app = express();
const endpointSecret = '...';

app.post('/webhooks', bodyParser.raw({ type: 'application/json' }), (req, res) => {
  const timestamp = req.headers['x-digifi-event-timestamp'];
  const signature = req.headers['x-digifi-signature'];
  
  if (!digifi.verifyWebhookSignature(req.body, endpointSecret, timestamp, signature)) {
    res.status(400).send({ message: 'Invalid signature' });
    
    return;
  }
  
  if (!digifi.verifyWebhookTimestamp(timestamp)) {
    res.status(400).send({ message: 'Invalid timestamp' });
    
    return;
  }

  switch (req.body.eventType) {
    case 'application.created': {
      handleApplicationCreate();
    }
    case 'application.updated': {
      handleApplicationUpdate();
    }
  }

  res.status(200).send({});
});

app.listen(3000, () => {
  console.log(`Example app listening at http://localhost:3000`)
});

Preventing Replay Attacks

A replay attack is when an attacker intercepts a valid payload and its signature, then re-transmits them. To mitigate such attacks, DigiFi includes a timestamp in the x-digifi-event-timestamp header. Because this timestamp is part of the signed payload, it is also verified by the signature, so an attacker cannot change the timestamp without invalidating the signature. If the signature is valid but the timestamp is too old, you can have your application reject the payload.

Our libraries have a default tolerance of five minutes between the timestamp and the current time. You can change this tolerance by providing an additional parameter when verifying signatures. Use Network Time Protocol (NTP) to ensure that your server’s clock is accurate and synchronizes with the time on DigiFi's servers.

DigiFi generates the timestamp and signature each time an event is sent to your endpoint. If DigiFi retries an event (e.g., your endpoint previously replied with a non-2xx status code), then a new signature and timestamp is generated for the new delivery attempt.


Verifying Signatures Manually

DigiFi generates signatures using a hash-based message authentication code (HMAC) with SHA-256.

Although it’s recommended to use our official libraries to verify webhook event signatures, you can create a custom solution by following these steps.

Step 1: Extract The Timestamp And Signatures From The Header
Retrieve the x-digifi-event-timestamp and x-digifi-signature from request headers.

Step 2: Prepare The signed_payload String
The signed_payload string is created by concatenating:

  • The timestamp (as a string),
  • The character ".", and
  • The actual JSON payload (i.e., the request body)

Step 3: Determine The Expected Signature
Compute an HMAC with the SHA256 hash function. Use the endpoint’s signing secret as the key, and use the signed_payload string as the message.

Step 4: Compare The Signatures
Compare the signature (or signatures) in the header to the expected signature. For an equality match, compute the difference between the current timestamp and the received timestamp, then decide if the difference is within your tolerance.

To protect against timing attacks, use a constant-time string comparison to compare the expected signature to each of the received signatures.