DSDenSign APIDeveloper Reference ← DenSign

DenSign API & Webhooks

Send documents for signature, track them, download the certified PDF, and get real-time completion events — all over a simple REST API. Available on the Business plan.

Authentication

Authenticate every request with your API key in the X-DenSign-Key header (or ?api_key= query param). Keep it secret — treat it like a password.

curl https://sign.dendat.ai/api/v1/documents \
  -H "X-DenSign-Key: YOUR_API_KEY"
Unauthenticated or invalid keys return 401 Unauthorized.

Base URL

https://sign.dendat.ai

Send a document for signature

POST/api/v1/send

Upload a PDF and one or more signers. DenSign auto-detects fields, emails each signer a secure link, and (optionally) calls your webhook on completion. multipart/form-data.

FieldReqDescription
fileyesThe PDF to be signed
titlenoDocument title (defaults to filename)
signer_nameyesFirst signer's name
signer_emailyesFirst signer's email
messagenoNote included in the signing email
webhook_urlnoURL to POST when the document is completed
curl -X POST https://sign.dendat.ai/api/v1/send \
  -H "X-DenSign-Key: YOUR_API_KEY" \
  -F "[email protected]" \
  -F "title=Service Agreement" \
  -F "signer_name=Jane Doe" \
  -F "[email protected]" \
  -F "webhook_url=https://yourapp.com/hooks/densign"

Response 201 Created

{
  "success": true,
  "document_id": 123,
  "status": "sent",
  "signing_url": "https://sign.dendat.ai/sign/<token>"
}

Get a document

GET/api/v1/document/{id}

Returns the document, its status, signers, and fields. Related: GET /api/v1/document/{id}/fields.

Download the signed PDF

GET/api/v1/document/{id}/download

Returns the completed, certified PDF (with the appended certificate page). Available once status = completed.

Audit trail

GET/api/v1/document/{id}/audit

Full, timestamped audit log — viewed, signed, completed, reminders — for legal evidence.

List documents

GET/api/v1/documents

Paginated list of your documents, filterable by status.

Bulk send

POST/api/v1/bulk-send

Send the same document to many recipients in one call. See also POST /api/v1/document/{id}/bulk-remind to nudge all pending signers.

Webhooks

Set webhook_url when sending. When every signer completes, DenSign POSTs a JSON event to your URL:

POST https://yourapp.com/hooks/densign
X-DenSign-Event: document.completed
X-DenSign-Signature: t=1720080000,v1=<hmac-sha256-hex>

{
  "id": "evt_...",
  "event": "document.completed",
  "created": 1720080000,
  "document_id": 123,
  "title": "Service Agreement",
  "status": "completed",
  "completed_at": "2026-07-04T09:00:00",
  "signed_file_hash": "3f9a2c...",
  "certificate_url": "https://sign.dendat.ai/verify?hash=3f9a2c...",
  "signers": [{ "name": "Jane Doe", "email": "[email protected]", "status": "signed", "signed_at": "..." }]
}

Respond 2xx to acknowledge. DenSign retries once on failure.

Verifying the webhook signature

Every webhook is signed so you can confirm it genuinely came from DenSign and was not tampered with. The X-DenSign-Signature header is t=<timestamp>,v1=<signature>, where the signature is HMAC-SHA256 of "{timestamp}.{raw_body}" using your webhook signing secret.

Use the raw request body (bytes) — not a re-serialized JSON object — or the signature won't match.

Python

import hmac, hashlib

def verify(raw_body: bytes, header: str, secret: str) -> bool:
    parts = dict(p.split("=", 1) for p in header.split(","))
    expected = hmac.new(secret.encode(),
                        f'{parts["t"]}.{raw_body.decode()}'.encode(),
                        hashlib.sha256).hexdigest()
    return hmac.compare_digest(expected, parts["v1"])

Node.js

const crypto = require("crypto");
function verify(rawBody, header, secret) {
  const p = Object.fromEntries(header.split(",").map(s => s.split("=")));
  const expected = crypto.createHmac("sha256", secret)
    .update(`${p.t}.${rawBody}`).digest("hex");
  return crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(p.v1));
}

Public document verification

Anyone holding a signed DenSign PDF can confirm it is authentic and unaltered — no account needed — at https://sign.dendat.ai/verify by entering the SHA-256 content hash printed on the certificate page. Great for counterparties, banks, and auditors.

Need an API key or higher limits? Upgrade to Business or email [email protected].