Skip to the content

SIGN PDF API · C#

Sign a PDF in C#.

This sign PDF API in C# example sends a template to one person, who signs on any device. Make a test key and a template, then run it. A test key sends nothing real and bills nothing.

SIGNED

Signed

JavaScriptPythonGoPHPC#

C#

using Docustay.Api.Api;
using Docustay.Api.Client;
using Docustay.Api.Model;
var config = new Configuration { BasePath = Environment.GetEnvironmentVariable("DOCUSTAY_URL") ?? "https://app.docustay.app" };
config.AccessToken = Environment.GetEnvironmentVariable("DOCUSTAY_API_KEY");
var api = new DocumentsApi(config);
var request = new SendRequest(
    templateId: Guid.Parse(Environment.GetEnvironmentVariable("DOCUSTAY_TEMPLATE_ID")!),
    parties: new List<SendRequestPartiesInner> { new SendRequestPartiesInner(seat: "signer_1", name: "Rosa Alvarez", email: "rosa@example.com") });

Send, listen, download

Three steps, one program.

1 · Install

Add the client.

dotnet add package Docustay.Api

The package targets .NET 8. Every call that creates something takes an idempotency key as its first argument: build one per attempt and reuse it when you retry. Set BasePath only when you point at a self-hosted install.

2 · Send

send.cs

using Docustay.Api.Api;
using Docustay.Api.Client;
using Docustay.Api.Model;

var config = new Configuration { BasePath = Environment.GetEnvironmentVariable("DOCUSTAY_URL") ?? "https://app.docustay.app" };
config.AccessToken = Environment.GetEnvironmentVariable("DOCUSTAY_API_KEY");
var api = new DocumentsApi(config);

var request = new SendRequest(
    templateId: Guid.Parse(Environment.GetEnvironmentVariable("DOCUSTAY_TEMPLATE_ID")!),
    parties: new List<SendRequestPartiesInner> { new SendRequestPartiesInner(seat: "signer_1", name: "Rosa Alvarez", email: "rosa@example.com") });
var doc = api.SendDocument(Guid.NewGuid().ToString(), request);
Console.WriteLine($"{doc.Id} {doc.State}");

This sends the template to one person. It reads the key and the template id from the environment.

3 · Then

Read the answer.

The C# program's answer holds the document's id and its state. Ask for it later with the same key, or get a signed webhook when it is signed. The quickstart shows the rest.

What happens next

A .NET client from NuGet: send from a service, a job or a console app.

When everyone has signed, the sealed PDF and its certificate go to everyone.

Certificate of completion

Document Services Agreement

Signed by Dana Whitfield · 14:02 UTC

Signed by Ada Lovelace · 14:09 UTC

File hash sha-256 9f2c…41ab

SIGNED
FIG. 02 · AFTER THE C# CALL · SAMPLE DATA

The request, by hand

What the C# program sends.

PartValue
Method and pathPOST /api/v1/documents/send
AuthorizationBearer, then your API key
Content-Typeapplication/json
Idempotency-KeyA fresh UUID for each document; keep it if you retry
BodytemplateId and parties: a seat, a name and an email for each person

The same request works from any language that can make an HTTPS call.

FIG. 03 · THE REQUEST

Line by line

What the C# program does.

Read it once and you can change it with confidence.

01

Base libraries only

The example uses System.Net.Http with top-level statements, so a one-file project on .NET 8 or newer is enough.

02

Build the JSON body

The body is a short JSON string with the templateId and one party for seat signer_1. A real program would build it with System.Text.Json.

03

Set the headers

Authorization carries the bearer key, the content is sent as application/json, and Idempotency-Key is a fresh Guid. Keep that value if you retry.

04

Check the status

A response that is not a success throws with the status and the body; otherwise the program prints the answer, which holds the document's id and its state.

When it goes wrong

Errors and retries in C#.

Every error from the API has the same shape: kind, a plain message, a requestId and a retryable flag.

01

Parse the error body

A failure comes back as a JSON object with a kind, a message, a requestId and a retryable flag. Deserialize it with the JSON library you already use and log the requestId.

02

Write the retry around the request

Retry a 429 after its Retry-After seconds and a 5xx after a pause, with the same Idempotency-Key each time. A generated C# client is available if you would rather not write that loop.

03

What is safe to retry

In C#, as anywhere, a 429 and a 5xx are safe to retry with the same Idempotency-Key: sending the same request again never sends a second document. A 400, 401, 403, 404 or 409 will give the same answer every time, so fix the cause before you try again.

Before you run it

What you need on hand.

Three things, none of them hard to get.

01

The .NET 8 SDK

Nothing to install from a package feed. The .NET SDK builds and runs the file, and HttpClient is part of the base libraries.

02

A test key

Make a key in the app under Developers, then API keys, and tick documents:read and documents:write. Give it to the C# program through DOCUSTAY_API_KEY. A key that starts dsk_test_ only does practice runs: the email goes to you and nothing counts.

03

A template id

Use your own copy of a built-in template, or one you made from HTML or a tagged PDF, and put its id in DOCUSTAY_TEMPLATE_ID before you run the C# file. Its seat names, such as signer_1, are what the parties in the request refer to.

04

Run it

Save the program as send.cs. It prints the document's id and its state, and the test email arrives in your own inbox within a minute or so.

Questions

Quick answers.

Does a test key send anything real?

No. A document sent with a dsk_test_ key is emailed only to you, carries a TEST watermark and is never counted.

Where do the key and template id come from?

From the environment: DOCUSTAY_API_KEY and DOCUSTAY_TEMPLATE_ID. The key never sits in the file.

How do I know it was signed?

Subscribe to documents.document.executed, or fetch the document by id.

Make a test key.

Create an API key