@turbodocx/sdk
v0.2.0
Published
TurboDocx JavaScript SDK - Digital signatures, document generation, and AI-powered workflows
Maintainers
Readme
@turbodocx/sdk
Official JavaScript/TypeScript SDK for TurboDocx
The most developer-friendly DocuSign & PandaDoc alternative for e-signatures and document generation. Send documents for signature and automate document workflows programmatically.
Documentation • API Reference • Examples • Discord
Why TurboDocx?
A modern, developer-first alternative to legacy e-signature platforms:
| Looking for... | TurboDocx offers | |----------------|------------------| | DocuSign API alternative | Simple REST API, transparent pricing | | PandaDoc alternative | Document generation + e-signatures in one SDK | | HelloSign/Dropbox Sign alternative | Full API access, modern DX | | Adobe Sign alternative | Quick integration, developer-friendly docs | | SignNow alternative | Predictable costs, responsive support | | Documint alternative | DOCX/PDF generation from templates | | WebMerge alternative | Data-driven document automation |
Other platforms we compare to: SignRequest, SignEasy, Zoho Sign, Eversign, SignWell, Formstack Documents
TurboDocx Ecosystem
| Package | Description | |---------|-------------| | @turbodocx/html-to-docx | Convert HTML to DOCX - fastest JS library | | @turbodocx/n8n-nodes-turbodocx | n8n community nodes for TurboDocx | | TurboDocx Writer | Microsoft Word add-in |
Features
- 🚀 Production-Ready — Battle-tested, processing thousands of documents daily
- 📝 Full TypeScript Support — Comprehensive type definitions with IntelliSense
- ⚡ Lightweight — Zero dependencies, tree-shakeable
- 🔄 Promise-based — Modern async/await API
- 🛡️ Type-safe — Catch errors at compile time, not runtime
- 🤖 100% n8n Parity — Same operations as our n8n community nodes
Installation
npm install @turbodocx/sdk# Yarn
yarn add @turbodocx/sdk
# pnpm
pnpm add @turbodocx/sdk
# Bun
bun add @turbodocx/sdkQuick Start
import { TurboSign } from '@turbodocx/sdk';
// 1. Configure with your API key and sender information
TurboSign.configure({
apiKey: process.env.TURBODOCX_API_KEY,
orgId: process.env.TURBODOCX_ORG_ID,
senderEmail: process.env.TURBODOCX_SENDER_EMAIL, // REQUIRED
senderName: process.env.TURBODOCX_SENDER_NAME // OPTIONAL (but strongly recommended)
});
// 2. Send a document for signature
const result = await TurboSign.sendSignature({
file: pdfBuffer,
documentName: 'Partnership Agreement',
recipients: [
{ name: 'John Doe', email: '[email protected]', signingOrder: 1 }
],
fields: [
{
type: 'signature',
recipientEmail: '[email protected]',
template: { anchor: '{signature1}', placement: 'replace', size: { width: 100, height: 30 } }
}
]
});
console.log('Document ID:', result.documentId);Configuration
import { TurboSign } from '@turbodocx/sdk';
// Basic configuration (REQUIRED)
TurboSign.configure({
apiKey: 'your-api-key', // REQUIRED
orgId: 'your-org-id', // REQUIRED
senderEmail: '[email protected]', // REQUIRED - reply-to address for signature requests
senderName: 'Your Company' // OPTIONAL but strongly recommended
});
// With custom options
TurboSign.configure({
apiKey: 'your-api-key',
orgId: 'your-org-id',
senderEmail: '[email protected]',
senderName: 'Your Company',
baseUrl: 'https://custom-api.example.com', // Optional: custom API endpoint
});Important: senderEmail is REQUIRED. This email will be used as the reply-to address for signature request emails. Without it, emails will default to "API Service User via TurboSign". The senderName is optional but strongly recommended for a professional appearance.
Environment Variables
We recommend using environment variables for your configuration:
# .env
TURBODOCX_API_KEY=your-api-key
TURBODOCX_ORG_ID=your-org-id
[email protected]
TURBODOCX_SENDER_NAME=Your Company NameTurboSign.configure({
apiKey: process.env.TURBODOCX_API_KEY,
orgId: process.env.TURBODOCX_ORG_ID,
senderEmail: process.env.TURBODOCX_SENDER_EMAIL,
senderName: process.env.TURBODOCX_SENDER_NAME
});API Reference
TurboSign
createSignatureReviewLink(options)
Upload a document for review without sending signature emails. Returns a preview URL.
const result = await TurboSign.createSignatureReviewLink({
fileLink: 'https://example.com/contract.pdf',
recipients: [
{ name: 'John Doe', email: '[email protected]', order: 1 }
],
fields: [
{ type: 'signature', page: 1, x: 100, y: 500, width: 200, height: 50, recipientOrder: 1 }
],
documentName: 'Service Agreement', // Optional
documentDescription: 'Q4 Contract', // Optional
senderName: 'Acme Corp', // Optional
senderEmail: '[email protected]', // Optional
ccEmails: ['[email protected]'] // Optional
});
console.log('Preview URL:', result.previewUrl);
console.log('Document ID:', result.documentId);sendSignature(options)
Upload a document and immediately send signature request emails.
const result = await TurboSign.sendSignature({
fileLink: 'https://example.com/contract.pdf',
recipients: [
{ name: 'Alice', email: '[email protected]', order: 1 },
{ name: 'Bob', email: '[email protected]', order: 2 } // Signs after Alice
],
fields: [
{ type: 'signature', page: 1, x: 100, y: 500, width: 200, height: 50, recipientOrder: 1 },
{ type: 'signature', page: 1, x: 100, y: 600, width: 200, height: 50, recipientOrder: 2 }
]
});
// Each recipient gets a unique signing URL
result.recipients.forEach(r => {
console.log(`${r.name}: ${r.signUrl}`);
});getStatus(documentId)
Check the current status of a document.
const status = await TurboSign.getStatus('doc-uuid-here');
console.log('Document Status:', status.status); // 'pending' | 'completed' | 'voided'
console.log('Recipients:', status.recipients);
// Check individual recipient status
status.recipients.forEach(r => {
console.log(`${r.name}: ${r.status}`); // 'pending' | 'signed' | 'declined'
});download(documentId)
Download the signed document as a Buffer/Blob.
const signedPdf = await TurboSign.download('doc-uuid-here');
// Node.js: Save to file
import { writeFileSync } from 'fs';
writeFileSync('signed-contract.pdf', signedPdf);
// Browser: Trigger download
const blob = new Blob([signedPdf], { type: 'application/pdf' });
const url = URL.createObjectURL(blob);
window.open(url);void(documentId, reason)
Cancel a signature request.
await TurboSign.void('doc-uuid-here', 'Contract terms changed');resend(documentId, recipientIds)
Resend signature request emails to specific recipients.
await TurboSign.resend('doc-uuid-here', ['recipient-uuid-1', 'recipient-uuid-2']);getAuditTrail(documentId)
Get the complete audit trail for a document, including all events and timestamps.
const audit = await TurboSign.getAuditTrail('doc-uuid-here');
console.log('Document:', audit.document.name);
for (const entry of audit.auditTrail) {
console.log(`${entry.actionType} - ${entry.timestamp}`);
if (entry.user) {
console.log(` By: ${entry.user.name} (${entry.user.email})`);
}
if (entry.recipient) {
console.log(` Recipient: ${entry.recipient.name}`);
}
}The audit trail includes a cryptographic hash chain for tamper-evidence verification.
TurboPartner (Partner API)
The TurboPartner module provides partner portal operations for managing organizations, users, API keys, and audit logs.
Configuration
import { TurboPartner } from '@turbodocx/sdk';
TurboPartner.configure({
partnerApiKey: process.env.TURBODOCX_PARTNER_API_KEY, // Must start with TDXP-
partnerId: process.env.TURBODOCX_PARTNER_ID, // UUID format
});Environment Variables:
# .env
TURBODOCX_PARTNER_API_KEY=TDXP-your-partner-api-key
TURBODOCX_PARTNER_ID=your-partner-uuidOrganization Management
// Create an organization
const org = await TurboPartner.createOrganization({
name: 'Acme Corp',
metadata: { industry: 'Technology' },
features: { maxUsers: 50, hasTDAI: true },
});
console.log('Org ID:', org.data.id);
// List organizations
const orgs = await TurboPartner.listOrganizations({ limit: 10, search: 'acme' });
// Get organization details (includes features and tracking)
const details = await TurboPartner.getOrganizationDetails('org-uuid');
console.log('Features:', details.data.features);
console.log('Tracking:', details.data.tracking);
// Update organization name
await TurboPartner.updateOrganizationInfo('org-uuid', { name: 'New Name' });
// Delete an organization
await TurboPartner.deleteOrganization('org-uuid');
// Update organization entitlements
await TurboPartner.updateOrganizationEntitlements('org-uuid', {
features: { maxUsers: 100, hasTDAI: true },
});Organization User Management
// List users in an organization
const users = await TurboPartner.listOrganizationUsers('org-uuid', { limit: 25 });
// Add a user to an organization
const user = await TurboPartner.addUserToOrganization('org-uuid', {
email: '[email protected]',
role: 'contributor', // 'admin' | 'contributor' | 'user' | 'viewer'
});
// Update a user's role
await TurboPartner.updateOrganizationUserRole('org-uuid', 'user-uuid', {
role: 'admin',
});
// Remove a user from an organization
await TurboPartner.removeUserFromOrganization('org-uuid', 'user-uuid');
// Resend invitation email
await TurboPartner.resendOrganizationInvitationToUser('org-uuid', 'user-uuid');Organization API Key Management
// List API keys
const keys = await TurboPartner.listOrganizationApiKeys('org-uuid');
// Create an API key (full key value is only returned on creation)
const key = await TurboPartner.createOrganizationApiKey('org-uuid', {
name: 'Production Key',
role: 'admin',
});
console.log('Key:', key.data.key);
// Update an API key
await TurboPartner.updateOrganizationApiKey('org-uuid', 'key-uuid', {
name: 'Updated Key Name',
});
// Revoke an API key
await TurboPartner.revokeOrganizationApiKey('org-uuid', 'key-uuid');Partner API Key Management
// List partner API keys
const partnerKeys = await TurboPartner.listPartnerApiKeys();
// Create a partner API key with scopes
const partnerKey = await TurboPartner.createPartnerApiKey({
name: 'CI/CD Key',
scopes: ['org:create', 'org:read', 'org:update'],
description: 'Key for automated deployments',
});
// Update a partner API key
await TurboPartner.updatePartnerApiKey('key-uuid', {
name: 'Updated Name',
scopes: ['org:create', 'org:read'],
});
// Revoke a partner API key
await TurboPartner.revokePartnerApiKey('key-uuid');Partner User Management
// List partner portal users
const partnerUsers = await TurboPartner.listPartnerPortalUsers();
// Add a user to the partner portal
const partnerUser = await TurboPartner.addUserToPartnerPortal({
email: '[email protected]',
role: 'admin', // 'admin' | 'member' | 'viewer'
permissions: {
canManageOrgs: true,
canManageOrgUsers: true,
canManagePartnerUsers: false,
canManageOrgAPIKeys: true,
canManagePartnerAPIKeys: false,
canUpdateEntitlements: true,
canViewAuditLogs: true,
},
});
// Update partner user permissions
await TurboPartner.updatePartnerUserPermissions('user-uuid', {
role: 'member',
permissions: { canManageOrgs: false },
});
// Remove a partner user
await TurboPartner.removeUserFromPartnerPortal('user-uuid');
// Resend partner portal invitation
await TurboPartner.resendPartnerPortalInvitationToUser('user-uuid');Audit Logs
// Get audit logs with filters
const logs = await TurboPartner.getPartnerAuditLogs({
action: 'org.created',
startDate: '2025-01-01',
endDate: '2025-12-31',
limit: 100,
});
for (const entry of logs.data.results) {
console.log(`${entry.action} - ${entry.resourceType} - ${entry.createdOn}`);
}Field Types
| Type | Description |
|:-----|:------------|
| signature | Signature field (draw or type) |
| initials | Initials field |
| text | Free-form text input |
| date | Date stamp |
| checkbox | Checkbox / agreement |
| full_name | Full name |
| first_name | First name |
| last_name | Last name |
| email | Email address |
| title | Job title |
| company | Company name |
Field Positioning
{
type: 'signature',
page: 1, // Page number (1-indexed)
x: 100, // X position from left (pixels)
y: 500, // Y position from top (pixels)
width: 200, // Field width (pixels)
height: 50, // Field height (pixels)
recipientOrder: 1, // Which recipient this field belongs to
required: true // Optional: default true for signature/initials
}Examples
For complete, working examples including template anchors, advanced field types, and various workflows, see the examples/ directory:
turbosign-send-simple.ts- Send document directly with template anchorsturbosign-basic.ts- Create review link first, then send manuallyturbosign-advanced.ts- Advanced field types (checkbox, readonly, multiline text, etc.)
Sequential Signing (Multiple Recipients)
const result = await TurboSign.sendSignature({
fileLink: 'https://example.com/contract.pdf',
recipients: [
{ name: 'Employee', email: '[email protected]', order: 1 },
{ name: 'Manager', email: '[email protected]', order: 2 },
{ name: 'HR', email: '[email protected]', order: 3 }
],
fields: [
// Employee signs first
{ type: 'signature', page: 1, x: 100, y: 400, width: 200, height: 50, recipientOrder: 1 },
{ type: 'date', page: 1, x: 320, y: 400, width: 100, height: 30, recipientOrder: 1 },
// Manager signs second
{ type: 'signature', page: 1, x: 100, y: 500, width: 200, height: 50, recipientOrder: 2 },
{ type: 'date', page: 1, x: 320, y: 500, width: 100, height: 30, recipientOrder: 2 },
// HR signs last
{ type: 'signature', page: 1, x: 100, y: 600, width: 200, height: 50, recipientOrder: 3 },
{ type: 'date', page: 1, x: 320, y: 600, width: 100, height: 30, recipientOrder: 3 }
]
});Polling for Completion
async function waitForCompletion(documentId: string, maxAttempts = 60) {
for (let i = 0; i < maxAttempts; i++) {
const status = await TurboSign.getStatus(documentId);
if (status.status === 'completed') {
return await TurboSign.download(documentId);
}
if (status.status === 'voided') {
throw new Error('Document was voided');
}
// Wait 30 seconds between checks
await new Promise(r => setTimeout(r, 30000));
}
throw new Error('Timeout waiting for signatures');
}With Express.js
import express from 'express';
import { TurboSign } from '@turbodocx/sdk';
const app = express();
TurboSign.configure({ apiKey: process.env.TURBODOCX_API_KEY });
app.post('/api/send-contract', async (req, res) => {
try {
const result = await TurboSign.sendSignature({
fileLink: req.body.pdfUrl,
recipients: req.body.recipients,
fields: req.body.fields
});
res.json({ success: true, documentId: result.documentId });
} catch (error) {
res.status(500).json({ error: error.message });
}
});Local Testing
The SDK includes a comprehensive manual test script to verify all functionality locally.
Running Manual Tests
# Install dependencies
npm install
# Run the manual test script
npx tsx manual-test.tsWhat It Tests
The manual-test.ts file tests all SDK methods:
- ✅
createSignatureReviewLink()- Document upload for review - ✅
sendSignature()- Send for signature - ✅
getStatus()- Check document status - ✅
download()- Download signed document - ✅
void()- Cancel signature request - ✅
resend()- Resend signature emails
Configuration
Before running, update the hardcoded values in manual-test.ts:
API_KEY- Your TurboDocx API keyBASE_URL- API endpoint (default:http://localhost:3000)ORG_ID- Your organization UUIDTEST_FILE_PATH- Path to a test PDF/DOCX fileTEST_EMAIL- Email address for testing
Expected Output
The script will:
- Upload a test document
- Send it for signature
- Check the status
- Test void and resend operations
- Print results for each operation
Error Handling
import { TurboSign, TurboDocxError } from '@turbodocx/sdk';
try {
await TurboSign.getStatus('invalid-id');
} catch (error) {
if (error instanceof TurboDocxError) {
console.error('Status:', error.statusCode); // HTTP status code
console.error('Message:', error.message); // Error message
console.error('Code:', error.code); // Error code (if available)
} else {
console.error('Unexpected error:', error);
}
}Common Error Codes
| Status | Meaning |
|:-------|:--------|
| 400 | Bad request — check your parameters |
| 401 | Unauthorized — check your API key |
| 404 | Document not found |
| 429 | Rate limited — slow down requests |
| 500 | Server error — retry with backoff |
TypeScript
Full TypeScript support with exported types:
import {
TurboSign,
SendSignatureRequest,
CreateSignatureReviewLinkRequest,
Recipient,
Field,
DocumentStatus,
TurboDocxError
} from '@turbodocx/sdk';
// Type-safe options
const options: SendSignatureRequest = {
fileLink: 'https://example.com/contract.pdf',
recipients: [{ name: 'John', email: '[email protected]', signingOrder: 1 }],
fields: [{ type: 'signature', page: 1, x: 100, y: 500, width: 200, height: 50, recipientEmail: '[email protected]' }]
};
const result = await TurboSign.sendSignature(options);Requirements
- Node.js 16+
- TypeScript 4.7+ (if using TypeScript)
Related Packages
| Package | Description | |:--------|:------------| | @turbodocx/n8n-nodes-turbodocx | n8n community nodes | | turbodocx-sdk (Python) | Python SDK | | turbodocx (Go) | Go SDK |
Support
License
MIT — see LICENSE


