Skip to main content

Official Python SDK for the Docuplete API

Project description

Docuplete Python SDK

Official Python client for the Docuplete API — document automation, guided client interviews, and e-signatures for high-compliance industries.

Installation

pip install docuplete
# or
poetry add docuplete

Requires Python 3.8+ and httpx (installed automatically).

Quick start

import os
from docuplete import Docuplete

client = Docuplete(api_key=os.environ["DOCUPLETE_API_KEY"])

# Create a session — returns an interview URL to send to your client
result = client.sessions.create(
    package_id=42,
    prefill={
        "first_name": "Jane",
        "last_name":  "Smith",
        "email":      "jane@example.com",
        "phone":      "555-867-5309",
    },
    link_expiry_days=14,
    reminders={"enabled": True, "interval_days": 3},
)

print(result["interview_url"])   # https://docuplete.com/...
print(result["session_token"])   # df_a1b2c3...
print(result["expires_at"])      # 2026-05-23T14:00:00Z

Sessions

Create a session

result = client.sessions.create(
    package_id=42,
    prefill={"first_name": "Jane", "email": "jane@example.com"},
    link_expiry_days=7,
    locale="es",
    reminders={"enabled": True, "interval_days": 2},
)

Multi-party signing

result = client.sessions.create(
    package_id=42,
    prefill={"property_address": "123 Main St"},
    signers=[
        {"email": "buyer@example.com",  "name": "Alice Buyer",  "order": 0},
        {"email": "seller@example.com", "name": "Bob Seller",   "order": 1},
        {"email": "agent@example.com",  "name": "Carol Agent",  "order": 2},
    ],
)

Bulk session creation (up to 100)

contacts = [{"email": "a@co.com", "name": "Alice"}, {"email": "b@co.com", "name": "Bob"}]

result = client.sessions.bulk_create([
    {
        "package_id": 42,
        "prefill": {"email": c["email"], "first_name": c["name"]},
    }
    for c in contacts
])

for r in result["results"]:
    if r["ok"]:
        print("Created:", r["session_token"])
    else:
        print(f"Item {r['index']} failed: {r['error']}")

Get session status

session = client.sessions.get("df_a1b2c3...")
print(session["status"])    # "generated"
print(session["answers"])   # {"first_name": "Jane", ...}
print(session["pdf_url"])   # download URL (when generated)

Session audit log

log = client.sessions.audit_log("df_a1b2c3...")
for entry in log["entries"]:
    print(entry["event"], entry["created_at"], entry["actor_ip"])

Multi-party signer status

result = client.sessions.signers("df_a1b2c3...")
for signer in result["signers"]:
    print(signer["email"], signer["status"])

Send or re-send a link

client.sessions.send_link(
    "df_a1b2c3...",
    recipient_email="jane@example.com",
    recipient_name="Jane Smith",
    custom_message="Please complete your intake form at your earliest convenience.",
)

Void a session

client.sessions.void("df_a1b2c3...", reason="Sent to wrong client", notify_signer=True)

PDF generation (manual trigger)

import time

result = client.sessions.generate("df_a1b2c3...")
if result["status"] == "generated":
    print("Ready:", result["download_url"])
else:
    # Poll until ready
    while True:
        time.sleep(2)
        status = client.sessions.get_generate_status(result["token"])
        if status["status"] == "ready":
            print("PDF:", status["download_url"])
            break
        if status["status"] == "failed":
            raise RuntimeError(status.get("error", "PDF generation failed"))

Packages

# List all packages
packages = client.packages.list()
for pkg in packages:
    print(pkg["id"], pkg["name"])

# Get a specific package
pkg = client.packages.get(42)

Webhook verification

Always verify the X-Docuplete-Signature header before processing a webhook payload.

FastAPI

import os
from fastapi import FastAPI, Request, HTTPException
from docuplete import construct_webhook_event

app = FastAPI()

@app.post("/webhook/docuplete")
async def docuplete_webhook(request: Request):
    raw_body = (await request.body()).decode()
    sig = request.headers.get("x-docuplete-signature", "")

    try:
        event = construct_webhook_event(
            raw_body, sig, os.environ["DOCUPLETE_WEBHOOK_SECRET"]
        )
    except ValueError:
        raise HTTPException(status_code=401, detail="Invalid signature")

    if event["event"] == "pdf.generated":
        print("PDF ready:", event["download_url"])
    elif event["event"] == "session.submitted":
        print("Submitted answers:", event["answers"])

    return {"ok": True}

Flask

import os
from flask import Flask, request
from docuplete import construct_webhook_event

app = Flask(__name__)

@app.post("/webhook/docuplete")
def docuplete_webhook():
    raw_body = request.get_data(as_text=True)
    sig = request.headers.get("X-Docuplete-Signature", "")

    try:
        event = construct_webhook_event(
            raw_body, sig, os.environ["DOCUPLETE_WEBHOOK_SECRET"]
        )
    except ValueError:
        return "Invalid signature", 401

    match event["event"]:
        case "pdf.generated":
            print("PDF ready:", event["download_url"])
        case "session.submitted":
            print("Submitted answers:", event["answers"])

    return "", 200

Django

import os, json
from django.http import HttpResponse
from django.views.decorators.csrf import csrf_exempt
from docuplete import construct_webhook_event

@csrf_exempt
def docuplete_webhook(request):
    raw_body = request.body.decode("utf-8")
    sig = request.headers.get("X-Docuplete-Signature", "")

    try:
        event = construct_webhook_event(
            raw_body, sig, os.environ["DOCUPLETE_WEBHOOK_SECRET"]
        )
    except ValueError:
        return HttpResponse(status=401)

    if event["event"] == "pdf.generated":
        print("PDF ready:", event["download_url"])

    return HttpResponse(status=200)

Error handling

from docuplete import Docuplete, DocupleteError

client = Docuplete(api_key=os.environ["DOCUPLETE_API_KEY"])

try:
    result = client.sessions.create(package_id=999, prefill={})
except DocupleteError as e:
    print(e.status)   # 404
    print(e.code)     # "package_not_found"
    print(str(e))     # "Package not found"
    print(e.issues)   # [] or ["field_name: message"]

Context manager

with Docuplete(api_key=os.environ["DOCUPLETE_API_KEY"]) as client:
    result = client.sessions.create(package_id=42, prefill={})
    # Connection pool is closed automatically on exit

Configuration

client = Docuplete(
    api_key="dp_live_...",
    timeout=60.0,           # seconds (default: 30)
    base_url="https://api.docuplete.com",  # override for testing
)

Links

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

docuplete-0.1.0.tar.gz (16.3 kB view details)

Uploaded Source

Built Distribution

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

docuplete-0.1.0-py3-none-any.whl (18.5 kB view details)

Uploaded Python 3

File details

Details for the file docuplete-0.1.0.tar.gz.

File metadata

  • Download URL: docuplete-0.1.0.tar.gz
  • Upload date:
  • Size: 16.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.13

File hashes

Hashes for docuplete-0.1.0.tar.gz
Algorithm Hash digest
SHA256 498c73a099a385995690d992b28530ebfa5fee403999eabd495c15056c220866
MD5 557b61b857866e12e8557768178f9526
BLAKE2b-256 116866081983163a2a08d699438e256b9ad06ef0d13fc50c0c62e369823714cf

See more details on using hashes here.

File details

Details for the file docuplete-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: docuplete-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 18.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.13

File hashes

Hashes for docuplete-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 0887caec583273479e8b7705d9f1383946657541d82c4b89e3ebf0fabf010560
MD5 5cb8a4e223fa147bc6e6ddd017bf61c8
BLAKE2b-256 de80ad46b593b5620ea3734f5ed0cd9a0ef0b6f147d54840f3d38d49dc361e61

See more details on using hashes here.

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