The DocsAutomator eSign API enables programmatic management of signing sessions, retrieval of signing links, progress tracking, and audit trail access.
Authentication
All API endpoints require bearer token authentication:
Authorization: Bearer YOUR_API_KEY
Base URL
https://api.docsautomator.co/esign
Session Management
List Signing Sessions
Retrieve all signing sessions with optional filtering.
Query Parameters:
| Parameter | Type | Required | Description |
|---|
status | string | No | Filter by status |
page | number | No | Page number (default: 1) |
limit | number | No | Results per page (default: 20, max: 100) |
email | string | No | Search by signer email |
Valid Status Values: pending, in_progress, completed, expired, cancelled, declined
curl -X GET "https://api.docsautomator.co/esign/sessions?status=pending&page=1&limit=20" \
-H "Authorization: Bearer YOUR_API_KEY"
Response:
{
"sessions": [
{
"id": "66f1a2b3c4d5e6f7a8b9c0d1",
"documentName": "Invoice #123",
"status": "in_progress",
"signingOrder": "sequential",
"signers": [
{ "index": 1, "email": "alice@example.com", "name": "Alice", "status": "signed" },
{ "index": 2, "email": "bob@example.com", "name": "Bob", "status": "invited" }
],
"expiresAt": "2026-05-20T10:00:00.000Z",
"completedAt": null,
"createdAt": "2026-04-20T10:00:00.000Z"
}
],
"pagination": {
"page": 1,
"limit": 20,
"total": 47,
"pages": 3
}
}
Get Session Details
GET
/esign/sessions/:sessionId
Returns comprehensive session information including signer statuses, document hashes, e-sign fields with positions, and completion timestamps.
Per-signer fields include declinedAt and declineReason for any signer who declined. When the session status is declined, the response additionally includes top-level declinedAt, declinedBy (email, name, signerIndex), and declineReason so you can read refusal details without inspecting the signers array.
Response:
{
"id": "66f1a2b3c4d5e6f7a8b9c0d1",
"documentName": "Invoice #123",
"status": "completed",
"signingOrder": "sequential",
"deliveryMethod": "email",
"currentSignerIndex": 2,
"originalPdfUrl": "https://files.docsautomator.co/f/...",
"signedPdfUrl": "https://files.docsautomator.co/f/...",
"originalDocumentHash": "sha256:...",
"signedDocumentHash": "sha256:...",
"esignFields": [
{
"fieldId": "signature_1",
"type": "signature",
"tagName": "{{esign.signature_1}}",
"signerIndex": 1,
"role": "buyer",
"value": "data:image/png;base64,...",
"signedAt": "2026-04-22T14:02:11.000Z",
"signedBy": "alice@example.com"
}
],
"signers": [
{
"index": 1,
"email": "alice@example.com",
"name": "Alice",
"role": "buyer",
"status": "signed",
"accessToken": "a1b2c3...",
"invitedAt": "2026-04-20T10:00:00.000Z",
"openedAt": "2026-04-22T13:55:04.000Z",
"signedAt": "2026-04-22T14:02:11.000Z",
"declinedAt": null,
"declineReason": null,
"ipAddress": "203.0.113.42",
"consentGivenAt": "2026-04-22T13:55:30.000Z",
"timezone": "America/New_York",
"geoLocation": { "country": "US", "region": "NY", "city": "New York" },
"signingDurationSeconds": 427
}
],
"reminderEnabled": true,
"reminderDays": 3,
"reminderCount": 0,
"lastReminderSent": null,
"expiresAt": "2026-05-20T10:00:00.000Z",
"completedAt": "2026-04-22T14:02:45.000Z",
"createdAt": "2026-04-20T10:00:00.000Z"
}
When status is declined, the response also includes:
{
"declinedAt": "2026-04-22T14:10:00.000Z",
"declinedBy": {
"email": "bob@example.com",
"name": "Bob",
"signerIndex": 2
},
"declineReason": "Terms need to be revised"
}
Get Signing Links
GET
/esign/sessions/:sessionId/links
Retrieves signing links for all signers when using manual delivery mode.
Returns expiration dates and signer status for each link.
Response:
{
"success": true,
"sessionId": "66f1a2b3c4d5e6f7a8b9c0d1",
"documentName": "Invoice #123",
"deliveryMethod": "manual",
"status": "pending",
"signers": [
{
"signerIndex": 1,
"email": "alice@example.com",
"name": "Alice",
"signingLink": "https://app.docsautomator.co/sign/a1b2c3d4e5f6g7h8",
"expiresAt": "2026-05-20T10:00:00.000Z",
"status": "pending"
}
]
}
Get Audit Trail
GET
/esign/sessions/:sessionId/audit
Returns chronological event log for the signing session.
Event Types:
| Event | Description |
|---|
session_created | Signing session initiated |
invite_sent | Email invitation dispatched |
invite_resent | Invitation re-sent to signer |
link_opened | Signer accessed signing link |
document_viewed | Signer viewed PDF |
consent_given | E-consent provided |
field_signed | Field value entered |
field_cleared | Field value cleared |
signer_completed | All fields finished |
signer_declined | Signer declined to sign |
session_completed | All signers done, PDF generated |
session_cancelled | Session cancelled |
session_expired | Session expired |
session_voided | Session voided by admin |
reminder_sent | Reminder email sent |
Response:
{
"sessionId": "66f1a2b3c4d5e6f7a8b9c0d1",
"events": [
{
"id": "66f1a2b3c4d5e6f7a8b9c0e5",
"eventType": "session_created",
"actorType": "system",
"actorEmail": null,
"actorSignerIndex": null,
"fieldId": null,
"fieldType": null,
"metadata": {
"documentName": "Invoice #123",
"signerCount": 2,
"signingOrder": "sequential"
},
"ipAddress": null,
"userAgent": null,
"timestamp": "2026-04-20T10:00:00.000Z",
"timezone": null,
"geoLocation": null
},
{
"id": "66f1a2b3c4d5e6f7a8b9c0e6",
"eventType": "field_signed",
"actorType": "signer",
"actorEmail": "alice@example.com",
"actorSignerIndex": 1,
"fieldId": "signature_1",
"fieldType": "signature",
"metadata": {},
"ipAddress": "203.0.113.42",
"userAgent": "Mozilla/5.0 ...",
"timestamp": "2026-04-22T14:02:11.000Z",
"timezone": "America/New_York",
"geoLocation": { "country": "US", "region": "NY", "city": "New York" }
}
],
"reconstructed": false
}
reconstructed: true indicates that some events were inferred from the session document because the original audit events were missing (e.g., pruned from an older session).
Cancel Session
POST
/esign/sessions/:sessionId/cancel
Cancel an active signing session.
Request body:
{
"reason": "Optional cancellation reason"
}
Response:
{
"success": true,
"message": "Signing session has been cancelled"
}
Cannot cancel completed sessions.
Resend Invitation
POST
/esign/sessions/:sessionId/resend/:signerIndex
Resends invitation email to a specific signer (indexed 1, 2, 3, etc.).
Response:
{
"success": true,
"message": "Invitation resent to alice@example.com"
}
Webhook Events
| Event | When it fires |
|---|
(no event field) | All signers completed — signed PDF ready |
esign.session_created | Session created with deliveryMethod: "manual" |
esign.signer_signed | An individual signer completed all their fields |
esign.session_declined | A signer declined to sign |
esign.session_expired | Session expired before all signers completed |
See eSign overview — Webhook Integration for the full payload of each event.
Session Created (Manual Delivery)
Triggered when signing session created with deliveryMethod: "manual". Use to retrieve and distribute signing links manually.
Signing Completed
Triggered when all signers complete signing and final PDF is generated.
Payload:
{
"signedPdfUrl": "https://...",
"sessionId": "unique-identifier",
"documentName": "Document name",
"status": "completed",
"completedAt": "ISO date string",
"signers": [
{
"email": "signer@example.com",
"name": "Signer Name",
"signedAt": "ISO date string"
}
],
"fieldValues": { },
"googleDriveFileId": "1aBcDeFgHiJkLmNoPqRsTuVwXyZ",
"googleDriveUrl": "https://drive.google.com/file/d/1aBcDeFgHiJkLmNoPqRsTuVwXyZ/view",
"googleDriveFolderId": "0BxAbCdEfGhIjKlMnOpQrStUvWx",
"sourceData": { },
"additionalParams": { }
}
The googleDriveFileId, googleDriveUrl, and googleDriveFolderId fields are only present when “Save to Google Drive” is enabled in the Signed PDF Delivery settings.
Signer Signed
Fires once per signer as they complete, including the final signer. Use to track progress for multi-party documents.
{
"event": "esign.signer_signed",
"sessionId": "unique-identifier",
"documentName": "Document name",
"status": "in_progress",
"signer": {
"email": "signer@example.com",
"name": "Signer Name",
"signerIndex": 1,
"role": "buyer",
"signedAt": "ISO date string"
},
"progress": {
"completed": 1,
"total": 2,
"allSigned": false
},
"sourceData": { },
"additionalParams": { }
}
For the final signer, progress.allSigned is true but the session status is still in_progress. The separate Signing Completed webhook fires afterwards, once the signed PDF is ready.
Session Expired
Fires when a signing session expires before all signers complete. An expiration email is also sent to workspace notification recipients.
{
"event": "esign.session_expired",
"sessionId": "unique-identifier",
"documentName": "Document name",
"status": "expired",
"expiredAt": "ISO date string",
"expiresAt": "ISO date string",
"pendingSigners": [
{
"email": "signer@example.com",
"name": "Signer Name",
"signerIndex": 2,
"status": "invited"
}
],
"sourceData": { },
"additionalParams": { }
}
If a session is already declined, cancelled, or completed before its expiration time, this webhook does not fire.
Passing Additional Parameters
Include webhookParams in document creation requests to receive custom data in webhook notifications:
{
"docId": "your-automation-id",
"data": { ... },
"webhookParams": {
"orderId": "ORD-12345",
"customerId": "CUST-789"
}
}
Parameters are returned in all webhook notifications as additionalParams.
Status Reference
Session Statuses
| Status | Description |
|---|
pending | Awaiting signer action |
in_progress | At least one signer started |
completed | All signers finished |
expired | Expired before completion |
cancelled | Cancelled by admin |
declined | Signer declined |
Signer Statuses
| Status | Description |
|---|
pending | Invitation not sent |
invited | Email sent |
opened | Link opened |
signed | All fields completed |
declined | Declined to sign |
Error Responses
{
"error": true,
"message": "Description"
}
| Code | Description |
|---|
| 400 | Bad request — invalid parameters |
| 401 | Unauthorized — invalid/missing API key |
| 404 | Not found — session doesn’t exist |
| 429 | Rate limited |
| 500 | Server error |
Rate Limits
Rate limits apply to the public signing page routes (not the authenticated admin API endpoints):
| Route | Limit |
|---|
| Signing page access | 100 requests per 15 minutes per IP |
| Field submissions | 30 requests per minute per IP |
Code Examples
Node.js — List and Monitor Sessions
const axios = require('axios');
const API_KEY = 'your_api_key';
const BASE_URL = 'https://api.docsautomator.co/esign';
async function listPendingSessions() {
const response = await axios.get(`${BASE_URL}/sessions`, {
headers: { Authorization: `Bearer ${API_KEY}` },
params: { status: 'pending', limit: 50 }
});
return response.data.sessions;
}
async function getSessionWithAudit(sessionId) {
const [session, audit] = await Promise.all([
axios.get(`${BASE_URL}/sessions/${sessionId}`, {
headers: { Authorization: `Bearer ${API_KEY}` }
}),
axios.get(`${BASE_URL}/sessions/${sessionId}/audit`, {
headers: { Authorization: `Bearer ${API_KEY}` }
})
]);
return {
...session.data,
auditTrail: audit.data.events
};
}
Python — Webhook Handler
from flask import Flask, request, jsonify
app = Flask(__name__)
@app.route('/webhook/esign', methods=['POST'])
def handle_esign_webhook():
payload = request.json
if payload.get('event') == 'esign.session_created':
for signer in payload.get('signingLinks', []):
send_custom_email(
to=signer['email'],
signing_link=signer['signingLink']
)
elif payload.get('status') == 'completed':
signed_pdf_url = payload['signedPdfUrl']
order_id = payload.get('additionalParams', {}).get('orderId')
drive_url = payload.get('googleDriveUrl') # Present if Save to Drive is enabled
process_signed_document(signed_pdf_url, order_id, drive_url=drive_url)
return jsonify({'received': True})