Document Stack
Document Stack
Docs

Python SDK — Advanced

Advanced patterns for the Document Stack Python SDK: async support, batch generation, error handling, and custom configuration.

Client Configuration

Full Configuration
from document_stack import DocumentStack

client = DocumentStack(
    api_key=os.environ["DS_API_KEY"],
    base_url="https://api.documentstack.dev",  # custom base URL
    timeout=30,          # request timeout in seconds
    max_retries=3,       # retry transient errors
    retry_delay=1.0,     # initial retry delay in seconds
)

Async Support

The Python SDK provides an async client for use with asyncio:

Async Client
import asyncio
from document_stack import AsyncDocumentStack

async def main():
    client = AsyncDocumentStack(api_key=os.environ["DS_API_KEY"])

    pdf = await client.generate(
        template_id="tmpl_abc123",
        data={"name": "Alice", "amount": 99.99},
    )
    print("PDF URL:", pdf.url)

asyncio.run(main())

Batch Generation

Use the async client with asyncio.gather for concurrent PDF generation:

Batch with Semaphore
import asyncio
from document_stack import AsyncDocumentStack

async def generate_pdf(client, semaphore, customer):
    async with semaphore:
        return await client.generate(
            template_id="tmpl_invoice",
            data=customer,
        )

async def batch_generate():
    client = AsyncDocumentStack(api_key=os.environ["DS_API_KEY"])
    semaphore = asyncio.Semaphore(5)  # max 5 concurrent

    customers = [
        {"name": "Alice", "invoice_id": "INV-001"},
        {"name": "Bob", "invoice_id": "INV-002"},
        {"name": "Charlie", "invoice_id": "INV-003"},
    ]

    results = await asyncio.gather(
        *[generate_pdf(client, semaphore, c) for c in customers]
    )

    for r in results:
        print(f"Generated: {r.url}")

asyncio.run(batch_generate())

Rate Limiting

The semaphore prevents hitting rate limits. Adjust concurrency based on your plan's rate limits.

Saving PDFs Locally

Download and Save
import httpx

pdf = client.generate(
    template_id="tmpl_abc123",
    data={"name": "Alice"},
)

# Download the PDF from the returned URL
response = httpx.get(pdf.url)
with open("invoice.pdf", "wb") as f:
    f.write(response.content)

print("Saved to invoice.pdf")

Error Handling

Typed Exceptions
from document_stack import DocumentStack, DocumentStackError

client = DocumentStack(api_key=os.environ["DS_API_KEY"])

try:
    pdf = client.generate(
        template_id="tmpl_invalid",
        data={},
    )
except DocumentStackError as e:
    print(f"Status: {e.status}")       # 404
    print(f"Message: {e.message}")     # "Template not found"
    print(f"Request ID: {e.request_id}")
except Exception as e:
    print(f"Unexpected error: {e}")

Django Integration

A common pattern for Django views:

Django View
from django.http import FileResponse
from document_stack import DocumentStack
import httpx

client = DocumentStack(api_key=settings.DS_API_KEY)

def download_invoice(request, invoice_id):
    invoice = Invoice.objects.get(id=invoice_id)

    pdf = client.generate(
        template_id="tmpl_invoice",
        data={
            "customerName": invoice.customer.name,
            "amount": str(invoice.amount),
            "date": invoice.date.isoformat(),
        },
    )

    response = httpx.get(pdf.url)
    return FileResponse(
        io.BytesIO(response.content),
        content_type="application/pdf",
        filename=f"invoice-{invoice_id}.pdf",
    )

Next Steps