Custom signature workflow

Basics

When a signature request is created using the API, the workflow followed by signers can be highly customized, including:

  • the branding, the content and the list of emails sent to signers
  • the signature page on which the signers are redirected
  • the branding of the Signature attestation document

The minimal/simplest signature workflow is the following:

  1. An email asking to sign the document is sent to each signer by the Woleet platform. This email includes a link redirecting the signer to a signature page.
  2. The signer reads the email, clicks on the link and is redirected to a signature page.
  3. The signature page eventually signs the document by delegating the signature to the Woleet backend (the signer authentication is done using a secret identifier included in the redirection link)

The default signature workflow sends more emails (see below for a full description) but all additional emails can be disabled or customized.
Note that although emails are always sent by the Woleet platform, the email and the name of the sender can also be customized.

The default email asking to sign the document redirects signers to a default signature page hosted by the Woleet platform. However, the redirection can be easily modified to redirect to a custom signature page. Since implementing a custom signature page is straightforward (it can be as simple as one POST call) it is easy to implement a fully customized signature workflow.

Email types

Here is the list of all email types sent by the Woleet platform when using the default signature workflow:

Type

Purpose

Comment

Identifier

Signature request to signer

Sent to the signer when the signature request is activated (ie. its state is IN_PROGRESS)

Mandatory: cannot be disabled
Must provide a link to a signature page including the secret identifier of the signer

signatureRequestSigneeEmail

Signature reminder to signer

Send to the signer 3 days after the signature request if the signer has not signed yet

signatureReminderSigneeEmail

Signature canceled to signer

Sent to the signer when the signature request is canceled. (ie. its state is CANCELED)

signatureCanceledSigneeEmail

Signature closed to signer

Sent to the signer when the signature request is closed. (ie. its stated is CLOSED).

signatureClosedSigneeEmail

Signature confirmation to signer

Sent to the signer right after he signs the document

Can provide a link to the "Signature verification" page

signatureConfirmedSigneeEmail

Signature confirmation to requester

Sent to the requester right after each signature

Not sent if the requester is also the signer (same email)
Can provide a link to the "Signature verification" page

signatureConfirmedRequesterEmail

Signature feedback to requester

Sent to the requester if a signee reports some feedback about the signature request

Mandatory: cannot be disabled

signatureFeedbackRequesterEmail

Signature proof to signer

Sent to the signer when his signature proof is ready

The signature proof is provided as an attachement

signatureProofConfirmedSigneeEmail

Signature attestation

Sent to the requester and the signers when the signature request is completed or closed and the proof of signature of its audit trail by Woleet is ready

The "Signature attestation" PDF document is provided as an attachement

signatureAttestationEmail

Templating engine

Each email type has a default template. The Woleet platform uses Velocity Engine 2.2 as templating framework.
Default templates are made of HTML content using Velocity Template Language annotations and can be overwritten by custom templates.
Custom templates can also use Velocity Template Language annotations.

Customize the workflow

The default signature workflow can be customized using the vars property of the signature request. This property can be used to store a set of variables as key/value pairs. These variables can be used to:

  • disable some email types
  • provide custom templates for some email types
  • brand the Signature attestation document
  • define or overwrite variables used by templates

Templates have access to a set of predefined variables depending on the type of email (eg. requesterName) plus to all variables defined at signature request level using the vars property. Variables defined at signature request level overwrite predefined ones, and can themselves be overwritten by variables defined at signer level.

Disable some email types

To disable a given email type, set a {email type identifier}Disabled boolean variable to true:

{
  ...
  "vars": {
    "signatureProofConfirmedSigneeEmailDisabled": true,
    "signatureConfirmedSigneeEmailDisabled": true      
  }
}

Note that all email types but signatureRequestSigneeEmail and signatureFeedbackRequesterEmail can be deactivated.

Provide custom templates for some email types

To provide a custom template for a given email type, store the template of the content in a {email type identifier}ContentTemplate string variable, and the template of the subject in a {email type identifier}SubjectTemplate string variable:

{
  ...
  "vars": {
    "signatureRequestSigneeEmailSubjectTemplate": "Please sign '$fileName'"
    "signatureRequestSigneeEmailContentTemplate": "Hi, Please sign '$fileName' at <a href=\"https://sign.acme.com/?signatureRequestURL=$tools.urlEncode($signatureRequestURL)\">Sign</a>"
  }
}

Customize the Signature attestation document

At the very end of the signature workflow (ie. when the signature request is CLOSED or COMPLETED) the Signature attestation document (a PDF file) is by default sent by email to all signees.
The template used to generate this document cannot be customized yet, but uses variables allowing to "brand" the document by overwriting their default value:

Name

Purpose

brandColor1

Main brand color of the service

brandColor2

Alternate brand color of the service

textColor1

Main text color of the service

textColor2

Alternate text color of the service

serviceName

Name of the service

serviceEmail

Email of the service

serviceURL

URL of the service

serviceLogoURL

URL of the logo of the service

serviceIllustrationURL

URL of the illustration of the service

serviceContactEmail

Contact email of the service

serviceDocumentationURL

URL of the documentation of the service

serviceAddress

Postal address of the service

Define or overwrite variables used by templates

Some variable are predefined and can be used in various templates.
To overwrite a predefined variable, simply define a variable with the same name at signature request level:

{
  ...
  "vars": {
    "serviceName": "ACME Sign",
    "requesterName": "ACME Corp."
  }
}

List of predefined variables

Here is the list of all predefined variables that can be used in email templates:

Name

Purpose

Comment

lang

Language to use in the email (as an ISO639-1 string).

Computed from the signature request's lang properties: currently, since only en or fr are supported by default templates, it is always fallbacks to one of these values, except if overwritten in vars.

requesterName

Name of the signature requester.

Defaults to "{first name} {last name}" of the account creating the signature request.

requesterEmail

Email of the signature requester.

Defaults to the email of the account creating the signature request.

signeeName

Name of the signer (eg. John Doe)

Defaults to the commonName property of the signer.

signeeEmail

Email of the signer

isRequester

true if the signer is also the requester of the signature.

signatureRequestURL

URL of the signature request, including the secret identifier of the signer as a request parameter.

Intended to be provided to the signature page, allowing it to authenticate as the signer to retrieve and/or sign the signature request.
Defaults to https://api.woleet.io/v1/signatureRequest/{signatureRequestId}?signeeId={signeeId}.

signeeId

Secret identifier of the signer (required to authenticated as the signer to retrieve and/or sign the signature request).

requiresOTP

true if an SMS OTP is required for the signer to sign.

If true the signature page needs to request the platform to send an OTP to the signer, and needs to provide this OTP to sign.

signingURL

URL of the default signature page (without the signatureRequestURL parameter).

As an example, the default signatureRequestSigneeEmail template builds a Sign button redirecting to $signingURL?signatureRequestURL=$tools.urlEncode($signatureRequestURL)

signatureRequestId

Identifier of the signature request.

signatureRequestName

Name of the signature request.

signatureRequestSharingURL

URL of the signature request's sharing page.

This page can be used by anybody having the URL to:

  • follow the state of the signature request
  • verify all signatures
  • download the signature proofs
  • download the Signature attestation PDF document (if available).

documentName

Name of the document to sign.

Equals to fileName if set, or equals to signatureRequestName

fileName

Name of the file to sign.

If set in the signature request.

fileURL

URL of the data to sign (if set).

If set in the signature request.

serviceName

Name of the service managing the signature request.
This name is used as sender name for all emails and OTPs.

Defaults to "Woleet".

serviceEmail

Email of the service managing the signature request.
This email is used as sender email for all emails.

Defaults to "[email protected]".

serviceURL

URL of the service managing the signature request.

Defaults to "app.wolelet.io".

serviceLogoURL

URL of the logo of the service managing the signature request.

Defaults to Woleet's logo.

serviceContactEmail

Contact email of the service managing the signature request.

Defaults to Woleet's contact email.

serviceDocumentationURL

URL of the documentation of the service managing the signature request.

Defaults to Woleet's documentation.

Utilities

You can use the tools.urlEncode macro to URL encode any URL parameter:

<a href="$signingURL?signatureRequestURL=$tools.urlEncode($signatureRequestURL)">
  #if($lang == "en")
    Sign
  #elseif($lang == "fr")
    Signer
  #end
</a>

Examples

Here is a sample curl call creating a customized signature request:

  • it disables all optional emails
  • it provides a custom template for email sent to signers
  • the custom template provides the name and a link to the file to sign to the signer, so that he can download it
  • it redirects the signer to a custom signature page using a srURL argument to retrieve the signature request URL
  • it overwrites the name of the requester to "ACME Corp. legal dept."
  • it uses "ACME Corp." and "[email protected]" as the sender name and email for all emails sent
curl -u {login}:{password} -X POST --header 'Content-Type: application/json' --header 'Accept: application/json' -d '{
  "name": "ACME Corp. Terms and Conditions",
  "vars": {
    "serviceName": "ACME Corp.",
    "serviceEmail": "[email protected]",
    "requesterName": "ACME Corp. legal dept.",
    "signatureConfirmedSigneeEmailDisabled": true,
    "signatureConfirmedRequesterEmailDisabled": true,
    "signatureProofConfirmedSigneeEmailDisabled": true,
    "signatureAttestationEmailDisabled": true,
    "signatureRequestSigneeEmailSubjectTemplate": "Please sign $fileName",
    "signatureRequestSigneeEmailContentTemplate": "Hi $signeeName,<br>$requesterName invites you to sign <a href=\"$fileURL\">$fileName</a><br><a href=\"https://sign.acme.com/?srURL=$tools.urlEncode($signatureRequestURL)\">Sign</a>"
  },
  "hashToSign": "c8db8eaef2524d4c823d7b014214fda86f6480cc6d145f4c908cc01de37fb102",
  "fileName": "ACME Corp. TCU",
  "fileURL": "https://acme.com/privacy.html",
  "authorizedSignees": [ { "commonName": "John Doe", "email": "[email protected]"} ]
}' 'https://api.woleet.io/v1/signatureRequest'

Customize the signature page

To customize the signature page, you need to host a new signature page on your own, and redirect signers to this page by overwriting the signingURL variable, or by providing a custom template for the Signature request to signer email.

Here is a sample minimal HTML/Javascript code implementing a custom signature page:

<html>

<head>
  <script>

    // Get signature request URL parameter
    var srURL = new URL(window.location.href).searchParams.get("srURL");
    console.log("signature request URL: ", srURL);

    // Get the signer secret identifier
    var signeeId = new URL(srURL).searchParams.get("signeeId");
    console.log("signer secret identifier: ", signeeId);

    // Sign the signature request on behalf of the signer
    function sign() {

      // Build the delegate URL from the signature request URL
      var delegateURL = new URL(srURL);
      delegateURL = delegateURL.origin + delegateURL.pathname + "/delegate";
      console.log("delegate URL: ", delegateURL);

      // Call the delegate URL
      var http = new XMLHttpRequest();
      http.open('POST', delegateURL, true);
      http.setRequestHeader('Content-type', 'application/json');
      http.onreadystatechange = function () {
        if (http.readyState == 4 && http.status == 200) {
          console.log("done");
        }
      }
      http.send(JSON.stringify({ signeeId: signeeId }));
    }

  </script>
</head>

<body>
<button onclick="sign()">Sign</button>
</body>

</html>