For developers

API keys + HMAC webhooks

Bearer-authed REST API for backends; every outbound webhook is HMAC-SHA-256-signed.

What it does

Programmatic clients authenticate with dsk_-prefixed API keys (SHA-256 hashed at rest, returned once on creation). The same routes that accept session cookies also accept Bearer tokens via requireAuth. Webhooks for signing requests and auth-proof carry an x-docsign-signature header so partners can verify integrity offline.

How it works

  1. 1

    Settings โ†’ API keys โ†’ Create key. Copy the plaintext immediately โ€” it's shown once.

  2. 2

    Authenticate every backend request with Authorization: Bearer dsk_โ€ฆ

  3. 3

    Set a callbackUrl + callbackSecret on signing requests / auth-proof challenges to receive webhooks.

  4. 4

    Verify each webhook with HMAC-SHA-256(rawBody, callbackSecret) against the x-docsign-signature header.

Why it matters

  • Same code path as the in-app routes โ€” no parallel API surface to maintain.
  • Keys carry ~192 bits of entropy; SHA-256 at rest is acceptable without a salt.
  • Per-key lastUsedAt makes 'who's still using this old key' a one-line query.

Verify a webhook signature

Copy-paste starting point for integrating this feature.

Verify a webhook signature
import { createHmac } from "node:crypto";

export function verifyWebhook(rawBody, headerSig, secret) {
  const expected = "sha256=" + createHmac("sha256", secret)
    .update(rawBody)
    .digest("hex");
  // Constant-time compare to avoid timing oracles.
  return expected.length === headerSig.length
    && createHmac("sha256", secret).update(rawBody).digest("hex")
       === headerSig.replace(/^sha256=/, "");
}

Want to try it?

Grab an API key from Settings โ†’ API keys, then jump into the developer docs.

Related features