RESTful API for eSignatures, payments, and customer management. Authenticate with your API key and start building.
All API requests require an x-api-key header. Your API key follows the format:
Generate API keys from Admin → API Settings in your Sign-n-Pay dashboard.
All request bodies should be JSON with the Content-Type: application/json header.
All responses follow a standard structure:
{
"success": true,
"message": "Operation completed successfully",
"data": { ... }
}200/201Success400Bad request — invalid parameters401Unauthorized — invalid or missing API key404Resource not found409Conflict — resource already exists429Rate limit exceeded500Server errorAPI requests are limited to 100 requests per minute per API key.
/v1/external/customersCreate a new customer. Returns 409 if a customer with the same email already exists (with existingCustomerId in the response).
| Name | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Customer's full name |
email | string | Yes | Customer's email address |
phoneNumber | string | No | Customer's phone number |
{
"name": "John Doe",
"email": "john@example.com",
"phoneNumber": "555-123-4567"
}{
"success": true,
"message": "Customer created successfully",
"data": {
"id": "507f1f77bcf86cd799439011",
"name": "John Doe",
"email": "john@example.com",
"phoneNumber": "555-123-4567",
"internalCustomerId": "CUS-abc123"
}
}/v1/external/customersList all customers with optional filtering.
| Name | Type | Required | Description |
|---|---|---|---|
limit | number | No | Max results (default: 100, max: 500) |
offset | number | No | Skip this many results |
search | string | No | Search by name or email |
{
"success": true,
"message": "Found 25 customers",
"data": {
"customers": [...],
"pagination": { "limit": 100, "offset": 0, "count": 25 }
}
}/v1/external/customers/:idGet customer details by ID, including related subscriptions and invoices.
{
"success": true,
"message": "Customer retrieved",
"data": {
"customer": {
"id": "507f1f77bcf86cd799439011",
"name": "John Doe",
"email": "john@example.com",
"phoneNumbers": ["555-123-4567"],
"subscriptions": [...],
"invoices": [...]
}
}
}Packages must be configured in the Sign-n-Pay admin UI before they can be sent via API. This includes setting up pricing, templates, and subscription terms.
/v1/external/packagesList all available packages configured for your tenant.
{
"success": true,
"message": "Packages retrieved",
"data": {
"packages": [
{
"id": "pkg123",
"title": "Monthly Subscription",
"description": "Standard monthly plan",
"subscriptionCost": 99.00,
"setupCost": 0
}
]
}
}/v1/external/packages/:packageId/sendSend a package to a customer. Creates a pending subscription, invoice, and sends the e-sign agreement. The subscription starts in 'pending' status until payment is received.
| Name | Type | Required | Description |
|---|---|---|---|
customerId | string | Yes | Customer ID to send the package to |
emailInvoice | boolean | No | Send email notification (default: true) |
ccEmails | string[] | No | Additional email addresses to CC |
customMergeTagValues | object | No | Custom values for merge tags in the template |
{
"customerId": "507f1f77bcf86cd799439011",
"emailInvoice": true,
"ccEmails": ["manager@company.com"],
"customMergeTagValues": {
"companyName": "Acme Corp",
"contractDate": "01/20/2026"
}
}{
"success": true,
"message": "Package sent successfully",
"data": {
"subscriptionId": "sub123",
"invoiceId": "inv456",
"invoiceUrl": "https://sign-n-pay.com/tenant/cust123/invoice/inv456",
"signingRequestId": "req789",
"signingUrl": "https://sign-n-pay.com/sign?token=abc123",
"customerId": "507f1f77bcf86cd799439011",
"packageId": "pkg123"
}
}Create and manage e-sign templates via API or the Sign-n-Pay admin UI. Templates define the document, signature fields, and signer roles.
/v1/external/esign/templatesList all available e-sign templates with their configured signers and merge tags.
{
"success": true,
"message": "Templates retrieved",
"data": {
"templates": [
{
"id": "template123",
"name": "Standard NDA",
"description": "Non-disclosure agreement",
"signers": [
{ "id": "signer1", "role": "customer", "label": "Client", "signingOrder": 1 }
],
"mergeTags": [
{ "tagName": "customer_name" },
{ "tagName": "contract_date" }
]
}
]
}
}Upload documents via presigned S3 URLs. Supports PDF and DOCX (auto-converted to PDF). Create templates programmatically with signers and fields.
/v1/external/esign/templatesCreate a template and get a presigned S3 URL to upload the file (valid 15 minutes). For multi-file uploads, pass a files array.
| Name | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Template name |
fileName | string | Yes | Original file name |
fileSize | number | Yes | Size in bytes (max 300MB) |
fileType | string | Yes | "pdf" or "docx" |
isOneTime | boolean | No | If true, hidden from template list |
{
"name": "My Contract",
"fileName": "contract.pdf",
"fileSize": 245000,
"fileType": "pdf"
}{
"success": true,
"data": {
"templateId": "abc123",
"uploadUrl": "https://s3.amazonaws.com/...",
"s3Key": "templates/tenant/abc123/original.pdf"
}
}/v1/external/esign/templates/:id/finalize-uploadFinalize after uploading to S3. Converts DOCX to PDF if needed. For multi-file, pass fileKeys to merge. Returns previewUrl for rendering the merged PDF in a field placement UI.
{
"success": true,
"data": {
"id": "abc123",
"name": "My Contract",
"fileType": "pdf",
"isActive": true,
"previewUrl": "https://s3.amazonaws.com/...",
"pageCount": 4,
"signers": [...],
"nextSteps": {
"addSigners": "POST /v1/external/esign/templates/abc123/signers",
"addFields": "POST /v1/external/esign/templates/abc123/fields",
"createRequest": "POST /v1/external/esign/requests"
}
}
}/v1/external/esign/templates/:id/reorder-pagesReorder pages in the template PDF. Updates all field and merge-tag page numbers. Returns a new previewUrl so the user can preview the reordered document before sending.
| Name | Type | Required | Description |
|---|---|---|---|
pageOrder | number[] | Yes | Array of 1-based page numbers in desired order, e.g. [3, 1, 2]. Must include every page exactly once. |
{
"success": true,
"data": {
"id": "abc123",
"pageCount": 3,
"previewUrl": "https://s3.amazonaws.com/...",
"fields": [{ "id": "f1", "fieldType": "signature", "pageNumber": 2, ... }],
"signers": [{ "id": "s1", "label": "Signer 1", ... }]
}
}/v1/external/esign/templates/:id/signersAdd a signer role to a template (e.g., Buyer, Seller).
| Name | Type | Required | Description |
|---|---|---|---|
role | string | Yes | Role identifier |
label | string | Yes | Display name |
order | number | No | Signing order |
color | string | No | Hex color for UI |
/v1/external/esign/templates/:id/fieldsPlace a signature, text, date, or checkbox field on a template page.
| Name | Type | Required | Description |
|---|---|---|---|
signerId | string | Yes | Template signer ID |
fieldType | string | Yes | signature, initials, date, text, checkbox, merge_tag |
pageNumber | number | Yes | 1-based page number |
xPercent | number | Yes | X position (0-100%) |
yPercent | number | Yes | Y position (0-100%) |
widthPercent | number | Yes | Width (0-100%) |
heightPercent | number | Yes | Height (0-100%) |
/v1/external/esign/requestsCreate a signing request from a template. All signers receive links immediately (parallel signing). Only the first signer is required; additional signers are optional.
| Name | Type | Required | Description |
|---|---|---|---|
templateId | string | Yes | Template to use |
name | string | Yes | Name for this signing request |
signers | array | Yes | Map real people to template signer roles |
mergeTagValues | object | No | Values for merge tags |
customerId | string | No | Associate with a customer |
sendNotification | boolean | No | Send email to all signers (default: true) |
expiresAt | string | No | ISO date for expiration (default: 30 days) |
{
"templateId": "template123",
"name": "NDA - Acme Corp",
"signers": [
{ "templateSignerId": "signer_1", "name": "Alice", "email": "alice@acme.com" },
{ "templateSignerId": "signer_2", "name": "Bob", "email": "bob@vendor.com" }
],
"mergeTagValues": { "customer_name": "Acme Corp" },
"sendNotification": true
}{
"success": true,
"data": {
"signingRequestId": "req123",
"status": "pending",
"signerLinks": [
{ "signerId": "inst_1", "name": "Alice", "email": "alice@acme.com", "signingUrl": "https://...", "status": "pending" },
{ "signerId": "inst_2", "name": "Bob", "email": "bob@vendor.com", "signingUrl": "https://...", "status": "pending" }
]
}
}/v1/external/esign/sendSend an e-sign agreement to one or more signers. Creates a signing request and optionally sends email notifications.
| Name | Type | Required | Description |
|---|---|---|---|
templateId | string | Yes | ID of the e-sign template |
name | string | Yes | Name for this signing request |
signers | array | Yes | Array of signer mappings (see example) |
mergeTagValues | object | No | Values for merge tags in the template |
customerId | string | No | Associate with a customer |
sendNotification | boolean | No | Send email notification (default: true) |
{
"templateId": "template123",
"name": "NDA - John Doe",
"signers": [
{
"templateSignerId": "signer1",
"name": "John Doe",
"email": "john@example.com"
}
],
"mergeTagValues": {
"customer_name": "John Doe",
"contract_date": "January 20, 2026"
},
"customerId": "507f1f77bcf86cd799439011",
"sendNotification": true
}{
"success": true,
"message": "E-sign agreement sent successfully",
"data": {
"signingRequestId": "req123",
"name": "NDA - John Doe",
"status": "pending",
"signerLinks": [
{
"signerId": "signer456",
"name": "John Doe",
"email": "john@example.com",
"signingUrl": "https://sign-n-pay.com/sign?token=xyz789",
"status": "pending"
}
],
"customerId": "507f1f77bcf86cd799439011",
"expiresAt": "2026-02-20T00:00:00.000Z",
"createdAt": "2026-01-21T00:00:00.000Z"
}
}/v1/external/esign/requests/:idGet the status of a signing request, including signer completion status and download URL.
{
"success": true,
"message": "Signing request retrieved",
"data": {
"signingRequest": {
"id": "req123",
"name": "NDA - John Doe",
"status": "completed",
"completedAt": "2026-01-20T15:30:00Z",
"signers": [
{
"name": "John Doe",
"email": "john@example.com",
"status": "completed",
"signedAt": "2026-01-20T15:30:00Z"
}
],
"documentUrl": "https://sign-n-pay.com/download/doc123"
}
}
}/v1/external/esign/send-documentUpload a PDF and send for signature in one call. Creates a one-time document (not saved as template). Ideal for documents that don't need to be reused.
| Name | Type | Required | Description |
|---|---|---|---|
document | string | Yes | Base64-encoded PDF file (max 50MB) |
fileName | string | Yes | Original file name (must end in .pdf) |
name | string | Yes | Name for this signing request |
signers | array | Yes | Array of signers with name and email |
customerId | string | No | Associate with a customer |
sendNotification | boolean | No | Send email notification (default: true) |
expiresInDays | number | No | Days until expiration (default: 30, max: 90) |
signaturePosition | object | No | Custom signature field position |
{
"document": "JVBERi0xLjQK...base64...",
"fileName": "contract.pdf",
"name": "Service Agreement - John Doe",
"signers": [
{ "name": "John Doe", "email": "john@example.com" }
],
"customerId": "507f1f77bcf86cd799439011",
"sendNotification": true
}{
"success": true,
"message": "Document sent for signature successfully",
"data": {
"signingRequestId": "req123",
"name": "Service Agreement - John Doe",
"status": "pending",
"signerLinks": [
{
"signerId": "signer456",
"name": "John Doe",
"email": "john@example.com",
"signingUrl": "https://sign-n-pay.com/sign?token=xyz789",
"status": "pending"
}
],
"isOneTimeDocument": true,
"expiresAt": "2026-02-20T00:00:00.000Z"
}
}/v1/external/esign/requests/:id/downloadGet a fresh download URL for the signed document. Can be called multiple times to generate new URLs.
| Name | Type | Required | Description |
|---|---|---|---|
expiresIn | number | No | URL expiration in seconds (default: 3600, max: 604800) |
{
"success": true,
"message": "Download URL generated successfully",
"data": {
"signingRequestId": "req123",
"name": "NDA - John Doe",
"status": "completed",
"completedAt": "2026-01-20T15:30:00Z",
"downloadUrl": "https://s3.amazonaws.com/...",
"expiresIn": 3600,
"expiresAt": "2026-01-21T16:30:00Z"
}
}Use this workflow when you want to place signature fields from your own UI. Upload a document, add fields with precise positioning, then send for signature.
/v1/external/esign/documentsUpload a PDF document for field placement. Creates a draft document that can have fields added before sending.
| Name | Type | Required | Description |
|---|---|---|---|
document | string | Yes | Base64-encoded PDF file (max 50MB) |
fileName | string | Yes | Original file name (must end in .pdf) |
name | string | Yes | Name for this document |
signers | array | No | Define signers (can add emails later when sending) |
{
"document": "JVBERi0xLjQK...base64...",
"fileName": "contract.pdf",
"name": "Service Agreement",
"signers": [
{ "name": "Client" },
{ "name": "Company Representative" }
]
}{
"success": true,
"message": "Document uploaded successfully. Add fields and then send.",
"data": {
"documentId": "doc123",
"name": "Service Agreement",
"status": "draft",
"pageCount": 5,
"signers": [
{ "id": "signer1", "index": 0, "name": "Client", "color": "#3B82F6" },
{ "id": "signer2", "index": 1, "name": "Company Representative", "color": "#10B981" }
],
"previewUrl": "https://s3.amazonaws.com/...",
"expiresAt": "2026-01-22T00:00:00Z",
"nextSteps": {
"addFields": "POST /v1/external/esign/documents/doc123/fields",
"send": "POST /v1/external/esign/documents/doc123/send"
}
}
}/v1/external/esign/documents/:idGet document details including current fields and signers.
{
"success": true,
"message": "Document retrieved",
"data": {
"documentId": "doc123",
"name": "Service Agreement",
"status": "draft",
"fileName": "contract.pdf",
"fileSize": 245789,
"createdAt": "2026-01-21T00:00:00Z",
"signers": [
{ "id": "signer1", "name": "Client", "role": "Signer 1", "color": "#3B82F6", "signingOrder": 1 }
],
"fields": [
{ "id": "field1", "type": "signature", "signerId": "signer1", "pageNumber": 1, "x": 55, "y": 75, "width": 25, "height": 6 }
],
"fieldsCount": 1,
"previewUrl": "https://s3.amazonaws.com/..."
}
}/v1/external/esign/documents/:idDelete a draft document. Cannot delete documents that have already been sent.
{
"success": true,
"message": "Document deleted",
"data": { "documentId": "doc123" }
}/v1/external/esign/documents/:id/fieldsGet all fields currently placed on the document.
{
"success": true,
"message": "Found 3 fields",
"data": {
"documentId": "doc123",
"fields": [
{ "id": "field1", "type": "signature", "signerId": "signer1", "pageNumber": 1, "x": 55, "y": 75, "width": 25, "height": 6 }
],
"signers": [
{ "id": "signer1", "name": "Client", "color": "#3B82F6", "signingOrder": 1 }
]
}
}/v1/external/esign/documents/:id/fieldsAdd fields to the document. Fields are appended to existing fields.
| Name | Type | Required | Description |
|---|---|---|---|
fields | array | Yes | Array of field objects to add |
{
"fields": [
{
"type": "signature",
"signerId": "signer1",
"pageNumber": 1,
"x": 55,
"y": 75,
"width": 25,
"height": 6,
"label": "Client Signature",
"required": true
},
{
"type": "date",
"signerId": "signer1",
"pageNumber": 1,
"x": 82,
"y": 75,
"width": 15,
"height": 6
}
]
}{
"success": true,
"message": "Added 2 fields",
"data": {
"documentId": "doc123",
"fieldsAdded": 2,
"totalFields": 2,
"fields": [...],
"nextStep": "POST /v1/external/esign/documents/doc123/send"
}
}/v1/external/esign/documents/:id/fieldsReplace all fields on the document with a new set of fields.
| Name | Type | Required | Description |
|---|---|---|---|
fields | array | Yes | Array of field objects (replaces existing) |
{
"fields": [
{
"type": "signature",
"signerId": "signer1",
"pageNumber": 1,
"x": 55,
"y": 80,
"width": 25,
"height": 6
}
]
}{
"success": true,
"message": "Replaced with 1 fields",
"data": {
"documentId": "doc123",
"fieldsAdded": 1,
"totalFields": 1,
"fields": [...]
}
}/v1/external/esign/documents/:id/fieldsRemove all fields from the document.
{
"success": true,
"message": "All fields removed",
"data": { "documentId": "doc123", "fieldsRemoved": 3 }
}/v1/external/esign/documents/:id/sendSend the prepared document for signature. All signers must have email addresses assigned.
| Name | Type | Required | Description |
|---|---|---|---|
signers | array | Yes | Map signer IDs to email addresses |
customerId | string | No | Associate with a customer |
sendNotification | boolean | No | Send email notification (default: true) |
expiresInDays | number | No | Days until expiration (default: 30, max: 90) |
{
"signers": [
{ "signerId": "signer1", "email": "client@example.com" },
{ "signerId": "signer2", "email": "rep@company.com" }
],
"customerId": "cust123",
"sendNotification": true,
"expiresInDays": 30
}{
"success": true,
"message": "Document sent for signature",
"data": {
"signingRequestId": "req123",
"name": "Service Agreement",
"status": "pending",
"signerLinks": [
{
"signerId": "signer456",
"name": "Client",
"email": "client@example.com",
"signingUrl": "https://sign-n-pay.com/sign?token=...",
"status": "pending"
}
],
"customerId": "cust123",
"expiresAt": "2026-02-20T00:00:00Z"
}
}signature — Signature capture fieldinitials — Initials fielddate — Auto-filled date fieldtext — Text input fieldcheckbox — Checkbox field/v1/external/invoicesCreate an invoice for a customer. The invoice is created in NOT_PAID status. By default, an email with the payment link is sent to the customer.
| Name | Type | Required | Description |
|---|---|---|---|
customerId | string | Yes | Customer ID to invoice |
name | string | Yes | Invoice line item name/description |
amount | number | Yes | Total invoice amount |
description | string | No | Additional description |
isOneTimePayment | boolean | No | One-time vs recurring (default: true) |
lineItems | array | No | Detailed line items |
sendEmail | boolean | No | Send invoice email to customer (default: true) |
{
"customerId": "507f1f77bcf86cd799439011",
"name": "Consulting Services - January",
"amount": 500.00,
"description": "Professional consulting services",
"isOneTimePayment": true,
"sendEmail": true,
"lineItems": [
{
"name": "Consulting",
"description": "10 hours at $50/hr",
"quantity": 10,
"unitPrice": 50.00
}
]
}{
"success": true,
"message": "Invoice created and email sent",
"data": {
"id": "inv123",
"refId": "INV-A1B2C3",
"name": "Consulting Services - January",
"amount": 500.00,
"status": "NOT_PAID",
"customerId": "507f1f77bcf86cd799439011",
"customerName": "John Doe",
"customerEmail": "john@example.com",
"invoiceUrl": "https://sign-n-pay.com/tenant/cust123/invoice/inv123",
"emailSent": true,
"createdAt": "2026-01-21T00:00:00.000Z"
}
}/v1/external/invoicesList all invoices with optional filtering.
| Name | Type | Required | Description |
|---|---|---|---|
limit | number | No | Max results (default: 100) |
offset | number | No | Skip this many results |
customerId | string | No | Filter by customer |
status | string | No | Filter by status (NOT_PAID, PAID, FAILED) |
{
"success": true,
"message": "Found 15 invoices",
"data": {
"invoices": [...],
"pagination": { "limit": 100, "offset": 0, "count": 15 }
}
}/v1/external/invoices/:idGet invoice details by ID.
{
"success": true,
"message": "Invoice retrieved",
"data": {
"invoice": {
"id": "inv123",
"refId": "INV-A1B2C3",
"name": "Consulting Services - January",
"amount": 500.00,
"status": "PAID",
"paidDate": "2026-01-20T12:00:00Z",
"authorizeTransactionId": "txn123",
"customer": {
"id": "cust123",
"name": "John Doe"
}
}
}
}/v1/external/subscriptionsCreate a recurring subscription for a customer. The subscription starts in 'pending' status until the customer makes their first payment. An initial invoice is automatically created.
| Name | Type | Required | Description |
|---|---|---|---|
customerId | string | Yes | Customer ID |
name | string | Yes | Subscription name |
amount | number | Yes | Recurring amount |
cadence | number | No | Billing frequency (default: 30) |
cadenceUnit | string | No | 'days' or 'months' (default: 'days') |
startDate | string | No | First billing date (ISO format) |
packageId | string | No | Associate with a package |
{
"customerId": "507f1f77bcf86cd799439011",
"name": "Monthly Retainer",
"amount": 299.00,
"cadence": 30,
"cadenceUnit": "days",
"startDate": "2026-02-01"
}{
"success": true,
"message": "Subscription created successfully (pending payment)",
"data": {
"id": "sub123",
"refId": "SUB-X1Y2Z3",
"name": "Monthly Retainer",
"amount": 299.00,
"cadence": 30,
"cadenceUnit": "days",
"status": "pending",
"isActive": false,
"customerId": "507f1f77bcf86cd799439011",
"customerName": "John Doe",
"nextPaymentDate": "2026-02-01T00:00:00.000Z",
"billingDayOfMonth": 1,
"invoiceId": "inv456",
"invoiceUrl": "https://sign-n-pay.com/tenant/cust123/invoice/inv456",
"createdAt": "2026-01-21T00:00:00.000Z"
}
}/v1/external/subscriptionsList all subscriptions with optional filtering.
| Name | Type | Required | Description |
|---|---|---|---|
limit | number | No | Max results (default: 100) |
offset | number | No | Skip this many results |
customerId | string | No | Filter by customer |
status | string | No | Filter by status (active, pending, cancelled) |
isActive | boolean | No | Filter by active status |
{
"success": true,
"message": "Found 10 subscriptions",
"data": {
"subscriptions": [...],
"pagination": { "limit": 100, "offset": 0, "count": 10 }
}
}/v1/external/subscriptions/:idGet subscription details by ID.
{
"success": true,
"message": "Subscription retrieved",
"data": {
"subscription": {
"id": "sub123",
"refId": "SUB-X1Y2Z3",
"name": "Monthly Retainer",
"amount": 299.00,
"status": "active",
"isActive": true,
"nextPaymentDate": "2026-02-01T12:00:00Z",
"lastPaymentDate": "2026-01-01T12:00:00Z",
"customer": {
"id": "cust123",
"name": "John Doe"
}
}
}
}/v1/external/subscriptions/:idUpdate a subscription. Use this to modify amount, billing day, or deactivate.
| Name | Type | Required | Description |
|---|---|---|---|
name | string | No | Updated subscription name |
amount | number | No | Updated recurring amount |
isActive | boolean | No | Activate/deactivate subscription |
{
"amount": 349.00,
"name": "Premium Monthly Retainer"
}{
"success": true,
"message": "Subscription updated",
"data": {
"subscription": {
"id": "sub123",
"name": "Premium Monthly Retainer",
"amount": 349.00,
"status": "active"
}
}
}/v1/external/subscriptions/:idCancel a subscription. This stops future billing but does not issue refunds.
{
"success": true,
"message": "Subscription canceled",
"data": {
"subscription": {
"id": "sub123",
"status": "canceled",
"isActive": false,
"canceledAt": "2026-01-20T15:00:00Z"
}
}
}Configure a webhook URL to receive real-time notifications when signing events occur. All payloads include an X-Webhook-Signature header (HMAC-SHA256) for verification.
/v1/external/webhook-configGet current webhook configuration.
{
"success": true,
"data": {
"webhookUrl": "https://your-app.com/webhooks/esign",
"hasSecret": true,
"events": [
"document.sent",
"document.viewed",
"signer.completed",
"document.completed",
"document.declined",
"document.expired"
]
}
}/v1/external/webhook-configConfigure webhook URL and secret for receiving e-sign event notifications.
| Name | Type | Required | Description |
|---|---|---|---|
webhookUrl | string | No | URL to receive webhooks (null to disable) |
regenerateSecret | boolean | No | Generate new webhook signing secret |
{
"webhookUrl": "https://your-app.com/webhooks/esign",
"regenerateSecret": true
}{
"success": true,
"data": {
"webhookUrl": "https://your-app.com/webhooks/esign",
"hasSecret": true,
"secret": "abc123...newSecret...",
"events": ["document.sent", "signer.completed", "document.completed", ...]
}
}document.sentSigning request created and sentdocument.viewedSigner viewed the documentsigner.completedA signer completed their signaturedocument.completedAll signers completed (includes signedDocumentUrl)document.declinedA signer declined to signdocument.expiredSigning request expired{
"event": "document.completed",
"timestamp": "2026-01-20T15:30:00Z",
"data": {
"signingRequestId": "req123",
"signingRequestName": "NDA - John Doe",
"templateId": "tpl456",
"status": "completed",
"customerId": "cust789",
"signedDocumentUrl": "https://s3.amazonaws.com/...",
"completedAt": "2026-01-20T15:30:00Z"
}
}X-Webhook-Signature header.