Quick Start: Signature Appliance Local API

The DocuSign Signature Appliance Local API is the most performant of the appliance's APIs. It is available for the desktop and server versions of Windows.

The DocuSign Signature Appliance Local API

Getting Started

Obtain a developer account

Sign up for a free DocuSign Signature Appliance Developer Sandbox account.

Check that your signing account was created by using the Developer Web App to sign a PDF.

Introduction

The DocuSign Signature Appliance Local API includes four components:
  • SAPICrypt provides signing and verification methods.
  • SAPIUM provides user management methods.
  • SAPICryptCOM is the same as SAPICrypt, but provides a COM interface to the methods.
  • SAPIUMCOM is the same as SAPIUM, but provides a COM interface to the methods.

The Local API includes a client-side implementation of:

  • Hash value calculations of the documents or data to be signed. This enables only the document’s hash value to be sent to the signing appliance. Sending only the hash provides greater performance and security compared with sending the entire document to the server.
  • HTTPS communication with the signing server.

Software download and installation

The Local API is available for Windows desktop and server systems. To write your first Local program, please follow these steps:
  1. Check that your signing account was created by using the Developer Web App to sign a PDF.
  2. Make a jpg scan of your signature and use the Developer Web App to upload it to the DocuSign Signature Appliance used for developers. Click on your name (upper right corner of the web screen) to upload your graphical signature.
  3. Download and install the Developer bundle. The download includes the CoSign Client for Windows, and the SDK for SAPI Local.
  4. C and C++ require library header files for projects. Download, unzip and install the files within your project, or in a common library directory.
  5. Sign a document from your desktop to confirm that the CoSign Client is properly installed and configured. Open a Windows Explorer file window and select a PDF file. Then use the context menu item "Sign with CoSign". The Omnisign client will open and enable you to sign the PDF. Or use Word to sign a document.
  6. The Local API runtime files, including the .dll files were installed as part of the download. See the C:\Program Files\ARX\ARX Signature API directory. These dll files are sufficient for .NET and C# projects. See the C/C++ section below for header file information.

Creating a Visual Studio Project

C and C++

  1. Create a new C language project in Visual Studio
  2. Add the SAPI SDK Include directory to the project
  3. Add the SAPI SDK Lib directory to the project
  4. Sapicrypt.lib and/or sapium.lib should be added as dependencies to the project
  5. Compile and Link your project

C#

  1. Create a new C# language project in Visual Studio
  2. The CoSign Signature Local interface for .NET projects is available as an interop assembly on top of SAPI COM
  3. For 64bit machines, add a reference to SAPICryptCOM64.dll and/or SAPIUMCOM64.dll. For 32bit machines, add a reference to SAPICryptCOM.dll and/or SAPIUMCOM.dll. This will create a COM interop as the project’s Reference Properties (e.g. Interop.SAPILib)
  4. Compile and run your project

VB.Net

  1. Create a new VB.Net language project in Visual Studio
  2. The CoSign Signature Local interface for .NET projects is available as an interop assembly on top of SAPI COM
  3. For 64bit machines, add a reference to SAPICryptCOM64.dll and/or SAPIUMCOM64.dll. For 32bit machines, add a reference to SAPICryptCOM.dll and/or SAPIUMCOM.dll. This will create a COM interop as the project’s Reference Properties (e.g. Interop.SAPILib)
  4. Compile and run your project

Hello World: Signing a PDF

The Hello World example simply signs a PDF file based on set of fixed values.

Many other options and scenarios are available for signing including signing a previously defined blank digital signature field, providing the user with a WYSIWYG user interface for placing and sizing the signature, omitting the graphical representation of the digital signature, etc.

Hello World source on GitHub

Custom Values

First we define the custom parameters that will be used in this example.

wchar_t *filePath      = L"c:\\temp\\demo.pdf"; // PDF file to sign
wchar_t *username      = L"John Miller";        // CoSign Account Username
wchar_t *domain        = NULL;                  // CoSign Account Domain
wchar_t *password      = L"12345678";           // CoSign Account Password
int     sigPageNum     = 1;                     // Create Signature on the first page
int     sigX           = 145;                   // Signature Field X location
int     sigY           = 125;                   // Signature Field Y location
int     sigWidth       = 160;                   // Signature Field Width
int     sigHeight      = 45;                    // Signature Field Height
wchar_t *timeFormat    = L"hh:mm:ss";           // The display format of the time
wchar_t *dateFormat    = L"dd/MM/yyyy";         // The display format of the date
// Elements to display on the Signature Field
int     appearanceMask = SAPI_ENUM_DRAWING_ELEMENT_GRAPHICAL_IMAGE |
                         SAPI_ENUM_DRAWING_ELEMENT_SIGNED_BY       |
                         SAPI_ENUM_DRAWING_ELEMENT_TIME;
string filePath       = @"c:\temp\demo.pdf";  // PDF file to sign
string username       = "John Miller";        // CoSign account username
string password       = "12345678";           // CoSign account password
string domain         = null;                 // CoSign account domain
int    sigPageNum     = 1;                    // Create signature on the first page
int    sigX           = 145;                  // Signature field X location
int    sigY           = 125;                  // Signature field Y location
int    sigWidth       = 160;                  // Signature field width
int    sigHeight      = 45;                   // Signature field height
string timeFormat     = "hh:mm:ss";           // The display format of the time
string dateFormat     = "dd/MM/yyyy";         // The display format of the date
// Elements to display on the signature field
int    appearanceMask = (int) SAPI_ENUM_DRAWING_ELEMENT.SAPI_ENUM_DRAWING_ELEMENT_GRAPHICAL_IMAGE |    
                        (int) SAPI_ENUM_DRAWING_ELEMENT.SAPI_ENUM_DRAWING_ELEMENT_SIGNED_BY |
                        (int) SAPI_ENUM_DRAWING_ELEMENT.SAPI_ENUM_DRAWING_ELEMENT_TIME;
Dim filePath As String = "c:\\temp\\demo.pdf"   'PDF file to sign
Dim username As String = "John Miller"          'CoSign account username
Dim password As String = "12345678"             'CoSign account password
Dim domain As String = Nothing                  'CoSign account domain
Dim sigPageNum As Integer = 1                   'Create signature on the first page
Dim sigX As Integer = 145                       'Signature field X location
Dim sigY As Integer = 125                       'Signature field Y location
Dim sigWidth As Integer = 160                   'Signature field width
Dim sigHeight As Integer = 45                   'Signature field height
Dim timeFormat As String = "hh:mm:ss"           'The display format of the time
Dim dateFormat As String = "dd/MM/yyyy"         'The display format of the date
'Elements to display on the signature field
Dim appearanceMask As Integer = _
    SAPI_ENUM_DRAWING_ELEMENT.SAPI_ENUM_DRAWING_ELEMENT_GRAPHICAL_IMAGE Or _
    SAPI_ENUM_DRAWING_ELEMENT.SAPI_ENUM_DRAWING_ELEMENT_SIGNED_BY Or _
    SAPI_ENUM_DRAWING_ELEMENT.SAPI_ENUM_DRAWING_ELEMENT_TIME

 

Parameter Meaning
filePath Path to PDF file
username User name for authenticating with the signing appliance
password The user’s password for CoSign
domain In an active directory environment, the name of the domain to which the user belongs. In a Directory Independent environment or LDAP environment, this parameter is ignored and its value is NULL
sigPageNum PDF page number for the signature field
sigX X coordinate for the signature field rectangle
sigY Y coordinate for the signature field rectangle
sigWidth Width for the signature field rectangle
sigHeight Height for the signature field rectangle
timeFormat The display format of the time. See 145 page of the manual
dateFormat The display format of the date. See 144 page of the manual
appearanceMask Appearance Mask specifying which components (Date, Signer’s Title, Reason) will be included with the graphical representation of the digital signature. See 159 page of the manual

Instantiate and Init CoSign Signature Local

The Init function initializes the CoSign Signature Local library and must be called before any other function in the library.

// Initialize SAPI library
if ((rc = SAPIInit()) != SAPI_OK)
{
	printf("Error on SAPIInit, rc = 0x%x, Extended error 0x%x\n", 
        rc, SAPIExtendedLastErrorGet());
	return -1;
}
SAPICrypt SAPI = new SAPICryptClass();
 
// Initialize SAPI library
if ((rc = SAPI.Init()) != SAPI_OK)
{
	throw new Exception(string.Format(
        "Failed to initialize SAPI ({0})", rc.ToString("X")));
}
'Initialize CoSign Signature Local library
rc = SAPI.Init
If rc <> SAPI_OK Then Throw New Exception(String.Format( _
    "Failed to initialize SAPI ({0})", rc.ToString("X")))

HandleAcquire

The HandleAcquire function acquires a Local session handle that is used to make calls to all Local API functions that require such a handle. HandleAcquire begins a session that is terminated only by calling HandleRelease with the session handle as a parameter.

An application can have more than one Local API session handle opened with the library, and is usually used by server applications that serve multiple users in parallel. A typical single threaded Local API application starts by calling Init followed by HandleAcquire. It ends by calling HandleRelease followed by Finalize.

if ((rc = SAPIHandleAcquire(&hSessionHandle)) != SAPI_OK)
{
	printf("Error on SAPIHandleAcquire, rc = 0x%x, Extended error 0x%x\n", 
        rc, SAPIExtendedLastErrorGet());
	return -1;
}
// Acquire CoSign Signature Local session handle
if ((rc = SAPI.HandleAcquire(out sesHandle)) != SAPI_OK)
{
	throw new Exception(string.Format("Failed in SAPIHandleAcquire() ({0})", 
        rc.ToString("X")));
}
'Acquire CoSign Signature Local session handle
rc = SAPI.HandleAcquire(sesHandle)
If rc <> SAPI_OK Then Throw New Exception(String.Format( _
    "Failed in SAPIHandleAcquire() ({0})", rc.ToString("X")))

Logon

The Logon function performs a login to the DocuSign Signing Appliance by using the provided credentials. This function is called in either of the following two scenarios:

  • In an environment in which the signing appliance automatically displays a login dialog for a new session, but the application wants to avoid this popup, either because it has its own popup or because the operation is not interactive.
  • When the application runs under certain credentials but wants to login to the DocuSign Signing Appliance under different credentials. For example, a web server application that serves many different users.
// Personalize SAPI Session
if ((rc = SAPILogon(hSession, (SAPI_LPCWSTR) username, (SAPI_LPCWSTR) domain, 
    (unsigned char*) password, (wcslen(password)+1)*2)) != SAPI_OK)
{
	SAPIHandleRelease (hSession);   // Release memory allocated for Session Handle
	printf("Error on SAPILogon, rc = 0x%x, Extended error 0x%x\n", rc, 
        SAPIExtendedLastErrorGet());
	return -1;
}

// Personalize the CoSign Signature Local Session
if ((rc = SAPI.Logon(sesHandle, username, domain, password)) != SAPI_OK)
{
	throw new Exception(string.Format("Failed to authenticate user ({0})", 
        rc.ToString("X")));
}
'Personalize the CoSign Signature Local Session
rc = SAPI.Logon(sesHandle, username, domain, password)
If rc <> SAPI_OK Then Throw New Exception(String.Format( _
    "Failed to authenticate user ({0})", rc.ToString("X")))

Defining signature field settings

SigFieldSettings is a structure that holds all the information that can be set for a signature field. Note that one of the fields in the structure is the AppearanceMask field which is a bit mask indicating which information is displayed when the signature field is signed (graphical image, signer, reason, date).

// Instantiate SAPI_SIG_FIELD_SETTINGS struct
SAPI_SIG_FIELD_SETTINGS sSigFieldSettings;
memset(&sSigFieldSettings, 0, sizeof(SAPI_SIG_FIELD_SETTINGS));
sSigFieldSettings.StructLen = sizeof(SAPI_SIG_FIELD_SETTINGS);
 
// Define Signature Field Settings
sSigFieldSettings.Page              = sigPageNum;
sSigFieldSettings.X                 = sigX;
sSigFieldSettings.Y                 = sigY;
sSigFieldSettings.Width             = sigWidth;
sSigFieldSettings.Height            = sigHeight;
sSigFieldSettings.AppearanceMask    = appearanceMask;
sSigFieldSettings.SignatureType     = SAPI_ENUM_SIGNATURE_DIGITAL;
sSigFieldSettings.DependencyMode    = SAPI_ENUM_DEPENDENCY_MODE_INDEPENDENT;
swprintf((wchar_t*)sSigFieldSettings.TimeFormat.DateFormat, dateFormat);
swprintf((wchar_t*)sSigFieldSettings.TimeFormat.TimeFormat, timeFormat);
sSigFieldSettings.TimeFormat.ExtTimeFormat = 
    SAPI_ENUM_EXTENDED_TIME_FORMAT_GMT;   // Display GMT offset
SigFieldSettingsClass SFS = new SigFieldSettingsClass();
TimeFormatClass TF = new TimeFormatClass();
 
// Define signature field settings
SFS.Page            = sigPageNum;
SFS.X               = sigX;
SFS.Y               = sigY;
SFS.Width           = sigWidth;
SFS.Height          = sigHeight;
SFS.AppearanceMask  = appearanceMask;
SFS.SignatureType   = SAPI_ENUM_SIGNATURE_TYPE.SAPI_ENUM_SIGNATURE_DIGITAL;
SFS.DependencyMode  = SAPI_ENUM_DEPENDENCY_MODE.SAPI_ENUM_DEPENDENCY_MODE_INDEPENDENT;
TF.DateFormat       = dateFormat;
TF.TimeFormat       = timeFormat;
TF.ExtTimeFormat    = 
    SAPI_ENUM_EXTENDED_TIME_FORMAT.SAPI_ENUM_EXTENDED_TIME_FORMAT_GMT; // Display GMT offset
SFS.TimeFormat      = TF;
'Instantiate SigFieldSettings object
Dim SFS As New SigFieldSettingsClass
Dim TF As New TimeFormatClass
 
' Define signature field settings
SFS.Page = sigPageNum
SFS.X = sigX
SFS.Y = sigY
SFS.Width = sigWidth
SFS.Height = sigHeight
SFS.AppearanceMask = appearanceMask
SFS.SignatureType = SAPI_ENUM_SIGNATURE_TYPE.SAPI_ENUM_SIGNATURE_DIGITAL
SFS.DependencyMode = _
    SAPI_ENUM_DEPENDENCY_MODE.SAPI_ENUM_DEPENDENCY_MODE_INDEPENDENT
TF.DateFormat = dateFormat
TF.TimeFormat = timeFormat
TF.ExtTimeFormat = _
    SAPI_ENUM_EXTENDED_TIME_FORMAT.SAPI_ENUM_EXTENDED_TIME_FORMAT_GMT 
    ' Display GMT offset
SFS.TimeFormat = TF

 

Signing

The SignatureFieldCreateSign function both creates and signs a new signature field in a specific file. The signature field is created with attributes according to the SigFieldSettings object.

// Create and sign a new signature field in the document
if ( SAPI_OK != (rc = SAPISignatureFieldCreateSign (
	hSession,                       // Session Handle
	SAPI_ENUM_FILE_ADOBE,           // Type of the file to sign - PDF
	(SAPI_LPCWSTR)filePath,         // Path to PDF file to sign
	&sSigFieldSettings,             // Signature Field details
	0,                              // Flags
	NULL,                           // Credentials (only if prompt-for-sign feature is enabled)
	0)))                            // Credentials length
{
	SAPILogoff(hSession);           // Release user context
	SAPIHandleRelease (hSession);   // Release memory allocated for Session Handle
	printf("Error on SAPISignatureFieldCreateSign, rc = 0x%x, 
        Extended error 0x%x\n", rc, SAPIExtendedLastErrorGet());
	return -1;
}
// Create and sign a new signature field in the document
if (SAPI_OK != (rc = SAPI.SignatureFieldCreateSign(
	sesHandle,                                  // Session Handle
	SAPI_ENUM_FILE_TYPE.SAPI_ENUM_FILE_ADOBE,   // Type of the file to sign - PDF
	filePath,                                   // Path to PDF file to sign
	SFS,                                        // Signature Field details
	0,                                          // Flags
	null)))                                     // Credentials (only if prompt-for-sign feature is enabled)
{
	throw new Exception(string.Format("Failed in SAPISignatureFieldCreateSign() ({0})", 
        rc.ToString("X")));
}
Dim fileType As SAPI_ENUM_FILE_TYPE = SAPI_ENUM_FILE_TYPE.SAPI_ENUM_FILE_ADOBE  
'Type of the file to sign - PDF
Dim flags As Integer = 0
 
'Create and sign a new signature field in the document
rc = SAPI.SignatureFieldCreateSign(sesHandle, fileType, filePath, SFS, flags, Nothing)
If rc <> SAPI_OK Then Throw New Exception(String.Format( _
    "Failed in SAPISignatureFieldCreateSign() ({0})", rc.ToString("X")))

Cleaning Up

The Logoff function ends the session with the appliance under a specific user’s credentials; HandleRelease releases all the resources related to any kind of SAPI handles.

SAPILogoff(hSession);               // Release user context
SAPIHandleRelease (hSession);       // Release Session Handle
SAPI.Logoff(sesHandle);          // Release user context
SAPI.HandleRelease(sesHandle);   // Release session handle
SAPI.Logoff(sesHandle)         'Release user context
SAPI.HandleRelease(sesHandle)  'Release session handle