API Documentation

Create and manage contracts programmatically with the CanUSign API.

Authentication

All API requests require authentication using a Bearer token. Create an API key in your Settings.

Authorization: Bearer canu_your_api_key_here

Rate Limiting

The API is rate limited to 60 requests per minute per API key.

Rate limit headers are included in all responses:

  • X-RateLimit-Limit - Max requests per window
  • X-RateLimit-Remaining - Remaining requests
  • X-RateLimit-Reset - Window reset time (ISO 8601)

Base URL

https://canusign.com/api/v1

Endpoints

POST/contracts

Create a new contract.

Request Body

{
  "title": "My Contract",
  "content": "<p>Contract content in HTML...</p>",
  "signatureFields": [
    {
      "label": "Client",
      "page": 1,
      "x": 10,
      "y": 80
    },
    {
      "label": "Provider",
      "page": 1,
      "x": 60,
      "y": 80
    }
  ],
  "tags": [
    "business"
  ],
  "finalize": true
}

Response

{
  "success": true,
  "contract": {
    "id": "clx123...",
    "token": "ABC123XY",
    "title": "My Contract",
    "status": "pending",
    "signUrl": "https://canusign.com/sign/ABC123XY",
    "createdAt": "2024-01-15T10:30:00Z"
  }
}
GET/contracts

List all your contracts.

Query Parameters

  • status - Filter by status (draft, pending, signed)
  • limit - Results per page (default: 50, max: 100)
  • offset - Pagination offset

Response

{
  "contracts": [
    {
      "id": "clx123...",
      "token": "ABC123XY",
      "title": "My Contract",
      "status": "pending",
      "signatures": [],
      "createdAt": "2024-01-15T10:30:00Z"
    }
  ],
  "pagination": {
    "total": 1,
    "limit": 50,
    "offset": 0,
    "hasMore": false
  }
}
GET/contracts/:id

Get contract details by ID or token.

DELETE/contracts/:id

Delete a contract. Signed contracts cannot be deleted.

GET/contracts/from-template

List all available templates with their variables. Use this to discover which templates and variable fields are available before creating a contract.

Query Parameters

  • language - Template language (de, en, es, fr, it, pt, nl, pl). Default: en

Response

{
  "templates": [
    {
      "id": "dpa",
      "name": "Data Processing Agreement (EN)",
      "category": "legal",
      "icon": "🔐",
      "availableLanguages": [
        "de",
        "en",
        "es",
        "..."
      ],
      "variables": [
        {
          "id": "controller_name",
          "label": "Controller Name"
        },
        {
          "id": "processor_name",
          "label": "Processor Name"
        }
      ],
      "hasContent": true
    }
  ],
  "language": "en",
  "total": 45
}
POST/contracts/from-template

Create a contract from a pre-built template. No need to provide HTML — just choose a template, language, and fill in the variables.

Request Body

{
  "template": "dpa",
  "language": "en",
  "variables": {
    "controller_name": "Acme Corp",
    "processor_name": "Cloud Services GmbH",
    "controller_address": "123 Main St, Berlin",
    "processor_address": "456 Tech Ave, Munich"
  },
  "title": "DPA - Acme & Cloud Services",
  "tags": [
    "dpa",
    "gdpr"
  ],
  "finalize": true
}

Response

{
  "success": true,
  "contract": {
    "id": "clx456...",
    "token": "DEF789AB",
    "title": "DPA - Acme & Cloud Services",
    "status": "pending",
    "signUrl": "https://canusign.com/sign/DEF789AB",
    "createdAt": "2025-01-15T10:30:00Z"
  },
  "template": {
    "id": "dpa",
    "language": "en",
    "variablesFilled": 4,
    "variablesAvailable": 12
  }
}

Webhooks

Overview

Webhooks allow you to receive real-time HTTP notifications when events happen on your contracts. Instead of polling the API, register a URL and we'll send a POST request with event data whenever something changes.

Available Events

  • contract.created — A new contract was created
  • contract.signed — A signer submitted their signature
  • contract.completed — All required signatures collected
  • contract.deleted — A contract was deleted

Payload Format

{
  "id": "del_abc123...",
  "event": "contract.signed",
  "created_at": "2025-01-15T10:30:00Z",
  "data": {
    "id": "clx123...",
    "token": "ABC123XY",
    "title": "Service Agreement",
    "fieldId": "signer_a",
    "signerName": "John Doe"
  }
}

HTTP Headers

  • X-CanUSign-Signature — HMAC-SHA256 signature: sha256=<hex>
  • X-CanUSign-Event — Event type (e.g. contract.signed)
  • X-CanUSign-Delivery — Unique delivery ID
  • User-Agent CanUSign-Webhook/1.0

Signature Verification

Every webhook delivery is signed with your webhook secret using HMAC-SHA256. Always verify the signature before processing events.

Node.js

const crypto = require('crypto');

function verifyWebhook(payload, signature, secret) {
  const expected = 'sha256=' + crypto
    .createHmac('sha256', secret)
    .update(payload)
    .digest('hex');
  return crypto.timingSafeEqual(
    Buffer.from(signature),
    Buffer.from(expected)
  );
}

Python

import hmac, hashlib

def verify_webhook(payload: bytes, signature: str, secret: str) -> bool:
    expected = 'sha256=' + hmac.new(
        secret.encode(), payload, hashlib.sha256
    ).hexdigest()
    return hmac.compare_digest(signature, expected)

Webhook Endpoints

GET/webhooks

List all your webhooks.

POST/webhooks

Create a new webhook endpoint.

Request Body

{
  "url": "https://your-server.com/webhooks",
  "events": [
    "contract.signed",
    "contract.completed"
  ]
}

Response

{
  "success": true,
  "webhook": {
    "id": "clx789...",
    "url": "https://your-server.com/webhooks",
    "events": [
      "contract.signed",
      "contract.completed"
    ],
    "active": true,
    "secret": "whsec_a1b2c3d4...",
    "createdAt": "2025-01-15T10:30:00Z"
  }
}

The secret is only returned on creation. Store it securely to verify webhook signatures.

PATCH/webhooks/:id

Update webhook URL, events, or active status. All fields are optional.

{
  "url": "https://new-server.com/hooks",
  "events": [
    "contract.completed"
  ],
  "active": false
}
DELETE/webhooks/:id

Delete a webhook.

GET/webhooks/:id

Get webhook details.

Examples (cURL)

Create contract with custom HTML

curl -X POST https://canusign.com/api/v1/contracts \
  -H "Authorization: Bearer canu_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Service Agreement",
    "content": "<h1>Service Agreement</h1><p>Terms...</p>",
    "finalize": true
  }'

Create contract from template

curl -X POST https://canusign.com/api/v1/contracts/from-template \
  -H "Authorization: Bearer canu_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "template": "dpa",
    "language": "en",
    "variables": {
      "controller_name": "Acme Corp",
      "processor_name": "Cloud Services GmbH"
    },
    "title": "DPA - Acme & Cloud",
    "finalize": true
  }'

List available templates

curl https://canusign.com/api/v1/contracts/from-template?language=en \
  -H "Authorization: Bearer canu_your_api_key"

Claude Code / MCP Integration

Use CanUSign directly from Claude Code with our MCP server. Create contracts just by describing them in natural language.

1. Install the MCP Server

npx canusign-mcp-server

2. Configure Claude Code

Add to your ~/.claude/claude_desktop_config.json:

{
  "mcpServers": {
    "canusign": {
      "command": "npx",
      "args": [
        "canusign-mcp-server"
      ],
      "env": {
        "CANUSIGN_API_KEY": "canu_your_api_key_here"
      }
    }
  }
}

3. Use it!

Ask Claude to create contracts for you:

“Create a service agreement between Acme Corp and John Doe for web development at $5000”

“Create a DPA (Data Processing Agreement) between Acme Corp as controller and Cloud GmbH as processor for customer data processing”

The MCP server uses the /contracts/from-template endpoint to create contracts from pre-built templates with pre-filled variables.

Questions? Contact support