1. Overview — what this article covers
You will learn, step-by-step, how to implement DocuSign eSignature in a .NET (ASP.NET Core) app:
key concepts and authentication options (JWT vs Authorization Code)
installing and configuring the official DocuSign C# SDK and quickstart links.
code sample to create and send an envelope (server-side)
embedded signing (recipient view) sample for in-app signing
implementing and securing DocuSign Connect (webhook) listener in ASP.NET Core, including validation.
testing, error handling, logging, and deployment considerations
best practices for security, compliance, and monitoring
I’ll include working C# snippets and notes you can drop into an ASP.NET Core project.
2. Quick background: DocuSign building blocks
Account / Integration Key — your DocuSign developer account (Demo) and the App (Integration Key) you create in the DocuSign Admin.
Envelope — a container for documents, recipients, and signing fields.
Recipient & Tabs — signer (email/name) and signing tab positions (fields).
Authentication — DocuSign supports OAuth: Authorization Code and JWT Grant; for server-to-server automated flows, JWT Grant is recommended.
Connect (Webhooks) — DocuSign’s webhook system to notify your app of envelope events (completed, declined, etc.).
3. Prerequisites
DocuSign developer account ( https://developers.docusign.com ) — use Demo (sandbox).
Integration Key (app) created in DocuSign Admin with the redirect URI (if using Auth Code) or configured for JWT.
RSA keypair (private key) generated and uploaded to your DocuSign app (for JWT flow).
.NET 6 / .NET 7+ SDK and an ASP.NET Core Web API or MVC project.
NuGet packages:
DocuSign.eSign(official C# SDK).
Install the SDK
dotnet add package DocuSign.eSign
4. Authentication: choose the right flow
JWT Grant (service integrations): no user interaction; server exchanges signed JWT for access token. Best for backend services that act on behalf of users or a system account. Requires consent once (admin or user).
Authorization Code Grant (user interactive): redirect user to DocuSign login page, user consents and returns code. Best for user-driven flows where the signer must authenticate with DocuSign.
Recommendation: Use JWT for server flows (creating envelopes programmatically, embedded signing server prepares envelope); use Authorization Code when the user must sign in to DocuSign itself.
5. Getting an access token (JWT) — minimal example
Upload your RSA private key to the DocuSign app (Admin → Apps and Keys).
Grant consent to your Integration Key for the impersonated user (admin consent or via browser link).
Below is a minimal JWT token flow using the DocuSign SDK helper. The SDK exposes helper classes; you can also form JWT by hand.
using DocuSign.eSign.Client;
using System.Security.Cryptography;
using System.IO;
public class DocuSignAuthService
{
private readonly string _integrationKey = "<INTEGRATION_KEY>";
private readonly string _userId = "<IMPERSONATED_USER_ID_GUID>";
private readonly string _authBasePath = "account-d.docusign.com"; // demo
private readonly string _privateKeyPath = "docusign_private_key.pem"; // RSA private key (PKCS8)
public ApiClient CreateApiClient()
{
var apiClient = new ApiClient($"https://{_authBasePath}");
return apiClient;
}
public string GetAccessToken()
{
var apiClient = CreateApiClient();
// Read private key
var privateKey = File.ReadAllText(_privateKeyPath);
// Requests JWT token. SDK provides a helper method.
var oauthToken = apiClient.RequestJWTUserToken(
_integrationKey,
_userId,
new List<string> { "signature", "impersonation" },
System.Text.Encoding.UTF8.GetBytes(privateKey),
3600);
return oauthToken.access_token;
}
}
Notes
Use the SDK method
RequestJWTUserTokencarefully (it expects private key bytes in a certain format). Refer SDK docs for exact signature.In production, store private keys in a secure store (KeyVault, AWS KMS) — never commit to repo.
6. Create and send an envelope (server side)
This example creates an envelope with a single PDF and a single signer.
using DocuSign.eSign.Api;
using DocuSign.eSign.Model;
using DocuSign.eSign.Client;
using System.Collections.Generic;
public class DocuSignService
{
private readonly string _accountId;
private readonly ApiClient _apiClient;
public DocuSignService(string accessToken, string accountId, string basePath = "https://demo.docusign.net/restapi")
{
_apiClient = new ApiClient(basePath);
_apiClient.Configuration.DefaultHeader.Add("Authorization", "Bearer " + accessToken);
_accountId = accountId;
}
public EnvelopeSummary SendEnvelope(byte[] pdfBytes, string signerEmail, string signerName, string signerClientUserId = null)
{
var envelopesApi = new EnvelopesApi(_apiClient.Configuration);
// Document
var doc = new Document
{
DocumentBase64 = Convert.ToBase64String(pdfBytes),
Name = "Sample Document",
FileExtension = "pdf",
DocumentId = "1"
};
// Signer
var signer = new Signer
{
Email = signerEmail,
Name = signerName,
RecipientId = "1",
RoutingOrder = "1"
};
// Example: add a signHere tab at absolute position
signer.Tabs = new Tabs
{
SignHereTabs = new List<SignHere> {
new SignHere { DocumentId = "1", PageNumber = "1", XPosition = "100", YPosition = "150" }
}
};
var envDef = new EnvelopeDefinition
{
EmailSubject = "Please sign this document",
Documents = new List<Document> { doc },
Recipients = new Recipients { Signers = new List<Signer> { signer } },
Status = "sent" // "sent" to send immediately, "created" to save as draft
};
var result = envelopesApi.CreateEnvelope(_accountId, envDef);
return result;
}
}
This SendEnvelope returns an EnvelopeSummary with the envelopeId you can store and track.
7. Embedded Signing (In-app signing / Recipient View)
For in-app signing (so the signer stays in your app), create a recipient view (signing URL). This requires the signer to be a embedded recipient — set clientUserId on the signer object.
public string CreateRecipientView(string envelopeId, string signerEmail, string signerName, string returnUrl)
{
var viewRequest = new RecipientViewRequest
{
ReturnUrl = returnUrl, // user returns here after signing
ClientUserId = "123", // must match Signer.clientUserId
AuthenticationMethod = "none",
UserName = signerName,
Email = signerEmail
};
var envelopesApi = new EnvelopesApi(_apiClient.Configuration);
var result = envelopesApi.CreateRecipientView(_accountId, envelopeId, viewRequest);
return result.Url; // redirect user to this URL (or open in iframe if allowed)
}

Join the conversation! Your thoughts help the community grow.