Today, developers and even non-developers employ strong tools to speed up their job. Documents in PDF format are necessary for work. They can be manually created, but why would you put yourself through that stress?
With the aid of some tools, you may easily manufacture almost everything you need to carry out complicated activities. You don’t even need to know how to code to use them, but even if you do know how to code, you don’t necessarily have to build from scratch.

This is why products like Retool were developed. Retool is a low-code platform that is used by businesses to build applications faster, these applications include creating admin panels, dashboards, and even PDFs. Yes, you can create them with the help of mostly drag-and-drop tools available in Retool. Although, you would most likely enjoy using Retool when you have basic knowledge of APIs, JavaScript, or databases.
The good news is that I would be showing you how to easily generate PDFs in Retool like ABC. So, let’s dive right in!
Why use CraftMyPDF for PDF Generation?
Taking advantage of external APIs is a great way to generate PDFs because they make life so much easier by providing pre-designed templates you can edit according to your needs.

CraftMyPDF offers a very sophisticated way of generating PDF documents, let’s look at some benefits this service provides:
- Cloud-based PDF generation: We provide cloud-based PDF generation API and Image generation API.
- A drag-and-drop template editor that makes it easy for you to create PDFs and images from reusable templates.
- CraftMyPDF supports JavaScript expressions similar to Retool and allows you to create dynamic PDFs and images with Javascript.
- Powerful expressions and formatting support for DateTime, currency, and custom formats.
- Regional API endpoints that are designed for clients in the same region.
Steps to Generate Dynamic PDFs with Retool
1. Register and create a new PDF template
The first step in this process is to register (if you haven’t), not to worry the registration is free and doesn’t require your credit card details.
After registration, login, and you would be directed to your dashboard which contains your workspaces. On your toolbar, go to Manage Templates and then click on New PDF Template to create a new PDF template. In this example, I’d be creating a logo consulting invoice. Here’s what you need to do:
- Give your template a name, left mine as the default name (New Template)
- Select a template of your choice (I chose the logo consulting invoice)
- Click on the Create button to generate your PDF. After creating, you’d be referred back to your dashboard.

2. Get API Key from “API Integration”
Now, back to your dashboard, click on the API Integration toolbar and copy the default API key that has been generated for you. We would be using this API key to create a resource on Retool so make sure it’s copied on your clipboard.

3. Create or sign in Retool
Go to retool.com, and create an account if you haven’t, if you have already, sign in to your retool account. You should see a page similar to the screenshot below

3. Create REST-API in resource
On your toolbar, click on Resources, you should see a button at the top-right called Create new, select it, and then resource. The next step is to choose a resource type from the list of available APIs. After choosing the REST API, you should be directed to a page where you configure the REST API. You would need to do the following:
- Choose a name for the resource (Ignore the folder root for now)
- Add a base URL for the API, mine is http://api.craftmypdf.com/v1
- Add a header name along with the API key copied from your CraftMyPDF dashboard, in my case the header name was X-API-KEY. If you’re wondering why we need this, a header essentially acts as an additional source of information for every API call you make. You can quickly identify problems with an API thanks to them.
- Click on create resource button. You should get a prompt saying you should create an app, ignore it for now and click go back to resources. You should get something similar to the screenshot below

4. Create PostgreSQL in resource
On your toolbar click on Resources, you should see a button at the top-right called Create new, select it, and then resource, just like we did when we created the REST-API resource. The next thing to do is to select a resource type from the database list, select the PostgreSQL database and you should be taken to a page where you configure the database. You would need to do the following:
- Choose a name for your resource
- Add your hostname

- Add your database name
- Add your authentication method, I used the user and password authentication
- Test your connection to make sure everything works fine.

- Create resource and click on go back to resources. Voila! You are getting there.
5. Create a new app
Go to your Apps dashboard on your toolbar. On the bottom right, click on Create new button, choose App to create a new app, add a name of your choice and that’s it! You would be directed to your app’s dashboard.

6. Setup a query for invoice data
After creating an app, click on the edit button to make changes to your newly created app.
You would also need to set up your PostgreSQL database on your app. Here’s what you need to do:
- On the bottom left corner, click on the new button and then resource query to add your resource to the app.
- Click on the Resource name and search for the name of the PostgreSQL database resource created earlier which was (in my case) named sampleDb.
- Rename your query to a name you think is best. I renamed my query to queryInvoices to make it easy for anyone who reads it to understand. In the query editor, write the command select * from invoices to select all the data from our invoice database.
- Run the command to make sure everything works fine. You should get something similar to the screenshot below

7. Set up a table component for invoice data
After creating the queries, the next is to create the user interface of our app by using the drag-and-drop component available in our Retool editor. All the components we are using are available at the top right corner of our editor like tables, buttons, text input, PDF, and so on. In no particular order, we would start creating our user interface so, let’s get to this!
We will first create an invoice table to display these invoice data.
On the top right corner of the app, drag a table component and change the name to what you see fit. This table contains the data invoices, so I named it tblInvoices for easy understanding. The next step is to pass the PostgreSQL query that was created earlier to the data block. In my case, it was {{ queryInvoices.data }}

8. Setup a query for invoice line items
The next step is to access the list of items linked with the invoice number. Let’s create another PostgreSQL resource to do that
- On the bottom left corner, click on the new button and then resource query to add your resource to the app.
- Click on the Resource name and search for the name of the PostgreSQL database resource created earlier which was (in my case) sampleDb.
- Give your query a name. I renamed my query to queryLineItems. In the query editor, write the command select * from line_items where invoice_number = {{tblInvoices.selectedRow.data.invoice_number}} to select all the data linked to that particular invoice number.
- Run the command to make sure everything works fine. You should get something similar to the screenshot below

9. Setup table component for line items
The next step is to create a table to display these items.
On the top right corner of the app, drag a table component and change the name to whatever you like (I named mine tblLineItem). This table displays all the items associated with the invoice number we are trying to fetch. In the data block, pass in the PostgreSQL query that we created earlier, to fetch the invoice items. In my case, it was {{ queryLineItems.data }}

10. Create JSON and send API to CraftMyPDF
The next step is to set up your REST API. Here’s what you need to do:
Step 1: On the bottom left corner, click on the new button and then resource query to add your resource to the app.
Step 2: Click on the Resource name and search for the name of the resource REST-API you created earlier which was (in my case) CraftMyPDF. You can also give your REST API a new name if you like, or you can choose to stick with the default name (changed mine to CreatePDF)
Step 3: Change the action type to POST
Step 4: Enter create in the URL, the complete URL is https://api.craftmypdf.com/v1/create
For the details of REST API, please look at our API reference

Next, in the Body select JSON and you would need to pass two things:
(i) template_id
field: The template ID of the PDF template
(ii) data
field: The JSON data, you would need to manually write out the JSON in an external editor. The following is the JSON data
{{
{
"invoice_number": tblInvoices.selectedRow.data.invoice_number,
"date": tblInvoices.selectedRow.data.date,
"due_date": tblInvoices.selectedRow.data.due_date,
"currency": tblInvoices.selectedRow.data.currency,
"discount": 5,
"tax": 7,
"company_name": "LOGO Consulting Pte Ltd",
"email": "[email protected]",
"client": tblInvoices.selectedRow.data.client ,
"client_address": tblInvoices.selectedRow.data.client_address,
"client_address2": tblInvoices.selectedRow.data.client_address2,
"client_address3": tblInvoices.selectedRow.data.client_address3,
"items": formatDataAsArray(queryLineItems.data)
}
}}
We need to find a way to convert the data from the queries into an array of objects that we can access. Retool supports two data conversion methods which are formatDataAsArray
and formatDataAsObject
.
We would be using the formatDataAsArray
, in this case, each key is a column name that points to an array of column values, that is we are going to display the data as an array of objects.
Notice how I passed in the table component tblInvoices that was created earlier in our Retool app by using the formatDataAsArray
JSON format.
The following is the complete setup for template_id
and data
field

Save and Run the command to make sure everything works fine. You should get something similar response to the screenshot below.

11. Add a component to view generated PDF
On the top right corner of the app, search for the PDF component and drag it into your app. Add your file URL, which is the URL link to the PDF that was stored in the CreatePDF REST-API resource. In my case, my file URL would be {{ CreatePDF.data.file }}. This allows viewing our invoices in the app.

12. Create a button to generate PDFs
Generate PDF button: Let’s add a button called “Generate PDF” and configure it such that it executes our query when clicked. On the right-hand side of the app, drag a button to the main, go to the event handler, and add the CreatePDF (craftMyPDF) REST-API resource to trigger the button.

13. Add a text for URL
Let’s add a text URL that would allow us to easily download the generated invoice PDF. On the right-hand side of the app, drag a text button, and edit the name of the text button if you like (I changed mine to lblURL).
Next step is to add the label name of your choice and the URL link to the PDF in JSON format. In my case, it was Download at: {{ CreatePDF.data.file }}

The PDF that was generated in your CraftMyPDF template should be available for download.

Conclusion
Whew! I know that was a lot to process, take your time to understand each process. Once it clicks, life becomes easier. Thank you for reading!