Tailprint
Scale & SDKs 8 min read • Published: 2026-11-13

High-Throughput Async Batch PDF Rendering, Auto-Merging & Signed Webhooks in Python, TypeScript, Laravel & Go

How to render hundreds of PDFs in parallel with POST /v1/render/batch, merge outputs into a single print run, verify HMAC-SHA256 webhooks, and use official SDKs for Python, TypeScript, PHP/Laravel, and Go.

End-of-month billing runs, payroll statements, and logistics manifest pipelines often need to generate hundreds or thousands of PDFs at once without blocking HTTP worker threads or risking duplicate renders during network retries.

⚡ Parallel Worker Pool + Idempotency + 4 Official SDKs

Tailprint v1.4 introduces asynchronous batch rendering (POST /v1/render/batch) with optional single-file PDF merging (merge_output: true), HMAC-SHA256 signed webhook delivery, 24-hour Idempotency-Key protection, and zero-dependency SDKs for TypeScript/Node.js, Python, PHP/Laravel, and Go.

1. Async Batch Rendering & Auto-Merge (POST /v1/render/batch)

Submit up to 50 documents (raw HTML, public URLs, or hosted template_id items) in a single call. Tailprint immediately returns a 202 Accepted with a job_id, processes the batch across our pre-warmed Chromium pool, optionally merges all generated PDFs into a single master PDF, and dispatches a signed webhook when finished:

curl -X POST https://tailprint.com/v1/render/batch \
  -H "Authorization: Bearer sec_live_your_api_key" \
  -H "Idempotency-Key: billing-run-2026-11-batch-01" \
  -H "Content-Type: application/json" \
  -d '{
    "merge_output": true,
    "merged_filename": "november-2026-invoices.pdf",
    "webhook_url": "https://api.yourdomain.com/webhooks/tailprint",
    "items": [
      {
        "template_id": "invoice-modern",
        "filename": "inv-1001.pdf",
        "data": {
          "invoice_number": "INV-1001",
          "issue_date": "2026-11-13",
          "seller": { "name": "Tailprint ApS" },
          "buyer": { "name": "Customer A" },
          "items": [{ "description": "Pro Tier", "quantity": 1, "unit_price": 49 }]
        }
      },
      {
        "template_id": "invoice-modern",
        "filename": "inv-1002.pdf",
        "data": {
          "invoice_number": "INV-1002",
          "issue_date": "2026-11-13",
          "seller": { "name": "Tailprint ApS" },
          "buyer": { "name": "Customer B" },
          "items": [{ "description": "Business Tier", "quantity": 1, "unit_price": 119 }]
        }
      }
    ]
  }'

2. Official Multi-Language SDK Examples (v1.4)

TypeScript / Node.js (npm install tailprint)

import { Tailprint } from 'tailprint';
const tp = new Tailprint({ apiKey: process.env.TAILPRINT_API_KEY });

const job = await tp.renderBatchAndWait({
  merge_output: true,
  items: [
    { template_id: 'invoice-modern', data: inv1 },
    { template_id: 'invoice-modern', data: inv2 },
  ],
});
console.log(job.merged_output?.download_url);

Python (pip install tailprint)

from tailprint import Tailprint
tp = Tailprint(api_key="sec_live_...")

status = tp.render_batch_and_wait(
    items=[
        {"template_id": "invoice-modern", "data": inv1},
        {"template_id": "invoice-modern", "data": inv2},
    ],
    merge_output=True,
    idempotency_key="batch-2026-11"
)
print(status["merged_output"]["download_url"])

PHP & Laravel (composer require tailprint/tailprint)

use Tailprint\Laravel\Facades\Tailprint;

// Stream directly from a Laravel Controller:
return Tailprint::template('invoice-modern', $invoiceData)
    ->idempotencyKey('inv-' . $invoice->id)
    ->download('invoice.pdf');

Go (go get github.com/coheroseb/tailprint/sdk/go)

client := tailprint.NewClient(os.Getenv("TAILPRINT_API_KEY"))

pdfBytes, err := client.RenderTemplate(
    ctx,
    "invoice-modern",
    invoiceData,
    &tailprint.RequestOptions{IdempotencyKey: "inv-1001"},
)

Ready to build with Tailprint?

Get 100 free vector PDF and image renders every month with zero credit card required.