Skip to content

Latest commit

 

History

History
377 lines (269 loc) · 25.9 KB

webhooks.md

File metadata and controls

377 lines (269 loc) · 25.9 KB

Webhooks in Adobe Sign v6

On this page

Overview

Webhooks are HTTPS callbacks that receive real-time notification messages for events. When the event occurs, the service makes an HTTPS POST request to the webhook's HTTPS URL. In simple words, a webhook is a web service that accepts HTTPS POST requests (rather, listens to requests) from a source. As a developer, you can create webhooks in Adobe Sign to listen to events happening for your agreements and other resources. The webhooks can be created using REST APIs as well as the Adobe Sign web application.

How do webhooks work?

Webhooks are a useful tool for apps that want to receive and process real-time data updates happening in Adobe Sign; for example, after an agreement is signed, update the status of that agreement in an on-premises Content Management System like SharePoint.

Instead of requiring your application to make an API call every X number of minutes to check for a specific event in Sign (also known as polling), you can now register webhooks in Adobe Sign, which will push HTTPS POST notifications to your webhook’s URL telling your application that the event has occurred. This push-based model requires fewer API requests overall and provides you with real-time updates, allowing you to build more robust apps and update your application instantly.

Adobe Sign webhooks notifications are generated by changes to the agreement as it progresses from creation to sending to completed or aborted state. In the webhook notification, we provide updated information about the status of these agreements, optionally including the detailed agreement information, information about the documents, participants information and finally, the signed document.

A simple workflow for webhooks:

  1. A webhook client application (your app) calls POST /webhooks with a user token to register (“create”) a webhook for a resource.

  2. Adobe Sign validates that the request and the webhook URL is valid. There is a defined mechanism for this validation where Adobe Sign makes an HTTPS GET request (with the calling application's client ID in a custom HTTPS request header) to the webhook URL and the webhook URL is expected to respond in a specific way; see Verification of intent.

  3. Adobe Sign sends a success response (any HTTPS 2XX code) to your client app with the unique webhook identifier and Location header, which contains the URL of the webhook resource created in Adobe Sign.

  4. Whenever an event happens in Sign, a notification for that event will be sent to the webhook URL.

Creating a webhook

Prerequisites

Before you can create webhooks in Adobe Sign, you must complete the following prerequisites:

  1. Obtain a unique set of application credentials (an application ID and an application secret). Account administrators can generate these credentials through the Adobe Sign API page under "My Profile".

  2. Webhook API calls require an OAuth Access Token. Each operation on a resource requires specific OAuth scope(s), and your application will need to request all of the needed scopes during the OAuth authorization process.

  3. Use the access token received from the OAuth authentication and authorization process in the following REST endpoints to perform operations on behalf of the user who authorized the API access.

OAuth scopes for webhooks

To call webhook APIs, you must enable webhook scopes for your application. The scopes webhook_read, webhook_write, and webhook_retention are needed to call GET, POST/PUT and DELETE APIs respectively.

Configure a webhook and subscribe to events

To create a webhook in Adobe Sign, you must configure a webhook URL and register it as a webhook with Adobe Sign, specifying the events on which the notifications should be sent. This can be done by calling the POST /webhooks API from the client application, passing along the subscription data. The subscription specifies how a subscriber intends to consume events. The first requirement is the foundation by which the subscriptions are managed. At the most basic level, a subscription really needs the following fields:

  • An event name: The names of events to which you want to subscribe

  • A resource type and corresponding resource identifier

  • A webhook URL, to receive event notifications from Adobe Sign: This is the URL where your webhook will listen for HTTPS POST notifications sent by Adobe Sign for all the events to which you’ve subscribed.

When Adobe Sign receives a webhook creation call from your app, the Sign service first verifies the intent of the webhook URL by making a GET call (see the next section) to the webhook URL. If that call succeeds, the Sign service then returns the response of the POST call, with the URL of the newly created webhook resource contained in the HTTPS Location header. The client service can later make PUT/GET/DELETE calls on this URL; see the list of APIs for webhook subscription management.

Verification of intent of the webhook URL

Before registering a webhook successfully, Adobe Sign verifies that the webhook URL that is provided in the registration request really intends to receive notifications. For this purpose, when a new webhook registration request is received by Adobe Sign, it first makes a verification request to the webhook URL. This verification request is an HTTPS GET request sent to the webhook URL with a custom HTTP header, X-AdobeSign-ClientId. The value in this header is set to the client ID (Application ID) of the API application that is requesting to register the webhook. To register a webhook successfully, the webhook URL must respond to this verification request with an HTTPS 2XX response code, and it also MUST send back the same client ID value in one of the following two ways.

  • In a custom response header, X-AdobeSign-ClientId. This is the same header which was passed in the request, and can be echoed back in the response.

    Sample: JavaScript

    // Fetch client id
    var clientid = request.headers['X-ADOBESIGN-CLIENTID'];
    
    //Validate it
    if (clientid ==="BGBQIIE7H253K6") //Replace 'BGBQIIE7H253K6' with the client id of the application using which the webhook is created
    {
        //Return it in response header
        response.headers['X-AdobeSign-ClientId'] = clientid;
        response.status = 200;  // default value
    }

    Sample: PHP

    <?php
    // Fetch client id
    $clientid = $_SERVER['HTTP_X_ADOBESIGN_CLIENTID'];
    //Validate it
    if($clientid == "BGBQIIE7H253K6") //Replace 'BGBQIIE7H253K6' with the client id of the application using which the webhook is created
    {
        //Return it in response header
      header("X-AdobeSign-ClientId:$clientid");
      header("HTTP/1.1 200 OK"); // default value
    }
    ?>
  • In the JSON response body of the response with the key of xAdobeSignClientId and its value being the same client ID that was sent in the request.

    Sample: JavaScript

    // Fetch client id
    var clientid = request.headers['X-ADOBESIGN-CLIENTID'];
    
    
    //Validate it
    if (clientid ==="BGBQIIE7H253K6") //Replace 'BGBQIIE7H253K6' with the client id of the application using which the webhook is created
    {
        var responseBody = {
                            "xAdobeSignClientId" : clientid // Return Client Id in the body
                          };
        response.headers['Content-Type'] = 'application/json';
        response.body = responseBody;
        response.status = 200;
    }

    Sample: PHP

    <?php
    // Fetch client id
    $clientid = $_SERVER['HTTP_X_ADOBESIGN_CLIENTID'];
    //Validate it
    if($clientid == "BGBQIIE7H253K6") //Replace 'BGBQIIE7H253K6' with the client id of the application using which the webhook is created
    {
      //Return it in response body
      header("Content-Type: application/json");
      $body = array('xAdobeSignClientId' => $clientid);
      echo json_encode($body);
      header("HTTP/1.1 200 OK"); // default value
    }
    ?>

    Sample JSON response body:

    {
        "xAdobeSignClientId": "BGBQIIE7H253K6"
    }

The webhook will be successfully registered only on a success response (2XX response code) and the validation of the client ID in either the header or response body. The purpose of this verification request is to demonstrate to Adobe Sign that your webhook really does want to receive notifications at that URL. Had you accidentally entered the wrong URL, the webhook would fail to respond correctly to the verification-of-intent request, and Adobe Sign would not send any notifications to that URL. Your app can also validate that it will receive notifications only through webhooks which are registered by a specific application. This can be done by validating the client ID of the application passed in the X-AdobeSign-ClientId header. If the webhook does not recognize that client ID, it MUST NOT respond with the success response code and Adobe Sign will take care that the URL is not registered as a webhook.

The call to verify the webhook URL will be made in the following scenarios:

  • Registering a webhook: If this verification of webhook URL call fails, the webhook will not be created.
  • Updating a webhook: INACTIVE to ACTIVE: If this verification of webhook URL call fails, the webhook state will not be changed to ACTIVE.

How to respond to a webhook notification

Adobe Sign performs an implicit verification of intent in each webhook notification request that is sent to the webhook URL. Every webhook notification HTTPS request contains the customer HTTP header called X-AdobeSign-ClientId. The value of this header is the client ID (Application ID) of the application that created the webhook. We will consider the webhook notification successfully delivered, if and only if a success response (2XX response code) is returned and the the client ID is sent in either the HTTP header (X-AdobeSign-ClientId) or in a JSON response body with key as xAdobeSignClientId and value as the same client ID; otherwise, Adobe Sign will retry to deliver the notification to the webhook URL until the retries are exhausted.

Hosting your webhook in the cloud

Webhooks, as responsive functions, are ideally suited to hosting in the cloud. Several technology vendors have made available cloud-based, on-demand function execution platforms:

  • Adobe I/O Runtime (based on Apache OpenWhisk)
  • IBM Cloud Functions (based on Apache OpenWhisk)
  • Microsoft Azure Functions (how-to)
  • Amazon AWS Lambda Functions (how-to)

These platforms let you place your webhook code in the cloud, where it’s always ready to respond to Adobe Sign; using cloud-based functions offloads the most demanding functionality of your application to the cloud, which lets you build apps that can focus on functionality for the user without worrying about network loads and management.

Webhook properties

Webhook URL

A webhook is an HTTPS-based service that listens at a specific URL for incoming HTTPS POST notification messages that are triggered when events occur. After you configure a webhook to listen on a given URL, note that URL for registering with Adobe Sign. You need this URL to subscribe your webhook to the events for which you want to be notified.

  • The client must include an HTTPS URL to which Adobe Sign can send a POST request. This URL must be available on the public internet. For example, 127.0.0.1 and localhost URIs will not work, since the Adobe Sign Service will not be able to contact your local computer.

  • Make sure your webhook supports POST requests for incoming notifications and GET requests for the verification of intent request.

  • Your webhook URL must not be blocked by a firewall.

Webhook status

  • A webhook can be either active or inactive. By default, a webhook is active.

  • An active webhook will receive requests for events as they occur within Adobe Sign.

  • A webhook marked as inactive will stop receiving event requests. If an event’s request is processing while the webhook is made inactive, this request will finish. Any other existing, unprocessed event requests will be canceled and not sent to your endpoint.

  • If an inactive webhook is made active, it will begin receiving event requests once more as soon as new event requests are created.

Webhook scopes

Currently webhooks are supported at Account, Group, User Account, and Resource levels.

  • Account level webhook: The webhook will be created on a account for all the subscribed events happening in that account. To create an account level webhook, specify the scope as ACCOUNT in the POST /webhooks API call.

  • Group level webhook: The webhook will be created on a group for all the subscribed events happening in that group. To create a group level webhook, specify the scope as "GROUP" in the POST /webhooks API call.

  • User Account level webhook: The webhook will be created for a user for the events happening for that specific user. To create a user level webhook, specify the scope as "USER" in the POST /webhooks API call.

  • Resource level webhook: This will be created for a specific resource. Events specific to this resource will be pushed to the webhook URL. To create a resource level webhook, specify the scope as "RESOURCE", resourceType as AGREEMENT or WIDGET or MEGASIGN, and the resourceId of the resource for which you want to create the webhook in the POST /webhooks API call.

Webhook events

Events are the reason for webhooks: webhooks are a way for your Adobe Sign integration to listen for and respond to Adobe Sign events. Details about webhook events can be found on the Webhook Events page, including:

The following is a list of all webhook events:

AGREEMENT_ACTION_COMPLETED AGREEMENT_OFFLINE_SYNC MEGASIGN_ALL
AGREEMENT_ACTION_DELEGATED AGREEMENT_RECALLED MEGASIGN_CREATED
AGREEMENT_ACTION_REPLACED_SIGNER AGREEMENT_REJECTED MEGASIGN_RECALLED
AGREEMENT_ACTION_REQUESTED AGREEMENT_SHARED MEGASIGN_SHARED
AGREEMENT_ALL AGREEMENT_UPLOADED_BY_SENDER WIDGET_ALL
AGREEMENT_AUTO_CANCELLED_CONVERSION_PROBLEM AGREEMENT_USER_ACK_AGREEMENT_MODIFIED WIDGET_AUTO_CANCELLED_CONVERSION_PROBLEM
AGREEMENT_CREATED AGREEMENT_VAULTED WIDGET_CREATED
AGREEMENT_DOCUMENTS_DELETED AGREEMENT_WEB_IDENTITY_AUTHENTICATED WIDGET_DISABLED
AGREEMENT_EMAIL_BOUNCED AGREEMENT_WORKFLOW_COMPLETED WIDGET_ENABLED
AGREEMENT_EMAIL_VIEWED LIBRARY_DOCUMENT_CREATED WIDGET_MODIFIED
AGREEMENT_EXPIRED LIBRARY_DOCUMENT_AUTO_CANCELLED_CONVERSION_PROBLEM WIDGET_SHARED
AGREEMENT_KBA_AUTHENTICATED LIBRARY_DOCUMENT_MODIFIED  
AGREEMENT_MODIFIED LIBRARY_DOCUMENT_ALL  

Webhook conditional parameters

When you register or update a webhook, you can specify whether you want to receive the minimum payload or detailed info such as participant info, document info, and more details using these parameters. By default, all the conditional parameters are set to false and Adobe Sign will send the minimum payload (resourceId, status and name) in the payload info. Specify the following conditional parameters in the API request to receive the corresponding details in the payload:

Agreement

  • includeDetailedInfo: Determines whether agreement detailed info will be returned in the response payload. Based on the state of the agreement and the event being notified, the keys in the JSON payload will change.

  • includeDocumentsInfo: Determines whether document info will be returned in the response payload. This might or might not be applicable in a specific event’s payload.

  • includeParticipantsInfo: Determines whether participants info will be returned in the response payload; the participants info JSON keys will change based on the event being notified. For example, an AGREEMENT_CREATED event does not contain the key for nextParticipant, while the AGREEMENT_ACTION_REQUESTED event will have it.

  • includeSignedDocuments: Determines whether signed documents will be returned in the webhook response payload. If set to true, the signed document will be returned in base64-encoded format in JSON when signing is complete. This will be sent only in the notification for the AGREEMENT_WORKFLOW_COMPLETED event.

Library Document

  • includeDetailedInfo: Determines whether library document detailed info will be returned in the response payload. Based on the state of the library document and the event being notified, the keys in the JSON payload will change.

  • includeDocumentsInfo: Determines whether document info will be returned in the response payload. This might or might not be applicable in a specific event’s payload.

Widget

  • includeDetailedInfo: Determines whether widget detailed info will be returned in the response payload.

  • includeDocumentsInfo: Determines whether document info will be returned in the response payload.

  • includeParticipantsInfo: Determines whether participants info will be returned in the response payload.

MegaSign

  • includeDetailedInfo: Determines whether megasign detailed info will be returned in the response payload.

Managing webhooks and subscriptions (webhook APIs)

The Adobe Sign webhook APIs are essential, as you use the POST /webhooks API to create your webhook, and use the other API endpoints to retrieve information about your webhooks and their status, as well as to modify or delete webhooks. Details are on the Webhook APIs page, which covers the following endpoints:

Securing webhooks

Adobe Sign secures your webhooks in the following ways:

  • Allowing only HTTPS URLs: Only HTTPS URLs are permitted to register as webhook urls.

  • Validating webhooks subscription for authentication and authorization for webhooks created through the API: This is done using the existing API authentication and authorization validation in Sign. The first step for securing Adobe Sign webhooks is to include the standard authentication mechanism (OAuth access token and authorization header). While setting up a webhook subscription, we will validate that the token is valid and the API caller has permissions to create a webhook on the resource. We will also validate that the API caller has appropriate authorization to create account-level webhooks.

  • Two-way SSL authentication: Adobe Sign supports a two-way SSL handshake when making callbacks to our customer’s servers. Two-way SSL, often called Client-Side SSL, is a mode of SSL wherein both the server and the client (web browser) present certificates to identify themselves. We allow the account admins, via their account Security Settings page, to upload an identifying certificate, which the AdobeSign webhooks system will use to identify itself when making webhook calls to their servers. Adobe Sign will verify SSL certificates when delivering payloads to HTTPS webhook addresses. Webhooks that fail the SSL certificate verification will not successfully deliver to their respective hosts. Please ensure your server is correctly configured to support HTTPS with a valid SSL certificate.

  • Keeping the webhook configuration immutable: If your webhook URL changes, there is a possibility that your application consumer key and consumer secret have been compromised. By requiring you to create a new webhook configuration, we also require you to resubscribe to your user’s events. This requires the use of access tokens that a malicious party is less likely to posses. As a result, the likelihood that another party will receive your user’s private information is reduced.

  • Sending and receiving the client ID in the webhook notification request: You can whitelist the client/application ids through which you want to receive the payload. Notifications from the remaining apps can be ignored.

  • Recommended server configurations: We are only supporting TLS 1.2 for webhooks. TLS 1.0 and 1.1 are not supported.

  • IP validation: To prevent setting an internal subnet (for example, a 10.x address), special IP address ranges such as the 169.254.169.254 range, and other invalid IP addresses as webhook URLs, Adobe Sign will validate the IP address at the time of webhook creation as well as while sending notifications. If the IP address is invalid, the webhook will not be created. IP validation is done in the following way:

    1. The host name is resolved using DNS lookup.

    2. The IP address obtained is validated. The following IP addresses are considered invalid and a webook cannot be created using them:

      • SiteLocalAddress
      • LoopbackAddress
      • LinkLocalAddress
      • AnyLocalAddress
      • MulticastAddress
  • Avoid sending sensitive information: Adobe Sign will not send any sensitive information such as passwords or signing URLs in the payload.

Best practices

  • Be prepared to dedupe events: If you have more than one app sharing the same webhook URL and the same user mapped to each app, the same event will be sent to your webhook multiple times (once per app). In some cases your webhook may receive duplicate events. Your webhook application should be tolerant of this and dedupe by event ID.

  • Always respond to webhook requests quickly: Your app only has ten seconds to respond to webhook requests. For the verification request, this is never really an issue, since your app doesn’t need to do any real work to respond. For notification requests, however, your app will usually do something that takes time in response to the request. For example, it may need to process and then store signed documents. To make sure you can always respond within ten seconds, you should always do your work on a separate thread or asynchronously, using a queue.

  • Manage concurrency: When a user makes a number of changes in rapid succession, your app is likely to receive multiple notifications for the same user at roughly the same time. If you’re not careful about how you manage concurrency, your app can end up processing the same changes for the same user more than once.

    To take advantage of Adobe Sign webhooks, a clear understanding of the use of the information needs to be understood. Be sure to ask questions such as:

    1. What data do you want to return in payload?
    2. Who will be accessing this information?
    3. What decisions or reporting will be generated?
  • Recommendations for receiving signed documents: There are several factors to consider when determining how to receive agreements (signed PDFs) from Adobe Sign in your document management system. While it is perfectly acceptable to just select the IncludeSignedDocument option while creating a webhook to include the PDF documents when an event is triggered, you might consider using the Adobe Sign API to retrieve the documents when a triggering event (such as agreement status Complete) is received.