New:Thread Pilot—AI follow-ups for Gmail.
Learn more

eSign API Documentation

Programmatically send documents for signature using the REST API.

Authentication

All API requests require a Bearer token. Create an API key from Settings.

curl -X POST https://www.switchlabs.dev/api/esign/v1/documents \
  -H "Authorization: Bearer esk_your_api_key_here" \
  -H "Content-Type: multipart/form-data" \
  ...

Base URL

https://www.switchlabs.dev/api/esign/v1

Endpoints

POST/documents

Create a new document and optionally send it immediately. The API also accepts JSON payloads withfileBase64,templateId, per-envelopewebhooks, and embedded recipients viaclientUserId /deliveryMethod.

Form Data Parameters

ParameterTypeDescription
fileFilePDF file (required)
titlestringDocument title (required)
recipientsJSONArray of {name, email, role?} (required)
fieldsJSONArray of field placements (optional)
signing_orderstring"parallel" or "sequential"
sendstring"true" to send immediately

Field Placement Format

{
  "recipient_index": 0,    // Index into recipients array
  "type": "signature",     // signature, initials, text, date, date_signed, checkbox
  "page_index": 0,         // Zero-based page number
  "x": 0.1,               // Normalized position (0-1)
  "y": 0.8,
  "width": 0.2,
  "height": 0.05,
  "required": true,
  "font_size": 10         // Optional, text/date fields (6-36, default 14)
}

Example

curl -X POST https://www.switchlabs.dev/api/esign/v1/documents \
  -H "Authorization: Bearer esk_..." \
  -F "file=@contract.pdf" \
  -F "title=Service Agreement" \
  -F 'recipients=[{"name":"John","email":"john@example.com"}]' \
  -F 'fields=[{"recipient_index":0,"type":"signature","page_index":0,"x":0.1,"y":0.85,"width":0.25,"height":0.05}]' \
  -F "send=true"

Response

{
  "id": "abc123...",
  "status": "sent",
  "recipients": [
    {
      "id": "def456...",
      "signing_url": "https://www.switchlabs.dev/sign/..."
    }
  ]
}

Recipient access codes

Create the document as a draft, configure each recipient's access code, then send it. Codes can only be changed before sending. Share the code separately; it is never included in a signing invitation or returned by the API.

PUT /documents/{documentId}/recipients/{recipientId}/access
Content-Type: application/json

{ "accessCode": "your-separately-shared-code" }

Response: { "accessCodeRequired": true }

Use 8–64 case-sensitive characters without leading or trailing spaces. Send { "accessCode": null } to remove a draft's code. GET on the same endpoint returns only whether a code is required. PUT requires the documents:write scope; GET requires documents:read. The Business API entitlement and document ownership checks apply.

Recipients must enter the code before opening or signing the document. Failed attempts are limited. An access code establishes knowledge of that code; it does not verify a government identity. The completion certificate records the authentication method and accepted electronic-record disclosure version.

GET/documents

List your documents with optional filtering.

Query Parameters

statusFilter by status (draft, sent, completed, etc.)
limitResults per page (max 100, default 50)
offsetPagination offset
GET/documents/{id}/status

Get document status with recipient signing details.

GET/documents/{id}/download?file=completed

Download PDF bytes. file iscompleted (default, the signed PDF),certificate (certificate of completion), ororiginal. Completed and certificate return 409 until every signer has finished. The signed PDF's SHA-256 is returned inX-ESign-Document-Hash.

POST/documents/{id}/send

Send a draft document for signing.

// Optional body
{
  "message": "Please sign at your earliest convenience"
}

PowerForms

Templates can be published as public self-service URLs from the Templates UI. A PowerForm creates a new document from the template, sends it immediately, and can redirect the first signer directly into signing.

GET  https://sign.switchlabs.dev/f/{slug}
POST /api/esign/powerforms/{slug}

{
  "title": "Optional document title override",
  "recipients": [
    { "name": "Ada Lovelace", "email": "ada@example.com" }
  ]
}

Webhooks

Configure webhooks from Settings to receive real-time notifications when documents are signed, completed, or declined.

Available Events

document.createdDocument was created
document.sentDocument was sent for signing
document.completedAll parties signed
document.declinedA signer declined
document.voidedDocument was voided by sender
recipient.signedA recipient completed signing
recipient.viewedA recipient viewed the document
recipient.declinedA recipient declined to sign
reminder.sentA reminder was sent

Payload Format

{
  "event": "recipient.signed",
  "document_id": "abc123...",
  "recipient_id": "def456...",
  "timestamp": "2026-03-26T12:00:00.000Z",
  "data": {
    "fieldCount": 3
  }
}

Signature Verification

Each webhook includes an X-ESign-Signature header with an HMAC-SHA256 signature of the payload body using your webhook secret.

// Node.js verification
const crypto = require('crypto');

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

Rate Limits

PlanDocs/MonthRecipients/DocAPI Access
Free32No
ProUnlimited10No
BusinessUnlimitedUnlimitedYes

Contact

Tell us what you're building and we'll get in touch fast

Ship a proof-of-concept, integrate credit reporting, or hand off the workflow entirely—we respond within one business day and loop in the right Switch Labs partner for your stack.

Response Time
< 24 hours
Delivery Options
Product | Services

By submitting you agree to let Switch Labs contact you about relevant products and services.

eSign - Switch Labs