HTML to PDF in Bubble
Convert HTML to PDF in Bubble with the API Connector. Set up the call, pass dynamic HTML, get a PDF link back and save it to a file field.
Bubble apps often need to hand users a document, such as an invoice, a quote, a certificate or a report. Bubble has no built-in HTML-to-PDF action, so most apps either use a plugin or call a PDF API through the API Connector.
This guide covers the API Connector route. It gives you full control over the layout with your own HTML and CSS.
Quick answer: in the API Connector, add a POST call to https://html-pdf.com/v1/pdf with the header Authorization: Bearer YOUR_API_KEY and this JSON body. The response contains a url to the PDF.
{ "html": <html>, "response": "url" }
Native options and their limits
This section covers what you can do without an API, and why it falls short.
- Browser print. You can open a page and let the user "Print → Save as PDF". The result depends on the user's browser, includes page chrome, and can't run in a backend workflow.
- PDF plugins. Several marketplace plugins convert a page or a group to PDF in the browser. Many rasterize the screen into an image, so text isn't selectable and long content splits awkwardly.
A server-side Chromium render avoids both problems. You get selectable text, real page breaks, headers and footers, and it works in backend workflows.
Step 1: get an API key
First, create a free account.
Sign up at https://html-pdf.com/login. You get 100 free credits (1 credit = 1 PDF page), and purchased credits never expire.
Step 2: add the API in the API Connector
Next, register html-pdf.com as an API with your key.
Install the API Connector plugin (by Bubble), then click Add another API and fill in these values.
- API Name:
html-pdf - Authentication:
Private key in header - Key name:
Authorization - Key value:
Bearer YOUR_API_KEY
A private key in header stays on Bubble's server and is never exposed to the browser.
Step 3: configure the call
Now add the call that renders the PDF. Name it Render PDF and use these settings.
- Use as:
Action(so it appears in workflows) - Data type:
JSON - Method / URL:
POSThttps://html-pdf.com/v1/pdf - Headers:
Content-Type=application/json - Body type:
JSON
Use this body.
{
"html": <html>,
"format": "A4",
"margin": "15mm",
"print_background": true,
"filename": "document.pdf",
"response": "url"
}
<html> creates a dynamic parameter. Uncheck Private next to it so you can set it from workflows.
Bubble inserts the value as-is, so it must be a valid JSON string including the quotes. When you set it in a workflow, use the dynamic expression with :formatted as JSON-safe, which adds the quotes and escapes characters like " and line breaks.
Why "response": "url"
By default the API returns raw PDF bytes. Bubble's API Connector expects a JSON (or text) response and won't turn binary data into a file. With "response": "url" the API returns JSON instead.
{ "url": "https://...", "expires_at": "..." }
The link is valid for 24 hours, which is plenty for Bubble to download it into its own storage.
Step 4: initialize the call
Bubble needs one test request to learn the response shape.
Give the html parameter a test value such as "<h1>Hello from Bubble</h1>" (with the quotes, since it's raw JSON here) and click Initialize call. Bubble sends a real request (it uses 1 credit) and shows the detected fields. Confirm that url is a text field and save.
If initialization fails, the response body explains why. Errors look like {"error": {"code", "message", "hint"}}, for example 401 for a wrong key or 402 insufficient_credits when your balance is empty.
Step 5: use it in a workflow
Here is a typical "Download invoice" button workflow.
- Plugins → html-pdf - Render PDF, with
htmlset to your HTML. Build it with Bubble's text editor and dynamic data, for example<h1>Invoice Current Page Invoice's Number</h1>..., then apply:formatted as JSON-safeto the whole expression. - Make changes to a thing on the invoice. Set its
PDF(file field) toResult of step 1's url. Bubble saves the file from the URL into its own storage so it outlives the 24-hour link. If your editor doesn't accept a URL for a file field directly, store the URL in a text field and save the file with a file-upload plugin, or save it in a backend workflow. - Optional: Open an external website with
Result of step 1's urlto let the user download it immediately, or Send email with the link.
The same call works in backend workflows (API workflows). You can generate PDFs on a schedule or when data changes, without a user on the page.
Building the HTML
These tips help your template print cleanly.
Keep your template in an option set, a text field, or a "template" thing, and fill in dynamic values with Bubble expressions.
- Use inline
<style>with@page { size: A4; margin: 18mm; }and send"prefer_css_page_size": true. - Add
break-inside: avoidon table rows and totals so they don't split across pages. - Reference images and fonts by absolute
https://URLs. - Escape user-entered text before inserting it into HTML.
Ready-made layouts are at https://html-pdf.com/templates, and a full invoice example is at https://html-pdf.com/generate-invoice-pdf.
Rendering a page by URL
You can also turn an existing page into a PDF instead of sending HTML.
Send "url": "https://..." in place of html. The page must be publicly reachable without login, so this is best for public pages. For private data, pass HTML.
Use wait_delay or wait_for_expression if the page draws content with JavaScript after loading.
More options
These extra options cover most layout needs.
format: A3 to A6, Letter, Legal, Tabloid. Uselandscape: truefor wide tables.header_html/footer_htmlwithpageNumberandtotalPagesfor "Page 1 of 3".max_pagesto cap cost on unexpectedly long documents.
Requests can be up to 20 MB with 30 seconds per render.
FAQ
How do I create a PDF in Bubble?
Add a POST call to https://html-pdf.com/v1/pdf in the API Connector with your HTML and "response": "url". Run it as a workflow action and save the returned url to a file field.
Why does the API Connector not return a file?
Bubble's API Connector can't turn binary PDF bytes into a file. Send "response": "url" to get JSON with a download link valid for 24 hours, and let Bubble save it from there.
Does it support page numbers?
Yes. Use header_html or footer_html with the pageNumber and totalPages classes to print "Page 1 of 3".
Is there a free plan?
You get 100 free credits once you confirm your email, with no card. One credit is one PDF page, and purchased credits never expire.
Full reference: https://html-pdf.com/docs.
