How this works (and what it is not)
Make has a general purpose HTTP app that can call any web API from a scenario. This guide uses it. CastPDF has no Make app, module or listing of its own, and a ready-made CastPDF app for Make is not available yet. So you will not find CastPDF in the module search: you add the HTTP app and point it at our endpoint.
That sounds more technical than it is. The CastPDF API is one URL. You send it JSON with a template ID and your data, and it sends back a PDF or a link to one. Everything else in this guide is about getting that JSON right inside Make.
A word on labels
Make updates its modules from time to time, and field names can shift between versions. The names used here match the HTTP app when this was written. If your screen differs, look for the field with the same job.
Set up the Make a request module
Before you start, create a template in the CastPDF dashboard and copy its ID. Then create a test key. Test keys cost nothing, stamp a watermark on every page and allow 20 requests per minute, which is plenty while you build.
- Add the HTTP module. In your scenario, click the plus after the module that provides your data. Search for HTTP and choose Make a request.
- Enter the URL and method. Set URL to
https://api.castpdf.com/v1/pdfand Method toPOST. - Store the key safely. If the module offers an authentication type with an API key option, create a keychain connection that sends
Authorizationin the header with the valueBearerplus your key. Otherwise add a header under Headers with that name and value. - Choose a raw JSON body. Set Body type to Raw and Content type to JSON (application/json).
- Fill in the request content. Paste the JSON from the next section into Request content. Replace the sample values with mapped items from earlier modules.
- Parse the response. Set Parse response to Yes, so Make turns the JSON answer into fields you can map.
- Raise the timeout. Open the advanced settings and set Timeout to at least 60 seconds. A render can take up to 30 seconds.
- Run it once. Click Run once and open the bubble on the HTTP module. A status of 200 and a
urlfield under Data mean it worked.
Why bother with a keychain connection? A key typed into the Headers list is visible to anyone who can open the scenario, and it travels with every copy or blueprint export. A connection keeps it in one place. When you swap the test key for a live key, you change it there once.
The request content, mapped field by field
Picture a small wholesale bakery. Each new order in its order system should become an invoice PDF with a link the office can send on. This is the request content for one order, with Make mapping pills written as numbered references.
{
"template_id": "3c9e7a10-52f4-4b8d-a1e6-0f2d9c4b7e85",
"data": {
"currency": "EUR",
"customer": { "name": "{{1.customer_name}}", "city": "{{1.customer_city}}" },
"invoice": { "number": "{{1.order_number}}", "issued": "{{formatDate(now; "YYYY-MM-DD")}}" },
"items": {{4.items}}
},
"filename": "invoice-{{1.order_number}}.pdf",
"response": "url"
}Most values are text, so they sit inside quotes. The items value is different: it must arrive as a real JSON array, so it has no quotes. The next section shows how to build that array, because a mapped array does not turn into JSON on its own.
Once Make fills in the pills, CastPDF receives a plain body like this one. Every field is a real CastPDF field, and an unknown field would be rejected with a 400 error.
{
"template_id": "3c9e7a10-52f4-4b8d-a1e6-0f2d9c4b7e85",
"data": {
"currency": "EUR",
"customer": { "name": "Café Lindqvist", "city": "Malmö" },
"invoice": { "number": "BK-20417", "issued": "2026-10-03" },
"items": [
{ "description": "Sourdough loaves", "quantity": 40, "unit_price": 3.2 },
{ "description": "Cardamom buns, tray of 24", "quantity": 6, "unit_price": 28 }
]
},
"filename": "invoice-BK-20417.pdf",
"response": "url"
}The template decides the page size and layout, so the body stays short. Add format or orientation only when one scenario needs a different page from the template’s own settings, for example US Letter for a customer in Chicago.
Line items: aggregator or Create JSON
Invoices, quotes and packing lists all carry a list of lines. In Make, those lines usually arrive as an array in a bundle, or as separate bundles from an Iterator. Either way, you need one JSON array in the body. There are two dependable ways to get it.
Option 1: Array aggregator, then Create JSON
Add an Iterator over the order lines, then an Array aggregator that collects description, quantity and unit_price from each bundle. Next, add the JSON app’s Create JSON module with a data structure that has an items array. Map the aggregator’s array into it. Its output is a JSON string you can map straight into the request content.
Option 2: build the whole body with Create JSON
The cleaner route is to let Create JSON produce the entire CastPDF body. Define a data structure with template_id, data, filename and response, then map every value into it. Put the single JSON output in Request content and nothing else. Make then handles quotes, accents and line breaks for you.
Option 2 also fixes the most common failure of hand-typed bodies. A customer note with a double quote or a line break breaks the JSON, and CastPDF answers 400 invalid_request. Create JSON escapes those characters, so the body stays valid whatever your data contains.
Use the link in the next module
With Parse response on, the HTTP module outputs the answer under Data. The fields are url, expires_at, pages, bytes and id. Map url wherever the link should go: an email, a chat message, or a status field in your order system.
The link is signed and works without an API key until expires_at. After that it stops working. That date follows your plan’s storage period, and test key files last 1 day. To keep a permanent copy, add a second HTTP module that downloads the url and passes the file to your storage app.
You can also skip the link and ask for the file itself. Leave out the response field and CastPDF returns the binary PDF. The HTTP module then outputs it as a file you can attach to an email or upload. The link route is usually simpler in Make, because a text field is easier to map and to read in the execution log.
Troubleshooting common errors
Errors come back as JSON with a code, a message and a docs_url. By default the HTTP module treats any status outside 2xx and 3xx as an error and stops the run, which is what you want. Open the module’s bubble to read the code.
| Status and code | What it means | What to do in Make |
|---|---|---|
| 401 invalid_api_key | The key is missing, mistyped or revoked. | Check the header name is Authorization and the value is Bearer, a space, then the key. |
| 422 template_render_error | The template failed with this data. details give the line and column. | Look for an empty mapping, then compare the body with the sample data in the dashboard. |
| 400 invalid_request | Broken JSON or a field CastPDF does not accept. | Build the body with Create JSON, and check field names for typos. |
| 429 rate_limited | Too many requests in a minute, or too many renders at once. | Add a Break error handler with automatic retries, and wait at least the Retry-After seconds. |
| Timeout | Make gave up before the PDF was ready. | Set the module Timeout to at least 60 seconds and retry with the same Idempotency-Key. |
The Break handler needs one scenario setting: allow storing of incomplete executions. Make then retries the failed bundle on its own schedule. Add an Idempotency-Key header whose value is the order number. A retry that finds a finished PDF gets that PDF back and is not counted again. Every code is listed in the errors reference.
What it costs
On the CastPDF side, one request makes one PDF, and you pay per document, never per page. Test keys are free while you build. The Free plan includes 100 live PDFs a month, and the paid plans are on the pricing page.
Make bills separately for the modules your scenario runs. The Iterator, aggregator, Create JSON and HTTP modules each use part of your Make plan on every run. Fewer modules per order means a cheaper scenario, which is one more reason to let Create JSON build the whole body.
Next steps
The invoice template already has a line items table that repeats its header on every page, so it is a good start. The Liquid docs cover filters such as money and format_date for the values you map. If you build elsewhere, read the guide for workflow automation nodes or the one for internal admin panels.