> ## Documentation Index
> Fetch the complete documentation index at: https://docs.flowx.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Fill a document template from a workflow and download it

> Map a Script node's output into the Template Filling node, fix a node that shows no mapping options, and turn the returned downloadPath into a working download URL.

export const date_0 = "October 2026"

export const scope_0 = "The workflow ran end to end: a Script node's output was mapped into the Template Filling node, the PDF was generated with the mapped values, and the download URL returned the file with a token and rejected the request without one."

export const release_4 = "5.10"

export const release_3 = "5.10"

export const release_2 = "5.10"

export const release_1 = "5.13"

export const release_0 = "5.10"

<Badge color="green" icon="circle-check">Tested · {date_0}</Badge>

<Check>
  **Built and run by the FlowX docs team on a live FlowX environment.** {scope_0}
</Check>

This guide answers three questions about generating a document in an integration workflow:

1. How do I pass a Script node's output into the **Template Filling** node?
2. Why does the Template Filling node show no mapping options?
3. How do I build the download URL for the generated document?

The first two questions apply to the Template Filling node, which is available on SaaS. The download URL section applies to every deployment, including self-hosted FlowX.AI 5.9.x and 5.1.x.

<Info>
  **Prerequisites**: a project with an integration workflow, and a document template in the project's **Document templates**. For creating and editing templates, see [Managing templates](/5.9/docs/platform-deep-dive/core-extensions/content-management/documents-plugin/managing-html-templates).
</Info>

***

## How do I pass a Script node's output into the Template Filling node?

<Badge color="blue" icon="cloud">SaaS · {release_0}</Badge>

<Info>
  **Available on SaaS with FlowX.AI {release_0}.** This feature is live on managed (SaaS) deployments now. Self-hosted deployments will receive it with the next LTS release family.
</Info>

A Script node's `output` is merged into the root of the workflow data, with no prefix for the node name. A key the script writes as `output.customer` is available to every later node as `customer`, and its fields as `customer.fullName`. The Template Filling node reads its template values from that workflow data.

<Steps>
  <Step title="Write the values from the Script node">
    Assign each value the template needs to a key on `output`:

    ```javascript theme={"dark"}
    // Script node placed before the Template Filling node
    output.customer = {
      fullName: input.applicant.firstName + " " + input.applicant.lastName,
      contractNumber: input.contractNumber
    };
    ```

    Later nodes reference these values as `${customer.fullName}` and `${customer.contractNumber}`. For the expression rules, see [Referencing workflow data in node configurations](/5.9/docs/platform-deep-dive/integrations/integration-designer#referencing-workflow-data-in-node-configurations).
  </Step>

  <Step title="Declare the keys in the workflow data model">
    The data mapper in the Template Filling node lists the attributes of the workflow's **Data Model** as its source, and a key the Script node writes isn't offered until it's declared there. Add the keys to the workflow data model with the same names and nesting (in this example, a `customer` object with `fullName` and `contractNumber`). See [Workflow data models](/5.9/docs/platform-deep-dive/integrations/workflow-data-models).

    <Tip>
      You can also declare a key from inside the mapper. In a template field, type the path, for example `${customer.fullName}`, click **Add new attribute**, and save the **Attribute Settings**. The attribute is added to the workflow data model when you save the mapping.
    </Tip>
  </Step>

  <Step title="Define the template's input parameters">
    The mapper fills only the template attributes selected as input parameters. Open the document template and:

    1. On the **Data Model** tab, add an attribute for each value, for example `fullName` and `contractNumber` of type string.
    2. On the **Input Parameters** tab, click **Define parameters**, select the attributes, and click **Done**.

    In the template markup, insert each value with a Thymeleaf `th:text` attribute:

    ```html theme={"dark"}
    <p>Contract number: <strong th:text="${contractNumber}"></strong></p>
    <p>Customer: <strong th:text="${fullName}"></strong></p>
    ```

    A bare `${fullName}` outside a `th:` attribute is printed as is in the generated document.

    <Frame>
      ![Template Input Parameters tab listing contractNumber and fullName as string input parameters](https://s3.eu-west-1.amazonaws.com/docx.flowx.ai/final-3-template-input-parameters.png)
    </Frame>
  </Step>

  <Step title="Add and configure the Template Filling node">
    Add **Template Filling** from the node palette after the Script node and set:

    * **Template**: the document template to fill, from this project or one of its library dependencies
    * **Language**: the template language
    * **Document Tag**: the tag stored with the generated file, for example `ContractTemplate`
    * **Document format**: **PDF** (default) or **DOCX**
    * **Response Key**: the key that holds the generated file's details, for example `generatedContract`

    **Template**, **Language**, **Document Tag**, and **Response Key** are required.
  </Step>

  <Step title="Map the workflow attributes onto the template">
    Under **Input Mapping**, click the wrench icon (**Configure mapping**) on the **Template Input** card. In the **Input Mapping** window:

    1. In the workflow panel on the left, click **Define parameters**, select the workflow attributes to map (for example `customer`), and click **Done**.
    2. In the field next to each template attribute, type `${customer.` and pick the suggested path, for example `${customer.fullName}`.
    3. Optionally, click **Test** to see the mapped output under **Preview results**.
    4. Click **Save**.

    <Frame>
      ![Input Mapping window with customer.fullName and customer.contractNumber mapped onto the fullName and contractNumber template attributes](https://s3.eu-west-1.amazonaws.com/docx.flowx.ai/final-2-input-mapping-modal.png)
    </Frame>

    The **Template Input** card then shows how many attributes are mapped, for example **2 mapped**.

    <Frame>
      ![Template Filling node after the Script node, with the Template Input card showing 2 mapped](https://s3.eu-west-1.amazonaws.com/docx.flowx.ai/final-1-template-filling-node.png)
    </Frame>
  </Step>
</Steps>

### Template Filling nodes created before data mapping

<Badge color="blue" icon="cloud">SaaS · {release_1}</Badge>

<Info>
  **Available on SaaS with FlowX.AI {release_1}.** This feature is live on managed (SaaS) deployments now. Self-hosted deployments will receive it with the next LTS release family.
</Info>

Data mapping arrived in FlowX.AI 5.13. Template Filling nodes created before then show an **Enable data mapping** toggle:

* **On**: the node uses the data mapper (**Configure mapping** on the **Template Input** card). Values typed by hand are ignored.
* **Off**: under **Template Variables**, click **Configure Variables** and enter a value for each template variable, either fixed text or an expression such as `${customer.fullName}`.

New nodes always use the mapper and don't show the toggle.

***

## Why does the Template Filling node show no mapping options?

<Badge color="blue" icon="cloud">SaaS · {release_2}</Badge>

<Info>
  **Available on SaaS with FlowX.AI {release_2}.** This feature is live on managed (SaaS) deployments now. Self-hosted deployments will receive it with the next LTS release family.
</Info>

The mapper needs a selected template whose data model has input attributes. Find the message or symptom you see in the table below:

| What you see | Cause | Fix |
| - | - | - |
| **No template selected** | No template is set in **Template**. | Select a template. |
| **This template has no input attributes to map onto** | The template has no data model attributes, or none is selected as an input parameter. | Open the template, add attributes on its **Data Model** tab, and select them on the **Input Parameters** tab. Then reopen the node. |
| The same message, followed by **so it can only be filled in by hand**, and the **Enable data mapping** toggle is unavailable | The node predates data mapping, and the template has no input attributes. | Add input parameters to the template as in the previous row, or fill the values by hand under **Template Variables**. |
| The mapper opens with **No workflow parameters** on the left | No workflow attributes have been added to the mapper yet. | Click **Define parameters**, select the attributes, and click **Done**. |
| The mapper opens, but the Script node's keys aren't listed as sources | The keys aren't declared in the workflow data model. | Add them to the workflow **Data Model**, as in [Declare the keys in the workflow data model](#how-do-i-pass-a-script-nodes-output-into-the-template-filling-node). |
| The document is generated, but every template value is empty | Data mapping is on, but no mapping was saved. The node sends empty template data. | Click **Configure mapping**, map the attributes, and save. |
| The document shows `${fullName}` literally instead of the value | The template markup uses a bare `${...}` placeholder. | Insert the value with a `th:text` attribute, for example `<strong th:text="${fullName}"></strong>`. |

For the template data model and the **Input Parameters** tab, see [Managing templates](/5.9/docs/platform-deep-dive/core-extensions/content-management/documents-plugin/managing-html-templates).

***

## How do I build the download URL for the generated document?

<Badge color="green" icon="globe">All Deployments</Badge>

The download URL is the Documents plugin base URL followed by the `downloadPath` the plugin returns:

```
https://{your-flowx-api-host}/document/ + downloadPath
```

`downloadPath` is relative, for example `internal/files/{fileId}/download`, so the complete URL has the form `https://{your-flowx-api-host}/document/internal/files/{fileId}/download`. The `/document` prefix is the route the Documents plugin is exposed on, as listed in the [ingress service route reference](/5.9/setup-guides/ingress-configuration). Keep the trailing slash after `document`, because `downloadPath` doesn't start with one.

### What does the Template Filling node return?

<Badge color="blue" icon="cloud">SaaS · {release_3}</Badge>

<Info>
  **Available on SaaS with FlowX.AI {release_3}.** This feature is live on managed (SaaS) deployments now. Self-hosted deployments will receive it with the next LTS release family.
</Info>

The node stores the Documents plugin response under its **Response Key**. With the response key `generatedContract`, the workflow data contains:

```json theme={"dark"}
{
  "generatedContract": {
    "customId": null,
    "fileId": "{fileId}",
    "documentType": "ContractTemplate",
    "documentLabel": "GENERATED_PDF",
    "filePath": "{storage-object-path}",
    "downloadPath": "internal/files/{fileId}/download",
    "originalFileName": "ContractTemplate.pdf",
    "noOfPages": 1,
    "error": null
  }
}
```

`customId` holds the **Folder** value, and is `null` when **Folder** is empty. The response also carries `minioPath`, which is deprecated: use `filePath` instead. `filePath` is the object path in file storage, not a URL.

If generation fails, the node run fails. The Documents plugin error is returned under the response key, or, when the node can't reach the plugin, the output holds an `error` message and an `errorType`.

### Build the URL in the workflow

<Badge color="blue" icon="cloud">SaaS · {release_4}</Badge>

<Info>
  **Available on SaaS with FlowX.AI {release_4}.** This feature is live on managed (SaaS) deployments now. Self-hosted deployments will receive it with the next LTS release family.
</Info>

Add a Script node after the Template Filling node and prefix `downloadPath`:

```javascript theme={"dark"}
var downloadPath = input.generatedContract.downloadPath;

if (downloadPath != null) {
  output.contractUrl = "https://{your-flowx-api-host}/document/" + downloadPath;
}
```

Return `contractUrl` in the End node output, then map it into process data in the process that started the workflow. For the round trip from process to workflow and back, see [Call an external API from a process](/5.9/cookbooks/call-external-api).

### Build the URL in a process

On self-hosted FlowX.AI 5.9.x and 5.1.x, you generate documents from a process through the Documents plugin, and the reply carries the same `downloadPath`. Build the complete URL in a business rule:

* **5.9.x**: see [Generating documents](/5.9/docs/platform-deep-dive/core-extensions/content-management/documents-plugin/generating-from-html-templates) for the request and reply, and [Preview an uploaded file](/5.9/docs/building-blocks/ui-designer/ui-component-types/file-preview#preview-an-uploaded-file) for the business rule.
* **5.1.x**: see [Generating documents](/5.1/docs/platform-deep-dive/core-extensions/content-management/documents-plugin/generating-from-html-templates) and [Creating and uploading a new document](/5.1/docs/platform-deep-dive/core-extensions/content-management/documents-plugin/uploading-a-new-document) for the same business rule.

<Tip>
  On SaaS with FlowX.AI 5.13, File Preview doesn't need the complete URL: set its **Source** to **Document Plugin Path** and point it at `downloadPath` directly. See [File sources in FlowX.AI 5.13](/5.9/docs/building-blocks/ui-designer/ui-component-types/file-preview#file-sources-in-flowx-ai-5-13).
</Tip>

<Note>
  The download endpoint requires authentication. The FlowX renderer recognizes a Documents plugin download by the URL ending in `download`, which is how `downloadPath` ends, and fetches it with the user's token. A plain browser link to the same URL has no token and is rejected. For linking to a stored file from a **File download** component, see [File download](/5.9/docs/building-blocks/ui-designer/ui-component-types/file-download).
</Note>

***

## Related resources

<CardGroup cols={2}>
  <Card title="Template Filling node" icon="file-pdf" href="/5.9/docs/platform-deep-dive/integrations/integration-designer#template-filling-node">
    Every field of the Template Filling node.
  </Card>

  <Card title="Script node" icon="code" href="/5.9/docs/platform-deep-dive/integrations/integration-designer#script-node">
    How Script node output merges into workflow data.
  </Card>

  <Card title="Managing templates" icon="files" href="/5.9/docs/platform-deep-dive/core-extensions/content-management/documents-plugin/managing-html-templates">
    Create document templates and define their data model.
  </Card>

  <Card title="Generating documents" icon="file-lines" href="/5.9/docs/platform-deep-dive/core-extensions/content-management/documents-plugin/generating-from-html-templates">
    Generate documents from a process through the Documents plugin.
  </Card>
</CardGroup>


## Related topics

- [Integration Designer](/5.9/docs/platform-deep-dive/integrations/integration-designer.md)
- [AI node types](/5.9/ai-platform/agent-builder/node-types.md)
- [Generating documents](/5.9/docs/platform-deep-dive/core-extensions/content-management/documents-plugin/generating-from-html-templates.md)
- [FlowX.AI 5.10.0 Release Notes](/release-notes/v5.x/v5.10.0-july-2026/v5.10.0-july-2026.md)
- [Reusable UI Templates](/5.9/docs/building-blocks/reusable-resources/reusable-ui.md)


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.