blog
How to Generate Custom Quotes/Proposals Automatically
When your PDF pipeline cracks at 2 AM and customers are waiting on invoices, debugging headless Chromium is the last thing you want to do. This guide cuts to what actually matters for document automation API in production: templates that render the same way every time, render jobs that survive queue spikes, and an API surface with clear failure modes so on-call is boring.
Updated 2026-02-24
Problem
A backend worker needs to render documents idempotently from queue events and avoid duplicate PDFs during retries.
Treat rendering as a backend job pipeline: idempotent requests, queue control, and deterministic templates.
Typst playground
A backend worker needs to render documents idempotently from queue events and avoid duplicate PDFs during retries.
Queue receipt Typst template
Sample JSON payload
#set page(paper: "a4", margin: 18mm)
#set text(font: "Inter", size: 10pt)
#let data = sys.inputs
#text(size: 22pt, weight: "bold")[#data.title]
#v(4pt)
#text(fill: rgb("#64748b"))[#data.reference + " - " + data.date]
#v(12pt)
#block(
fill: rgb("#f8fafc"),
stroke: 0.5pt + rgb("#e2e8f0"),
inset: 12pt,
radius: 4pt,
)[
#text(weight: "semibold")[#data.customer]
#linebreak()
#text(fill: rgb("#64748b"))[#data.status]
]
#v(12pt)
#table(
columns: (1fr, auto, auto),
inset: 7pt,
stroke: 0.5pt + rgb("#e2e8f0"),
[*Item*], [*Qty*], [*Amount*],
..data.line_items.map(item => (
item.name,
str(item.qty),
"$" + str(item.amount),
)).flatten(),
)Queue render receipt
Idempotent
Queue render receipt
Idempotent
Solution & copyable API code
Feed render jobs through queues partitioned by document type or priority. This prevents a noisy workload from starving critical documents. Attach stable idempotency keys per business document event so retries do not create duplicate outputs.
const response = await fetch(`${process.env.DOCUFORGE_API_URL}/v1/render`, {
method: "POST",
headers: {
"X-API-Key": process.env.DOCUFORGE_API_KEY,
"Content-Type": "application/json",
},
body: JSON.stringify({ template_id: "tpl_how_to_generate_custom_quotes_and_proposals_automatically", data: payload }),
});
const pdf = Buffer.from(await response.arrayBuffer());Customization tips
- Attach an idempotency key to each business event before rendering.
- Keep retry metadata outside the PDF payload so document output stays deterministic.
- Keep brand colors, spacing, and repeated footer copy in shared template variables.
- Pass customer-specific values through JSON data instead of forking the template.
- Store one approved sample payload per template so preview regressions are easy to catch.
Points cles
- Queue partitioning and idempotency are mandatory at scale.
- Template version IDs should be explicit in production render events.
- Monitor usage and quotas by plan and document family.
- Keep failure handling deterministic with typed error branches.
Why teams choose DocuForge for this workflow
- Render API is queue-friendly with predictable request/response envelopes.
- Usage and billing endpoints support operational visibility.
- No headless Chrome dependency in the main render engine path.
Ressources associees
FAQ
How do we avoid duplicate documents on retries?
Use business-event idempotency keys and persist render outcomes before acknowledging queue completion.
What should we put in dead-letter queues?
Jobs with non-retryable schema/template failures and jobs that exceeded bounded retry policy.
Ressources associees
Livrez plus vite avec une API orientee templates
Testez vos templates dans le playground, puis reutilisez la meme requete en production.
