Secure Exchanges SDK Documentation
Search Results for

    Show / Hide Table of Contents

    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

    1. Initial Request: When you call MultiRecipientMessage, only the first signer is activated
    2. First Signer: Receives their URL/email immediately and can sign the document
    3. Automatic Progression: After the first signer completes, the system automatically notifies the second signer
    4. White-Label Emails: Use Answer.HtmlMsg to 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

    1. Load PDF: Read the file and calculate its SHA512 hash
    2. Create zones: Use ZoneBuilder with isPki: true
    3. Get token: Call SignHelper.GetCertificationToken() to obtain certification data
    4. Certify PDF: Use PkiFileHelper.CertifyPkiPdf() to prepare the document
    5. Send: Pass the CertifiedPdfContainer in MutliRecipientArgs.CertifiedPdfs

    See Also

    • Getting Started
    • Signature Zones
    • Best Practices
    In this article
    Back to top Secure Exchanges Inc. - Documentation