Skip to main content

TurboDocx Python SDK - Digital signatures, document generation, and AI-powered workflows

Project description

TurboDocx

turbodocx-sdk

Official Python 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.

PyPI Version PyPI Downloads Python Versions License: MIT

DocumentationAPI ReferenceExamplesDiscord


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
  • Async-First — Native asyncio support with sync wrappers available
  • 🐍 Pythonic API — Idiomatic Python with type hints throughout
  • 📝 Full Type Hints — Complete type annotations for IDE support
  • 🛡️ Pydantic Models — Validated request/response models
  • 🤖 100% n8n Parity — Same operations as our n8n community nodes

Installation

pip install turbodocx-sdk
Other package managers
# Poetry
poetry add turbodocx-sdk

# Pipenv
pipenv install turbodocx-sdk

# Conda
conda install -c conda-forge turbodocx-sdk

Quick Start

Async (Recommended)

import asyncio
import os
from turbodocx_sdk import TurboSign

async def main():
    # 1. Configure with your API key and sender information
    TurboSign.configure(
        api_key=os.getenv("TURBODOCX_API_KEY"),
        org_id=os.getenv("TURBODOCX_ORG_ID"),
        sender_email=os.getenv("TURBODOCX_SENDER_EMAIL"),  # REQUIRED
        sender_name=os.getenv("TURBODOCX_SENDER_NAME")      # OPTIONAL (but strongly recommended)
    )

    # 2. Send a document for signature
    with open("contract.pdf", "rb") as f:
        pdf_file = f.read()

    result = await TurboSign.send_signature(
        file=pdf_file,
        document_name="Partnership Agreement",
        recipients=[
            {"name": "John Doe", "email": "john@example.com", "signingOrder": 1}
        ],
        fields=[
            {
                "type": "signature",
                "recipientEmail": "john@example.com",
                "template": {"anchor": "{signature1}", "placement": "replace", "size": {"width": 100, "height": 30}}
            }
        ]
    )

    print(f"Document ID: {result['documentId']}")

asyncio.run(main())

Sync

from turbodocx_sdk import TurboSignSync

TurboSignSync.configure(api_key="your-api-key")

result = TurboSignSync.send_signature(
    file_link="https://example.com/contract.pdf",
    recipients=[{"name": "John Doe", "email": "john@example.com", "signingOrder": 1}],
    fields=[{"type": "signature", "page": 1, "x": 100, "y": 500, "width": 200, "height": 50, "recipientOrder": 1}]
)

Configuration

from turbodocx_sdk import TurboSign
import os

# Basic configuration (REQUIRED)
TurboSign.configure(
    api_key="your-api-key",           # REQUIRED
    org_id="your-org-id",             # REQUIRED
    sender_email="you@company.com",   # REQUIRED - reply-to address for signature requests
    sender_name="Your Company"        # OPTIONAL but strongly recommended
)

# With environment variables (recommended)
TurboSign.configure(
    api_key=os.environ["TURBODOCX_API_KEY"],
    org_id=os.environ["TURBODOCX_ORG_ID"],
    sender_email=os.environ["TURBODOCX_SENDER_EMAIL"],
    sender_name=os.environ["TURBODOCX_SENDER_NAME"]
)

# With custom options
TurboSign.configure(
    api_key=os.environ["TURBODOCX_API_KEY"],
    org_id=os.environ["TURBODOCX_ORG_ID"],
    sender_email=os.environ["TURBODOCX_SENDER_EMAIL"],
    sender_name=os.environ["TURBODOCX_SENDER_NAME"],
    base_url="https://custom-api.example.com",  # Optional
    timeout=30.0,                                # Optional: seconds
)

Important: sender_email 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 sender_name is optional but strongly recommended for a professional appearance.

Environment Variables

# .env
TURBODOCX_API_KEY=your-api-key
TURBODOCX_ORG_ID=your-org-id
TURBODOCX_SENDER_EMAIL=you@company.com
TURBODOCX_SENDER_NAME=Your Company Name
from dotenv import load_dotenv
import os
load_dotenv()

TurboSign.configure(
    api_key=os.environ["TURBODOCX_API_KEY"],
    org_id=os.environ["TURBODOCX_ORG_ID"],
    sender_email=os.environ["TURBODOCX_SENDER_EMAIL"],
    sender_name=os.environ["TURBODOCX_SENDER_NAME"]
)

API Reference

TurboSign

create_signature_review_link()

Upload a document for review without sending signature emails.

result = await TurboSign.create_signature_review_link(
    file_link="https://example.com/contract.pdf",
    recipients=[
        {"name": "John Doe", "email": "john@example.com", "signingOrder": 1}
    ],
    fields=[
        {"type": "signature", "page": 1, "x": 100, "y": 500, "width": 200, "height": 50, "recipientEmail": "john@example.com"}
    ],
    document_name="Service Agreement",        # Optional
    document_description="Q4 Contract",       # Optional
    sender_name="Acme Corp",                  # Optional
    sender_email="contracts@acme.com",        # Optional
    cc_emails=["legal@acme.com"]              # Optional
)

print(f"Preview URL: {result['previewUrl']}")
print(f"Document ID: {result['documentId']}")

send_signature()

Upload a document and immediately send signature request emails.

result = await TurboSign.send_signature(
    file_link="https://example.com/contract.pdf",
    recipients=[
        {"name": "Alice", "email": "alice@example.com", "signingOrder": 1},
        {"name": "Bob", "email": "bob@example.com", "signingOrder": 2}
    ],
    fields=[
        {"type": "signature", "recipientEmail": "alice@example.com", "page": 1, "x": 100, "y": 500, "width": 200, "height": 50},
        {"type": "signature", "recipientEmail": "bob@example.com", "page": 1, "x": 100, "y": 600, "width": 200, "height": 50}
    ]
)

for recipient in result["recipients"]:
    print(f"{recipient['name']}: {recipient['signUrl']}")

get_status()

Check the current status of a document.

status = await TurboSign.get_status("doc-uuid-here")

print(f"Status: {status['status']}")  # 'pending', 'completed', 'voided'

for recipient in status["recipients"]:
    print(f"{recipient['name']}: {recipient['status']}")

download()

Download the signed document.

pdf_bytes = await TurboSign.download("doc-uuid-here")

# Save to file
with open("signed-contract.pdf", "wb") as f:
    f.write(pdf_bytes)

void_document()

Cancel a signature request.

await TurboSign.void_document("doc-uuid-here", reason="Contract terms changed")

resend_email()

Resend signature request emails.

await TurboSign.resend_email("doc-uuid-here", recipient_ids=["recipient-uuid-1"])

Field Types

Type Description Required Auto-filled
signature Signature field (draw or type) Yes No
initials Initials field Yes No
text Free-form text input No No
date Date stamp No Yes (signing date)
checkbox Checkbox / agreement No No

Examples

For complete, working examples including template anchors, advanced field types, and various workflows, see the examples/ directory:

Sequential Signing

result = await TurboSign.send_signature(
    file_link="https://example.com/contract.pdf",
    recipients=[
        {"name": "Employee", "email": "employee@company.com", "signingOrder": 1},
        {"name": "Manager", "email": "manager@company.com", "signingOrder": 2},
        {"name": "HR", "email": "hr@company.com", "signingOrder": 3}
    ],
    fields=[
        # Employee signs first
        {"type": "signature", "recipientEmail": "employee@company.com", "page": 1, "x": 100, "y": 400, "width": 200, "height": 50},
        {"type": "date", "recipientEmail": "employee@company.com", "page": 1, "x": 320, "y": 400, "width": 100, "height": 30},
        # Manager signs second
        {"type": "signature", "recipientEmail": "manager@company.com", "page": 1, "x": 100, "y": 500, "width": 200, "height": 50},
        # HR signs last
        {"type": "signature", "recipientEmail": "hr@company.com", "page": 1, "x": 100, "y": 600, "width": 200, "height": 50}
    ]
)

Polling for Completion

import asyncio

async def wait_for_completion(document_id: str, max_attempts: int = 60):
    for _ in range(max_attempts):
        status = await TurboSign.get_status(document_id)

        if status["status"] == "completed":
            return await TurboSign.download(document_id)

        if status["status"] == "voided":
            raise Exception("Document was voided")

        await asyncio.sleep(30)  # Wait 30 seconds

    raise TimeoutError("Timeout waiting for signatures")

With FastAPI

from fastapi import FastAPI, HTTPException
from turbodocx_sdk import TurboSign
import os

app = FastAPI()
TurboSign.configure(api_key=os.environ["TURBODOCX_API_KEY"])

@app.post("/api/send-contract")
async def send_contract(pdf_url: str, recipients: list, fields: list):
    try:
        result = await TurboSign.send_signature(
            file_link=pdf_url,
            recipients=recipients,
            fields=fields
        )
        return {"success": True, "document_id": result["documentId"]}
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))

With Django

from django.http import JsonResponse
from turbodocx_sdk import TurboSignSync
import os

TurboSignSync.configure(api_key=os.environ["TURBODOCX_API_KEY"])

def send_contract(request):
    result = TurboSignSync.send_signature(
        file_link=request.POST["pdf_url"],
        recipients=request.POST["recipients"],
        fields=request.POST["fields"]
    )
    return JsonResponse({"document_id": result["documentId"]})

Local Testing

The SDK includes a comprehensive manual test script to verify all functionality locally.

Running Manual Tests

# Install dependencies
pip install -e .

# Run the manual test script
python manual_test.py

What It Tests

The manual_test.py file tests all SDK methods:

  • create_signature_review_link() - Document upload for review
  • send_signature() - Send for signature
  • get_status() - Check document status
  • download() - Download signed document
  • void_document() - Cancel signature request
  • resend_email() - Resend signature emails

Configuration

Before running, update the hardcoded values in manual_test.py:

  • API_KEY - Your TurboDocx API key
  • BASE_URL - API endpoint (default: http://localhost:3000)
  • ORG_ID - Your organization UUID
  • TEST_FILE_PATH - Path to a test PDF/DOCX file
  • TEST_EMAIL - Email address for testing

Expected Output

The script will:

  1. Upload a test document
  2. Send it for signature
  3. Check the status
  4. Test void and resend operations
  5. Print results for each operation

Error Handling

from turbodocx_sdk import TurboSign, TurboDocxError

try:
    await TurboSign.get_status("invalid-id")
except TurboDocxError as e:
    print(f"Status: {e.status_code}")
    print(f"Message: {e.message}")
    print(f"Code: {e.code}")
except Exception as e:
    print(f"Unexpected error: {e}")

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

Type Hints

Full type hint support for IDE autocompletion:

from turbodocx_sdk import TurboSign
from turbodocx_sdk.types import (
    PrepareForSigningOptions,
    Recipient,
    Field,
    DocumentStatus
)

recipients: list[Recipient] = [
    {"name": "John", "email": "john@example.com", "order": 1}
]

fields: list[Field] = [
    {"type": "signature", "page": 1, "x": 100, "y": 500, "width": 200, "height": 50, "recipientOrder": 1}
]

Requirements

  • Python 3.9+
  • aiohttp (for async)
  • requests (for sync)

Related Packages

Package Description
@turbodocx/sdk (JS) JavaScript/TypeScript SDK
turbodocx (Go) Go SDK
@turbodocx/n8n-nodes-turbodocx n8n community nodes

Support


License

MIT — see LICENSE


TurboDocx

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

turbodocx_sdk-0.1.4.tar.gz (848.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

turbodocx_sdk-0.1.4-py3-none-any.whl (14.3 kB view details)

Uploaded Python 3

File details

Details for the file turbodocx_sdk-0.1.4.tar.gz.

File metadata

  • Download URL: turbodocx_sdk-0.1.4.tar.gz
  • Upload date:
  • Size: 848.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for turbodocx_sdk-0.1.4.tar.gz
Algorithm Hash digest
SHA256 5d6987db34baa0dc79c166361ea47bf057362c413add168defa558b574381205
MD5 b3f7cf809d29097d130652068a7a294b
BLAKE2b-256 6f3131b0504bf517abf0344b4c35acf7da877eccef1f3884f66607fbb0ce7181

See more details on using hashes here.

Provenance

The following attestation bundles were made for turbodocx_sdk-0.1.4.tar.gz:

Publisher: publish-py.yml on TurboDocx/SDK

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file turbodocx_sdk-0.1.4-py3-none-any.whl.

File metadata

  • Download URL: turbodocx_sdk-0.1.4-py3-none-any.whl
  • Upload date:
  • Size: 14.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for turbodocx_sdk-0.1.4-py3-none-any.whl
Algorithm Hash digest
SHA256 ca25f7c63acb4b65444feea80826aeaa224b200c099dd8d0487c7b7568d75ea6
MD5 d893bceddbd3b33eabb5b4e6d819f882
BLAKE2b-256 c0d52ee876da4b7074a39effb3d302449615e6f3213c11270ae3afc90e31dca7

See more details on using hashes here.

Provenance

The following attestation bundles were made for turbodocx_sdk-0.1.4-py3-none-any.whl:

Publisher: publish-py.yml on TurboDocx/SDK

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page