Documentation

API Reference & Guides

Send your first NDA in 5 minutes. Everything you need to embed legally-binding NDA signing into your product.

Quickstart

Four steps to your first signed NDA.

Every step is one HTTP call or one console click. No SDK install, no SaaS sales motion, no contract negotiation.

Sign up and get your account

Create a free NDAKit account in under 60 seconds. No credit card required for the free tier.

browser
https://ndakit.com/signup

Create an API key in your dashboard

Open Dashboard → API Keys → Create. Use a test key (`ndak_test_…`) while you build, then promote to a live key (`ndak_live_…`) when you ship.

shell
export NDAKIT_API_KEY="ndak_test_xxxxxxxxxxxx"

POST /v1/ndas with party info

A single API call generates a legally-vetted NDA pre-loaded with state-specific compliance.

curl
curl https://api.ndakit.com/v1/ndas \
  -H "Authorization: Bearer $NDAKIT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "type": "mutual",
    "party_b_name": "Acme Corp",
    "party_b_email": "ceo@acme.com",
    "purpose": "evaluating partnership",
    "jurisdiction": "DE"
  }'

Subscribe to webhooks for the lifecycle

NDAKit fires signed webhooks for every state change — sent, viewed, signed, declined. Verify the HMAC signature and you are off to the races.

webhook
// nda.signed payload
{
  "id": "evt_8H2k...",
  "type": "nda.signed",
  "data": {
    "id": "nda_8H2k...",
    "party_b_email": "ceo@acme.com",
    "signed_at": "2026-04-29T16:21:08Z",
    "pdf_url": "https://api.ndakit.com/v1/ndas/nda_8H2k.../pdf"
  }
}

Reference

Browse the API surface.

Endpoints
  • GET /v1/ndas
    List NDAs in your account
  • POST /v1/ndas
    Create a new NDA
  • GET /v1/ndas/:id
    Retrieve a single NDA
  • POST /v1/ndas/:id/send
    Send for signing
  • GET /v1/ndas/:id/audit
    Audit trail export
  • POST /v1/webhooks
    Manage webhook endpoints
Concepts
  • NDAs
    The core resource — a generated, sendable document
  • Templates
    Mutual, one-way, contractor, vendor — bring your own on Scale+
  • Recipients
    Counterparties who sign at branded URLs without an account
  • Webhooks
    HMAC-signed events delivered with exponential-backoff retries
  • Compliance
    State-specific overlays auto-applied based on recipient jurisdiction
SDKs
  • Node / TypeScriptcoming soon
  • Pythoncoming soon
  • curlavailable now

Example: Create NDA

POST /v1/ndas

Idempotent. JSON in, JSON out. Returns a draft NDA with a preview URL — call /send when you are ready to ship.

Request
HTTP
POST /v1/ndas HTTP/1.1
Host: api.ndakit.com
Authorization: Bearer ndak_live_xxxxxxxxxxxx
Content-Type: application/json
Idempotency-Key: 8e8b0c2c-cf7c-4f3e-9c2a-7b1c2d4f5a01

{
  "type": "mutual",
  "party_b_name": "Acme Corp",
  "party_b_email": "ceo@acme.com",
  "party_b_address": "1 Market St, San Francisco, CA",
  "purpose": "evaluating a strategic partnership",
  "jurisdiction": "DE",
  "duration_years": 3,
  "include_non_solicitation": true
}
Response
HTTP
HTTP/1.1 201 Created
Content-Type: application/json

{
  "id": "nda_8H2kQp9rT4xL",
  "object": "nda",
  "type": "mutual",
  "status": "draft",
  "party_a_name": "Your Company, Inc.",
  "party_b_name": "Acme Corp",
  "party_b_email": "ceo@acme.com",
  "jurisdiction": "DE",
  "duration_years": 3,
  "compliance_overlays": [],
  "preview_url": "https://app.ndakit.com/preview/nda_8H2kQp9rT4xL",
  "created_at": "2026-04-29T16:18:42Z"
}

Webhooks

Verify the HMAC signature.

Every webhook is signed with HMAC-SHA256 over timestamp.body. Reject any request older than 5 minutes to prevent replay attacks.

webhook handler
import crypto from 'node:crypto';

// Express-style handler
app.post('/webhooks/ndakit', async (req, res) => {
  const signature = req.header('NDAKit-Signature');
  const timestamp = req.header('NDAKit-Timestamp');
  const secret = process.env.NDAKIT_WEBHOOK_SECRET;

  // Reject replays older than 5 minutes
  if (Math.abs(Date.now() / 1000 - Number(timestamp)) > 300) {
    return res.status(400).send('stale');
  }

  const expected = crypto
    .createHmac('sha256', secret)
    .update(`${timestamp}.${req.rawBody}`)
    .digest('hex');

  if (!crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expected))) {
    return res.status(401).send('bad signature');
  }

  const event = JSON.parse(req.rawBody);
  // event.type — 'nda.signed', 'nda.declined', etc.
  res.status(200).end();
});