Official PHP SDK for TurboDocx - Digital signatures, document generation, and AI-powered workflows
The most developer-friendly DocuSign & PandaDoc alternative for e-signatures and document generation. Send documents for signature and automate document workflows programmatically.
Website β’ Documentation β’ API & SDK β’ Examples β’ Discord
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
| 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 |
- π Production-Ready β Battle-tested, processing thousands of documents daily
- π Strong Typing β PHP 8.1+ enums and typed properties with PHPStan level 8
- β‘ Modern PHP β Readonly classes, named parameters, match expressions
- π Industry Standard β Guzzle HTTP client, PSR standards compliance
- π‘οΈ Type-safe β Catch errors at development time with static analysis
- π€ 100% n8n Parity β Same operations as our n8n community nodes
- PHP 8.1 or higher
- Composer
- ext-json
- ext-fileinfo
composer require turbodocx/sdk<?php
use TurboDocx\TurboSign;
use TurboDocx\Config\HttpClientConfig;
use TurboDocx\Types\Recipient;
use TurboDocx\Types\Field;
use TurboDocx\Types\SignatureFieldType;
use TurboDocx\Types\TemplateConfig;
use TurboDocx\Types\FieldPlacement;
use TurboDocx\Types\Requests\SendSignatureRequest;
// 1. Configure with your API key and sender information
TurboSign::configure(new HttpClientConfig(
apiKey: $_ENV['TURBODOCX_API_KEY'],
orgId: $_ENV['TURBODOCX_ORG_ID'],
senderEmail: $_ENV['TURBODOCX_SENDER_EMAIL'], // REQUIRED
senderName: $_ENV['TURBODOCX_SENDER_NAME'] // OPTIONAL (but strongly recommended)
));
// 2. Send a document for signature
$result = TurboSign::sendSignature(
new SendSignatureRequest(
recipients: [
new Recipient('John Doe', '[email protected]', 1)
],
fields: [
new Field(
type: SignatureFieldType::SIGNATURE,
recipientEmail: '[email protected]',
template: new TemplateConfig(
anchor: '{signature1}',
placement: FieldPlacement::REPLACE,
size: ['width' => 100, 'height' => 30]
)
)
],
file: file_get_contents('contract.pdf'),
documentName: 'Partnership Agreement'
)
);
echo "Document ID: {$result->documentId}\n";use TurboDocx\TurboSign;
use TurboDocx\Config\HttpClientConfig;
// Basic configuration (REQUIRED)
TurboSign::configure(new HttpClientConfig(
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(new HttpClientConfig(
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.
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(new HttpClientConfig(
apiKey: getenv('TURBODOCX_API_KEY'),
orgId: getenv('TURBODOCX_ORG_ID'),
senderEmail: getenv('TURBODOCX_SENDER_EMAIL'),
senderName: getenv('TURBODOCX_SENDER_NAME')
));
// Or use auto-configuration from environment
TurboSign::configure(HttpClientConfig::fromEnvironment());Upload a document for review without sending signature emails. Returns a preview URL.
use TurboDocx\Types\Requests\CreateSignatureReviewLinkRequest;
$result = TurboSign::createSignatureReviewLink(
new CreateSignatureReviewLinkRequest(
recipients: [
new Recipient('John Doe', '[email protected]', 1)
],
fields: [
new Field(
type: SignatureFieldType::SIGNATURE,
recipientEmail: '[email protected]',
page: 1,
x: 100,
y: 500,
width: 200,
height: 50
)
],
fileLink: 'https://example.com/contract.pdf', // Or use file: for upload
documentName: 'Service Agreement', // Optional
documentDescription: 'Q4 Contract', // Optional
ccEmails: ['[email protected]'] // Optional
)
);
echo "Preview URL: {$result->previewUrl}\n";
echo "Document ID: {$result->documentId}\n";Upload a document and immediately send signature request emails.
use TurboDocx\Types\Requests\SendSignatureRequest;
$result = TurboSign::sendSignature(
new SendSignatureRequest(
recipients: [
new Recipient('Alice', '[email protected]', 1),
new Recipient('Bob', '[email protected]', 2) // Signs after Alice
],
fields: [
new Field(
type: SignatureFieldType::SIGNATURE,
recipientEmail: '[email protected]',
page: 1,
x: 100,
y: 500,
width: 200,
height: 50
),
new Field(
type: SignatureFieldType::SIGNATURE,
recipientEmail: '[email protected]',
page: 1,
x: 100,
y: 600,
width: 200,
height: 50
)
],
file: file_get_contents('contract.pdf')
)
);
// Get recipient sign URLs
$status = TurboSign::getStatus($result->documentId);
foreach ($status->recipients as $recipient) {
echo "{$recipient->name}: {$recipient->signUrl}\n";
}Check the current status of a document.
$status = TurboSign::getStatus('doc-uuid-here');
echo "Document Status: {$status->status->value}\n"; // 'pending', 'completed', 'voided'
echo "Recipients:\n";
// Check individual recipient status
foreach ($status->recipients as $recipient) {
echo " {$recipient->name}: {$recipient->status->value}\n";
if ($recipient->signedAt) {
echo " Signed at: {$recipient->signedAt}\n";
}
}Download the signed PDF document.
$pdfContent = TurboSign::download('doc-uuid-here');
// Save to file
file_put_contents('signed-contract.pdf', $pdfContent);
// Or send as HTTP response
header('Content-Type: application/pdf');
header('Content-Disposition: attachment; filename="signed.pdf"');
echo $pdfContent;Cancel a signature request that hasn't been completed.
use TurboDocx\Types\Responses\VoidDocumentResponse;
$result = TurboSign::void('doc-uuid-here', 'Document needs to be revised');
echo "Status: {$result->status}\n";
echo "Voided at: {$result->voidedAt}\n";Resend signature request emails to specific recipients (or all).
// Resend to specific recipients
$result = TurboSign::resend('doc-uuid-here', ['recipient-id-1', 'recipient-id-2']);
// Resend to all recipients
$result = TurboSign::resend('doc-uuid-here', []);
echo "Message: {$result->message}\n";Get the complete audit trail for a document.
$audit = TurboSign::getAuditTrail('doc-uuid-here');
echo "Audit Trail:\n";
foreach ($audit->entries as $entry) {
echo " {$entry->timestamp} - {$entry->event} by {$entry->actor}\n";
if ($entry->ipAddress) {
echo " IP: {$entry->ipAddress}\n";
}
}TurboSign supports 11 different field types:
use TurboDocx\Types\SignatureFieldType;
SignatureFieldType::SIGNATURE // Signature field
SignatureFieldType::INITIAL // Initial field
SignatureFieldType::DATE // Date stamp (auto-filled when signed)
SignatureFieldType::TEXT // Free text input
SignatureFieldType::FULL_NAME // Full name (auto-filled from recipient)
SignatureFieldType::FIRST_NAME // First name
SignatureFieldType::LAST_NAME // Last name
SignatureFieldType::EMAIL // Email address
SignatureFieldType::TITLE // Job title
SignatureFieldType::COMPANY // Company name
SignatureFieldType::CHECKBOX // Checkbox fieldTurboSign supports two ways to position fields:
new Field(
type: SignatureFieldType::SIGNATURE,
recipientEmail: '[email protected]',
page: 1, // Page number (1-indexed)
x: 100, // X coordinate
y: 500, // Y coordinate
width: 200, // Width in pixels
height: 50 // Height in pixels
)new Field(
type: SignatureFieldType::SIGNATURE,
recipientEmail: '[email protected]',
template: new TemplateConfig(
anchor: '{signature1}', // Text to find in PDF
placement: FieldPlacement::REPLACE, // How to place the field
size: ['width' => 100, 'height' => 30]
)
)Placement Options:
FieldPlacement::REPLACE- Replace the anchor textFieldPlacement::BEFORE- Place before the anchorFieldPlacement::AFTER- Place after the anchorFieldPlacement::ABOVE- Place above the anchorFieldPlacement::BELOW- Place below the anchor
// Checkbox (pre-checked, readonly)
new Field(
type: SignatureFieldType::CHECKBOX,
recipientEmail: '[email protected]',
page: 1,
x: 100,
y: 600,
width: 20,
height: 20,
defaultValue: 'true', // Pre-checked
isReadonly: true // Cannot be unchecked
)
// Multiline text field
new Field(
type: SignatureFieldType::TEXT,
recipientEmail: '[email protected]',
page: 1,
x: 100,
y: 200,
width: 400,
height: 100,
isMultiline: true, // Allow multiple lines
required: true, // Field is required
backgroundColor: '#f0f0f0' // Background color
)
// Readonly text (pre-filled, non-editable)
new Field(
type: SignatureFieldType::TEXT,
recipientEmail: '[email protected]',
page: 1,
x: 100,
y: 300,
width: 300,
height: 30,
defaultValue: 'This text is pre-filled',
isReadonly: true
)TurboSign supports three ways to provide the document:
$result = TurboSign::sendSignature(
new SendSignatureRequest(
file: file_get_contents('contract.pdf'),
fileName: 'contract.pdf', // Optional
// ...
)
);$result = TurboSign::sendSignature(
new SendSignatureRequest(
fileLink: 'https://example.com/contract.pdf',
// ...
)
);$result = TurboSign::sendSignature(
new SendSignatureRequest(
deliverableId: 'deliverable-uuid-from-turbodocx',
// ...
)
);$result = TurboSign::sendSignature(
new SendSignatureRequest(
recipients: [
new Recipient('John Doe', '[email protected]', 1)
],
fields: [
new Field(
type: SignatureFieldType::SIGNATURE,
recipientEmail: '[email protected]',
template: new TemplateConfig(
anchor: '{signature1}',
placement: FieldPlacement::REPLACE,
size: ['width' => 100, 'height' => 30]
)
)
],
file: file_get_contents('contract.pdf')
)
);$result = TurboSign::sendSignature(
new SendSignatureRequest(
recipients: [
new Recipient('Alice', '[email protected]', 1), // Signs first
new Recipient('Bob', '[email protected]', 2), // Signs after Alice
new Recipient('Carol', '[email protected]', 3) // Signs last
],
fields: [
// Fields for each recipient...
],
file: file_get_contents('contract.pdf')
)
);$result = TurboSign::sendSignature(/* ... */);
// Poll for completion
while (true) {
sleep(2);
$status = TurboSign::getStatus($result->documentId);
if ($status->status === 'completed') {
echo "Document completed!\n";
// Download signed document
$signedPdf = TurboSign::download($result->documentId);
file_put_contents('signed.pdf', $signedPdf);
break;
}
echo "Status: {$status->status}\n";
}For more examples, see the examples/ directory.
The SDK provides typed exceptions for different error scenarios:
use TurboDocx\Exceptions\AuthenticationException;
use TurboDocx\Exceptions\ValidationException;
use TurboDocx\Exceptions\NotFoundException;
use TurboDocx\Exceptions\RateLimitException;
use TurboDocx\Exceptions\NetworkException;
try {
$result = TurboSign::sendSignature(/* ... */);
} catch (AuthenticationException $e) {
// 401 - Invalid API key or access token
echo "Authentication failed: {$e->getMessage()}\n";
} catch (ValidationException $e) {
// 400 - Invalid request data
echo "Validation error: {$e->getMessage()}\n";
} catch (NotFoundException $e) {
// 404 - Document not found
echo "Not found: {$e->getMessage()}\n";
} catch (RateLimitException $e) {
// 429 - Rate limit exceeded
echo "Rate limit: {$e->getMessage()}\n";
} catch (NetworkException $e) {
// Network/connection error
echo "Network error: {$e->getMessage()}\n";
}All exceptions extend TurboDocxException and include:
statusCode(HTTP status code, if applicable)errorCode(Error code string, e.g., 'AUTHENTICATION_ERROR')message(Human-readable error message)
MIT
- π TurboDocx
- π Documentation
- π¬ Discord Community
- π GitHub Issues
- @turbodocx/html-to-docx - Convert HTML to DOCX
- @turbodocx/n8n-nodes-turbodocx - n8n integration
- TurboDocx Writer - Microsoft Word add-in