Document Stack
Document Stack
Docs

Scheduled PDF Generation

Automate recurring PDF generation with cron jobs, task schedulers, and event-driven triggers.

Overview

Many workflows require PDFs on a schedule — monthly invoices, weekly reports, daily summaries. This guide covers common patterns for automating PDF generation.

Node.js Cron Job

Using node-cron
import cron from "node-cron";
import { DocumentStack } from "@document-stack/sdk-node";

const client = new DocumentStack({ apiKey: process.env.DS_API_KEY! });

// Run on the 1st of every month at 9 AM
cron.schedule("0 9 1 * *", async () => {
    console.log("Starting monthly invoice generation...");

    const customers = await db.query(
        "SELECT * FROM customers WHERE billing_active = true"
    );

    for (const customer of customers) {
        const pdf = await client.generate({
            templateId: "tmpl_invoice",
            data: {
                customerName: customer.name,
                amount: customer.monthlyCharge,
                period: new Date().toLocaleDateString("en-US", {
                    month: "long",
                    year: "numeric",
                }),
            },
        });

        await sendEmail(customer.email, "Your Monthly Invoice", pdf.url);
    }

    console.log(`Generated ${customers.length} invoices`);
});

Python Scheduler

Using APScheduler
from apscheduler.schedulers.blocking import BlockingScheduler
from document_stack import DocumentStack

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

@scheduler.scheduled_job("cron", day=1, hour=9)
def generate_monthly_reports():
    customers = db.get_active_customers()

    for customer in customers:
        pdf = client.generate(
            template_id="tmpl_report",
            data={
                "customerName": customer.name,
                "period": "January 2025",
                "metrics": customer.get_monthly_metrics(),
            },
        )
        send_email(customer.email, pdf.url)

scheduler.start()

Serverless (AWS Lambda)

Lambda Handler
import { DocumentStack } from "@document-stack/sdk-node";

const client = new DocumentStack({ apiKey: process.env.DS_API_KEY! });

export const handler = async (event: any) => {
    const { templateId, data, recipientEmail } = event;

    const pdf = await client.generate({ templateId, data });

    // Send via SES or store in S3
    await sendEmail(recipientEmail, pdf.url);

    return { statusCode: 200, body: JSON.stringify({ url: pdf.url }) };
};

// Trigger: CloudWatch Events rule (cron expression)
// cron(0 9 1 * ? *)  — 1st of every month at 9 AM UTC

Common Schedule Patterns

Use CaseCron ExpressionDescription
Monthly invoices0 9 1 * *1st of month, 9 AM
Weekly reports0 8 * * 1Every Monday, 8 AM
Daily summaries0 18 * * *Every day, 6 PM
Quarterly statements0 9 1 1,4,7,10 *Jan/Apr/Jul/Oct 1st

Time Zones

Always configure your scheduler with an explicit time zone to avoid surprises with daylight saving time.

Best Practices

  • Log every generation for audit trails
  • Use dead letter queues for failed generations
  • Set up alerts for schedule failures
  • Test schedules in staging before production
  • Implement idempotency — duplicate runs shouldn't create duplicate documents

Next Steps