Subscriptions and Webhooks
Snapdocs Connect facilitates the signing experiences for wet, full eClose, and hybrid signing activities. To build trust that Snapdocs is facilitating the closings as expected, Snapdocs Connect offers a broadcast of status and document events, such that connected systems can bring transparency back to the loan. We also offer document events that support the automation of downstream actions, such as downloading signed and executed packages back to the system of record.
Webhooks allow you to subscribe to events happening with the closings. Rather than making an API call when an event happens, Snapdocs Connect can send an HTTP request to an endpoint in your system. You can configure subscribed events in your using the API endpoints detailed below.
Follow the below steps to set up the notifications:
- Designate an existing endpoint from your ecosystem to trigger the appropriate work in order to download the signed documents from Snapdocs.
- Add a subscription to the event you would like to be notified using the URL from the previous step.
Manage subscriptions
Reference the Subscriptions documentation for more details about the available subscription APIs.
Subscription Events
Listed below are few examples of subscription events.
Event | Description |
---|---|
borrower.esigning_available | A borrower has been prompted to eSign a closing package. |
borrower.esigning_complete | A borrower has eSigned a closing package. |
borrower.preview_available | Closing documents are available for a borrower to review. |
borrower.preview_complete | A borrower has reviewed closing documents. |
document.created | A closing document has been generated. |
status.changed | An event resulting in a closing Status change has been generated. |
Please see Create a subscription for the complete list of subscribable events.
Webhooks (Listeners)
The endpoint at the URL you specify in webhooks settings will receive requests from Snapdocs Connect like the following:
Method type: POST
Headers:
- Content-Type:
application/json
The webhook event object
Key | Type | Description |
---|---|---|
event_id | String | A unique identifier for the event object. |
closing_uuid | String | The internal unique identifier for a Snapdocs closing. |
event_name | String | The name of the event being broadcast via the webhook. |
created_at | Integer | The Unix timestamp for when the event was generated. |
Payload | Object | An object containing additional information about the event. |
Example webhook payload
{
"event_id": "572f592a-fbec-49d9-a28a-88d8e38175be",
"closing_uuid": "d679e2ad-278d-e547-9756-84639ba3865b",
"event_name": "borrower.preview_available",
"created_at": 1618936005,
"payload": {
"external_identifiers": [{
"external_system": "other_los",
"external_type": "file_number",
"value": "1234"
}]
}
}
external_identifiers may have 0 or more records .
Handle the Snapdocs requests
-
Event type — 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.
-
Handle duplicate events — Webhook endpoints might occasionally receive the same event more than once. We advise you to guard against duplicated event receipts by making your event processing idempotent.
-
Verify events are sent from Snapdocs — Use webhook signatures to verify if the events are sent from Snapdocs.
-
Verify event timestamp — We do not guarantee that you get these notifications in the order they occurred. Please use the timestamp in the event object for each notification to determine when the notification occurred.
Webhook responses
If the webhook arrives successfully, please respond with a 200 Http status. We encourage client integrations to use different Http status if webhook does not arrive successfully or if webhook's request processing fails.
Respond with a 200 upon successful arrival of webhook prior to processing an event and regardless of success in event processing.
If Snapdocs does not receive a 200 response, Snapdocs will attempt to redeliver the webhook event. Snapdocs retries run at an exponential backoff over the course of many hours.
Please refer to the response examples below for success and bad requests.
HTTP/1.1 200 OK
Content-Type: application/json
{
"status": "OK",
"code": 200,
"message": "webhook received successfully"
}
HTTP/1.1 400 Bad Request
Content-Type: application/json
{
"status": "Bad Request",
"code": 400,
"message": "[reason for failure]"
}
Retries
If your service has problems handling notifications at any time, we will attempt to re-send failed notifications up to 13 times over the course of 24 hours from the first attempt, with increasing durations between each subsequent attempt.
Example webhook service
Below is a simple AWS Lambda function to demonstrate the webhook at Lenders.
import json
import os
import logging
logger = logging.getLogger()
LOG_LEVEL = os.environ.get('LOG_LEVEL', 'WARNING').upper()
logger.setLevel(level=LOG_LEVEL)
success_code = 200
success_body = {
"status": "OK",
"code": success_code,
"message": "webhook received successfully"
}
def download_scanback_document(document_uuid):
logger.info("downloading scanback document %s", document_uuid)
pass
def process_snapdocs_event(event_body):
try:
# check event body
logger.debug("%s %s %s", event_body.get('event_id'), event_body.get('closing_uuid'),
event_body.get('event_name'))
logger.debug("lender system attributes %s", event_body.get("payload"))
# typically we put the message into a message broker to be processed downstream
if event_body.get('event_name') == 'document.created':
if event_body.get('document_type') == 'scanback_documents':
download_scanback_document(event_body.get('document_uuid'))
except Exception as e:
logger.error(e)
return 500, {
"status": "Failed to process event",
"code": 500,
"message": f"webhook received but could not process {str(e)}"
}
return success_code, success_body
def handle(event, context):
code = success_code
response_body = success_body
try:
if event['body']:
body = json.loads(event['body'])
code, response_body = process_snapdocs_event(body)
else:
raise "no data found in the post body"
except Exception as e:
code = 400
response_body = {
"status": "Bad Request",
"code": code,
"message": f"failed to parse the webhook, {str(e)}"
}
finally:
return {"statusCode": code, "body": json.dumps(response_body)}
Note that in production the web listener more likely will return 200
status code upon receiving the message, and push it to a message broker or queue to have it processed by downstream systems.
Updated about 2 years ago