Sample Javascript code to to fetch the client id, validate it, and then return it in the response header
- Adobe Acrobat Sign Integrations
- What's New
- Product Versions and Lifecycle
- Acrobat Sign for Salesforce
- Install the Package
- Configure the Package
- User Guide
- Enable Digital Authentication
- Developer Guide
- Advanced Customization Guide
- Field Mapping and Templates Guide
- Mobile App User Guide
- Flows Automation Guide
- Document Builder Guide
- Configure Large Documents
- Upgrade Guide
- Release Notes
- FAQs
- Troubleshooting Guide
- Additional Articles
- Acrobat Sign for Microsoft
- Acrobat Sign for Microsoft 365
- Acrobat Sign for Outlook
- Acrobat Sign for Word/PowerPoint
- Acrobat Sign for Teams
- Acrobat Sign for Microsoft PowerApps and Power Automate
- Acrobat Sign Connector for Microsoft Search
- Acrobat Sign for Microsoft Dynamics
- Acrobat Sign for Microsoft SharePoint
- Overview
- SharePoint On-Prem: Installation Guide
- SharePoint On-Prem: Template Mapping Guide
- SharePoint On-Prem: User Guide
- SharePoint On-Prem: Release Notes
- SharePoint Online: Installation Guide
- SharePoint Online: Template Mapping Guide
- SharePoint Online: User Guide
- SharePoint Online: Web Form Mapping Guide
- SharePoint Online: Release Notes
- Acrobat Sign for Microsoft 365
- Acrobat Sign for ServiceNow
- Acrobat Sign for HR ServiceNow
- Acrobat Sign for SAP SuccessFactors
- Acrobat Sign for Workday
- Acrobat Sign for NetSuite
- Acrobat Sign for SugarCRM
- Acrobat Sign for VeevaVault
- Acrobat Sign for Coupa BSM Suite
- Acrobat Sign for Zapier
- Acrobat Sign Developer Documentation
Overview
A webhook is a user-defined HTTPS request triggered when a subscribed event occurs at the source site (Adobe Acrobat Sign, in this case).
Effectively, a webhook is nothing but a REST service that accepts data or a stream of data.
Webhooks are meant for service-to-service communication in a PUSH model.
When a subscribed event is triggered, Acrobat Sign constructs an HTTPS POST with a JSON body and delivers that to the URL specified.
Webhooks offer multiple benefits over the previous callback method, some of which are:
- Admins can enable their webhooks without having to involve Acrobat Sign support to list the callback URL
- Webhooks are better in terms of data "freshness," the efficiency of communication, and security. No polling required
- Webhooks allow for different levels of scope (Account/Group/User/Resource) easily.
- Webhooks are a more modern API solution, allowing for a more straightforward configuration of modern applications
- Multiple webhooks can be configured per scope (Account/Group/User/Resource), where Callbacks were required to be unique
- Webhooks allow for the selection of the data to be returned, where callbacks are an "all or nothing" solution
- Metadata carried with a webhook can be configured (Basic or Detailed)
- Webhooks are far easier to create, edit, or disable as needed since the UI is entirely within the control of the admin.
This document is primarily focused on the Webhooks UI in the Acrobat Sign web application (Previously Adobe Sign).
Developers that are looking for API details can find more information here:
How it's used
Admins will first need to have a webhook service, ready to accept the inbound push from Acrobat Sign. There are many options in this regard, and as long as the service can accept POST and GET requests, the webhook will be successful.
Once the service is in place, an Acrobat Sign admin can create a new webhook from the Webhook interface in the Account menu of the Acrobat Sign site.
Admins can configure the webhook to trigger for Agreement, Web form (Widget), or Send in Bulk (MegaSign) events. Library Template (Library Document) resource can also be configured through the API.
The scope of the webhook can include the whole account or individual groups through the admin interface. The API allows for more granularity through the selection of USER or RESOURCE scopes.
The type of data that is pushed to the URL is configurable and can include things like the Agreement Info, Participant Info, the Document Info, and so on.
Once the webhook is configured and saved, Acrobat Sign will push a new JSON object to the defined URL every time the subscribed event is triggered. No ongoing manipulation of the webhook is required unless you want to change the event trigger criteria or the JSON payload.
Verification of intent of the webhook URL
Before registering a webhook successfully, Acrobat Sign verifies whether the webhook URL that is provided in the registration request intends to receive notifications or not. For this purpose, when Acrobat Sign receives a new webhook registration request, it first makes a verification request to the webhook URL. This verification request is an HTTPS GET request sent to the webhook URL. This request has a custom HTTP header X-AdobeSign-ClientId. The value in this header is set to the client ID (Application ID) of the API application requesting to create/register the webhook. To successfully register a webhook, the webhook URL must respond to this verification request with a 2XX response code, AND additionally, it MUST send back the same client id value in one of the following two ways:
- Either in a response header X-AdobeSign-ClientId. This is the same header passed in the request and echoed back in the response.
- Or in the JSON response body with the key of xAdobeSignClientId and its value being the same client ID sent in the request.
The webhook will be successfully registered only on a success response(2XX response code) and validation of client id either in header or response body. The purpose of this verification request is to demonstrate that your webhook URL does want to receive notifications at that URL. If you accidentally entered the wrong URL, the URL would fail to respond correctly to the verification of intent request, and Acrobat Sign will not send any notifications to that URL. Additionally, the webhook URL can also validate that it would receive notifications only through the webhooks 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 URL does not recognize that client id, it MUST NOT respond with the success response code, and Acrobat Sign will take care that the URL is not registered as a webhook.
The verification of the webhook URL call will be made in the following scenarios:
- Registering Webhook: If this verification of the webhook URL call fails, the webhook will not be created.
- Updating Webhook: INACTIVE to ACTIVE: If this verification of the webhook URL call fails, the webhook state will not be changed to ACTIVE.
How to respond to a webhook notification
Acrobat Sign performs an implicit verification of intent in each webhook notification request sent to the webhook URL. Thus, every webhook notification HTTPS request also contains the custom 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 client id is sent in either the HTTP header (X-AdobeSign-ClientId) or via a JSON response body with key as xAdobeSignClientId and value as the same client id; otherwise we will retry to deliver the notification to the webhook URL until the retries are exhausted.
As mentioned above, the header 'X-AdobeSign-ClientId' which is included in every notification request from Sign, the value of this header(client id) should be echoed back in response in either of two ways:
1. HTTP header X-AdobeSign-ClientId and value as this client id
|
---|
// 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 code to to fetch the client id, validate it, and then return it in the response header |
---|
<?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 } ?> |
2. JSON response body with key as xAdobeSignClientId and value as the same client id
Sample Javascript code to to fetch the client id, validate it, and return it in the response body |
---|
// 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 code to to fetch the client id, validate it, and return it in the response body |
---|
<?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 body of the response |
---|
{ "xAdobeSignClientId": "BGBQIIE7H253K6" } |
Prerequisites
You will need:
- A Microsoft account with license to create Azure Functions Applications
- An existing Azure Function Application, you can create one using https://docs.microsoft.com/en-us/azure/azure-functions/functions-create-first-azure-function
- Basic knowledge of Javascript, so that you can understand and write the code in any language of your choice
Steps to create an Azure Functions Trigger that serves as an Acrobat Sign webhook
To create a Javascript HTTP Trigger function:
1. Login via you Microsoft account https://portal.azure.com/
2. Open you Azure Function Application displayed under Function Apps tab.
This will open your list of Azure Function Applications:
3. Choose the application where in you want to create this new function
4. Click on the Create (+) button to create a new Azure function
5. Select Webhook + API as the scenario and Javascript as the language
6. Click Create this function
A new function that has the capability of handling an incoming API request is created.
Add logic to register Acrobat Sign webhook
Before registering a webhook successfully, Acrobat Sign verifies that the webhook URL that is provided in the registration request, really intends to receive notifications or not. For this purpose, when a new webhook registration request is received by Acrobat 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 of the application that is requesting to create/register the webhook. To successfully register a webhook, the webhook URL must respond to this verification request with a 2XX response code AND additionally it must send back the same client id value in one of the following two ways.
There are two options you can follow:
Option 1: Pass Client Id in X-AdobeSign-ClientId as response Header
Pass X-AdobeSign-ClientId in the response header. This is the same header which was passed in the request, and must be echoed back in the response.
Replace the Index.js file with the following:
module.exports = function (context, req) {
var clientId = req.headers['x-adobesign-clientid'];
// Validate that the incoming ClientID is genuine
if (clientId === '123XXX456') {
context.res = {
// status: 200, /* Defaults to 200 */ // any 2XX response is acceptable
body: "Notification Accepted",
headers : {
'x-adobesign-clientid' : req.headers['x-adobesign-clientid']
}
};
}
else {
context.res = {
status: 400,
body: "Opps!! Illegitimate Call identified"
};
}
context.done();
};
Test the behavior by mocking the request:
1. Click on the Test button at extreme right corner
2. Mock the dummy request
Although response headers are not shown above but you can observe it via mocking it by postman/DHC or any other service.
Option 2: Pass Client Id in the response body with key xAdobeSignClientId
In the JSON response body with the key of xAdobeSignClientId and its value being the same client ID that was sent in the request header.
Replace the Index.js file with the following:
module.exports = function (context, req) {
var clientId = req.headers['x-adobesign-clientid'];
// Validate that the incoming ClientID is genuine
if (clientId === '123XXX456') {
context.res = {
// status: 200, /* Defaults to 200 */ // any 2XX response is acceptable
body: {
'xAdobeSignClientId' : clientId
},
headers : {
'Content-Type' : 'application/json'
}
};
}
else {
context.res = {
status: 400,
body: "Opps!! Illegitimate Call identified"
};
}
context.done();
};
Test the behavior by mocking the request
1. Click on the Test button at extreme right corner
2. Mock the dummy request
Also note the same behavior for clientID is expected when the Webhook URL receives POST notifications.
Ready to Use
Once you have verified the behavior, the webhook URL is functional as per Acrobat Sign standards. You can further update the custom logic as per your requirements.
Get the Function URL
- Click on Get function URL
Copy the URL and use it for creating webhooks in Acrobat Sign.
Creating the AWS Lambda function
To create an AWS Lambda function, login to your AWS Management Console and select the AWS Lambda service from the services list.
- Click Create a Lambda function using "Author From Scratch" option
- In the Configure function page enter the function name "lambdaWebhooks" and select Node.js 4.3 as the Runtime
- For the Role choose an existing role or create a new role from template(s)
- If you have chosen Create new role from template(s) enter a role name (e.g. role-lamda) and select Simple Microservices permissions from the Policy templates list
- Click the Create function button
- On the new AWS lamda function page, select "Edit code inline" as "Code entry type", keep the index.handler as Handler.
- Add logic to register the Acrobat Sign Webhook
Before registering a webhook successfully, Acrobat Sign verifies that the webhook URL that is provided in the registration request, really intends to receive notifications or not. For this purpose, when a new webhook registration request is received by Acrobat 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 of the application that is requesting to create/register the webhook. To successfully register a webhook, the webhook URL must respond to this verification request with a 2XX response code AND additionally it must send back the same client id value in one of the following two ways. Also note the same behavior for clientID is expected when the Webhook URL receives POST notifications.
Follow either of the two cases:
Case 1: Pass Client Id in X-AdobeSign-ClientId as response Header
- Pass X-AdobeSign-ClientId in the response header. This is the same header which was passed in the request, and must be echoed back in the response.
Code Snippet
In index.js file, replace the automatically generated code snippet with the following code:
- Pass X-AdobeSign-ClientId in the response header. This is the same header which was passed in the request, and must be echoed back in the response.
Sample node JS code to to fetch the client id, validate it, and then return it in the response header |
---|
exports.handler = function index(event, context, callback) { // Fetch client id var clientid = event.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 response = { statusCode: 200, headers: { "X-AdobeSign-ClientId": clientid } }; callback(null,response); } else { callback("Oops!! illegitimate call"); } } |
Case 2: Pass Client Id in the response body with key xAdobeSignClientId
In the JSON response body with the key of xAdobeSignClientId and its value being the same client ID that was sent in the request header.
Code Snippet
Replace the Index.js file with the following :
Sample node JS code to to fetch the client id, validate it, and then return it in the response header |
---|
exports.handler = function index(event, context, callback) { // Fetch client id var clientid = event.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 };
var response = { statusCode: 200, body: JSON.stringify(responseBody) };
callback(null,response); } else { callback("Opps!! illegitimate call"); } } |
- Save the function. Lambda function is created and we are almost ready to use it in a real-time webhook.
Configuring the AWS API Gateway
To make this Lambda publicly accessible through an HTTP method, we need to configure the AWS API Gateway using our function(created above) as the backend for the API.
In AWS Management Console select the API Gateway from the AWS services and click Create API button
- In the Create new API page select New API and enter webhooks as the API name.
- Click the Create API button
- Select the Actions drop-down list and select the Create Resource option
- Check the Configure as proxy resource option and enter validate as the Resource Name and {proxy+} in the Resource Path
- Leave the Enable API Gateway CORS option unchecked and click the Create Resource button
- Keep the Lambda Function Proxy selected as Integration type and select the region where you have created your Lambda function in the Lambda region drop-down list (probably it's the same region where you are creating the API Gateway).
- Enter validate as the Lambda Function and click the Save button
- In the Add Permission to Lambda Function pop-up window select OK
If all the above steps are executed successfully, you'll see something like this:
Deploying API
The next step is deploying this API so it becomes ready to use.
- In the Actions drop-down select Deploy API
- Select [New Stage] in the Deployment stage and enter prod (or anything you like to identify this stage) in the Stage name
- Click the Deploy button
API is now ready to use and you can find the invoke URL in the blue box as shown below:
Take note of this URL as you'll need to enter it as your real-time webhook URL.
Ready to Use
It's done. Use this above url with "/{nodeJSfunctionName}" appended as webhook url in POST /webhooks API request. Once you have verified the behavior, the Webhook URL is functional as per
Acrobat Sign standards. You can further update/add the custom logic as per your requirement.
Configuration options
Configuring the Webhook requires five elements to be defined:
- Name - An intuitive name that other admins can readily understand is suggested.
- Scope - How wide of a net is the webhook catching? Account and Group are available in the interface.
- The API supports Account, Group, User, and Resource scopes.
- Only one Scope per webhook can be defined.
- URL - The target URL that Acrobat Sign pushed the JSON payload to.
- Events - The trigger that causes Acrobat Sign to build the JSON and push it to the URL.
- Each event builds a different payload relevant to the trigger event.
- Multiple Events can be included in one webhook.
- Notification Parameters - The Notification Parameters identify the sections of the Event JSON payload, allowing you to select only the sections of the Event that are important for this webhook (and thus reducing the unnecessary data sent to your URL).
Once the webhook is fully defined, click Save, and the new webhook will start reacting to trigger events immediately.
Please configure your webhook URL to respond to the webhook verification and webhook notification requests as per the verification protocol explained above. The client ID (Application ID) that will be sent to webhooks created from the Acrobat Sign web application will be - UB7E5BXCXY
Scopes
- Account: All the subscribed events occurring in the account trigger the push.
- Account admins have the authority to see all webhooks defined for the account and all groups within that account.
- Group: All the subscribed events occurring in the group trigger the push. NOTE: Group scoped webhooks exist only for that one group.
- Group admins will only see the webhooks that are dedicated to their group. They cannot see the Account level webhooks or webhooks bound to other groups.
- Accounts that have Users in Multiple Groups enabled will see the option to set the group that the scope should be applied to.
- User Account: All subscribed events for a user account trigger the push. User-level webhooks can only be created via API.
- Resource level webhook: This will be created for a specific resource. Events specific to this resource will be pushed to the webhook URL. Resource-level webhooks can only be created via API.
URL
A webhook URL is a server that listens for incoming HTTPS POST notification messages that are triggered when events occur.
You need this URL to subscribe to your webhook to events.
- The client must include an HTTPS URL that Acrobat Sign can POST to. This URL must be available on the public internet.
- For example, 127.0.0.1 and localhost URIs will not work.
- The URL endpoint must be listening on port 443 or 8443 (decided by the customer when defining the callback URL).
- Make sure the webhook supports POST requests for incoming event notifications and GET requests for the verification request.
- The URL should not be blocked by a firewall.
Below are the events that can trigger a push to the webhook URL, grouped by object and listed in the order found in the UI.
The value on the left is the value you will see in the Acrobat Sign UI. The value on the right is the webhook name in the API.
For complete details regarding the webhooks and their payloads, see the Acrobat Sign developers guide.
Agreements:
UI Element | Webhook name |
Agreement all events | AGREEMENT_ALL |
Agreement created | AGREEMENT_CREATED |
Agreement sent | AGREEMENT_ACTION_REQUESTED |
Agreement participant completed | AGREEMENT_ACTION_COMPLETED |
Agreement workflow completed | AGREEMENT_WORKFLOW_COMPLETED |
Agreement expired | AGREEMENT_EXPIRED |
Agreement deleted | AGREEMENT_DOCUMENTS_DELETED |
Agreement cancelled | AGREEMENT_RECALLED |
Agreement rejected | AGREEMENT_REJECTED |
Agreement shared | AGREEMENT_SHARED |
Agreement delegated | AGREEMENT_ACTION_DELEGATED |
Agreement participant replaced | AGREEMENT_ACTION_REPLACED_SIGNER |
Agreement modified | AGREEMENT_MODIFIED |
Agreement modification acknowledged | AGREEMENT_USER_ACK_AGREEMENT_MODIFIED |
Agreement email viewed | AGREEMENT_EMAIL_VIEWED |
Agreement email bounced | AGREEMENT_EMAIL_BOUNCED |
Agreement creation failed | AGREEMENT_AUTO_CANCELLED_CONVERSION_PROBLEM |
Agreement synced post offline event | AGREEMENT_OFFLINE_SYNC |
Agreement uploaded by sender | AGREEMENT_UPLOADED_BY_SENDER |
Agreement vaulted | AGREEMENT_VAULTED |
Agreement participant social identity authenticated | AGREEMENT_WEB_IDENTITY_AUTHENTICATED |
Agreement participant KBA authenticated | AGREEMENT_KBA_AUTHENTICATED |
Agreement reminder sent | AGREEMENT_REMINDER_SENT |
Agreement signer name changed by signer | AGREEMENT_SIGNER_NAME_CHANGED_BY_SIGNER |
Agreement Webhooks only available via API | |
NA | AGREEMENT_EXPIRATION_UPDATED |
NA |
AGREEMENT_READY_TO_NOTARIZE |
NA |
AGREEMENT_READY_TO_VAULT |
Send in Bulk:
UI Element | Webhook name |
Send in Bulk all events | MEGASIGN_ALL |
Send in Bulk created |
MEGASIGN_CREATED |
Send in Bulk shared |
MEGASIGN_SHARED |
Send in Bulk recalled |
MEGASIGN_RECALLED |
Web Forms:
UI Element | Webhook name |
Web Form all events | WIDGET_ALL |
Web Form created |
WIDGET_CREATED |
Web Form enabled |
WIDGET_ENABLED |
Web Form disabled |
WIDGET_DISABLED |
Web Form modified |
WIDGET_MODIFIED |
Web Form shared |
WIDGET_SHARED |
Web Form creation failed |
WIDGET_AUTO_CANCELLED_CONVERSION_PROBLEM |
Library templates (API Only):
UI Element | Webhook name |
NA | LIBRARY_DOCUMENT_ALL |
NA | LIBRARY_DOCUMENT_CREATED |
NA | LIBRARY_DOCUMENT_AUTO_CANCELLED_CONVERSION_PROBLEM |
NA | LIBRARY_DOCUMENT_MODIFIED |
Notification Parameters
Notification Parameters allow you to customize the JSON payload to just specific elements of the event.
For example, in an Agreement participant replaced event, you may only want the Agreement Info and the Participant Info, leaving out the Document Info, and reducing the total size of the JSON sent to your webhook URL.
- Agreement
- Agreement Info - Detailed agreement information based on the state of the agreement at the time of the triggering event.
- Agreement Document Info - Includes any document information generated as a result of the event.
- Agreement Participant Info - Includes any participant information as a result of the event.
- Agreement Signed Document - Provides the signed PDF.
- Applicable to the Agreement Workflow Completed and Agreement All events.
- Send in Bulk
- Send in Bulk Info - Detailed information about the Send in Bulk object that triggered the event.
- Web Form
- Widget Info - Detailed information about the web form that triggered the event.
- Widget Document Info - The document information associated with the web form.
- Widget Participant Info - Information about the defined participants in the web form.
Two-way SSL authentication
Two-way SSL, often called Client-Side SSL or mutual TLS, is a mode of SSL wherein both the server and the client (web browser) present certificates to identify themselves.
Account admins can configure a client-side certificate on the Security Settings page.
Acrobat Sign verifies the SSL certificates when delivering payloads to the webhook URL. Webhooks that fail the SSL certificate verification will not deliver the JSON payload successfully.
Use Two-way SSL to authenticate the client (Acrobat Sign) and listening service to ensure that only Acrobat Sign can reach your webhook URL.
If the webhook was created by a Partner Application, the webhook will use a client certificate (if available) from the Partner Application's Account to identify itself when sending webhook notifications.
Below are the most common questions for both the web server verification process and the client certification verification.
Web server verification
During the registration of a webhook, Acrobat Sign verifies the webhook server URL.
Customers won't be able to register the webhook if the connection to the webhook callback URL cannot be completed from Acrobat Sign.
No.
The webhook callback URL can only be HTTPS on port 443 or 8443.
Acrobat Sign blocks outbound HTTPS traffic to all other ports.
A good way to verify the server certificate is to use the DigiCert® SSL Installation Diagnostics Tool.
Only enter the hostname e.g.: www.digicert.com
Common issues include:
- Problem: Using an untrusted CA or self-signed certificate
Fix: Use a public CA issued SSL certificate for the webhook callback server.
- Problem: The server is not sending the intermediate certificate
Fix: Install the intermediate certificates on the webhook callback server.
See https://www.digicert.com/kb/ssl-certificate-installation.htm for detailed information.
Client certificate verification
In order to set up a two-way SSL for a webhook, we require the administrator to upload a .p12 (or .pfx) file that contains the private key. The file is stored securely within the customer account, and the administrator has full control to remove it at any time.
In a two-way webhook setup, Acrobat Sign is the caller/client and needs the private key to prove that the call is made by Acrobat Sign on behalf of the customer account.
-
Verify that two-way SSL is enabled
Two-way SSL must be enabled on the webhook callback server.
Using any web browser, connect to the webhook callback URL. You should get:
400 Bad Request No required SSL certificate sent
This means the server is expecting the client to send client certificates (i.e.: Two-way SSL is enabled for the server).
If you don't see the above message, then two-way SSL is not enabled.
Note:You can use Postman, and do a POST request to the webhook callback URL. You should get a similar result.
-
The client credential can either be a self-signed certificate or CA issued certificate. However, it must minimally conform to the following X.509 v3 extensions:
X.509 v3 extension
Value
ExtendedKeyUsage
clientAuth (OID: 1.3.6.1.5.5.7.3.2)
KeyUsage
digitalSignature
The client certificate must be a PKCS12 file with extension .p12 or .pfx, and it must include both the client certificate (so the server can verify the identity of the client) and the client's private key (so the client can digitally sign messages for the server to verify during the SSL handshake).
Use the openssl command to verify the p12 (pfx) file:
openssl pkcs12 -info -in outfile.p12
The passphrase for the private key should be requested. The output should contain both certificates as well as an Encrypted Private Key like:
Bag Attributes localKeyID: 9D BD 22 80 E7 B2 B7 58 9E AE C8 42 71 F0 39 E1 E7 2B 57 DB subject=/C=US/ST=California/L=San Jose/O=Adobe Inc./CN=sp.adobesignpreview.com issuer=/C=US/O=DigiCert Inc/CN=DigiCert TLS RSA SHA256 2020 CA1 -----BEGIN CERTIFICATE----- MIIGwDCCBaigAwIBAgIQAhJSKDdyQZjlbYO5MJAYOTANBgkqhkiG9w0BAQsFADBP MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMSkwJwYDVQQDEyBE ... JAKQLQ== -----END CERTIFICATE----- Bag Attributes: <No Attributes> subject=/C=US/O=DigiCert Inc/CN=DigiCert TLS RSA SHA256 2020 CA1 issuer=/C=US/O=DigiCert Inc/OU=www.digicert.com/CN=DigiCert Global Root CA -----BEGIN CERTIFICATE----- MIIEvjCCA6agAwIBAgIQBtjZBNVYQ0b2ii+nVCJ+xDANBgkqhkiG9w0BAQsFADBh MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 ... -----END CERTIFICATE----- Bag Attributes localKeyID: 9D BD 22 80 E7 B2 B7 58 9E AE C8 42 71 F0 39 E1 E7 2B 57 DB Key Attributes: <No Attributes> -----BEGIN ENCRYPTED PRIVATE KEY----- MIIFDjBABgkqhkiG9w0BBQ0wMzAbBgkqhkiG9w0BBQwwDgQI7eNh2qlsLPkCAggA ... FHE= -----END ENCRYPTED PRIVATE KEY-----
Certificates should minimally include the end-entity certificate and the intermediate certificates. Ideally, it will also include the root CA certificate.
Alert:Make sure the .p12 or .pfx file is passphrase protected.
-
Create a self-signed client certificate (optional)
Client certificates can either be CA issued or self-signed, depending on your need.
To generate a self-signed client certificate, use the following openssl command:
openssl req -newkey rsa:4096 -keyform PEM -keyout ca.key -x509 -days 3650 -outform PEM -out ca.cer
Caution:Keep the resulting files secret as they are your self-signed CA certificates.
Next, generate the client .p12 file:
- Generate a private key for the SSL client:
openssl genrsa -out client.key 2048
- Use the client’s private key to generate a cert request:
openssl req -new -key client.key -out client.req
- Issue the client certificate using the cert request and the CA cert/key:
openssl x509 -req -in client.req -CA ca.cer -CAkey ca.key -set_serial 101 -extensions client -days 365 -outform PEM -out client.cer
- Convert the client certificate and private key to pkcs#12 format for use by browsers:
openssl pkcs12 -export -inkey client.key -in client.cer -out client.p12
- Remove the client private key, client certificate, and client request files as the pkcs12 has everything you need.
rm client.key client.cer client.req
- Generate a private key for the SSL client:
-
- Use Postman to load the client PFX file in Settings > Certificates.
- Select Add Certificate to add the client certificate.
- Configure the HTTP header for x-adobesign-clientid:
Once configured, send a POST request to the webhook callback URL.
You should get a 200 response.
-
Why does Acrobat Sign reject my PFX file even after I have verified it with Postman?
If you have followed the above process for pfx file verification, and Acrobat Sign still rejects the pfx file, it's likely the file was generated by a Microsoft tool that can produce a non-standard PKCS12 file.
In that case, use the below openssl commands to extract the certificates and private key from the pfx file, and then generate a properly formatted PKCS12 file:
// Extract certificates and private key from pfx file openssl pkcs12 -info -in microsoftclientssl.pfx -passin pass:"" -out clientcert.crt -nokeys openssl pkcs12 -info -in microsoftclientssl.pfx -passin pass:"" -out clientcert.key -nodes -nocerts // Create new PKCS12 file openssl pkcs12 -export -inkey clientcert.key -in clientcert.crt -out clientcert.pfx
How to enable or disable
Access to the Webhooks feature is enabled by default for enterprise plan accounts.
Group level admins can create/control the Webhooks that operate within their group only.
Access to the Webhooks page can be found in the left rail of the Admin menu: Account > Webhooks
Activate a webhook
When a webhook is first created, it is created in an Active status.
On the Webhooks page in Acrobat Sign, you will see the Active webhooks by default.
To activate an inactive webhook:
- Click the Options icon (three horizontal lines) on the right of the webhooks header row and select Show All Webhooks
- Single click the inactive webhook to select it
- This exposes the options for the webhook just under the header row
- Click Activate
The active webhook will start sending data to the target URL as soon as the next event is triggered.
Deactivate a webhook
Deactivating a webhook only requires that you
- Navigate to the Webhooks page
- Single click the webhook you want to deactivate
- Select Deactivate from the menu items under the header row
- Once deactivated, the webhook shows a status of Inactive
View or Edit a webhook
Webhooks can be edited and saved at any time, and upon saving a new configuration, that change takes effect immediately.
Only the Events and Notification Parameters can be edited.
If the Name, Scope or URL needs to be changed, a new webhook will have to be created.
To edit the parameters of a webhook:
- Navigate to the Webhooks page
- Single click the webhook you want to edit
- Click the View/Edit option under the header row
- Apply any changes needed, and click Save
Delete a webhook
A webhook can be deleted at any time.
Deleting a webhook destroys it in the system, so there is no ability to recover a deleted webhook.
Webhooks do not need to be deactivated first.
To delete a webhook:
- Navigate to Webhooks
- Select the webhook you want to delete by single clicking it
- Click the Delete option under the header row
- A challenge is presented to ensure you want to delete the webhook. click OK
Best Practices
- Subscribe to specific, needed events to limit the number of HTTPS requests to the server - The more specific you can make your webhooks, the less volume you'll need to sift through.
- Be duplicate resistant - 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 webhooks quickly - Your app only has five seconds to respond to webhook requests. For the verification request, this is rarely 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. It is recommended to work on a separate thread or asynchronously using a queue to ensure you can respond within five seconds
- 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. In order to take advantage of Acrobat Sign webhooks, a clear understanding of the use of the information needs to be understood. Be sure to ask questions such as:
- What data do you want to return in the payload?
- Who will be accessing this information?
- What decisions or reporting will be generated?
- Recommendations for receiving a signed document - There are several factors to consider when determining how to receive a signed PDF from Acrobat Sign in your document management system.
While it is perfectly acceptable to just select the Agreement Signed Document option while creating a webhook, you might consider using the Acrobat Sign API to retrieve the documents when a triggering event (such as agreement status Complete) is received.
Things to keep in mind...
JSON size limitation
The JSON payload size is limited to 10 MB.
If an event generates a larger payload, a webhook will be triggered but the conditional parameter attributes, if there in the request, will be removed to reduce the size of the payload.
"ConditionalParametersTrimmed " will be returned in the response when this happens to inform the client that the conditionalParameters info has been removed.
“conditionalParametersTrimmed” is an array object containing the information about the keys that have been trimmed.
The truncation will be done in following order :
- includeSignedDocuments
- includeParticipantsInfo
- includeDocumentsInfo
- includeDetailedInfo
Signed Documents will be truncated first, followed by participant info, document info and finally detailed info.
This may happen, for example, on an agreement completion event if it includes signed document (base 64 encoded) as well or for an agreement with multiple form fields
Webhook notifications
Acrobat Sign webhooks deliver notifications that are applicable for all participants of an agreement if there is a webhook configured for that user, their group, or their account.
Agreement events are processed in a way that if there is a webhook configured for the applicable participant of that event, a notification is sent to that webhook URL. In other words, webhooks are triggered for events in all applicable agreements, even those outside of the group or account in which the webhook is configured.
Notifications are delivered only for those events that the participant is involved with. E.g. The Sender of an agreement receives almost every notification, while Recipients only receive notifications from the start of their involvement in the agreement, and only for those events in which they are involved.
Webhook notifications follow the current authentication and visibility model of Acrobat Sign itself, meaning that users will have access to the agreement only when the user’s participation in an agreement has started.
The Sender sends an agreement for signature to three signers.
- There’s an account level WebhookX configured for the Senders account.
- Signer1 is a member of the same account as Sender but in a different Group, and there is a WehbhookY configured for that group.
- Signer2 is a member of a different Account, and there is an account level WebhookZ configured for the Signer2 account.
- Signer3 is a member of the same account as a Sender.
The Sender sends an agreement: WebhookX triggers on “Agreement created” and “Agreement sent” while WebhookY triggers on “Agreement sent”.
Signer1 signs: WebhookX triggers on “Agreement participant completed” and “Agreement sent”, WebhookY triggers on “Agreement participant completed” and WebhookZ triggers on “Agreement sent”.
Signer2 signs: WebhookX triggers on “Agreement participant completed” and “Agreement sent”, while WebhookZ sends notification for “Agreement participant completed”.
Signer3 signs: WebhookX triggers on “Agreement participant completed” and “Agreement workflow completed”, WebhookY triggers on “Agreement workflow completed”, and WebhookZ triggers on “Agreement workflow completed”.
Retry when the listening service is down
If the target URL for the webhook is down for any reason, Acrobat Sign will queue the JSON and retry the push in a progressive cycle over 72 hours.
The undelivered events will be persisted in a retry queue and a best effort will be made over the next 72 hours to deliver the notifications in the order they occurred.
The strategy for retrying delivery of notifications is a doubling of time between attempts, starting with a 1-minute interval increasing to every 12 hours, resulting in 15 retries in the space of 72 hours.
If the webhook receiver fails to respond within 72 hours, and there have been no successful notification deliveries in the last seven days, the webhook will be disabled. No notifications will be sent to this URL until the webhook is activated again.
All notifications between the time the webhook is disabled and subsequently enabled again will be lost.