App builders / Retool
Generate a PDF from Retool
An internal tool builder where the UI is assembled from components and the data comes from queries, which makes a file an awkward shape to pass around.
Making the request
A REST API resource with a query on it, or a raw fetch inside a JavaScript query. Queries run on the Retool backend rather than in the browser, which is what keeps the API key off the client.
What it does with the response
Retool queries are built around returning data that components can bind to, and a PDF is not that. The path that works reliably is to keep the bytes out of the query result entirely: store the document at render time, return its URL, and give the URL to the component that needs it. Where a file genuinely has to reach the browser, Retool's download utility takes the content, a filename and a type and hands the user a file. Both routes work; the URL route is the one that does not put a multi-megabyte string through a query result and into the app's state.
Where the document can go afterwards
This is the part that differs most between platforms, and it is usually the reason one platform was chosen over another in the first place.
- a PDF viewer component, given a URL, which is the common case for an internal review tool
- a browser download, through the download utility, when a user clicks a button
- a database column, if you are storing a reference rather than the file
- an email or storage service, called from a second query rather than from the browser
The limit that bites in production
Queries run on the Retool backend, so the API key lives in a resource configuration rather than in the app. That is the right place for it. What it means in practice is that a self-hosted instance needs outbound network access to the render API, which is a firewall question that tends to surface late.
The shape that works
Render with storage on, return the document URL from the query, and bind the viewer component to that URL. The app state then holds a string rather than a file, which keeps the app responsive and keeps large payloads out of the query cache.
// A JavaScript query. Storage on, so what comes back is a reference
// rather than several megabytes going into the app's state.
const res = await fetch("https://api.pdfpipe.xyz/v1/pdf", {
method: "POST",
headers: {
Authorization: `Bearer ${environment.PDFPIPE_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
html: buildInvoiceHtml.data,
filename: `${invoiceNumber.value}.pdf`,
store: true,
options: { format: "A4", margin: "16mm" },
}),
});
if (!res.ok) throw new Error(`Render failed: ${res.status}`);
const { id, url } = await res.json();
// Bind the PDF viewer component to this, rather than to a blob.
return { id, url };The mistake people make
Returning the raw bytes from a query so a component can show them. The result goes into the app's state, the state is serialised, and an internal tool that felt instant now takes seconds to switch tabs. Keep files behind URLs and let the app hold references.
Frequently asked
Can Retool handle the PDF bytes directly?
Retool queries are built around returning data that components can bind to, and a PDF is not that. The path that works reliably is to keep the bytes out of the query result entirely: store the document at render time, return its URL, and give the URL to the component that needs it. Where a file genuinely has to reach the browser, Retool's download utility takes the content, a filename and a type and hands the user a file. Both routes work; the URL route is the one that does not put a multi-megabyte string through a query result and into the app's state.
Should I store the document or pass the bytes through?
It depends on what the platform does with a large value. On a platform that serialises everything passing between steps, pushing several megabytes through the workflow is slow and sometimes capped, so storing the document and passing a URL is better. On a platform that hands you a file object natively, passing it straight to its destination is simpler and avoids a second fetch. The page above says which of those this platform is.
Where does the API key live?
In the platform's own secret or environment storage, never in a step body where it is visible in an execution log. Every platform on this list has somewhere to put it, and the execution logs of an automation platform are seen by more people than a codebase is.
Other platforms
Platforms of the same kind, and one from each of the other kinds.
Generate a PDF from Bubble
A visual application builder with its own database and workflow engine, where an external call is configured in the API Connector rather than written.
Generate a PDF from Power Automate
Microsoft's cloud flow automation, which sits closest to SharePoint, OneDrive, Outlook and Dataverse and is usually chosen because the documents have to land in one of them.
Generate a PDF from Pipedream
A workflow platform where the steps are real Node.js or Python, so anything the language can do the workflow can do.
Generate a PDF and attach it in Airtable
A database with a spreadsheet interface, where attachments are a first-class field type and are set in a way that surprises people.
Every automation platform covered
Grouped by what kind of platform it is, with the three that have their own guide linked out.
Storing generated PDFs and fetching them later
The capability several of these integrations are built on, with the retention that applies.
100 free documents a month, and a playground that runs a real render without a key, which is the fastest way to get an HTML sample worth wiring up.