Complete Examples
Complete SDK usage scenarios based on the official documentation.
Scenario 1: Sending a Secure Message with Files
using SecureExchangesSDK.Helpers;
using SecureExchangesSDK.Models.Args;
using SecureExchangesSDK.Models.Entity;
using SecureExchangesSDK.SecureExchanges;
using System;
using System.Collections.Generic;
// SDK credentials
Guid serial = new Guid("YOUR-SERIAL-GUID");
Guid APIuser = new Guid("YOUR-API-USER-GUID");
Guid APIpassword = new Guid("YOUR-API-PASSWORD-GUID");
Uri endpoint = new Uri("https://www.secure-exchanges.com/_api/0217/0217.asmx");
// Create recipient list
List<RecipientInfo> recipientList = new List<RecipientInfo>();
recipientList.Add(new RecipientInfo() { Email = "recipient@example.com" });
// Message content
string message = "My <strong>HTML</strong> message";
string subject = "My subject";
string password = null;
// Files (binary approach)
List<FileArgs> binaryFiles = new List<FileArgs>();
// Sending options
var sendMethod = SendMethodEnum.onlyEmail;
bool sendByMyOwnSMTPServer = false;
bool showSubject = true;
bool getNotify = true;
string culture = "en-CA";
int maxOpeningTime = 5;
int expirationMinutes = 30;
// Create message arguments
var arg = new MutliRecipientArgs(
endpoint, serial, APIuser, APIpassword, recipientList,
message, subject, password, binaryFiles,
sendMethod, sendByMyOwnSMTPServer, showSubject,
getNotify, culture, maxOpeningTime, expirationMinutes
);
// Add files using path
var filesPathList = new List<string>();
filesPathList.Add(@"c:\temp\document.pdf");
arg.FilesPath = filesPathList;
// Send the message
var messageAnswer = MessageHelper.MultiRecipientMessage(arg);
if (messageAnswer.Status == 200)
{
Console.WriteLine("Message sent successfully");
foreach (var recipientAnswer in messageAnswer.RecipientsAnswer)
{
Console.WriteLine($"Status: {recipientAnswer.Answer.Status}");
Console.WriteLine($"URL: {recipientAnswer.Answer.URL}");
// HtmlMsg contains complete white-label HTML for custom email delivery
Console.WriteLine($"HTML: {recipientAnswer.Answer.HtmlMsg}");
}
}
else
{
Console.WriteLine(messageAnswer.Data);
}
Scenario 2: Two-Party Contract Signing (Sequential Process)
This example shows how to send a PDF contract to two signers. The process is sequential: only the first signer receives their URL immediately, and the second signer will be notified after the first completes.
using SecureExchangesSDK.Helpers;
using SecureExchangesSDK.Models.Args;
using SecureExchangesSDK.Models.Entity;
using SecureExchangesSDK.Models.JSON;
using SecureExchangesSDK.Models.Transport;
using SecureExchangesSDK.SecureExchanges;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
// SDK credentials
Guid serial = new Guid("YOUR-SERIAL-GUID");
Guid APIuser = new Guid("YOUR-API-USER-GUID");
Guid APIpassword = new Guid("YOUR-API-PASSWORD-GUID");
Uri endpoint = new Uri("https://www.secure-exchanges.com/_api/0217/0217.asmx");
// Create two recipients (signers)
List<RecipientInfo> recipientList = new List<RecipientInfo>();
recipientList.Add(new RecipientInfo() { Email = "signer1@example.com" });
recipientList.Add(new RecipientInfo() { Email = "signer2@example.com" });
// Message content
string message = "Please sign this contract.";
string subject = "Contract Requiring Your Signature";
// Create message arguments
var arg = new MutliRecipientArgs(
endpoint, serial, APIuser, APIpassword, recipientList,
message, subject, null, null,
SendMethodEnum.onlyEmail, false, true,
true, "en-CA", 5, 10080 // 7 days expiration
);
// PDF file path
var filePath = @"c:\temp\contract.pdf";
arg.FilesPath = new List<string> { filePath };
// Get SHA512 hash of the file (required for signature tracking)
string SHA512 = CryptoHelper.GetSHA512OfFile(filePath);
// Create list of files requiring signature
List<SignFilesRequired> signFiles = new List<SignFilesRequired>();
signFiles.Add(new SignFilesRequired()
{
SHA512 = SHA512,
DoNotAppendCertificateToFile = false
});
// Create recipient-zone mapping dictionary
var recipientIndex = new Dictionary<RecipientInfo, List<FileZoneDefinition>>();
// Use ZoneBuilder to create signature zones
using (var zoneBuilder = new ZoneBuilder(filePath, isPki: false))
{
// Define signature zones for Signer 1
var signer1Zones = new SignZoneDetails[]
{
zoneBuilder.CreateFieldSignZone(1, "signature_signer1", 50, 650, 200, 50),
zoneBuilder.CreateFieldDateSignZone(1, "date_signer1", 260, 660, 100, 25, 12)
};
// Map zones to signer 1
recipientIndex.Add(recipientList[0], new List<FileZoneDefinition>()
{
new FileZoneDefinition
{
UniqueName = SHA512,
ZonesDef = new SignZoneDefinition { Zones = signer1Zones }
}
});
// Define signature zones for Signer 2
var signer2Zones = new SignZoneDetails[]
{
zoneBuilder.CreateFieldSignZone(1, "signature_signer2", 50, 550, 200, 50),
zoneBuilder.CreateFieldDateSignZone(1, "date_signer2", 260, 560, 100, 25, 12)
};
// Map zones to signer 2
recipientIndex.Add(recipientList[1], new List<FileZoneDefinition>()
{
new FileZoneDefinition
{
UniqueName = SHA512,
ZonesDef = new SignZoneDefinition { Zones = signer2Zones }
}
});
}
// Configure signing options
arg.FileToSign = signFiles;
arg.OwnerDontNeedToSign = true;
arg.SignRecipientsZoneDef = SignHelper.ConvertRecipientIndexToList(recipientIndex);
// CallBackParameters: Custom parameters that persist throughout the signing process.
// Essential for SESAR integration - they can be retrieved to classify signed documents.
arg.CallBackParameters = JsonConvert.SerializeObject(new List<CallBackParameter>
{
new CallBackParameter("ClientId", "CLI-12345"),
new CallBackParameter("DossierNumber", "DOS-2024-001"),
new CallBackParameter("DocumentType", "Contract")
});
// Send the message
var messageAnswer = MessageHelper.MultiRecipientMessage(arg);
// Process response
// IMPORTANT: Only the first signer is processed immediately.
// The second signer will be notified automatically after the first signs.
if (messageAnswer.Status == 200)
{
Console.WriteLine("Contract sent for signature");
// First signer's information
var firstSignerAnswer = messageAnswer.RecipientsAnswer[0].Answer;
Console.WriteLine($"Signer 1 URL: {firstSignerAnswer.URL}");
Console.WriteLine($"Signer 1 Code: {firstSignerAnswer.DefaultOpeningCode}");
// HtmlMsg contains the complete white-label HTML for custom email delivery
// Use this to send emails from your own SMTP server with your branding
Console.WriteLine($"White-label HTML available: {!string.IsNullOrEmpty(firstSignerAnswer.HtmlMsg)}");
}
else
{
Console.WriteLine(messageAnswer.Data);
}
Understanding the Sequential Process
- Initial Request: When you call
MultiRecipientMessage, only the first signer is activated - First Signer: Receives their URL/email immediately and can sign the document
- Automatic Progression: After the first signer completes, the system automatically notifies the second signer
- White-Label Emails: Use
Answer.HtmlMsgto send emails from your own SMTP server with your branding
CallBackParameters and SESAR Integration
The CallBackParameters property is essential when integrating with SESAR (Secure Exchanges Storage And Retrieval). These parameters:
- Persist throughout the entire process: From initial send until all signatures are complete
- Are encrypted on Secure Exchanges servers: Secure but retrievable by your system
- Enable document classification: SESAR can retrieve these parameters to automatically file and organize signed documents
// Define callback parameters for your business context
var callbackParams = new List<CallBackParameter>
{
new CallBackParameter("ClientId", "CLI-12345"),
new CallBackParameter("DossierNumber", "DOS-2024-001"),
new CallBackParameter("DocumentType", "Contract"),
new CallBackParameter("Department", "Sales")
};
// Serialize and assign to the message args
arg.CallBackParameters = JsonConvert.SerializeObject(callbackParams);
When the signing process completes, SESAR receives these parameters and can use them to:
- Automatically classify the signed document in the correct client folder
- Update your business system with the signature status
- Trigger downstream workflows based on document type
Scenario 3: Complete Signature with All Zone Types
This example demonstrates all available signature zone types.
var filePath = @"c:\temp\document.pdf";
string SHA512 = CryptoHelper.GetSHA512OfFile(filePath);
// Create zones with all available types
var zones = new List<SignZoneDetails>();
using (var zoneBuilder = new ZoneBuilder(filePath, isPki: false))
{
// Text field
zones.Add(zoneBuilder.CreateFieldTextZone(1, "fullName", 10, 700, 200, 30, "Enter your name", 14, true));
// Number field
zones.Add(zoneBuilder.CreateFieldNumberZone(1, "amount", 10, 650, 100, 30, 0, 14, true));
// Date picker (user selects date)
zones.Add(zoneBuilder.CreateFieldDateZone(1, "contractDate", 10, 600, 150, 30, 12, true));
// Date sign (auto-filled with signature timestamp)
zones.Add(zoneBuilder.CreateFieldDateSignZone(1, "signatureDate", 10, 550, 150, 30, 12));
// Signature zone
zones.Add(zoneBuilder.CreateFieldSignZone(1, "signature", 10, 450, 200, 60));
// Initials zone
zones.Add(zoneBuilder.CreateFieldInitialZone(1, "initials", 10, 400, 60, 30));
// Checkboxes
zones.Add(zoneBuilder.CreateFieldCheckBoxZone(1, "agreeTerms", 10, 350, false, true));
zones.Add(zoneBuilder.CreateFieldCheckBoxZone(1, "newsletter", 10, 320, true, false));
// Radio buttons (same groupId for mutual exclusion)
zones.Add(zoneBuilder.CreateFieldRadioZone(1, "Check", 10, 280, "paymentMethod", false));
zones.Add(zoneBuilder.CreateFieldRadioZone(1, "Wire Transfer", 40, 280, "paymentMethod", true));
}
Scenario 4: PKI Signature with PDF Certification
This example shows the complete PKI signature process with PDF document certification.
using SecureExchangesSDK.Helpers;
using SecureExchangesSDK.Models.Args;
using SecureExchangesSDK.Models.Entity;
using SecureExchangesSDK.Models.Transport;
using SecureExchangesSDK.SecureExchanges;
using SecureExchangesSignatureSDK.Helpers;
using SecureExchangesSignatureSDK.Models;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
// SDK credentials
Uri endpoint = new Uri("https://www.secure-exchanges.com/_api/0217/0217.asmx");
Guid serial = new Guid("YOUR-SERIAL-GUID");
Guid apiUser = new Guid("YOUR-API-USER-GUID");
Guid apiPassword = new Guid("YOUR-API-PASSWORD-GUID");
// 1. Load the PDF file to sign
string pdfPath = @"c:\temp\contract.pdf";
string pdfName = Path.GetFileName(pdfPath);
byte[] pdfBytes = File.ReadAllBytes(pdfPath);
string sha512 = CryptoHelper.GetSHA512HashOfBytes(pdfBytes);
// 2. Create signature zones with ZoneBuilder (PKI mode)
SignZoneDetails[] zones;
using (var zoneBuilder = new ZoneBuilder(pdfPath, isPki: true))
{
zones = new SignZoneDetails[]
{
zoneBuilder.CreateFieldSignZone(1, "signature1", 100, 650, 200, 50),
zoneBuilder.CreateFieldDateSignZone(1, "date1", 100, 600, 100, 25, 12)
};
}
// 3. Map zones to recipient
var recipient = new RecipientInfo { Email = "signer@example.com" };
var recipientIndex = new Dictionary<RecipientInfo, List<FileZoneDefinition>>
{
{
recipient,
new List<FileZoneDefinition>
{
new FileZoneDefinition
{
UniqueName = sha512,
ZonesDef = new SignZoneDefinition { Zones = zones }
}
}
}
};
var recipients = new List<RecipientInfo> { recipient };
// 4. Get certification token
var certificationTokenArgs = new GetCertificationTokenSDKArgs(
endpoint,
serial,
apiUser,
apiPassword,
sha512,
CertificationTokenType.CertifyDocument,
"en-CA"
);
var certificationTokenResponse = SignHelper.GetCertificationToken(certificationTokenArgs);
// 5. Certify the PDF with PkiFileHelper
var certifyPdfArgs = new CertifyPdfArgs
{
File = new FileArgs(pdfBytes, pdfName, FileHelper.GetMimeType(pdfName)),
RecipientZoneDefinitions = SignHelper.ConvertRecipientIndexToList(recipientIndex),
Recipients = recipients.Select(r => r.Email).ToList(),
CertifyData = certificationTokenResponse.CertificationData,
DetectExistingFields = false
};
CertifiedPdfContainer certifiedPdf;
using (var pkiHelper = new PkiFileHelper())
{
try
{
// Helper can be reused for multiple PDFs
certifiedPdf = await pkiHelper.CertifyPkiPdf(certifyPdfArgs);
}
catch (Exception ex)
{
throw new Exception($"PDF certification failed: {ex.Message}");
}
}
// 6. Configure and send the message
var args = new MutliRecipientArgs(
endpoint,
serial,
apiUser,
apiPassword,
recipients,
"Please sign this contract",
"Contract to sign",
null,
null,
SendMethodEnum.onlyEmail,
false,
true,
true,
"en-CA",
5,
10080 // 7 days
)
{
OwnerDontNeedToSign = true,
CertifiedPdfs = new List<CertifiedPdfContainer> { certifiedPdf }
};
// 7. Send the message
var response = MessageHelper.MultiRecipientMessage(args);
if (response.Status == 200)
{
Console.WriteLine("PKI document sent for signature");
var signerAnswer = response.RecipientsAnswer[0].Answer;
Console.WriteLine($"URL: {signerAnswer.URL}");
Console.WriteLine($"Code: {signerAnswer.DefaultOpeningCode}");
}
else
{
Console.WriteLine($"Error: {response.Data}");
}
PKI Process Steps
- Load PDF: Read the file and calculate its SHA512 hash
- Create zones: Use
ZoneBuilderwithisPki: true - Get token: Call
SignHelper.GetCertificationToken()to obtain certification data - Certify PDF: Use
PkiFileHelper.CertifyPkiPdf()to prepare the document - Send: Pass the
CertifiedPdfContainerinMutliRecipientArgs.CertifiedPdfs