# Docupilot Help Documentation

Docupilot is a document automation/generation software that allows you to create efficient document workflows for your business.

## Overview

{% embed url="<https://youtu.be/BXFeTPKbPCk>" %}

**Docupilot** replaces manual filling in of repetitive documents with a template-based system which reduces the amount of time spent on generating the content manually and also human errors. With Docupilot, you can automatically create any business document, below are just a few documents widely used.

* Proposals & Quotes
* Contracts & Agreements
* HR Documents
* Educational Certificates
* Purchase & Sales Orders
* Invoices & Receipts
* Real Estate Contracts & Rentals
* Legal documents
* Fillable PDF

You can then send the auto-generated documents to your clients, partners or anyone through different delivery methods like emailing as attachments, sending it for digital signing, or storing it and even integrating with your favorite apps like SalesForce, Zoho CRM & Google Drive, Zapier, etc.


# Getting Started

## What is a Document Template?

A Document template is a pre-formatted and/or pre written document containing placeholders, that can be replaced with your own content so as to quickly create a personalised document.

![](/files/-LM7PoCdIYK18YPnigAd)

### Why should you create Templates? <a href="#id-1" id="id-1"></a>

Creating and sending documents becomes much easier when you’re not starting from scratch. Build reusable templates with Docupilot to increase your productivity and maintain consistency across all documents created from the templates.

Templates help you achieve

* **Automation** - Auto-populate data from your CRM, Forms, Online database, etc, and automate your document generation workflow.
* **Consistency** - Helps you to keep your branding consistent, no more different formatting, different fonts, etc.
* **Accuracy** - Help you eliminate human errors like including wrong client name, etc.
* **Efficiency** - Automate tedious document creation. Save an hour per document and use that time to work on your business growth.<br>


# Building Templates

## Getting Started

To create a new template, click on the `Create a new Template` button on your dashboard.

![Create Template](/files/OL7mLKF0FJyNeZa29NA9)

### Supported Document types

You can choose any of the following document types to create your document template.

* Online Document Builder
* Word Document (.docx)
* PowerPoint (.pptx)
* Excel Document (.xlsx)
* Fillable PDF (.pdf)

#### Online Document Builder

Docupilot offers an online builder tool for creating custom templates from scratch.

To get started:

* Click the **Create a New Template** button on your dashboard.
* Select **Build from Scratch** > **Online Builder**.
* Enter a name and description for your template.
* Choose your document's output format, with options such as PDF, HTML, or PNG (image).

<figure><img src="/files/yuqsbqY1Xh2U3LxL1Usu" alt=""><figcaption><p>Online Document Builder</p></figcaption></figure>

#### Other Document Types

Here's how to get started with other supported document types (pdf, xlsx, docx, pptx) in Docupilot

* Click the "**Create a New Template**" button on your dashboard and choose "**Build from Scratch**."
* Select the desired template format and upload the document you wish to use.
* Enter a name and description for your template.
* Choose the format for the generated output documents from the dropdown menu.

<figure><img src="/files/QHLZWGkHlGhOD8PNIEjM" alt=""><figcaption></figcaption></figure>

## Template Gallery

The template gallery in Docupilot features a variety of standard templates for different documents, including contracts, invoices, and loan agreements. By identifying the specific document you need, you can quickly select an appropriate template from the gallery, saving time and allowing you to start with a template that meets your exact requirements.

For example, if you need a Rental Lease Agreement template, follow these steps:

1. Click the "**Create Template**" button from the top panel.
2. Choose "**Pick from Gallery**" and search for Rental Lease Agreement template and select it.
3. Select desired output document format from the output type dropdown.
4. Update the name and description and click "**Create Template**".

<figure><img src="/files/9AuHp1GwjwRgxyPcLgpe" alt=""><figcaption><p>Selecting the Rental Lease Agreement template from Gallery</p></figcaption></figure>

## Organizing Templates With Folders

You can organize your templates under folders so as to maintain them uncluttered.\
Docupilot lets you organize all your templates by categorizing them into customized folders of your choice.

### Adding Templates inside a particular Folder

* In the templates tab, click on the + button in the folders section.
* Type your desired folder name in the dialog and click on the save button.
* The folder is auto selected so you can start adding your templates, the templates will be added to that folder.
* Navigate to this folder to find the templates created inside this older.

<img src="/files/vc8bSUVASIv378M521bM" alt="Creating a New folder" width="355">

{% hint style="info" %}
You can create a template inside a specific folder or Home folder. You can move them to a folder of your choice by going to Template Preferences and selecting the desired folder from the list.<br>
{% endhint %}

{% hint style="warning" %}
If you delete a folder, templates inside that folder will be moved automatically to the Home folder.<br>
{% endhint %}

<br>


# Tokens (Merge Field)

Tokens helps you to generalize your template’s dynamic information and standardize the document creation process.

## What is a token?

Tokens help you to generalize your template’s dynamic information and standardize the document creation process. These tokens can automatically populate a Recipient’s Name, email address, Company name, and more.The format for token is **{{company\_name}}**, **{{client.name}}**. Think of the information that is always changing in your document, then replace that with a token.

{% hint style="warning" %}

* The token cannot contain any spaces in between.
* Special characters are not supported in tokens. Tokens only support underscores (\_) and nested tokens are separated by a dot (.)
* Token names should not start with an underscore (\_) except for predefined tokens.
* Token names cannot contain any special character except underscore(\_).
  {% endhint %}

## Token with special characters

To insert a token containing spaces and special characters, it should be enclosed with square brackets.\
For example:

1. `{{[company name]}}`
2. `{{[Discount %]}}`
3. `{{[Invoice #]}}`

Tokens with special characters can be used inside formatters.\
Examples:

1. `{{upper [First Name]}}`
2. `{{abbreviate [Full Name]}}`
3. `{{multiply [Sub Total] [Discount %]}}`

{% hint style="warning" %}
Note: Closing square bracket character `]` cannot be used as a token name.
{% endhint %}

## Predefined tokens

These tokens are predefined by Docupilot. They will automatically populate certain information specific to your document. (Ex. Current Date and Date Time with timezone)

Here is a list of all available predefined tokens:

| Token              | Description                                                                                                                                                                                                                                      |
| ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| {{\_date}}         | Displays the current date.                                                                                                                                                                                                                       |
| {{\_datetime}}     | Displays the current data and time with Timezone support.                                                                                                                                                                                        |
| {{\_auto\_number}} | Displays unique number in the document. You will need to define a starting number in [template preferences](/document-template/template-preferences#auto-number) and with each document that is generated, this number will be incremented by 1. |

## Auto Number

**Auto Number** feature allows you to generate unique number in the document. This feature will be useful if you are generating invoices, tickets, or other documents that need unique number in the document. You will need to define a starting number and with each new document generation, we will automatically increment that number. You can always reset it back to the number of your choice.

To display the Auto Number in your generated document, or in the output file name, or if you want to use it inside a delivery configuration you will need to use the token `{{_auto_number}}` in respective content/configurations. You can set the starting number in **Preferences** page -> **Advance settings**

![You can set the starting number in Preferences page -> Advance settings](/files/doq7pVVVKwG88gChPLg3)

## Conversion of token to plain text

When a token is preceded by a `'\'` (backslash) then it is considered as plain text and is printed in the output document.\
Examples:

| Input                 | Output              |
| --------------------- | ------------------- |
| `\{{name}}`           | {{name}}            |
| `\{{client.name}}`    | {{client.name}}     |
| `\{{[Company name]}}` | {{\[Company name]}} |

## Dynamic Tokens

Tokens can be generated dynamically inside a template by using the **var** helper in tandem with the **concat** helper.

| Token                                                                                                      | Value passed     | Final token                    |
| ---------------------------------------------------------------------------------------------------------- | ---------------- | ------------------------------ |
| {{var (concat Title "value")}}                                                                             | Title: Final     | {{var "Final\_value"}}         |
| <p>{{#each (group\_by firms lookup=”firmname”)}}<br>{{var (concat key "\_brand\_value")}}<br>{{/each}}</p> | firmname: Google | {{var "Google\_brand\_value"}} |


# Document Builder

## Getting Started

The Document builder gives you all the necessary tools to help you build your document in a PDF format. You can include Document Headers, Text, Images, Tables, Page Breaks, etc.

![Overview of Document Builder](/files/HHK4lF5TuEaU7HIRITFS)

## Types of Merge Fields

Docupilot supports a variety of merge fields for you to use in your document builder.

* Tokens (Merge Field)
* Condition (`if-else`)
* Loops
* Tables

Docupilot supports easy ways to insert Merge fields into your document template. **{{ }}** button on the toolbar helps you insert the merge fields.

![](/files/oEKsOruso4E2Xga9YbeF)

### Tokens (Merge Field)

These are simple words embraced in `{{}}`. When you provide your custom data, **Docupilot** will replace these fields with the data. For example **{{email}}, {{client\_name}}, {{company\_name}}**.

If you want to group your fields you can use dot(.) while defining the tokens. For example if you want to capture your client's first name & last name, you can write the tokens as **{{client.first\_name}}** and **{{client.last\_name}}**

### Previewing and Editing an HTML Template

Choose your preferred template. Upon selection, you'll be able to **Preview** it. To modify the template, click the "**Edit**" button.

<figure><img src="/files/OjM8IdLiSMr8ZVzc3tnu" alt=""><figcaption><p>Previewing and Editing an HTML Template</p></figcaption></figure>

### Condition (`if-else`)

You can use conditional statements to show or hide contents based on your data.

Conditional statements have the following syntax:

* `{{#if (a == b)}} a and b are same {{else if (c != d)}} c and d are not same {{/if}}`
* `{{#if (count > 3)}} count is greater than 3{{/if}}`
* `{{#if (item in "apple, ball")}} is apple or ball{{/if}}`

The syntax can be extended to support more complex use-cases:

* `{{#if (a == b or a == c)}} a is same as b or c {{/if}}`
* `{{#if (color == "red" or color == "blue")}}this is either red or blue{{/if}}`
* `{{#if (color == "red" and item == "ball")}}this is a red ball{{/if}}`
* `{{#if ((color == "red" and item == "ball") or (color == "blue" and item == "hat"))}}this is either a red ball or a blue hat{{/if}}`
* `{{#if (color in "red, blue")}}this is either red or blue{{/if}`
* `{{#if ("red, blue" contains color)}}this is either red or blue{{/if}}`

For example, If you are creating an invoice, you want to display CASH if the payment\_mode is cash, else if the payment\_mode is the card you want to show CARD.

```
{{#if (payment_mode == "cash")}}
CASH
{{else if (payment_mode == "card")}}
CARD
{{else}}
Please Insert preferred Mode of Payment{{/if}}
```

To use conditional statement for checking inverse or negation of a condition, use the **not** in the condition. For example, to add an instruction requesting to add secure link if payment mode is not available on record:

```
{{#if (not payment_mode)}}
Please Add your payment details in this secure link: <your secure payment link>
{{/if}}
```

You can use the conditional statements in three ways

* `if`
* `if-else`
* `if-else if`
* `if-else if-else`
* `if-else if-else if`
* `if-else if-else if-else`
* and so on

Below are a few examples:

| Example                                                                                                                                                                                                                                                                | Description                                                                                                                                                                                                                                            |
| ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| <p><code>{{#if show\_payment\_details}}</code></p><p><code>ACH to {{acNumber}}</code></p><p><code>{{/if}}</code></p>                                                                                                                                                   | prints the text `ACH to xxxxxxxxx` if `show_payment_details` is present and not `false`.                                                                                                                                                               |
| <p><code>{{#if (payment\_status == "paid")}}</code></p><p><code>payment cleared</code></p><p><code>{{/if}}</code></p>                                                                                                                                                  | prints `payment cleared` if `payment_status` equals to `"paid"` (case-sensitive)                                                                                                                                                                       |
| <p><code>{{#if (payment\_status != "paid")}}</code></p><p><code>unpaid</code></p><p><code>{{/if}}</code></p>                                                                                                                                                           | prints `unpaid` if `payment_status` not equal to `"paid"` (case-sensitive)                                                                                                                                                                             |
| <p><code>{{#if (payment\_status == "paid")}}</code></p><p><code>paid</code></p><p><code>{{else}}</code></p><p><code>unpaid</code></p><p><code>{{/if}}</code></p>                                                                                                       | prints `paid` if `payment_status` equals to `"paid"` otherwise prints `unpaid`                                                                                                                                                                         |
| <p><code>{{#if (payment\_status == "paid")}}</code></p><p><code>paid</code></p><p><code>{{else if (payment\_status == "initiated")}}</code></p><p><code>payment initiated</code></p><p><code>{{else}}</code></p><p><code>pending</code></p><p><code>{{/if}}</code></p> | <p>prints <code>paid</code> if <code>payment\_status</code> equals to <code>"paid"</code></p><p>prints <code>payment initiated</code> if <code>payment\_status</code> equals to <code>initiated</code></p><p>otherwise prints <code>pending</code></p> |
| <p><code>{{#if (price > 1000)}}</code></p><p><code>good deal</code></p><p><code>{{/if}}</code></p>                                                                                                                                                                     | prints the text `good deal` if price is greater than 1000                                                                                                                                                                                              |
| <p><code>{{#if (price >= 1000)}}</code></p><p><code>decent deal</code></p><p><code>{{/if}}</code></p>                                                                                                                                                                  | prints text `decent deal` if price is greater than or equal to 1000                                                                                                                                                                                    |
| <p><code>{{#if (price < 1000)}}</code></p><p><code>small deal</code></p><p><code>{{/if}}</code></p>                                                                                                                                                                    | prints text `small deal` If price less than 1000                                                                                                                                                                                                       |
| <p><code>{{#if (price <= 1000)}}</code></p><p><code>okay-ish deal</code></p><p><code>{{/if}}</code></p>                                                                                                                                                                | prints text `okay-ish deal` If price less than or equal to 1000                                                                                                                                                                                        |
| <p><code>{{#if (payment\_message contains "paid")}}</code></p><p><code>Payment is cleared</code><br><code>{{/if}}</code></p>                                                                                                                                           | prints `Payment is cleared` if `payment_message` contains the text `paid` *(for example, `this invoice has been paid` contains the text `paid` in it)*                                                                                                 |
| <p><code>{{#if (payment\_message not\_contains "paid")}}</code></p><p><code>Payment is due</code><br><code>{{/if}}</code></p>                                                                                                                                          | prints `Payment is due` if `payment_message` does not contain the text `paid` *(for example, `this invoice is not cleared` does not contain the text `paid` in it)*                                                                                    |
| <p><code>{{#if (status == "open" or status == "on-hold")}}</code></p><p><code>Payment is pending</code></p><p><code>{{/if}}</code></p>                                                                                                                                 | prints `Payment is pending` if `status` is `open` OR `on-hold`                                                                                                                                                                                         |
| <p><code>{{#if (status == "open" or status == "on-hold" or status == "under review")}}</code></p><p><code>Payment is pending</code></p><p><code>{{/if}}</code></p>                                                                                                     | prints `Payment is pending` if `status` is `open` OR `on-hold` OR `under review`                                                                                                                                                                       |
| <p><code>{{#if (status != "open" and status != "on-hold")}}</code></p><p><code>Payment is not pending</code></p><p><code>{{/if}}</code></p>                                                                                                                            | prints `Payment is not pending` if `status` is not `open` AND not `on-hold`                                                                                                                                                                            |
| <p><code>{{#if (status == "open" and priority == "high")}}</code></p><p><code>High priority open task</code></p><p><code>{{/if}}</code></p>                                                                                                                            | prints `High priority open task` if `status` is `open` AND if `priority` is `high`                                                                                                                                                                     |
| <p><code>{{#if (payment\_status != "paid")}}Please Clear the Dues within 30 days</code></p><p><code>{{/if}}</code></p>                                                                                                                                                 | prints `Please Clear the Dues within 30 days` if the `payment_status` is not equal to `paid`                                                                                                                                                           |
| <p><code>{{#if (status in "open,pending")}}In Progress... Please stay tuned for further updates.</code></p><p><code>{{/if}}</code></p>                                                                                                                                 | prints `In Progress... Please stay tuned for further updates.` if `status` is sub-string of `"open,pending"`                                                                                                                                           |

{% hint style="info" %}
The syntax for `if` statements used without any operators is as follows:

`{{#if myToken}}...{{/if}}`
{% endhint %}

#### Hiding Empty Sections & Lines

In the following example, when the `address` field has a value, it gives desired outcome. If the address is empty, it leaves an empty line in the output.

```
{{customer_name}},
{{#if address}}{{address}},{{/if}}
{{city}}, {{country}}
```

<table><thead><tr><th>Data</th><th>Output</th></tr></thead><tbody><tr><td><pre><code>customer_name = John Doe
street = WinWood St.
city = NY
country = US
</code></pre></td><td><pre><code>John Doe,
WinWood St.,
NY, US
</code></pre></td></tr><tr><td><pre><code>customer_name = John Doe
city = NY
country = US
</code></pre></td><td><pre><code>John Doe,
NY, US
</code></pre></td></tr></tbody></table>

To hide empty lines, we should open the `if` condition in previous line or close it in next line. Here are examples on how the output will look like when street address is passed and when it is not:

<table><thead><tr><th>Syntax</th><th>Data</th><th>Output</th></tr></thead><tbody><tr><td><pre><code>{{customer_name}},{{#if street}}
{{street}},{{/if}}
{{city}}, {{country}}
</code></pre></td><td><pre><code>customer_name = John Doe
city = NY
country = US
</code></pre></td><td><pre><code>John Doe,
NY, US
</code></pre></td></tr><tr><td><pre><code>{{customer_name}},{{#if street}}
{{street}},{{/if}}
{{city}}, {{country}}
</code></pre></td><td><pre><code>customer_name = John Doe
street = WinWood St.
city = NY
country = US
</code></pre></td><td><pre><code>John Doe,
WinWood St.,
NY, US
</code></pre></td></tr><tr><td><pre><code>{{customer_name}},
{{#if street}}{{street}},
{{/if}}{{city}}, {{country}}
</code></pre></td><td><pre><code>customer_name = John Doe
city = NY
country = US
</code></pre></td><td><pre><code>John Doe,
NY, US
</code></pre></td></tr><tr><td><pre><code>{{customer_name}},
{{#if street}}{{street}},
{{/if}}{{city}}, {{country}}
</code></pre></td><td><pre><code>customer_name = John Doe
street = WinWood St.
city = NY
country = US
</code></pre></td><td><pre><code>John Doe,
WinWood St.,
NY, US
</code></pre></td></tr></tbody></table>

### Lists (Loops)

Lists are used when you want to print a list of items in your document. Docupilot supports three types of loops in document builder.

* Simple List
* Advanced List
* Bulleted List
* Numbered List

#### Simple Loop

```
{{#each items}}
{{this}} 
{{/each}}
```

{% code title="Output" %}

```
Apple
Orange
Strawberry
```

{% endcode %}

#### Advanced Loop

You can use advanced loop, if you want to print list of items like line items. Think of this as a sub-form with multiple rows in your main form.

```
{{#each line_items}}
{{name}} ${{price}}
{{/each}}
```

{% code title="Output" %}

```
Iphone6 $799
Iphone7 $899
Iphone8 $999
```

{% endcode %}

### Bulleted List

```
• {{#list services}}{{this}}{{/list}}
```

### Numbered List

```
1. {{#list services}}{{this}}{{/list}}
```

{% hint style="info" %}
Please use bullet insertion buttons from editor's tools pane for Bulleted and Numbered lists to work
{% endhint %}

### Tables

A table is similar to an advanced list, but the data will be rendered in a table. For example, if you want to generate a invoice, you may want display a table with all the line items.

<figure><img src="/files/LmczJNAzT1U7zgFpTFy3" alt=""><figcaption></figcaption></figure>

#### Hiding Empty Tables

You can use IF condition to hide empty tables, you should wrap the entire table inside a IF condition.

```
{{#if line_items}}
{{!...INSERT THE ABOVE TABLE IN THIS LINE...}}
{{/if}}
```

#### Filtering rows in a Table based on empty column value

<figure><img src="/files/9JVJqkCWl5HLzeTUey98" alt=""><figcaption></figcaption></figure>

If the value for Quantity is empty in any row, it will be skipped in the output table.

#### Filtering rows in a Table based on a column value

<figure><img src="/files/o8372J1JzgORD8j9bmM8" alt=""><figcaption></figcaption></figure>

If the value for name is Iphone in any row, it will be skipped in the output table.

## Lookbacks

Lookbacks allow you to access parent context within a nested context. For example, you can access a variable that is outside the loop from inside it.

Format: **`{{../token_name}}`**

For example, if your input data for generating an invoice contains of `CustomerName`, `DiscountPercentage` and `LineItems` and you want to render `DiscountPercentage` against each line item, to access it you need to use **{{../DiscountPercentage}}** inside the loop **{{#each LineItems}} ... {{/each}}**

```
                                Sales Invoice

Customer: {{CustomerName}}
Membership Discount: {{DiscountPercentage}} %

{{#each LineItems}}
{{ProductName}} | {{Quantity}} | {{UnitPrice}} | {{../DiscountPercentage}}%
{{/each}}

Thank you for your business
```

<div><figure><img src="/files/SH2BEnbMprFFLww5AkCf" alt=""><figcaption><p>Example Sales Invoice Template</p></figcaption></figure> <figure><img src="/files/pQCoqFUhRFjks6GodX36" alt=""><figcaption><p>Example Sales Invoice Template - Output</p></figcaption></figure></div>

## Inserting a dynamic image

This will be helpful if you want to insert a dynamic image in the document.

Format : **{{insert\_image image1 width=width height=height max\_width=max\_width max\_height=max\_height}}**

* `width` (optional): Desired image width
* `height` (optional): Desired image height
* `max_width` (optional): Desired maximum width of the image
* `max_height` (optional): Desired maximum height of the image

**Example Usage**

| Syntax                                         | Description                                                                                                                                                                           |
| ---------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `{{insert_image image1 width=300 height=200}}` | The image inserted will be 300px wide and 200px tall                                                                                                                                  |
| `{{insert_image image1 width=300}}`            | Inserted image will be 300px wide, height will be auto adjusted based on the original image's aspect ratio. For example if original image is 600x500, inserted image will be 300x250. |
| `{{insert_image image1 height=300}}`           | Inserted image will be 300px tall, width will be auto adjusted based on the original image's aspect ratio.                                                                            |

### Constraining Image Dimensions

Use the `max_width` and `max_height` parameters to limit image dimensions.

**Examples:**

| Syntax                                                 | Description                                                                                                                                                                                                                                                                              |
| ------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `{{insert_image image1 max_width=300 max_height=300}}` | The image will be resized to fit into a 350x350 box. Aspect ratio will be maintained. For example, if the original image is 900x600, the inserted image will be 300x200                                                                                                                  |
| `{{insert_image image1 max_height=300}}`               | The image will be resized ensuring the height doesn't go beyond 300px. Aspect ratio will be maintained. For example, if the original image is 900x600, the inserted image will be 450x300                                                                                                |
| `{{insert_image image1 max_width=300}}`                | The image will be resized ensuring the width doesn't go beyond 300px. Aspect ratio will be maintained. For example, if the original image is 900x600, the inserted image will be 300x200                                                                                                 |
| `{{insert_image image1 width=300 max_height=500}}`     | The image width will be set to 300px. If the resulting height exceeds 500px, the image will be scaled down proportionally so that the height does not exceed 500 px while maintaining its aspect ratio. For example, if original image is 400x1000, the inserted image will be 200x500   |
| `{{insert_image image1 height=500 max_width=400}}`     | The image height will be set to 500px. If the resulting width exceeds 400px, the image will be scaled down proportionally so that the width does not exceed 400px while maintaining its aspect ratio. For example, if the original image is 1200x900, the inserted image will be 400x300 |

{% hint style="info" %}
The image URL need to be either publicly accessible so Docupilot can download and insert it in the document.

\
If you want to send only authenticated images, link your storage account like google drive, one drive, etc from **Settings > Linked Accounts** and enable **Use For Images** option if available. All image links sent to Docupilot will be downloaded using that authenticated account.
{% endhint %}

## Inserting a QR Code

This will be helpful if you want to insert a dynamic QR code from your data in the document.

Format: **{{insert\_qr url size="qr\_size" margin="qr\_margin" color="qr\_color(in hex values)" bg\_color="color\_code(in hex values)" branding\_url="image\_url" branding\_ratio="ratio\_value(between 1 to 10)"}}**

| Order | Name            | Description                                                                                                               | Mandatory                     |
| ----- | --------------- | ------------------------------------------------------------------------------------------------------------------------- | ----------------------------- |
| 1     | size            | QR Image size                                                                                                             | <p>No<br>Default: 100</p>     |
| 2     | margin          | QR Image height (px)                                                                                                      | <p>No</p><p>Default: 4</p>    |
| 3     | color           | Color of the QR                                                                                                           | <p>No<br>Default: #000000</p> |
| 4     | bg\_color       | Background Color for QR                                                                                                   | <p>No<br>Default: #FFFFFF</p> |
| 5     | branding\_url   | Inserts an image into the QR code for branding using a publicly accessible image URL.                                     | No                            |
| 6     | branding\_ratio | Set the size of the QR code’s branding image on a scale from 1 to 10, where 10 is the smallest size and 1 is the largest. | <p>No<br>Default: 4</p>       |

Example: `{{insert_qr url size="100"}}`

![100 X 100 with default margin 4 & value https://docupilot.com/](/files/TPGeDyVW3qvK9Z9aAP1y)

Example: `{{insert_qr url size="100" margin="3" bg_color="#3399FF"}}`

<figure><img src="/files/I4ayeEs59Kk42nyolKwx" alt=""><figcaption><p>100 X 100 with margin 3 &#x26; value https://docupilot.com</p></figcaption></figure>

Example: `{{insert_qr url margin="7" color="#FFFFFF" bg_color="#000000"}}`

<figure><img src="/files/2RaiYWeQZVDx432GuxBQ" alt=""><figcaption><p>Qr having margin 7 with white color and black background</p></figcaption></figure>

Example: `{{insert_qr url color="0000FF"}}`

<figure><img src="/files/dgPvBXpDwwOG1e91vByy" alt=""><figcaption><p>QR with color blue &#x26; value <a href="https://docupilot.com/">https://docupilot.app/</a></p></figcaption></figure>

Example: `{{insert_qr url margin="1" color="#FFFFFF" bg_color="#000000"}}`

<div align="center"><figure><img src="/files/Rf10IhyoUibdixzldrLB" alt="QR code example for background color" width="218"><figcaption><p>QR with white color and black background</p></figcaption></figure></div>

{% hint style="info" %}
The color of the QR should be given in hex coding only.
{% endhint %}

Example: `{{insert_qr url margin="1" color="#FFFFFF" bg_color="#000000" branding_url=image_url branding_ratio="4"}}`

<figure><img src="/files/Df8i10oaAi4WvWTXk8XB" alt="" width="226"><figcaption><p>QR code with branding image</p></figcaption></figure>

{% hint style="info" %}
The image URL need to be publicly accessible so we can download and insert it in the document.
{% endhint %}

#### Inserting a Barcode with a Transparent Background

This is useful if you need to insert a barcode with a transparent background into your document.

Example: `{{insert_qr url color="#FFFFFF" bg_color=”ffffff00”}}`

<figure><img src="/files/L2Q9xicgqCCbfjDIZD6r" alt="" width="312"><figcaption><p>QR code with transparent background</p></figcaption></figure>

## Inserting a Barcode

This will be helpful if you want to insert a barcode from your data in the document.

Format: **`{{insert_barcode name format="barcode_format" bar_width="width" height="height" margin="barcode_margin" color="color" background_color="bg_color" display_value=true/false}}`**

| Order | Name            | Description                                           | Mandatory | Default Value |
| ----- | --------------- | ----------------------------------------------------- | --------- | ------------- |
| 1     | barcode\_format | <p>Barcode formats<br></p><p>CODE128</p><p>CODE39</p> | No        | **CODE128**   |
| 2     | bar\_width      | The bar\_width option is the width of a single bar.   | No        | **2**         |
| 3     | height          | The height of the barcode.                            | No        | **100**       |
| 4     | barcode\_margin | Set the space margin around the barcode               | No        | **10**        |
| 4     | color           | Set the color of the bars and the text.               | No        | **#000**      |
| 5     | bg\_color       | Set the background of the barcode.                    | No        | **#fff**      |
| 6     | label           | Displaying the label below the barcode                | No        | **true**      |

\
Example: `{{insert_barcode item_name}}`

![CODE128 Format](/files/-M5InmpRu5KRxIxSN7A8)

Example: `{{insert_barcode name format="CODE39"}}`

![CODE39 Format](/files/-M5Ip6uYYG2T-aBNGg0f)

Example: `{{insert_barcode name bar_width="3"}}`

![Code 128 Format Barcode with width 3](/files/-M5IpSzbRNORnfnnu24S)

Example: `{{insert_barcode name format="CODE128" bar_width="2" height="25"}}`

![](/files/-M5IpxbGF2VSIi25Za3u)

Example: `{{insert_barcode name format="CODE128" bar_width="2" display_value= false}}`

![](/files/qvzf90KqxuRNuyS1sCp1)

Example: `{{insert_barcode name height="50" margin="10"}}`

<figure><img src="/files/CvDJHZGuLRkPbvIjfTIe" alt=""><figcaption><p>Code 128 barcode with height 50 px and margin 10</p></figcaption></figure>

Example: `{{insert_barcode name height="50" color="FF0000"}}`

<figure><img src="/files/Eo2KWGm6r9kj69Gk3GVw" alt=""><figcaption><p>Code 128 barcode with height 50 px and red in color</p></figcaption></figure>

#### Inserting a Barcode with a Transparent Background

This is useful if you need to insert a barcode with a transparent background into your document.

Format: `{{insert_barcode name bg_color='#ffffff00'}}`

<figure><img src="/files/gtli0TKoCbzzJbzMLuK9" alt="" width="375"><figcaption><p>Barcode with Trasnparent background</p></figcaption></figure>

## Inserting Google Maps

This will be helpful if you want to insert Google Maps from your data in the document.

Format: **{{insert\_map Address width="width" height="height" map\_type="maptype"}}**

| Order | Name     | Description                                                                   | Mandatory | Default Value |
| ----- | -------- | ----------------------------------------------------------------------------- | --------- | ------------- |
| **1** | width    | Width of the image (px)                                                       | No        | 600           |
| 2     | height   | Height of the image (px)                                                      | No        | 300           |
| 3     | map type | <p>Map types<br></p><p>roadmap</p><p>satellite</p><p>hybrid</p><p>terrain</p> | No        | **roadmap**   |
| 4     | Zoom     | Zoom into the image                                                           | No        | 13            |

Example: **{{insert\_map Location width="500" height="500" map\_type="roadmap"}}**

![Location Value is Manchester](/files/-LjqNJ8CNhiKfWOErv08)

Example: **{{insert\_map Location map\_type="roadmap" zoom= "20"}}**

<figure><img src="/files/A7X53NTyJ3b4voMwnd5E" alt=""><figcaption><p><strong>Location value is Manchester, with map type as road map and a Zoom set to 20</strong></p></figcaption></figure>

Example: **{{insert\_map Location height="300" zoom= "5"}}**

<figure><img src="/files/MXWACpdvfGujDDOsbCPr" alt=""><figcaption><p><strong>Location value is Manchester with height as 300 px and zoom set to 5</strong></p></figcaption></figure>

## Grid Helper

The Grid Helper will render the list input in a grid format, with specified column size.

Syntax: `{{#grid items col_size=3}}`\
`{{@item1.title}}{{@item2.title}}{{@item3.title}}`\
`{{/grid}}`

Example :

<figure><img src="/files/vah6VeeIoDyYaV2mNnwZ" alt=""><figcaption><p>Grid helper</p></figcaption></figure>

## Page Break

If you want to format your document into multiple pages properly, you can use the page break option. The content after the page break will begin in a new page.

![](/files/PhSt17v9F8h3xmacGBrj)

## Google Fonts

Docupilot supports all Google fonts to help you maintain your branding. Once you finish building your document, you will need to add a small code snippet by clicking on the source button in the document editor. You will need to change the font family accordingly to the choice of your fonts. You can find the font family here <https://fonts.google.com/>.

```css
<style type="text/css">body{
 font-family: 'Tangerine', serif;
}
</style>
```

![Google Fonts](/files/A7Z7xCArMeCWL1vgAXEN)

{% hint style="warning" %}
Sometimes the document builder will not show the specified font but the document will be generated in the specified font.
{% endhint %}

## Page Margins

Docupilot allows you to adjust the size of the top, bottom, left, right page margins in inches. You can set the margins in **preferences** -> **Advance settings**.

{% hint style="info" %}
The default margin is 0.4 inches on all sides. You can also set it to zero.
{% endhint %}

![Page Margins](/files/2K1XAtIKOt9gHHj7zTQJ)

## Comments

You can add comments in the document template to help your future editors. The comments will be removed in the output document.

{% hint style="success" %}
Comments Syntax : **{{!Your comments here}}**
{% endhint %}


# AI-Powered Template Builder

Take advantage of AI to build templates faster and easier

Docupilot’s AI Template Builder helps you create document templates effortlessly using simple prompts. Instead of manually adding text, merge fields, and formatting, the “Build with AI” option automates the process, saving time and effort.

> *For now this feature is available only with Online builder, we are soon adding these capabilities to Word document templates.*

<figure><img src="/files/cYKjvng8G2elSIzTV9cs" alt=""><figcaption><p>Build with AI option</p></figcaption></figure>

#### How to Create a Template Using AI

* From your dashboard, click on the "**Create Template"** > "**Build with AI**"
* You will be prompted to enter a **Template Name** and a **Template Description**. The description should suit your template accurately as this will become part of the input passed along with the prompt to our AI engine. For example, if you are creating an employment agreement, you can add the following:
  * Template Name: "Employment Agreement"
  * Template Description: "Agreement between new hires and \<My Company Inc.,> headquartered at 213 street, Brooklyn, NY"
* Click "**Create** **Template"** to continue.
* On the next page, you will see auto-generated prompt suggestions and an input box. Upon selecting an auto-generated prompt, it will be filled in the input box allowing to make changes to the prompt. Make sure the prompt is detailed enough to capture your requirements to get a more desirable outcome.
* Click **Generate**. Our AI engine will create a structured template based on your input. You can then review the template and make any necessary adjustments, such as modifying text, adding merge fields, or refining formatting.

<figure><img src="/files/T82SuzNxvlvhnB3GJuEu" alt=""><figcaption><p>Create template using AI</p></figcaption></figure>

For example, if you want to include your Store Name and Address, select the section in your template where these details are to be added, and explain the changes needed for this section and hit send. Template content will be updated accordingly.

<figure><img src="/files/gzvh81kxjSxVcsCNR6wX" alt=""><figcaption><p>Modifying the template using AI</p></figcaption></figure>


# Word Document (DOCX) & PowerPoint (PPTX)

This section helps you to generate dynamic Word documents and PowerPoint.

## Getting Started

You can use Word Documents or PowerPoint ( **.docx, .pptx** is the supported format ) as your document template, you can build your document in Ms Word, Google Docs or Zoho Writer and then upload it to Docupilot as a .docx or .pptx file. If you are already using a word document for your business, replace the information that will change like client company name, client name to {{client.name}}, {{client.company}}.

<div align="left"><figure><img src="/files/sAOOSL2D49fZJBSzk8Hl" alt="Word (.docx) template overview" width="563"><figcaption><p>Word (.docx) template overview</p></figcaption></figure></div>

### Uploading DOCX

<div align="left"><img src="/files/7L1R3jM03FFvV1t1OTcq" alt="" width="563"></div>

### Updating DOCX

You can update your Word Document templates in any of the following ways:

**Option 1: Using the Microsoft Word Add-In**\
With the Microsoft Word Add-In, you can upload your templates directly from Microsoft Word to Docupilot. For installation and usage refer to our [Word Add-In Guide](/integrations/microsoft-word-add-in#installing-the-docupilot-word-add-in-beta).

**Option 2: Manual Update**\
Alternatively, you can edit your template in any document editor (like Microsoft Word, Google Docs, or Zoho Writer), save it as a .docx file, and upload it manually to Docupilot.

<div align="left"><img src="/files/sjubgRVpCMKx1kwTfCVj" alt="" width="563"></div>

{% hint style="warning" %}
You cannot modify your Word Document template inside Docupilot.
{% endhint %}

## Types of Merge Fields <a href="#types-of-merge-fields" id="types-of-merge-fields"></a>

Docupilot supports a variety of merge fields for you to use.

* Tokens (Merge Field)
* Conditions (`if-else`)
* Loops
* Tables

### Tokens (Merge Field) <a href="#tokens-merge-field" id="tokens-merge-field"></a>

Tokens are placeholders that Docupilot replaces with your data when generating documents.

Tokens are placeholders enclosed within double curly brackets `{{ }}` that Docupilot replaces with your custom data when generating documents.

**Basic Tokens**

Each token corresponds to a specific data field. For example:

* `{{email}}` → Replaced with the email address.
* `{{clientName}}` → Replaced with the client’s name.
* `{{company_name}}` → Replaced with the company name.

**Nested Tokens (to handle grouped data)**

You can structure data hierarchically using dot notation. This is useful when working with related fields within an entity. For example:

* `{{client.first_name}}` → Replaced with the client’s first name.
* `{{client.last_name}}` → Replaced with the client’s last name.

### Condition (`if-else`)

You can use conditional statements to show or hide contents based on your data. For example, If you are creating an invoice, you want to display CASH if the payment\_mode is cash, else if the payment\_mode is the card you want to show CARD.

{% code overflow="wrap" %}

```
{{#if (payment_mode == "cash")}}
CASH
{{else if (payment_mode == "card")}}
CARD
{{else}}
Please Insert preferred Mode of Payment{{/if}}
```

{% endcode %}

To use conditional statement for checking inverse or negation of a condition, use the **not** in the condition. For example, to add an instruction requesting to add secure link if payment mode is not available on record:

{% code overflow="wrap" %}

```
{{#if (not payment_mode)}}
Please Add your payment details in this secure link: <your secure payment link>
{{/if}}
```

{% endcode %}

You can use the conditional statements in three ways

* `if`
* `if-else`
* `if-else if`
* `if-else if-else`
* `if-else if-else if`
* `if-else if-else if-else`
* and so on

Below are a few examples:

| Example                                                                                                                                                                                                                                                                | Description                                                                                                                                                                                                                                            |
| ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| <p><code>{{#if show\_payment\_details}}</code></p><p><code>ACH to {{acNumber}}</code></p><p><code>{{/if}}</code></p>                                                                                                                                                   | prints the text `ACH to xxxxxxxxx` if `show_payment_details` is present and not `false`.                                                                                                                                                               |
| <p><code>{{#if (payment\_status == "paid")}}</code></p><p><code>payment cleared</code></p><p><code>{{/if}}</code></p>                                                                                                                                                  | prints `payment cleared` if `payment_status` equals to `"paid"` (case-sensitive)                                                                                                                                                                       |
| <p><code>{{#if (payment\_status != "paid")}}</code></p><p><code>unpaid</code></p><p><code>{{/if}}</code></p>                                                                                                                                                           | prints `unpaid` if `payment_status` not equal to `"paid"` (case-sensitive)                                                                                                                                                                             |
| <p><code>{{#if (payment\_status == "paid")}}</code></p><p><code>paid</code></p><p><code>{{else}}</code></p><p><code>unpaid</code></p><p><code>{{/if}}</code></p>                                                                                                       | prints `paid` if `payment_status` equals to `"paid"` otherwise prints `unpaid`                                                                                                                                                                         |
| <p><code>{{#if (payment\_status == "paid")}}</code></p><p><code>paid</code></p><p><code>{{else if (payment\_status == "initiated")}}</code></p><p><code>payment initiated</code></p><p><code>{{else}}</code></p><p><code>pending</code></p><p><code>{{/if}}</code></p> | <p>prints <code>paid</code> if <code>payment\_status</code> equals to <code>"paid"</code></p><p>prints <code>payment initiated</code> if <code>payment\_status</code> equals to <code>initiated</code></p><p>otherwise prints <code>pending</code></p> |
| <p><code>{{#if (price > 1000)}}</code></p><p><code>good deal</code></p><p><code>{{/if}}</code></p>                                                                                                                                                                     | prints the text `good deal` if price is greater than 1000                                                                                                                                                                                              |
| <p><code>{{#if (price >= 1000)}}</code></p><p><code>decent deal</code></p><p><code>{{/if}}</code></p>                                                                                                                                                                  | prints text `decent deal` if price is greater than or equal to 1000                                                                                                                                                                                    |
| <p><code>{{#if (price < 1000)}}</code></p><p><code>small deal</code></p><p><code>{{/if}}</code></p>                                                                                                                                                                    | prints text `small deal` If price less than 1000                                                                                                                                                                                                       |
| <p><code>{{#if (price <= 1000)}}</code></p><p><code>okay-ish deal</code></p><p><code>{{/if}}</code></p>                                                                                                                                                                | prints text `okay-ish deal` If price less than or equal to 1000                                                                                                                                                                                        |
| <p><code>{{#if (payment\_message contains "paid")}}</code></p><p><code>Payment is cleared</code><br><code>{{/if}}</code></p>                                                                                                                                           | prints `Payment is cleared` if `payment_message` contains the text `paid` *(for example, `this invoice has been paid` contains the text `paid` in it)*                                                                                                 |
| <p><code>{{#if (payment\_message not\_contains "paid")}}</code></p><p><code>Payment is due</code><br><code>{{/if}}</code></p>                                                                                                                                          | prints `Payment is due` if `payment_message` does not contain the text `paid` *(for example, `this invoice is not cleared` does not contain the text `paid` in it)*                                                                                    |
| <p><code>{{#if (status == "open" or status == "on-hold")}}</code></p><p><code>Payment is pending</code></p><p><code>{{/if}}</code></p>                                                                                                                                 | prints `Payment is pending` if `status` is `open` OR `on-hold`                                                                                                                                                                                         |
| <p><code>{{#if (status == "open" or status == "on-hold" or status == "under review")}}</code></p><p><code>Payment is pending</code></p><p><code>{{/if}}</code></p>                                                                                                     | prints `Payment is pending` if `status` is `open` OR `on-hold` OR `under review`                                                                                                                                                                       |
| <p><code>{{#if (status != "open" and status != "on-hold")}}</code></p><p><code>Payment is not pending</code></p><p><code>{{/if}}</code></p>                                                                                                                            | prints `Payment is not pending` if `status` is not `open` AND not `on-hold`                                                                                                                                                                            |
| <p><code>{{#if (status == "open" and priority == "high")}}</code></p><p><code>High priority open task</code></p><p><code>{{/if}}</code></p>                                                                                                                            | prints `High priority open task` if `status` is `open` AND if `priority` is `high`                                                                                                                                                                     |
| <p><code>{{#if (payment\_status != "paid")}}Please Clear the Dues within 30 days</code></p><p><code>{{/if}}</code></p>                                                                                                                                                 | prints `Please Clear the Dues within 30 days` if the `payment_status` is not equal to `paid`                                                                                                                                                           |
| <p><code>{{#if (status in "open,pending")}}In Progress... Please stay tuned for further updates.</code></p><p><code>{{/if}}</code></p>                                                                                                                                 | prints `In Progress... Please stay tuned for further updates.` if `status` is sub-string of `"open,pending"`                                                                                                                                           |

#### Hiding Empty Sections & Lines

In the following example, when the `address` field has a value, it gives desired outcome. If the address is empty, it leaves an empty line in the output.

{% code overflow="wrap" %}

```
{{customer_name}},
{{#if address}}{{address}},{{/if}}
{{city}}, {{country}}
```

{% endcode %}

<table><thead><tr><th>Data</th><th width="228.4296875">Output</th></tr></thead><tbody><tr><td><pre><code>customer_name = John Doe
city = NY
country = US
</code></pre></td><td><pre><code>John Doe,
NY, US
</code></pre></td></tr><tr><td><pre><code>customer_name = John Doe
street = WinWood St.
city = NY
country = US
</code></pre></td><td><pre><code>John Doe,
WinWood St.,
NY, US
</code></pre></td></tr></tbody></table>

To hide empty lines, we should open the `if` condition in previous line or close it in next line. Here are examples on how the output will look like when street address is passed and when it is not:

<table><thead><tr><th>Syntax</th><th>Data</th><th>Output</th></tr></thead><tbody><tr><td><pre><code>{{customer_name}},{{#if street}}
{{street}},{{/if}}
{{city}}, {{country}}
</code></pre></td><td><pre><code>customer_name = John Doe
city = NY
country = US
</code></pre></td><td><pre><code>John Doe,
NY, US
</code></pre></td></tr><tr><td><pre><code>{{customer_name}},{{#if street}}
{{street}},{{/if}}
{{city}}, {{country}}
</code></pre></td><td><pre><code>customer_name = John Doe
street = WinWood St.
city = NY
country = US
</code></pre></td><td><pre><code>John Doe,
WinWood St.,
NY, US
</code></pre></td></tr><tr><td><pre><code>{{customer_name}},
{{#if street}}{{street}},
{{/if}}{{city}}, {{country}}
</code></pre></td><td><pre><code>customer_name = John Doe
city = NY
country = US
</code></pre></td><td><pre><code>John Doe,
NY, US
</code></pre></td></tr><tr><td><pre><code>{{customer_name}},
{{#if street}}{{street}},
{{/if}}{{city}}, {{country}}
</code></pre></td><td><pre><code>customer_name = John Doe
street = WinWood St.
city = NY
country = US
</code></pre></td><td><pre><code>John Doe,
WinWood St.,
NY, US
</code></pre></td></tr></tbody></table>

{% hint style="warning" %}

#### Avoid Placing {{/if}} and Section Break on the Same Line

If you are using section breaks in your Word template, avoid placing `{{#if ...}}` or `{{/if}}` and the section break on the same line. Doing so may cause headers or footers from the next section to appear in the previous section.

**Why this happens:**

Based on how the if condition is evaluated, it may remove the section break altogether thereby applying the same headers/footers/styles to both the sections.

**How to avoid this from happening:**

* Do not place the opening or closing `if` and the section break on the same line.
* Instead, add the section break on a new line before or after the `if` block like in the examples below:

*Adding if condition after the section break*

```
<insert section break here>
{{#if condition}}
...content...
{{/if}}
```

-or-

*Adding if condition before the section break*

```
{{#if condition}}
...content...
{{/if}}
<insert section break here>
```

{% endhint %}

### Lists (Loops) <a href="#loops-list" id="loops-list"></a>

Lists are used when you want to print a list of items in your document.

* Simple List
* Advanced List
* Bulleted List
* Numbered List

#### Simple List <a href="#simple-loop-list" id="simple-loop-list"></a>

{% code overflow="wrap" %}

```
{{#each items}}
{{this}}
{{/each}}
```

{% endcode %}

{% code overflow="wrap" %}

```
Apple
Orange
Strawberry
```

{% endcode %}

#### Advanced List <a href="#complex-loop-list" id="complex-loop-list"></a>

You can use an advanced loop if you want to print list of items like line items. Think of this as a subform with multiple rows in your main form.

```
{{#each line_items}}
{{name}} ${{price}}
{{/each}}
```

{% code overflow="wrap" %}

```
Iphone6 $799
Iphone7 $899
Iphone8 $999
```

{% endcode %}

### Bulleted List

<div align="left"><img src="/files/-LfyxD-XDVHpdmRw6lVq" alt="Bulleted List" width="563"></div>

#### Nested Bullets:

Bulleted lists can be nested so as to have a multi layered information.

For example, below syntax demonstrates nested list up to 2 levels.

<div align="left"><img src="/files/-MX6wpiQ0ZPcaLGGl3nD" alt="Nested Bullet List 1" width="563"></div>

{% hint style="info" %}
Note : The second level will be printed only when `products` has at least one entry.
{% endhint %}

Similarly, for a nested list up to 3 levels.

<div align="left"><img src="/files/-MX6xLjFLSf9DRct_ORA" alt="Nested Bullet List 2" width="563"></div>

{% hint style="info" %}
Note : In the above example second and third levels will be printed only when `items` and `sub_categories` have at least one entry.
{% endhint %}

{% hint style="info" %}
Note : The above syntax can be extended for multiple levels based on requirement.
{% endhint %}

### Numbered List

<div align="left"><img src="/files/-LfyxI4N9uO64-R32NFU" alt="Numbered List" width="563"></div>

### Tables <a href="#tables" id="tables"></a>

Tables are similar to Complex list, but the data will be rendered in a table. Example if you want to generate a invoice, you may want display a table with all the line items.

<div align="left"><img src="/files/-LMwUlijwo0K6BPkDDid" alt="Tables Syntax" width="563"></div>

#### Hiding Empty Tables <a href="#hiding-empty-tables" id="hiding-empty-tables"></a>

You can use IF condition to hide empty tables, you should wrap the entire table inside a IF condition.

{% code overflow="wrap" %}

```
{{#if line_items}}
{{!...INSERT THE ABOVE TABLE IN THIS LINE...}}
{{/if}}
```

{% endcode %}

#### Filtering rows in a Table based on empty column value

<div align="left"><img src="/files/-LfyxmsAz8ZpgBermb66" alt="If the value for name is empty in any row, it will be skipped in the output table." width="563"></div>

#### Filtering rows in a Table based on a column value

<div align="left"><img src="/files/-LfyxvtCYMeY9kPoN4LH" alt="If the value for name is Iphone in any row, it will be skipped in the output table." width="563"></div>

## Inserting a dynamic image

This will be helpful if you want to insert dynamic image in the document.

Format : **{{insert\_image image1 width=width height=height max\_width=max\_width max\_height=max\_height}}**

* `width` (optional): Desired image width
* `height` (optional): Desired image height
* `max_width` (optional): Desired maximum width of the image
* `max_height` (optional): Desired maximum height of the image

**Example Usage**

<table><thead><tr><th valign="middle">Syntax</th><th>Description</th></tr></thead><tbody><tr><td valign="middle"><code>{{insert_image image1 width=300 height=200}}</code></td><td>The image inserted will be 300px wide and 200px tall</td></tr><tr><td valign="middle"><code>{{insert_image image1 width=300}}</code></td><td>Inserted image will be 300px wide, height will be auto adjusted based on the original image's aspect ratio. For example if original image is 600x500, inserted image will be 300x250.</td></tr><tr><td valign="middle"><code>{{insert_image image1 height=300}}</code></td><td>Inserted image will be 300px tall, width will be auto adjusted based on the original image's aspect ratio.</td></tr></tbody></table>

### Constraining Image Dimensions

Use the `max_width` and `max_height` parameters to limit image dimensions.

**Examples:**

| Syntax                                                 | Description                                                                                                                                                                                                                                                                              |
| ------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `{{insert_image image1 max_width=300 max_height=300}}` | The image will be resized to fit into a 350x350 box. Aspect ratio will be maintained. For example, if the original image is 900x600, the inserted image will be 300x200                                                                                                                  |
| `{{insert_image image1 max_height=300}}`               | The image will be resized ensuring the height doesn't go beyond 300px. Aspect ratio will be maintained. For example, if the original image is 900x600, the inserted image will be 450x300                                                                                                |
| `{{insert_image image1 max_width=300}}`                | The image will be resized ensuring the width doesn't go beyond 300px. Aspect ratio will be maintained. For example, if the original image is 900x600, the inserted image will be 300x200                                                                                                 |
| `{{insert_image image1 width=300 max_height=500}}`     | The image width will be set to 300px. If the resulting height exceeds 500px, the image will be scaled down proportionally so that the height does not exceed 500 px while maintaining its aspect ratio. For example, if original image is 400x1000, the inserted image will be 200x500   |
| `{{insert_image image1 height=500 max_width=400}}`     | The image height will be set to 500px. If the resulting width exceeds 400px, the image will be scaled down proportionally so that the width does not exceed 400px while maintaining its aspect ratio. For example, if the original image is 1200x900, the inserted image will be 400x300 |

{% hint style="info" %}
The image URL need to be either publicly accessible so Docupilot can download and insert it in the document.

If you want to send only authenticated images, link your storage account like google drive, one drive, etc from **Settings > Linked Accounts** and enable **Use For Images** option if available. All image links sent to Docupilot will be downloaded using that authenticated account.
{% endhint %}

## Inserting Dynamic Links

You can insert **dynamic hyperlinks** into images and text within your templates. These links change based on the data you pass when generating a document.

### Adding hyperlink to an image:

1. Right-click the image
2. Select **Link**
3. in the **Address** field, enter: `docupilot:my_link`

<div align="left"><figure><img src="/files/YalqrOpiAOtq4wBGSott" alt="Dynamic hyperlink for images" width="563"><figcaption><p>Dynamic hyperlink for images in Word and Powerpoint</p></figcaption></figure></div>

### Adding hyperlink to text:

1. Highlight the text you want to link
2. Right-click and select **Link**
3. In the **Address** field, enter: `docupilot:my_link`

<div align="left"><figure><img src="/files/9UxxfobD3LC4o8yafGBk" alt="Dynamic hyperlink for text in Word and Powerpoint" width="563"><figcaption><p>Dynamic hyperlink for text in Word and Powerpoint</p></figcaption></figure></div>

#### How It Works

* `my_link` is a dynamic token.
* During document generation, Docupilot will replace it with the actual URL you provide in your data.
* Clicking the image or text in the generated document will open the corresponding URL.

{% hint style="info" %}
Tip: You can use multiple dynamic links in a template by giving each one a unique token (e.g., `docupilot:link1`, `docupilot:link2`)
{% endhint %}

## Inserting a dynamic QR Code <a href="#inserting-qr-code" id="inserting-qr-code"></a>

This will be helpful if you want to insert dynamic QR code from your data in the document.

Format - **{{insert\_qr url size="qr\_size" margin="qr\_margin" color="color\_code(in hex values)" bg\_color="color\_code(in hex values)" branding\_url="image\_url" branding\_ratio="ratio\_value(between 1 to 10)"}}**&#x200C;

<table><thead><tr><th>Order</th><th width="150.46875">Name</th><th width="260.28125">Description</th><th width="166.03515625">Mandatory</th></tr></thead><tbody><tr><td>1</td><td>size</td><td>QR Size</td><td>No<br>Default: 100</td></tr><tr><td>2</td><td>margin</td><td>QR Image height (px)</td><td><p>No</p><p>Default: 4</p></td></tr><tr><td>3</td><td>color</td><td>Color of QR core</td><td>No<br>Default: #000000</td></tr><tr><td>4</td><td>bg_color</td><td>Background Color for QR</td><td>No<br>Default: #FFFFFF</td></tr><tr><td>5</td><td>branding_url</td><td>Inserts an image in QR for branding</td><td>No</td></tr><tr><td>6</td><td>branding_ratio</td><td>Set the size of the QR code’s branding image on a scale from 1 to 10, where 10 is the smallest size and 1 is the largest.</td><td>No<br>Default: 4</td></tr></tbody></table>

Example - `{{insert_qr url size="100"}}`

<div align="left"><img src="/files/TPGeDyVW3qvK9Z9aAP1y" alt="Qr with size 100 and default margin 4 with value https://docupilot.com/" width="189"></div>

Example - `{{insert_qr url size="100" margin="3" bg_color="#3399FF"}}`

<div align="left"><img src="/files/I4ayeEs59Kk42nyolKwx" alt="Qr with size 100 and margin 3 with value https://docupilot.com" width="224"></div>

Example: `{{insert_qr url margin="7" color="#FFFFFF" bg_color="#000000"}}`

<div align="left"><figure><img src="/files/2RaiYWeQZVDx432GuxBQ" alt="" width="177"><figcaption><p>Qr with margin 7, white color and black background</p></figcaption></figure></div>

Example: `{{insert_qr url color="0000FF"}}`

<div align="left"><figure><img src="/files/dgPvBXpDwwOG1e91vByy" alt="" width="185"><figcaption><p>QR with color blue &#x26; value <a href="https://docupilot.app/">https://docupilot.com/</a></p></figcaption></figure></div>

Example: `{{insert_qr url margin="1" color="#FFFFFF" bg_color="#000000"}}`

<div align="left"><figure><img src="/files/Rf10IhyoUibdixzldrLB" alt="" width="218"><figcaption><p>QR with white color and black background</p></figcaption></figure></div>

{% hint style="info" %}
The color of the QR should be given in hex coding only.
{% endhint %}

Example: `{{insert_qr url margin="1" color="#FFFFFF" bg_color="#000000" branding_url=image_url branding_ratio="4"}}`

<div align="left"><figure><img src="/files/Df8i10oaAi4WvWTXk8XB" alt="" width="226"><figcaption><p>QR code with branding image</p></figcaption></figure></div>

{% hint style="info" %}
The image URL need to be publicly accessible so we can download and insert it in the document.
{% endhint %}

#### Inserting a Barcode with a Transparent Background

This is useful if you need to insert a barcode with a transparent background into your document.

Example: `{{insert_qr url color="#FFFFFF" bg_color=”ffffff00”}}`

<div align="left"><figure><img src="/files/L2Q9xicgqCCbfjDIZD6r" alt="" width="312"><figcaption><p>QR code with transparent background</p></figcaption></figure></div>

## Inserting Google Maps <a href="#inserting-google-maps" id="inserting-google-maps"></a>

This will be helpful if you want to insert Google Maps from your data in the document.‌

Format - **{{insert\_map Location width="map\_width" height="map\_height" map\_type="maptype" zoom="map\_zoom"}}**&#x200C;

The supported map types are as follows. The default map type is the roadmap.‌

1. roadmap
2. satellite
3. hybrid
4. terrain

Example - **{{insert\_map Location width="500" height="500" map\_type="roadmap"}}**

<div align="left"><img src="https://blobscdn.gitbook.com/v0/b/gitbook-28427.appspot.com/o/assets%2F-LDwD-wIOendMUiQ8uVr%2F-LjqKFkGneund1-S_wz0%2F-LjqNJ8CNhiKfWOErv08%2Fstaticmap.png?alt=media&#x26;token=18e9b585-fae8-4902-bec9-5306e424fd69" alt="Location Value is Manchester" width="563"></div>

Example: **{{insert\_map Location map\_type="roadmap" zoom= "20"}}**

<div align="left"><figure><img src="/files/A7X53NTyJ3b4voMwnd5E" alt="" width="469"><figcaption><p><strong>Location value is Manchester, with map type as road map and a Zoom set to 20</strong></p></figcaption></figure></div>

Example: **{{insert\_map Location height="300" zoom= "5"}}**

<div align="left"><figure><img src="/files/MXWACpdvfGujDDOsbCPr" alt="" width="466"><figcaption><p><strong>Location value is Manchester with height as 300 px and zoom set to 5</strong></p></figcaption></figure></div>

## Grid Helper

The Grid Helper will render the list input in a grid format, with specified column size.

Syntax: `{{#grid items col_size=3}}`\
`{{@item1}}{{@item2}{{@item3}}`\
`{{/grid}}`

Example:

<div align="left"><figure><img src="/files/59mIiGYrxOdhDMcR8mV8" alt="" width="563"><figcaption><p>Grid helper</p></figcaption></figure></div>

{% hint style="info" %}
If the number of columns ( i.e.,`col_size`) is 5, then **{{@item4}}** and **{{@item5}}** can be used to access entries 4th and 5th column items in each row.
{% endhint %}

## Rich Text Helper

The rich text helper enables content formatting in various ways, including bold, italic, underlined text, different fonts, sizes, colors, and more, surpassing plain text capabilities.It supports both HTML and Markdown format input to richtext.

Syntax : `{{richtext content}}`

Example:

<div align="left"><figure><img src="/files/haTUTT7hjKYohZb08fAN" alt="" width="563"><figcaption><p>Example Rich Input from Airtable demonstrating Bold text, Headings and List items.</p></figcaption></figure></div>

<div align="left"><figure><img src="/files/dvJDyJ9g0NRzrXvuQ60q" alt="" width="563"><figcaption><p>Document Generated retaining the same input structure while matching the style with the document template.</p></figcaption></figure></div>

## Repeat Slides

The Repeat Slides functionality allows you to repeat one or more slides within your presentation dynamically based on a list data. Place the repeat slide syntax anywhere within a dedicated text box on a slide.

Syntax:

`{{repeat_slides items count=3}}`

where `items` is the token referring to list data, `count` defines the number of slides to be repeated. For example, when `count` is set to `3`, 3 slides including the current one are repeated for each item in `items`.

Examples:

Simple product catalog: Consider the case where you want to repeat a slide for each product in your catalog, and you need to add 1 product into each slide separately, use the syntax `{{repeat_slides products}}` and add the placeholders like `{{product_name}}`, `{{specifications}}`, etc into the same slide. The generated document will contain appropriate resulting items.

Detailed product catalog: Consider similar case as above, but you want to add the each of the product details in 3 slides. Say, first slide of each product contains basic information, next slide contains specifications and the 3rd slide related to that product contains pricing and warranty information. Use the syntax `{{repeat_slides products count=3}}` and add placeholders for basic information `{{product_name}}`, etc., in first slide, `{{material_used}}`, `{{dimensions}}`, etc., in second slide and `{{price}}`, or a pricing table, and `{{warranty_information}}`, etc in third slide. For each product passed, the generated document will have 3 slides.

<div align="left"><figure><img src="/files/KRFVlpVw5Jl4dsSpdMJ7" alt="" width="563"><figcaption><p>Repeat Slides - Input</p></figcaption></figure></div>

<div align="left"><figure><img src="/files/bebMonygSKdredi5h4C2" alt="" width="563"><figcaption><p>Repeat Slides - Output</p></figcaption></figure></div>

## Embedding Fonts in a DOCX Template

To ensure a document retains a specific font that is not supported on our end, you must embed the fonts within the document. This will make sure that the generated document maintains the same font as the original.

**Here's how to embed fonts in your DOCX template:**

1. **Open Your DOCX Template:** Begin by opening your template using Microsoft Office.
2. **Enable Font Embedding:**

   * For Mac Users: Navigate to Preferences -> Save -> "Embed fonts in the file."
   * For Windows Users: Go to Options -> Save ->"Embed fonts in the file".

   If you're having trouble locating these settings within Microsoft Office, refer to this [article](https://www.support.microsoft.com/en-us/office/benefits-of-embedding-custom-fonts-cb3982aa-ea76-4323-b008-86670f222dbc) for guidance.
3. **Save and Upload:** Finally, save your document with the embedded fonts and upload the updated document to Docupilot.

<div align="left"><figure><img src="/files/1iEa9HsVCKjfdSCWz8ZY" alt="" width="563"><figcaption><p>Mac Users-Embedding Font in a DOCX Template</p></figcaption></figure></div>

<div align="left"><figure><img src="/files/BILTxqPKVPj8vtUK0kSW" alt="" width="563"><figcaption><p>Windows Users-Embedding Font in a DOCX Template</p></figcaption></figure></div>

## Comments

You can add comments in the document template to help your future editors. The comments will be removed in the output document.

{% hint style="success" %}
Comments Syntax : **{{!Your comments here}}**
{% endhint %}


# Excel (XLSX)

This section helps you to generate dynamic Excel Spread Sheets.

## Getting Started

You can use Excel Spread Sheets ( .xlsx is the supported format ) as your document template, you can build your document in Ms Excel, Google Sheets or other supporting platforms and then upload it to Docupilot as a .xlsx file. Replace the info in excel sheet like client name, client company name to {{client.name}} and {{client.company}}.

![Excel Spread Sheet (.xlsx) template overview.](/files/-MWTNTe3hldvklresAqm)

### Uploading XLSX

![](/files/LePnwffP5gC3wSu22u8v)

### Updating XLSX

If you want to make changes to your Excel Spread Sheet make changes in MS Excel, Google Sheets etc , and upload it to Docupilot as a .xlsx file.

![](/files/ywOFBVmYDTDilO0OG3J4)

## Types of Merge Fields <a href="#types-of-merge-fields" id="types-of-merge-fields"></a>

Docupilot supports a variety of merge fields for you to use.

* Tokens (Merge Field)
* Condition (`if-else`)
* Iterating inside a cell
* Tables

### Tokens (Merge Field) <a href="#tokens-merge-field" id="tokens-merge-field"></a>

These are simple fields embraced in `{{}}`. When you provide your custom data, **Docupilot** will replace these fields with the data. For example **{{email}}, {{clientname}}, {{company\_name}}**.

If you want to group your fields you can use dot(.) while defining the tokens. For example your client has first name & last name, you can write the tokens as **{{client.first\_name}}, {{client.last\_name}}.**

### Condition (`if-else`)

You can use conditional statements to show or hide contents based on your data. For example, If you are creating an invoice, you want to display CASH if the payment\_mode is cash, else if the payment\_mode is the card you want to show CARD.

```
{{#if (payment_mode == "cash")}}
CASH
{{else if (payment_mode == "card")}}
CARD
{{else}}
Please Insert preferred Mode of Payment{{/if}}
```

To use conditional statement for checking inverse or negation of a condition, use the **not** in the condition. For example, to add an instruction requesting to add secure link if payment mode is not available on record:

```
{{#if (not payment_mode)}}
Please Add your payment details in this secure link: <your secure payment link>
{{/if}}
```

{% hint style="info" %}
Note: The `if/else` statements work only when added inside a single cell. For example:

<img src="/files/fuY5ILTgPq8bXQlPlD6b" alt="" data-size="original">
{% endhint %}

You can use the conditional statements in the following ways

* `if`
* `if-else`
* `if-else if`
* `if-else if-else`
* `if-else if-else if`
* `if-else if-else if-else`
* and so on...

Below are a few examples:

| <p><code>{{#if show\_payment\_details}}</code></p><p><code>ACH to {{acNumber}}</code></p><p><code>{{/if}}</code></p>                                                                                                                                                   | prints the text `ACH to xxxxxxxxx` if `show_payment_details` is present and not `false`.                                                                                                                                                               |
| ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| <p><code>{{#if (payment\_status == "paid")}}</code></p><p><code>payment cleared</code></p><p><code>{{/if}}</code></p>                                                                                                                                                  | prints `payment cleared` if `payment_status` equals to `"paid"` (case-sensitive)                                                                                                                                                                       |
| <p><code>{{#if (payment\_status != "paid")}}</code></p><p><code>unpaid</code></p><p><code>{{/if}}</code></p>                                                                                                                                                           | prints `unpaid` if `payment_status` not equal to `"paid"` (case-sensitive)                                                                                                                                                                             |
| <p><code>{{#if (payment\_status == "paid")}}</code></p><p><code>paid</code></p><p><code>{{else}}</code></p><p><code>unpaid</code></p><p><code>{{/if}}</code></p>                                                                                                       | prints `paid` if `payment_status` equals to `"paid"` otherwise prints `unpaid`                                                                                                                                                                         |
| <p><code>{{#if (payment\_status == "paid")}}</code></p><p><code>paid</code></p><p><code>{{else if (payment\_status == "initiated")}}</code></p><p><code>payment initiated</code></p><p><code>{{else}}</code></p><p><code>pending</code></p><p><code>{{/if}}</code></p> | <p>prints <code>paid</code> if <code>payment\_status</code> equals to <code>"paid"</code></p><p>prints <code>payment initiated</code> if <code>payment\_status</code> equals to <code>initiated</code></p><p>otherwise prints <code>pending</code></p> |
| <p><code>{{#if (price > 1000)}}</code></p><p><code>good deal</code></p><p><code>{{/if}}</code></p>                                                                                                                                                                     | prints the text `good deal` if price is greater than 1000                                                                                                                                                                                              |
| <p><code>{{#if (price >= 1000)}}</code></p><p><code>decent deal</code></p><p><code>{{/if}}</code></p>                                                                                                                                                                  | prints text `decent deal` if price is greater than or equal to 1000                                                                                                                                                                                    |
| <p><code>{{#if (price < 1000)}}</code></p><p><code>small deal</code></p><p><code>{{/if}}</code></p>                                                                                                                                                                    | prints text `small deal` If price less than 1000                                                                                                                                                                                                       |
| <p><code>{{#if (price <= 1000)}}</code></p><p><code>okay-ish deal</code></p><p><code>{{/if}}</code></p>                                                                                                                                                                | prints text `okay-ish deal` If price less than or equal to 1000                                                                                                                                                                                        |
| <p><code>{{#if (payment\_message contains "paid")}}</code></p><p><code>Payment is cleared</code><br><code>{{/if}}</code></p>                                                                                                                                           | prints `Payment is cleared` if `payment_message` contains the text `paid` *(for example, `this invoice has been paid` contains the text `paid` in it)*                                                                                                 |
| <p><code>{{#if (payment\_message not\_contains "paid")}}</code></p><p><code>Payment is due</code><br><code>{{/if}}</code></p>                                                                                                                                          | prints `Payment is due` if `payment_message` does not contain the text `paid` *(for example, `this invoice is not cleared` does not contain the text `paid` in it)*                                                                                    |
| <p><code>{{#if (status == "open" or status == "on-hold")}}</code></p><p><code>Payment is pending</code></p><p><code>{{/if}}</code></p>                                                                                                                                 | prints `Payment is pending` if `status` is `open` OR `on-hold`                                                                                                                                                                                         |
| <p><code>{{#if (status == "open" or status == "on-hold" or status == "under review")}}</code></p><p><code>Payment is pending</code></p><p><code>{{/if}}</code></p>                                                                                                     | prints `Payment is pending` if `status` is `open` OR `on-hold` OR `under review`                                                                                                                                                                       |
| <p><code>{{#if (status != "open" and status != "on-hold")}}</code></p><p><code>Payment is not pending</code></p><p><code>{{/if}}</code></p>                                                                                                                            | prints `Payment is not pending` if `status` is not `open` AND not `on-hold`                                                                                                                                                                            |
| <p><code>{{#if (status == "open" and priority == "high")}}</code></p><p><code>High priority open task</code></p><p><code>{{/if}}</code></p>                                                                                                                            | prints `High priority open task` if `status` is `open` AND if `priority` is `high`                                                                                                                                                                     |
| <p><code>{{#if (payment\_status != "paid")}}Please Clear the Dues within 30 days</code></p><p><code>{{/if}}</code></p>                                                                                                                                                 | prints `Please Clear the Dues within 30 days` if the `payment_status` is not equal to `paid`                                                                                                                                                           |
| <p><code>{{#if (status in "open,pending")}}In Progress... Please stay tuned for further updates.</code></p><p><code>{{/if}}</code></p>                                                                                                                                 | prints `In Progress... Please stay tuned for further updates.` if `status` is sub-string of `"open,pending"`                                                                                                                                           |

#### Hiding Empty Sections & Lines

In the following example, when the `address` field has a value, it gives desired outcome. If the address is empty, it leaves an empty line in the output.

```
{{customer_name}},
{{#if address}}{{address}},{{/if}}
{{city}}, {{country}}
```

<table><thead><tr><th>Data</th><th>Output</th></tr></thead><tbody><tr><td><pre><code>customer_name = John Doe
city = NY
country = US
</code></pre></td><td><pre><code>John Doe,
NY, US
</code></pre></td></tr><tr><td><pre><code>customer_name = John Doe
street = WinWood St.
city = NY
country = US
</code></pre></td><td><pre><code>John Doe,
WinWood St.,
NY, US
</code></pre></td></tr></tbody></table>

To hide empty lines, we should open the `if` condition in previous line or close it in next line. Here are examples on how the output will look like when street address is passed and when it is not:

<table><thead><tr><th>Syntax</th><th>Data</th><th>Output</th></tr></thead><tbody><tr><td><pre><code>{{customer_name}},{{#if street}}
{{street}},{{/if}}
{{city}}, {{country}}
</code></pre></td><td><pre><code>customer_name = John Doe
city = NY
country = US
</code></pre></td><td><pre><code>John Doe,
NY, US
</code></pre></td></tr><tr><td><pre><code>{{customer_name}},{{#if street}}
{{street}},{{/if}}
{{city}}, {{country}}
</code></pre></td><td><pre><code>customer_name = John Doe
street = WinWood St.
city = NY
country = US
</code></pre></td><td><pre><code>John Doe,
WinWood St.,
NY, US
</code></pre></td></tr><tr><td><pre><code>{{customer_name}},
{{#if street}}{{street}},
{{/if}}{{city}}, {{country}}
</code></pre></td><td><pre><code>customer_name = John Doe
city = NY
country = US
</code></pre></td><td><pre><code>John Doe,
NY, US
</code></pre></td></tr><tr><td><pre><code>{{customer_name}},
{{#if street}}{{street}},
{{/if}}{{city}}, {{country}}
</code></pre></td><td><pre><code>customer_name = John Doe
street = WinWood St.
city = NY
country = US
</code></pre></td><td><pre><code>John Doe,
WinWood St.,
NY, US
</code></pre></td></tr></tbody></table>

### Iterating inside a cell

Multiple entries inside a cell can be incorporated by using the following syntax.

![Iterating a list inside a cell in Excel](/files/-MX8D-i6bpwL6ww6QuuF)

![Output for iterating a list inside a cell in Excel](/files/-MXVfA5yXu14cfBaIEi5)

## **Tables**

Dynamic tables allow a template to repeat a row for each item in a list, automatically adjusting during merging. Instead of setting a fixed number of rows, use loop tags `{{#each ...}}` ... `{{/each}}`. The result is a well-organized table—ideal for invoices, order summaries, schedules, or reports where record count changes.

Following are different ways in which a Dynamic Table can be created:

### Simple Table

A simple and straight forward table which addresses most use-cases. To create a simple table which repeat one or many rows for each item in a list, follow these instructions:

1. Identify the cell where table should start. *(ex: B3)*
2. Identify number of columns that are to be repeated as part of the Dynamic Table. *(ex: 3)*
3. Now, merge the number of cells starting from the start cell. *(ex: Merge B3 -> D3)*
4. Add the loop's opening tag `{{#each YOUR_TOKEN_NAME}}` . *(ex: `{{#each invoice_items}}` )*
5. In the next row, add the content for your columns.
   1. The content in each cell can be a dynamic placeholder (like `{{name}}`) or fixed text (like `Item Name`) or a combination (like `Item Name: {{name}}`).
   2. [Formatters/Modifiers](/document-template/formatting-your-data) can be used to format or style dynamic data in a cell. *(For example, adding `{{upper name}}` in B4 will display the names in uppercase.)*
   3. For *ex: consider an invoice invoice, where the item name, qty, and price are to be printed in 3 adjacent columns. Just `{{name}}` , `{{quantity}}`, and `{{price}}` in cells B4, C4 and D4*
6. If another row is to be repeated configure the next row as mentioned in 5.a. This can be done for as many rows as desired.
7. Once the repeated rows are configured, in the next row merge the cells similar to what was done in step 3. *(ex: Merge B5 -> D5)*
   1. Merged cell width should be same as the number of columns that need to be repeated. This is also same as the width of the cell where loop's opening tag is added.
8. Add the loop's closing tag `{{/each}}` in this merged cell *(ex: add `{{/each}}` in merged cell B5)*

Below is an example screenshot from an excel template which uses Dynamic table to print list of invoice line items. This example also demonstrates calculating the total price using [aggregate modifier](/document-template/formatting-your-data#aggregate).

![Inserting a Dynamic Table in Excel](/files/Vh1wsQ0Akoj9GtuayiV2)

{% hint style="info" %}
Note that the loop's opening cell and closing cell should be merged and span across same number of columns. The cells sand-witched in between the opening cell and closing cell will be repeated. Cells to the left and to the right will not be disturbed by dynamic table.
{% endhint %}

![Example output of a Dynamic Table in Excel](/files/kwnjtMQnoncNktAXF3eV)

### Nested Tables

A **Nested Table** is more than 1 simple table nested inside one another. Nested tables allow you to repeat a nested list of items. For example, to print a list of Departments and Employee details in each Department.

To create a nested table, follow the same instructions as explained under [Simple Tables](#simple-table). When configuring the cells after creating the opening cell, follow the same instructions atop to create a child dynamic table.

The image below depicts a Dynamic Table that iterates over a list of departments, prints the Department's name and then iterates over a list of Employees in each Department and prints their ID, Name, Designation and Salary.

<figure><img src="/files/TRMzSISEZdfn7rUsNZ5J" alt=""><figcaption><p>Nested Dynamic Tables in Excel</p></figcaption></figure>

<figure><img src="/files/0VukCgG7bmm1dClypIXW" alt=""><figcaption><p>Example output of a Nested Dynamic Tables in Excel</p></figcaption></figure>

{% hint style="info" %}
The example above shows Nested Dynamic tables with a 2 level nesting. There is currently no limit on the number of nesting levels supported.
{% endhint %}

### Legacy Tables

This section acts as a reference for templates that use older Dynamic Table syntax. This syntax has many limitations and is not recommended for use.

Syntax: `{{table:YOUR_LIST.PROPERTY_NAME}}`

Example:

* `{{table:line_items.name}}`
* `{{table:line_items.qty}}`
* `{{table:line_items.amount}}`

Here for the field named `line_items` – `name`, `amount` and `qty` are defined as the property of each `line_item`. The image below shows how this example looks like when implemented.

<figure><img src="/files/w1Kl2iqNWjTwRxCLdvJU" alt=""><figcaption><p>Legacy Dynamic Table in Excel</p></figcaption></figure>

<figure><img src="/files/8QU0uQbKv6wXv82t1FsC" alt=""><figcaption><p>Example output of a Legacy Dynamic Table in Excel</p></figcaption></figure>

{% hint style="info" %}
Legacy tables are very limited in terms of functionality. The new style Dynamic Tables are flexible, scalable and are recommended over Legacy Dynamic Tables.
{% endhint %}

## Inserting a dynamic image

This will be helpful if you want to insert dynamic image in the document.

Format : **{{insert\_image image1 width=width height=height max\_width=max\_width max\_height=max\_height}}**

* `width` (optional): Desired image width
* `height` (optional): Desired image height
* `max_width` (optional): Desired maximum width of the image
* `max_height` (optional): Desired maximum height of the image

**Example Usage**

<table><thead><tr><th width="380.8046875">Syntax</th><th>Description</th></tr></thead><tbody><tr><td><code>{{insert_image image1 width=300 height=200}}</code></td><td>The image inserted will be 300px wide and 200px tall</td></tr><tr><td><code>{{insert_image image1 width=300}}</code></td><td>Inserted image will be 300px wide, height will be auto adjusted based on the original image's aspect ratio. For example if original image is 600x500, inserted image will be 300x250.</td></tr><tr><td><code>{{insert_image image1 height=300}}</code></td><td>Inserted image will be 300px tall, width will be auto adjusted based on the original image's aspect ratio.</td></tr></tbody></table>

### Constraining Image Dimensions

Use the `max_width` and `max_height` parameters to limit image dimensions.

**Examples:**

| Syntax                                                 | Description                                                                                                                                                                                                                                                                              |
| ------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `{{insert_image image1 max_width=300 max_height=300}}` | The image will be resized to fit into a 350x350 box. Aspect ratio will be maintained. For example, if the original image is 900x600, the inserted image will be 300x200                                                                                                                  |
| `{{insert_image image1 max_height=300}}`               | The image will be resized ensuring the height doesn't go beyond 300px. Aspect ratio will be maintained. For example, if the original image is 900x600, the inserted image will be 450x300                                                                                                |
| `{{insert_image image1 max_width=300}}`                | The image will be resized ensuring the width doesn't go beyond 300px. Aspect ratio will be maintained. For example, if the original image is 900x600, the inserted image will be 300x200                                                                                                 |
| `{{insert_image image1 width=300 max_height=500}}`     | The image width will be set to 300px. If the resulting height exceeds 500px, the image will be scaled down proportionally so that the height does not exceed 500 px while maintaining its aspect ratio. For example, if original image is 400x1000, the inserted image will be 200x500   |
| `{{insert_image image1 height=500 max_width=400}}`     | The image height will be set to 500px. If the resulting width exceeds 400px, the image will be scaled down proportionally so that the width does not exceed 400px while maintaining its aspect ratio. For example, if the original image is 1200x900, the inserted image will be 400x300 |

{% hint style="info" %}
The image URL need to be either publicly accessible so Docupilot can download and insert it in the document.

If you want to send only authenticated images, link your storage account like google drive, one drive, etc from **Settings > Linked Accounts** and enable **Use For Images** option if available. All image links sent to Docupilot will be downloaded using that authenticated account.
{% endhint %}

## Adjust orientation for output PDF <a href="#types-of-merge-fields" id="types-of-merge-fields"></a>

To generate a PDF in landscape mode from an XLSX template, follow these steps:

1. Open your XLSX template and navigate to the '**Page Layout**' settings.
2. Select '**Page** **Orientation**' and choose '**Landscape**.'
3. Upload the XLSX template to Docupilot, and the output will be in landscape format when converted to PDF.

<figure><img src="/files/dBB0MYCsVVN8o0L9Q5XJ" alt=""><figcaption><p><strong>Page</strong> <strong>Orientation updated on a XLSX file</strong></p></figcaption></figure>


# Fillable PDF

With Docupilot, you can automate a fillable PDF document. Docupilot attempts to use field names and other properties from the underlying PDF field to create the token. You'll need to use a PDF editing software program like Nitro Pro and Adobe, PDFescape to create a fillable PDF.

![Example Fillable PDF](/files/-M6epJm9QYMxHmZwRFuy)

{% file src="/files/-M6eooG6nbOC3T5LHBXt" %}
Example Fillable PDF
{% endfile %}

**Checkbox**, **Radio** fields in the PDF has an "On" value or an "Export" value. When the value that you are passing matches this "On" value, the checkbox will be checked.

![Export Value](/files/-M6fD2UQM3xCbHKRTtdC)

{% hint style="warning" %}
The Export value for a checkbox is limited to 125 characters
{% endhint %}

### Uploading Fillable PDF to Docupilot

Once you have the PDF created, you can upload it to Docupilot and the fields are recognized automatically. If you need to make any changes, make the changes in your PDF editor, then upload the PDF to Docupilot.

### Editing a Fillable PDF

Fillable PDFs templates can be edited and customised using a paid version of Adobe Acrobat or some free tools like PDFEscape, etc.

> *Note that the 3rd party tools mentioned here are merely a suggestion. We strongly advise you to choose the tools after thoroughly reading relevant legal documentation of how these tools use/manage your data.*

### Flatten PDF

By default the fillable fields are removed in the generated PDF. You can preserve the generated PDF as a fillable PDF itself. You can goto the templates preferences section and uncheck the flatten pdf option as shown in the image below.

{% hint style="warning" %}
Save the changes after updating the preferences.
{% endhint %}

![Flatten PDF settings](/files/rlqttkLmExmeRnGDEIIX)

### Embed Images/Signature images

You can goto template preferences -> More options -> under insert dynamic images you can enter the width, height, and location of the image in the PDF. You need to pass a image url for the token fields to insert the image in the PDF.

![Dynamic Images settings](/files/E1KHkXNeB192Kj1bHaGP)

![xDynamic Images settings values](/files/dGQxZeHin3i4OS4Iq7HU)

{% hint style="info" %}
The image URL need to be publicly accessible so we can download and insert it in the document.
{% endhint %}

## Editing a PDF Document

To edit fillable PDF templates, consider using software like Adobe Acrobat. This allows you to modify text, insert signature fields (e.g., `\s1\`), or add new fillable fields. For a no-cost alternative, [PDFEscape](https://www.pdfescape.com/) is a viable option for making changes to PDF templates.

<figure><img src="/files/kY3Mj4e21ttsPv5n4uwu" alt=""><figcaption><p>Example: Adding a Text Form Field in a PDF document.</p></figcaption></figure>


# Template Preferences

Once you have created your HTML template, or uploaded your fillable PDF/PPTX/DOCX template, you can customise how the document generation should work for that template under `Preferences` tab.

<figure><img src="/files/uuqyHdYkK7hk3wSwQ72R" alt=""><figcaption><p>Preferences Tab.</p></figcaption></figure>

#### Updating basic settings

<figure><img src="/files/XNWAMCoNS6R3lApTfput" alt=""><figcaption><p>Basic Info section.</p></figcaption></figure>

<table><thead><tr><th width="189">Preference</th><th></th></tr></thead><tbody><tr><td>Title</td><td>Template name for your reference within Docupilot Dashboard.</td></tr><tr><td>Description</td><td>Template description to help idenitify what this template is used for.</td></tr><tr><td>Output file name</td><td><p>The file name of the generated document. Dynamic tokens can be configured here to create more personalised name for your Document.</p><p>Example: <code>Proposal for {{company}}</code></p></td></tr></tbody></table>

#### **Template Status - Publish VS Draft:**

The upper right corner of the Template Details page has a button for quickly switching the template status to either **Publish** or **Draft**.

Alternatively, you can update the status under **Preferences → Basic Info → Template Status** by selecting either **Publish** or **Draft** and **saving your changes**.

<div align="center" data-full-width="true"><figure><img src="/files/BPrk5e4GAlp8Mfao3MbG" alt=""><figcaption><p>Template status - Draft mode</p></figcaption></figure> <figure><img src="/files/wJ9GUKIcmUm4QGZtniAd" alt=""><figcaption><p>Template status - Publish mode</p></figcaption></figure></div>

If the template is in **"Draft"** mode, your generated document will have a watermark saying "This document is created using Docupilot" and your document credits will not be consumed. Once you have tested your templates and your integration completely, you can change your template status to **Publish**.

### Output Preferences:

<figure><img src="/files/82NrKF8oGVs6IOvmHY5N" alt=""><figcaption><p>Output Preferences section.</p></figcaption></figure>

<table><thead><tr><th width="148">Preference</th><th></th></tr></thead><tbody><tr><td>Output Type</td><td><p>The output type of generated document.</p><p>Supported output types:<br>For "Document Builder" templates <code>PDF</code>, <code>HTML</code> and <code>PNG</code><br>For "DOCX" templates <code>DOCX</code>, and <code>PDF</code></p><p>For "PPTX" templates <code>PPTX</code>, and <code>PDF</code></p><p>and for Fillable PDFs only <code>PDF</code> output is supported.</p></td></tr><tr><td>Page Size</td><td>The page size of the output document. You can choose between <code>A4/Letter/Legal/A3/A5/Tabloid</code> for your Document builder templates.<br>Page Size settings are not applicable for other template types (output page size for will be same as template page size)</td></tr><tr><td>Render Mode</td><td>. You can select between the "<code>For viewing on screen</code>" and " <code>For printing</code>" options for your HTML templates.</td></tr><tr><td>Orientation</td><td>The orientation of the output document. You can choose between <code>Portrait</code> and <code>Landscape</code> for your HTML templates. Orientation settings are not applicable for other template types.</td></tr><tr><td>Time Zone</td><td>The time zone to be used for the reserved tokens {{_date}} and {{_datetime}}</td></tr></tbody></table>

### Advanced Settings:

<figure><img src="/files/rgYG47xV6o9xkgbydJy1" alt=""><figcaption><p>Advanced Settings section.</p></figcaption></figure>

#### Auto Number:

Auto Number (`{{_auto_number}}`) displays a unique number across each generated document. Enable it and define a starting number and with each new document generation, that number will be automatically incremented. To learn more about the Auto number feature [here](https://help.docupilot.app/document-template/tokens-merge-field#auto-number).

#### Password:

If the output document type is PDF, you can set the password for the generated pdf in template.You can set a dynamic password for your created PDF using Tokens.

For example: `{{abbreviate customer_name}}{{format_date agreement_date format="DDMM"}}` can be used to create a dynamic password. If your customer name is "Acme Corp Limited" and agreement date is "2024 January, 15", the password will be "ACL1501"

#### Page Margins (inches):

Docupilot allows you to adjust the size of the top, bottom, left, right page margins in inches for each page in the template. Default page margins are set to 0.4 inches on all sides.

### Header and Footer :

<figure><img src="/files/E0XmirkJJ7No8C3ttbQh" alt=""><figcaption><p>Header and Footer section.</p></figcaption></figure>

In this section, Header and Footer for a document can be inserted in a **Document Builder (HTML)** template.

#### Page number and Total number of pages:

You can print **Page numbers** and **Total number of pages** in a document template using predefined tokens `{{_page_no}}` and `{{_total_pages}}.`

<table><thead><tr><th width="223">Token</th><th>Explanation</th></tr></thead><tbody><tr><td><code>{{_page_no}}</code></td><td>prints the current page number in generated document.</td></tr><tr><td><code>{{_total_pages}}</code></td><td>Prints the total number of pages in generated document.</td></tr></tbody></table>

Inserting `{{_page_no}}/{{_total_pages}}` in header or footer will print `1/12` on page 1, `2/12` on page 2, and so on on each page for a generated document that contains 12 pages.

{% hint style="warning" %}
Note : `Headers` and `footers` of a document are dependent on `page margins` of the template. Greater the sizes of margins, more information can be printed as `header` and `footer` of the document.
{% endhint %}


# Formatting Your Data

This section guides you to format your data. For example, you want to display your text in uppercase or lowercase and much more. Here formatting doesn't mean styling your content (font, size, color).

Here is a list of available modifiers/helpers. These modifiers/helpers are added along with the tokens(merge field).

| Modifier/Helper   | Description                                                                                                            | Example                                                                                                                                                                                                                                                                                                               |
| ----------------- | ---------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Uppercase         | Convert all characters to uppercase                                                                                    | **{{upper FieldName}}**                                                                                                                                                                                                                                                                                               |
| Lowercase         | Convert all characters to lowercase                                                                                    | **{{lower FieldName}}**                                                                                                                                                                                                                                                                                               |
| Capitalize        | <ol><li>Capitalize the first letter</li><li>Camel Cased Sentence</li></ol>                                             | <ol><li><strong>{{capitalize FieldName}}</strong></li><li><strong>{{capitalize FieldName format="words"}}</strong></li></ol>                                                                                                                                                                                          |
| Abbreviation      | Convert text to abbreviation (First letter of each word in caps)                                                       | **{{abbreviate FieldName "."}}**                                                                                                                                                                                                                                                                                      |
| Pad               | Appends or prepends a single character repeatedly to fill input to given width.                                        | <p><strong>{{pad number 9}}</strong></p><p><strong>{{pad number 5 pad\_with='\*' style='suffix'}}</strong></p>                                                                                                                                                                                                        |
| Concat            | Appends text.                                                                                                          | **{{concat string1 string2}}**                                                                                                                                                                                                                                                                                        |
| Format Date       | Change the format of date, datetime                                                                                    | <p><strong>{{format\_date \_date format="DD-MM-YY"}}</strong><br><strong>{{format\_date \_date format="DD-MMMM-YYYY" locale="fr"}}</strong><br><strong>{{format\_date \_date format="DD-MMMM-YYYY" locale="en" offset="+3 years"}}</strong></p>                                                                       |
| Format Number     | Change the format of a number (thousands and decimals)                                                                 | <p><strong>{{format\_number number decimal\_separator="."}}</strong><br><strong>{{format\_number number thousand\_separator=","}}</strong><br><strong>{{format\_number number precision="2"}}</strong><br><strong>{{format\_number number thousand\_separator="," decimal\_separator="." precision="3"}}</strong></p> |
| Format Phone      | <p>Change the format of your phone number.<br>It can also be used to format a number</p>                               | **{{format\_phone landline "(%3) %3-%4"}}**                                                                                                                                                                                                                                                                           |
| Number to words   | Converts the input number in to words.                                                                                 | **{{number\_to*****\_*****words input}}**                                                                                                                                                                                                                                                                             |
| Number to Ordinal | Converts the input number to its ordinal form, in words.                                                               | **{{number\_to\_ordinal input}}**                                                                                                                                                                                                                                                                                     |
| Join              | Joins the input array of strings with given separator (defaults to `,`)                                                | <p><strong>{{join items ", "}}</strong></p><p><strong>{{join FieldName ", " lookup="object.name"}}</strong></p>                                                                                                                                                                                                       |
| Replace           | Replaces the match string from input with given replace string                                                         | **{{replace str1 str2}}{{replace FieldName (regex "\[0-9]" "g") "\*"}}**                                                                                                                                                                                                                                              |
| Regex             | Return a RegExp class instance with given pattern and flags                                                            | **{{replace FieldName (regex "(0-9)" "g") "\*"}}**                                                                                                                                                                                                                                                                    |
| Split             | Splits input with given separator (defaults to `,`)                                                                    | **{{#each (split Fieldname ", ")}} ... {{/each}}**                                                                                                                                                                                                                                                                    |
| Strip             | Strips the input of given match characters (defaults to white space) from given position (`left` or `right` or `both`) | <p><strong>{{strip FieldName}}</strong></p><p><strong>{{strip FieldName "\*" side="left"}}</strong></p>                                                                                                                                                                                                               |
| Sort              | Sorts input in the given order (`asc` , `desc`)                                                                        | <p><strong>{{# list (sort FieldName lookup="price" order="asc")}} ... {{/list}}</strong></p><p><strong>{{#list (sort Fieldname order="asc")}} ... {{/list}}</strong></p>                                                                                                                                              |
| Var               | Can be used to store and retrieve the data within the template                                                         | <p><strong>{{var "FieldName" 500}}</strong></p><p><strong>{{var "FieldName"}}</strong></p>                                                                                                                                                                                                                            |
| Group by          | Groups data by given lookup.                                                                                           | <p><strong>{{#each (group\_by FieldName lookup="company")}}.....</strong></p><p><strong>{{/each}}</strong></p>                                                                                                                                                                                                        |
| Insert Link       | Inserts a URL or Hyperlink in the document                                                                             | **{{insert\_link url text="clickable display text"}}**                                                                                                                                                                                                                                                                |
| Url Encode        | Replaces special characters inside a URL with encoded text.                                                            | **{{url\_encode URL is\_url=true\|false}}**                                                                                                                                                                                                                                                                           |
| Url Decode        | Decodes encoded URLs into pre-encoded forms.                                                                           | **{{url\_decode URL is\_url=true\|false}}**                                                                                                                                                                                                                                                                           |
| Rand              | Returns a random value between the specified minimum and maximum values.                                               | **{{rand min max}}**                                                                                                                                                                                                                                                                                                  |
| As Number         | Converts any given input to a valid number.                                                                            | **{{as\_number FieldName}}**                                                                                                                                                                                                                                                                                          |
| As String         | Converts any given input to a valid string.                                                                            | **{{as\_string FieldName}}**                                                                                                                                                                                                                                                                                          |
| As Boolean        | Converts any given input to True or False.                                                                             | **{{as\_boolean FieldName}}**                                                                                                                                                                                                                                                                                         |

## **Format Date/Time**

To print date and time in desired format in the document, use this formatter. Format, Locale, and Offset can be adjusted.

#### Syntax

```
{{format_date token_name format="format" input_format="input format" locale="language_code" offset="add/subtract time"}}
```

* **format** - defines output format of the date/time
* **input\_format** - defines the input format of your date string (this must be used for consistent date interpretation if your input format is different from ISO format)
* **language** - output language for date/time. See supported languages below.
* **offset** - add/subtract offset to a given date. This can be used to calculate due dates, valid-until, etc. See offset examples below.

#### Examples:

<table><thead><tr><th width="332.38802083333337">Example</th><th align="center">Input</th><th align="center">Output</th></tr></thead><tbody><tr><td><code>{{format_date _date format="DD-MM-YY"}}</code></td><td align="center">2019-05-25</td><td align="center">25-05-19</td></tr><tr><td><code>{{format_date _date format="MMMM DD YYYY" locale="fr"}}</code></td><td align="center">2019-05-25</td><td align="center">mai 25 2019</td></tr><tr><td><code>{{format_date _date format="MMMM DD YYYY" locale="en" offset="+1years"}}</code></td><td align="center">2019-08-20</td><td align="center">August 20 2020</td></tr><tr><td><code>{{format_date _date offset="+1years"}}</code></td><td align="center">2019-08-20</td><td align="center">08-20-2020</td></tr></tbody></table>

| Example formats    | Output                    |
| ------------------ | ------------------------- |
| DD-MM-YY           | 21-11-18                  |
| Do-MM-YY           | 6th-08-21                 |
| ddd MMM DD HH:ss   | Wed Nov 21 14:08:25       |
| MMMM DD YYYY HH:ss | November 21 2018 14:08:25 |
| MMMM DD YYYY       | November 21 2018          |
| MMM DD YYYY        | Nov 21 2018               |
| YYYY-MM-DD         | 2018-11-21                |
| MM-DD-YYYY         | 01-22-2006                |
| MM/DD/YYYY         | 01/22/2006                |
| MM/DD/YY           | 01/22/06                  |
| DD-MM-YYYY         | 22-01-2006                |
| DD/MM/YYYY         | 22/01/2006                |
| DD/MM/YY           | 22/01/06                  |
| X                  | 1542758400                |

### Date/Time Format Cheatsheet

<table><thead><tr><th width="172.40625"></th><th width="150.97786458333334">Token</th><th>Output</th></tr></thead><tbody><tr><td><strong>Year</strong></td><td>YYYY</td><td>2000, 2001, 2002 ... 2012, 2013</td></tr><tr><td></td><td>YY</td><td>00, 01, 02 ... 12, 13</td></tr><tr><td><strong>Month</strong></td><td>MMMM</td><td>January, February, March ...</td></tr><tr><td></td><td>MMM</td><td>Jan, Feb, Mar ...</td></tr><tr><td></td><td>MM</td><td>01, 02, 03 ... 11, 12</td></tr><tr><td></td><td>M</td><td>1, 2, 3 ... 11, 12</td></tr><tr><td><strong>Day of Year</strong></td><td>DDDD</td><td>001, 002, 003 ... 364, 365</td></tr><tr><td></td><td>DDD</td><td>1, 2, 3 ... 364, 365</td></tr><tr><td><strong>Day of Month</strong></td><td>DD</td><td>01, 02, 03 ... 30, 31</td></tr><tr><td></td><td>D</td><td>1, 2, 3 ... 30, 31</td></tr><tr><td></td><td>Do</td><td>1st, 2nd, 3rd, 4th ...... 30th, 31st</td></tr><tr><td><strong>Day of Week</strong></td><td>dddd</td><td>Monday, Tuesday, Wednesday ...</td></tr><tr><td></td><td>ddd</td><td>Mon, Tue, Wed ...</td></tr><tr><td></td><td>d</td><td>1, 2, 3 ... 6, 7</td></tr><tr><td><strong>Hour</strong></td><td>HH</td><td>00, 01, 02 ... 23, 24</td></tr><tr><td></td><td>H</td><td>0, 1, 2 ... 23, 24</td></tr><tr><td></td><td>hh</td><td>01, 02, 03 ... 11, 12</td></tr><tr><td></td><td>h</td><td>1, 2, 3 ... 11, 12</td></tr><tr><td><strong>AM / PM</strong></td><td>A</td><td>AM, PM</td></tr><tr><td></td><td>a</td><td>am, pm</td></tr><tr><td><strong>Minute</strong></td><td>mm</td><td>00, 01, 02 ... 58, 59</td></tr><tr><td></td><td>m</td><td>0, 1, 2 ... 58, 59</td></tr><tr><td><strong>Second</strong></td><td>ss</td><td>00, 01, 02 ... 58, 59</td></tr><tr><td></td><td>s</td><td>0, 1, 2 ... 58, 59</td></tr><tr><td><strong>Sub-second</strong></td><td>SSS</td><td>000, 001, 002 ... 998, 999</td></tr><tr><td></td><td>SS</td><td>00, 01, 02 ... 98, 99</td></tr><tr><td></td><td>S</td><td>0, 1, 2 ... 8, 9</td></tr><tr><td><strong>Timestamp</strong></td><td>X</td><td>1381685817</td></tr></tbody></table>

### Language

<table><thead><tr><th width="155.9296875">Language code</th><th>Language &#x26; Country</th></tr></thead><tbody><tr><td>en-au</td><td>English (Australia)</td></tr><tr><td>en-ca</td><td>English (Canada)</td></tr><tr><td>en-ie</td><td>English (Ireland)</td></tr><tr><td>en-il</td><td>English (Israel)</td></tr><tr><td>en-nz</td><td>English (New Zealand)</td></tr><tr><td>en-gb</td><td>English (United Kingdom)</td></tr><tr><td>fr</td><td>French</td></tr><tr><td>fr-ca</td><td>French (Canada)</td></tr><tr><td>fr-ch</td><td>French (Switzerland)</td></tr><tr><td>de</td><td>German</td></tr><tr><td>de-at</td><td>German (Austria)</td></tr><tr><td>de-ch</td><td>German (Switzerland)</td></tr><tr><td>hu</td><td>Hungarian</td></tr><tr><td>pt</td><td>Portuguese</td></tr></tbody></table>

### Parsing dates accurately with Input Format

If the date values you pass to your date fields are in a specific format (for example, `DD/MM/YYYY`), you can use the `input_format` parameter to specify the format of your input dates.

Example - Syntax:

```
{{format_date due_date input_format='DD/MM/YYYY' format=”dddd, DD MMMM YYYY”}} 
```

Input data:

```
due_date = '31/12/2025'
```

Output:

```
Tuesday, 08 April 2025
```

If input\_format is not used, the due\_date value will be treated as an invalid date and the input date will be printed as-is on the document.

### Add/Subtract Time - Manipulate a date and/or time by adding/subtracting time

To adjust a date/time by a specific amount, you need to supply `<+/-> <amount as a number> <unit>` as the value for offset. Unit can be "years", "months", "weeks", "days", "hours", "minutes", or "seconds". Here are some examples:

* `+1hours`
* `-3days`
* `+5years+2months-3minutes`
* `+8h`

| Example                                                                    |    Input   |       Output      |
| -------------------------------------------------------------------------- | :--------: | :---------------: |
| `{{format_date _date format="MMMM DD YYYY" locale="en" offset="+1years"}}` | 2019-08-20 |   August 20 2020  |
| `{{format_date _date format="MMMM DD, YYYY" offset="+6months"}}`           | 2019-08-20 | February 20, 2020 |
| `{{format_date _date offset="+1years"}}`                                   | 2019-08-20 |     08-20-2020    |

## Format Number

This helper can be used to change the format of a number, including its thousands with separators, decimal with separators and precision.

#### Syntax

```
{{format_number number output_format="in" thousand_separator="thousand_sep" decimal_separator="decimal_sep" precision="number_of_decimal_places"}}
```

* **output\_format** (optional) - desired format of the number. Supported formats:
  * **default** - millions, billions.
  * **in** - lakh, crore.
* **thousand\_separator** (optional, default: `,` comma) - the character the should be used to separate thousands position.
* **decimal\_separator** (optional, default: `.`period) - the character that should be used to separate decimals.
* **precision** (optional, default: not-set) - number of decimal places required.

<table><thead><tr><th width="490.14453125">Example</th><th>Input</th><th>Output</th></tr></thead><tbody><tr><td><code>{{format_number price thousand_separator="." precision="0"}}</code></td><td>123456</td><td>123.456</td></tr><tr><td><code>{{format_number invoice_total thousand_separator="." decimal_separator="," precision="3"}}</code></td><td>12345.12345</td><td>12.345,123</td></tr><tr><td><code>{{format_number number precision="2"}}</code></td><td>123456</td><td>123,456.00</td></tr><tr><td><code>{{format_number number decimal_separator=","}}</code></td><td>909.876</td><td>909,876</td></tr><tr><td><code>{{format_number number output_format="in"}}</code></td><td>87904.987</td><td>87,904.987</td></tr><tr><td><code>{{format_number number output_format="in" thousand_separator="," decimal_separator="." precision="2"}}</code></td><td>87904.987</td><td>87,904.99</td></tr></tbody></table>

## Abbreviation

The **`abbreviate`** formatter allows you to automatically generate abbreviations by extracting the first letter of each word in a given text field and capitalizing it. This is useful for standardizing text and ensuring consistency in documents.

#### **Syntax:**

```
{{abbreviate token separator}}
```

* `token`: The field from which the abbreviation will be generated.
* `separator` (optional): A character or string to place between the extracted letters. If omitted, the abbreviation will be formed without separators.

#### Example Usage:

| Input Text              | Syntax                            | Output |
| ----------------------- | --------------------------------- | ------ |
| United Nations          | `{{abbreviate Organization}}`     | UN     |
| Central Processing Unit | `{{abbreviate partName "-"}}`     | C-P-U  |
| John Doe                | `{{abbreviate customerName "."}}` | J.D    |

## Format Phone

The **`format_phone`** formatter allows you to format phone numbers according to a specified pattern, ensuring consistency and readability in your documents.

**Syntax:**

```
{{format_phone landline format}}
```

* `landline`: The field containing the phone number.
* `format`: The desired format for the output. Ex: `(%3) %3-%4`

<table><thead><tr><th width="226.49609375">Input</th><th width="360.47265625">Syntax</th><th>Output</th></tr></thead><tbody><tr><td>landline=1234567890</td><td><code>{{format_phone landline "(%3) %3-%4"}}</code></td><td>(123) 456-7890</td></tr><tr><td>landline=9876543210</td><td><code>{{format_phone landline "+1-%3-%3-%4"}}</code></td><td>+1-987-654-3210</td></tr><tr><td>id_number=123456789012</td><td><code>{{format_phone id_number "%4-%4-%4"}}</code></td><td>1234-5678-9012</td></tr></tbody></table>

## Number to words

The **Number to Words** helper in Docupilot allows you to convert numeric input into words. This functionality supports customizable output formats, including options for language and currency.

#### Syntax

```
{{number_to_words input output_format="in" suffix=" " decimal_suffix=" " language=" "}}
```

* `input`: The numeric value to be converted.
* `output_format` (optional): Defines the format (default: `us`).
* `suffix` (optional): Adds a suffix for currency or other units (e.g., `dollars`, `kg`).
* `decimal_suffix` (optional): Defines a suffix for decimal parts if applicable (e.g., `cents`, `paise`).
* `language` (optional): Specifies the language for the output text. Learn more about available languages [here](#language).

| Example                                                                                  | Input    | Output                                                                                 |
| ---------------------------------------------------------------------------------------- | -------- | -------------------------------------------------------------------------------------- |
| `{{number_to_words number}}`                                                             | 123456   | one hundred and twenty-three thousand four hundred and fifty-six                       |
| `{{capitalize (number_to_words amount suffix="dollars" decimal_suffix="cents")}}`        | 800.658  | Eight hundred dollars six hundred and fifty-eight cents                                |
| `{{number_to_words currency output_format="in" suffix="rupees" decimal_suffix="paise"}}` | 9893.567 | nine thousand eight hundred and ninety-three rupees five hundred and sixty-seven paise |
| `{{number_to_words price output_format="in" suffix="rupees"}}`                           | 7000000  | seventy lakh rupees                                                                    |
| `{{number_to words price suffix="dollars"}}`                                             | 7000000  | seven million dollars                                                                  |
| `{{number_to_words input language="fr"}}`                                                | 8795     | huit mille sept cent quatre-vingt-quinze                                               |
| `{{number_to_words price suffix="Euros" decimal_suffix="Cents" language="de"}}`          | 8790.345 | achttausendsiebenhundertneunzig Euros dreihundertfünfundvierzig Cents                  |

{% hint style="info" %}
Note:

* The output is always in **words**.
* Decimals will be converted separately using the `decimal_suffix`.
* Use `capitalize` if the first letter needs to be uppercase.
  {% endhint %}

## Number to Ordinal

The `number_to_ordinal` formatter converts a numeric input into its ordinal form, expressed in words. This is useful for formatting numbers in legal, financial, or formal documents.

#### Syntax

```
{{number_to_ordinal number}}
```

* `number`: The numeric value to be converted into an ordinal.

#### Example Usage

#### Basic Conversion

```
{{number_to_ordinal number}}
```

**Input:**

```
number = 800
```

**Output:**

```
eight hundredth
```

#### Capitalizing Ordinal Output

```
{{capitalize (number_to_ordinal number1)}}
```

**Input:**

```
number1 = 582
```

**Output:**

```
Five hundred and eighty-second
```

#### Handling Decimal Values

```
{{number_to_ordinal number}}
```

**Input:**

```
number = 789.325
```

**Output:**

```
seven hundred and eighty-ninth
```

{% hint style="info" %}
Note:

* The output is always in **words**.
* Decimals are ignored when determining the ordinal form.
* Use `capitalize` if the first letter needs to be uppercase.
  {% endhint %}

## Join

The **Join** helper in Docupilot allows you to combine an array of strings or extract and join a specific property from a list of objects into a single string, using a specified separator. If no separator is provided, a comma (`,`) is used by default.

#### Syntax

```
{{join content separator lookup="lookup_key"}}
```

* `content`: The array of strings to join.
* `separator` (optional): The character or string to separate values (default: `,`).
* `lookup` (optional): The key to extract values from objects in an array.

#### Example Usage

#### Joining a Simple List with a Comma

```
{{join SampleName ","}}
```

**Input:**

```json
[
  "John",
  "Mary",
  "Paul"
]
```

**Output:**

```
John,Mary,Paul
```

#### Joining Object Values Using a Lookup Key

```
{{join employees lookup="Name.Firstname"}}
```

**Input:**

```json
[
  {"Name": {"Firstname": "Peter", "Lastname": "Parker"}},
  {"Name": {"Firstname": "Tony", "Lastname": "Stark"}},
  {"Name": {"Firstname": "Steve", "Lastname": "Rogers"}}
]
```

**Output:**

```
Peter,Tony,Steve
```

{% hint style="info" %}
Note:

* If `lookup` is provided, the helper will extract the specified key from each object before joining.
* The separator can be any character (e.g., `|`, `;`, `-`).
  {% endhint %}

## Replace

The **`replace`** formatter allows you to replace specific text or patterns within a string using either direct text matching or regular expressions (regex). This is useful for modifying content dynamically in templates.

#### Syntax

```
{{replace input match_str replace_str}}
```

* `input`: The text to be processed.
* `match_str`: The text or regex pattern to match.
* `replace_str`: The replacement string.

#### Example Usage

**Replacing a Specific Word**

```
{{replace text find replace}}
```

**Input:**

```
text = "Mary Ross"
find = "Ross"
replace = "Jane"
```

**Output:**

```
Mary Jane
```

**Replacing Characters Using Regex**

```
{{replace input (regex "[a]" "g") "e"}}
```

**Input:**

```
input = "Ragax"
```

**Output:**

```
Regex
```

**Using Regex with Replace**

Regex can be used to match multiple occurrences dynamically:

```
{{replace text (regex "[0-9]+" "g") "#"}}
```

**Input:**

```
text = "ID12345XYZ678"
```

**Output:**

```
ID#XYZ#
```

{% hint style="info" %}
Note:

* `match_str` can be either a direct text match or a regex pattern.
* Regex patterns must be enclosed within `(regex "pattern" "flags")`.
* the `g` (global) flag ensures multiple occurrences are replaced.
  {% endhint %}

## Regex

The **Regex** helper in Docupilot allows you to apply regular expressions to manipulate text dynamically in your templates. It is useful for pattern matching, replacing, or extracting specific content from text fields.

#### Syntax

```
{{regex pattern flags}}
```

* `pattern`: The regular expression pattern to apply.
* `flags` (optional): Regex flags for customization (default: no flags set).
* Commonly used flags:
  * `g` (global) - Applies the regex to all matches.
  * `i` (case insensitive) - Ignores case differences.
  * `m` (multi-line) - Allows multi-line matching.

#### Example Usage

#### Replacing Lowercase Letters with Asterisks

```
{{replace text (regex "[a-z]" "g") "*"}}
```

**Input:**

```
text = "MaryJane123"
```

**Output:**

```
M***J***123
```

**Replacing Numbers with a Symbol**

```
{{replace text (regex "[0-9]+" "g") "$"}}
```

**Input:**

```
text = "1239HomeAlone42"
```

**Output:**

```
$HomeAlone$
```

#### Extracting Only Numbers

```
{{replace text (regex "[0-9]+" "g") "*"}}
```

**Input:**

```
text = "My number is 456 and my ID is 7890."
```

**Output:**

```
My number is *** and my ID is ****.
```

{% hint style="info" %}
**Note**

* **Regex must be used with a helper like `replace`, `match`, or `test`.**
* Ensure that the regex pattern is correctly formatted.
* Flags modify how the pattern behaves (e.g., `g` for multiple matches).
  {% endhint %}

## Strip

The **Strip** helper in Docupilot allows you to remove specific characters from the beginning, end, or both sides of a given input. By default, it removes whitespace.

#### Syntax

```
{{strip input match_str side="left"}}
```

* `input`: The string from which characters will be removed.
* `match_str` (optional): The characters to be stripped (default: whitespace).
* `side` (optional): Determines where to remove characters from. Options:
  * `left`: Removes from the beginning.
  * `right`: Removes from the end.
  * `both` (default): Removes from both sides.

#### Example Usage

#### Removing Whitespace (Default Behavior)

```
{{strip text}}
```

**Input:**

```
text = "   Hello World   "
```

**Output:**

```
Hello World
```

#### Removing Specific Characters

```
{{strip text "-"}}
```

**Input:**

```
text = "---Hello---"
```

**Output:**

```
Hello
```

#### Stripping Characters from the Left Side

```
{{strip text "0" side="left"}}
```

**Input:**

```
000123450
```

**Output:**

```
123450
```

#### Stripping Characters from the Right Side

```
{{strip "text" "%" side="right"}}
```

**Input:**

```
text = "12345%%%"
```

**Output:**

```
12345
```

{% hint style="info" %}
Note:

* If `side` is omitted, the default behavior removes characters from both sides.
* `match_str` can be any character or set of characters.
* If `match_str` is not specified, only whitespace is removed.
  {% endhint %}

## Split

The **`split`** formatter allows you to break a string into an array based on a specified separator. This is useful for handling lists or structured text in templates.

**Syntax:**

```
{{split input separator}}
```

* `input`: The string to be split.
* `separator` (optional): The delimiter used for splitting. This can be a text character or a **regular expression** (Regex). If omitted, the default separator is `,` (comma).

#### Example Usage

#### Splitting by Default Separator (Comma)

```
{{#each (split items)}}
  {{this}}
{{/each}}
```

**Input:**

```
items = "apple,banana,cherry"
```

**Output:**

```
apple
banana
cherry
```

#### Splitting by Custom Separator

```
{{#each (split people "|")}}
  {{this}}
{{/each}}
```

**Input:**

```
people = "John|Doe|Smith"
```

**Output:**

```
John
Doe
Smith
```

#### Splitting Using Regex:

```
{{#each (split text (regex "\d+" "g"))}}
  {{this}}
{{/each}}
```

**Input:**

```
text = John1Doe2Cleveland
```

**Output:**

```
John
Doe
Cleveland
```

{% hint style="info" %}
Note:

* **Split is a nested formatter**, meaning it must be used within other formatters like `each` or `list`.
* When splitting on spaces, use `" "` as the separator.
* *See* [*Regex*](#regex) *for more information on how to use Regular Expressions.*
  {% endhint %}

## Sort

The **Sort** helper in Docupilot allows you to arrange data in ascending (`asc`) or descending (`desc`) order based on a specified key. This is useful for organizing lists dynamically in templates.

**Syntax**

```
 {{sort content order=order lookup="lookup_key"}}
```

* `content`: The array or list to be sorted.
* `order`: The sorting order (`asc` for ascending, `desc` for descending).
* `lookup` (optional): The key used for sorting within objects.

#### **Example Usage:**

**Sorting Numbers:**

```
{{#each (sort cost order="desc")}}
{{this}}
{{/each}}
```

**Input:** `[100, 50, 200]`

**Output:**

```
200
100
50
```

**Sorting Objects by a Key:**

```
{{#each (sort items lookup="price" order="asc")}}
  {{name}} is available at {{price}} per {{unit}}.
{{/each}}
```

**Input:**

```
[
  {"name": "Apple", "price": 3, "unit": "kg"},
  {"name": "Banana", "price": 1, "unit": "kg"},
  {"name": "Cherry", "price": 2, "unit": "kg"}
]
```

**Output:**

```
Banana is available at 1 per kg.
Cherry is available at 2 per kg.
Apple is available at 3 per kg.
```

{% hint style="info" %}
Note:

* **Sort is a nested formatter**, meaning it must be used within other formatters like `each` or `list`.
* The **lookup key** is required when sorting objects.
* Sorting is case-sensitive; ensure consistent casing in text-based sorting.
  {% endhint %}

## Filter

The `filter` helper can be used to refine lists by applying specific conditions, effectively narrowing down the data to what's most relevant. The syntax for the `filter` helper is `{{filter items condition}}`, where `items` is the list to be filtered and `condition` is the criteria applied to each item. Conditions can range from straightforward comparisons, like `(department == "Sales")`, to more complex expressions like `((LeadScore > 60 and LeadScore <= 80) and LeadRole == "vp" and LeadIndustry == "Healthcare")`. Here are a few examples showcasing the versatility of the `filter` helper:

1. Print a list of employees from Sales department and their salaries:

```
{{#each (filter Employees (Department == "Sales"))}}
{{FirstName}} | {{LastName}} | {{Salary}}
{{/each}}
```

2. Filter can be combined with sort to handle more advanced use-cases: For example, to print list of products in inventory that are priced higher than or equal to 50$ in descending order of price:

```
{{#each (sort (filter InventoryItems (Price >= 50)) order="desc" lookup="Price")}}
{{ProductName}} | {{Cateogory}} | {{Price}} | {{Margin}}
{{/each}}
```

3. Filtering a list of events to include only those happening in December

```
Following is the event catalog for December:
{{#each (filter Events (Month == "December"))}}
{{EventName}} takes place on {{EventScheduleDate}} at {{EventScheduleTime}}
{{/each}}
```

4. Above example can be modified further to make the month dynamic too, but we need to use Look-backs to achieve the same:

```
Following is the event catalog for {{DesiredMonth}}:
{{#each (filter Events (Month == ../DesiredMonth))}}
{{EventName}} takes place on {{EventScheduleDate}} at {{EventScheduleTime}}
{{/each}}
```

5. Filtering a collection of books to display only those published after the year 2000

```
{{#each (filter Books (PublishedYear > 2000))}}
{{BookName}} | {{Author}} | {{PublishedYear}}
{{/each}}
```

6. Filter a dataset to exclude items marked as inactive

```
{{#each (filter dataSet (status != "inactive"))}}
{{property1}} - {{property2}}
{{/each}}
```

7. Filter Leads that are VPs in Healthcare with lead score greater than 80

```
{{#each (filter Leads (LeadScore > 80 and (lower LeadRole) == "vp" and LeadIndustry == "Healthcare"))}}
{{LeadName}} | {{LeadEmail}} | {{LeadScore}}
{{/each}}
```

8. Print Leads that are from Healthcare or Pharma industry with lead score higher than 80 but lower than 95, in descending order of lead score.

```
{{#each (sort (filter Leads ((LeadIndustry == "Healthcare" or LeadIndustry == "Pharma") and (LeadScore > 80 and LeadScore < 95))) order="desc" lookup="LeadScore")}}
{{LeadName}} | {{LeadEmail}} | {{LeadScore}}
{{/each}}
```

These examples demonstrate the `filter` helper's capability to perform both simple and complex data filtering within a template, making it an essential tool for crafting dynamic content.

<div><figure><img src="/files/R0T7LQksYuP9WXK36HGC" alt=""><figcaption><p>Example Template using Filter helper</p></figcaption></figure> <figure><img src="/files/HfylFY67xGLrecr9AhQs" alt=""><figcaption><p>Example Output using Filter helper</p></figcaption></figure></div>

{% hint style="info" %}
Note:

* **Filter is a nested formatter**, meaning it must be used within other formatters like `each` or `list`.
* The **condition** is required when filtering a list of items.
  {% endhint %}

## Set and Get

**`{{set ...}}`** and **`{{get ...}}`** can be used to store values and access them later in your template. This is useful when you want to assign calculated values, reuse data, or simplify complex logic.

Syntax:

```
{{set "variable_name" "value"}}
{{get "variable_name"}}
```

* **set** stores a value to a variable name.
* **get** retrieves the stored value for later use.

**Example 1:**

Template:

```
{{set "name" "New York"}}
Welcome to the city {{get "name"}}
```

Output:

```
Welcome to the city New York
```

**Example 2:**

Template:

```
{{set "total" (calc "Price * Qty")}}
Total Amount: {{get "total"}}
```

Input:

```
Price = 100; Qty = 5
```

Output:

```
Total Amount: 500
```

**Example 3:**

Template:

```
{{set "discountPercentage" 20}}
{{#each items}}
{{#if (amount > 500)}}{{set "discountPercentage" 50}}{{/if}}
{{name}} @ {{amount}}
{{/each}}
Discount percentage to be applied = {{get "discountPercentage"}}%
```

Input1:

<pre class="language-json"><code class="lang-json"><strong>items = [
</strong>  {name: Service1, amount: 20},
  {name: Service2, amount: 30}
<strong>]
</strong></code></pre>

Output1:

```
Service1 @ 50
Service2 @ 30
Discount percentage to be applied = 20%
```

Input2:

<pre class="language-json"><code class="lang-json"><strong>items = [
</strong><strong>  {name: ServiceMini, amount: 20},
</strong><strong>  {name: ServiceMega, amount: 550}
</strong><strong>]
</strong></code></pre>

Output2:

```
ServiceMini @ 20
ServiceMega @ 550
Discount percentage to be applied = 50%
```

{% hint style="warning" %}
**`set`** and **`get`** are recommended over the older **`var`** for better clarity and future compatibility. **`var`** is in now legacy and should be avoided in all new templates.
{% endhint %}

## Var (legacy)

The `var` is a powerful tool designed for both storing and retrieving data within templates, enabling dynamic variable use. This functionality allows users to assign values to tokens directly within their documents through a simple syntax: `{{var "token" value}}`. For instance, assigning a numerical value or even transferring values between tokens is effortlessly done using `{{var "cost" 500}}` or `{{var "amount" MRP}}`, respectively. Retrieving the stored data is just as straightforward; by calling `{{var "token"}}`, the value assigned to the specified token is seamlessly inserted into the document.

#### Storing Data

Syntax: `{{var "token" value}}`

| Example                | Output                                                       |
| ---------------------- | ------------------------------------------------------------ |
| `{{var "cost" 500}}`   | Here the token cost is assigned a value of 500.              |
| `{{var "price" 7599}}` | Here the token price is assigned a value of 7599.            |
| `{{var "amount" MRP}}` | Here the value in token MRP is assigned to the token amount. |

#### Retrieving Data

Syntax: `{{var "token"}}`

| Example           | Output |
| ----------------- | ------ |
| `{{var "cost"}}`  | 500    |
| `{{var "price"}}` | 7599   |

## Pad helper

Pad helper fills up the input to the desired width by adding a single character repeatedly either at the beginning or at the end.

Syntax: `{{pad number output_width pad_with='character' style='prefix|suffix'}}`

Example 1:\
`{{pad number 7}}`

| Input | Output  |
| ----- | ------- |
| 123   | 0000123 |

Example 2:\
`{{pad number 9 pad_with='#' style='suffix'}}`

| Input  | Output    |
| ------ | --------- |
| 123456 | 123456### |

## Aggregate

Aggregate functionality helps to accumulate data from a collection of items to return a single result (like adding numbers in a list). It is useful in scenarios like invoice processing, where it can compute totals such as the total number of items sold, invoice sub total, grand total, factoring in discounts, etc.

Example: Consider a case where you want to generate an invoice which can auto-calculate quantity sold, sub total and grand total. Assuming `InvoiceLineItems` is the field which contains all line items where each line item contains properties: `name`, `qty` , `unit_price` and `discount`.

To calculate the total number of items sold as part of this invoice, we need to add `qty` from each line item. It can be done using:

`{{aggregate InvoiceLineItems formula="qty" operation="add"}}`

To compute the invoice total before applying any discounts, we need to add the result of `qty * unit_price` from each line item. This can be achieved using:

`{{aggregate InvoiceLineItems formula="qty * unit_price" operation="add"}}`

To compute discounted invoice total where discounts are applicable as percentage for each line item separately, we need to add the result of `qty * unit_price * (1 - discountPercentage / 100)` for each line item.

`{{aggregate InvoiceLineItems formula="qty * unit_price * (1 - discountPercentage / 100)" operation="add"}}`

*Note that each operator inside formula should have a leading and trailing space to work accurately. For example "qty\*unit\_price" will not work, only "qty \* unit\_price" will. This limitation may be addressed in one of our future updates.*

<div><figure><img src="/files/saW8K1i2jPzilAllPGcb" alt="" width="375"><figcaption><p>Sample Invoice using aggregate helper - Input</p></figcaption></figure> <figure><img src="/files/1s1ixj1hwvA2HtueLCmv" alt="" width="563"><figcaption><p>Sample Invoice using aggregate helper - Output</p></figcaption></figure></div>

## Concat

Syntax : `{{concat string1 string2 ....}}`

Example:\
`{{insert_image (concat "https:" url) 300 300}}`

Input:\
`//raw.githubusercontent.com/tiholic/exif-orientation-examples/master/Portrait_0.jpg`

Output:

![](/files/-McDhPFQJTke8vykBKNh)

## Group By

Group by helper groups the data with the value of lookup key as grouping criteria.

Syntax: `{{group_by ListName lookup="lookup_key"}}`

`Key` and `items` can be accessed from inside the iterator(`#each` or `#list`). `Key` contains value of `"lookup_key"` for the current record, `items` contain the records which are present under current group.

**Example 1:**

<figure><img src="/files/exDKy8fEZVPyDCAZ1KOH" alt=""><figcaption></figcaption></figure>

In this example:

* `employees` is the list being grouped.
* `lookup="Department"` groups the list based on the `Department` field.
* `{{key}}` holds the current group value (i.e., department name).
* `items` contains all employees in that department.
* The inner loop ( `{{#each items}}...{{/each}}` ) displays each employee’s ID, name, and designation under their respective department.

{% hint style="info" %}
In case if you are using this inside a table, ensure to merge all cells in the rows with opening or closing of each.
{% endhint %}

**Sample Input:**

| Emp\_ID | Employee\_Name | Designation | Department |
| ------- | -------------- | ----------- | ---------- |
| E001    | Alice          | Analyst     | Sales      |
| E002    | Bob            | Manager     | HR         |
| E003    | Charlie        | Associate   | HR         |
| E004    | John           | Executive   | Sales      |

**Sample Output :**

This will generate output grouped by department, with employee details listed under each.

<figure><img src="/files/EfRuFusyJwQLXHsWmLJc" alt=""><figcaption></figcaption></figure>

**Example 2:**

```handlebars
{{#each (group_by employees lookup="role.code")}}
Number of employees in role {{key}}: {{items.length}} and they are {{join items ", " lookup="name.first"}}
{{/each}}
```

Input: *(JSON)*

```json
{
  "employees": [
    { "role": {"code": "TL"}, "name": {"first": "Dave" } },
    { "role": {"code": "TL"}, "name": {"first": "Chris"} },
    { "role": {"code": "PM"}, "name": {"first": "Matt" } },
    { "role": {"code": "TL"}, "name": {"first": "Emma" } },
    { "role": {"code": "PM"}, "name": {"first": "Jenn" } }
  ]
}
```

Output :

```
Number of employees in role TL: 3 and they are Dave, Chris, Emma
Number of employees in role PM: 2 and they are Matt, Jenn
```

In the above example,

* **"TL"** and "**PM"** are the group **`keys`**.
* `items` corresponding to the key "**TL"** are :
  * `{ "role": { "code": "TL" }, "name": { "first": "Emma" } }`
  * `{ "role": { "code": "TL" }, "name": { "first": "Chris" } }`
  * `{ "role":{ "code": "TL" }, "name": { "first": "Dave" } }`
* `items` corresponding to the key "**PM"** are:
  * `{ "role": { "code": "PM" }, "name": { "first": "Jenn" } }`
  * `{ "role": { "code": "PM" }, "name": { "first": "Matt" } }`

**Example 3:**

```handlebars
{{#each (group_by places)}}
Number of branches in {{key}}: {{items.length}}
{{/each}}
```

Input: *(JSON)*

```json
{
  "places": [
    "New York",
    "Las Vegas",
    "Chicago",
    "New York",
    "Las Vegas",
    "New York"
  ]
}
```

Output:

```
Number of branches in New York: 3
Number of branches in Las Vegas: 2
Number of branches in Chicago: 1
```

In the above example,

* **"New York"**, "**Las Vegas"** and "**Chicago"** are the group `keys`.
* Number of `items` corresponding to the key "**New York"** are 3.
* Number of `items` corresponding to the key "**Las Vegas"** are 3.
* Number of `items` corresponding to the key "**Chicago"** is 1.

## Inserting a link

To insert a dynamic URL into your document.

Format: **`{{insert_link url text=text}}`**

<table><thead><tr><th width="200" align="center">Example</th><th width="285" align="center">Input</th><th align="center">Output</th></tr></thead><tbody><tr><td align="center">{{insert_link url}}</td><td align="center">url=https://docupilot.app/</td><td align="center"><a href="https://docupilot.app/">https://docupilot.app/</a></td></tr><tr><td align="center">{{insert_link url text=url_text}}</td><td align="center"><p>url=https://docupilot.app/</p><p>url_text="Example"</p></td><td align="center"><a href="https://docupilot.app/">Example</a></td></tr><tr><td align="center">{{insert_link url text="Click Here"}}</td><td align="center">url=https://docupilot.app/</td><td align="center"><a href="https://docupilot.app/">Click Here</a></td></tr></tbody></table>

#### Hyperlink style customization in Word documents

Inserted hyperlinks follow the source style in Builder templates. In case of Word Document templates, style customization can be done by opening **Format > Styles > Search and select "Hyperlink" >** click **Modify > Update to desired style** and click **Ok**

## URL encode

URL encode helper replaces special characters inside a URL with encoded text.

Syntax : `{{url_encode URL is_url=true|false}}`

**Example1:**

Syntax in Template

```handlebars
{{url_encode url is_url=true}}
```

Input sent to the template (JSON):

```json
{
  "url": "https://dummyimage.com/600x400/000/fff&text=hello world" 
}
```

Generated Output:

```
https://dummyimage.com/600x400/000/fff&text=hello%20world
```

**Example2:**

Syntax in Template

```handlebars
https://example.com?open={{url_encode url_part is_url=false}}
```

Input sent to the template (JSON):

```json
{
  "url_part": "https://dummyimage.com/600x400/000/fff&text=hello world"
}
```

Generated Output:

```
https://example.com?open=https%3A%2F%2Fdummyimage.com%2F600x400%2F000%2Ffff%26text%3Dhello%20world
```

## URL decode

URL decode helper decodes encoded URLs into pre-encoded forms.

Syntax : `{{url_decode URL is_url=true|false}}`

**Example1:**

Syntax in Template

```handlebars
{{url_decode url is_url=true}}
```

Input sent to the template (JSON):

```json
{ 
  "url": "https://dummyimage.com/600x400/000/fff&text=hello%20world"
}
```

Generated Output:

```
https://dummyimage.com/600x400/000/fff&text=hello world
```

**Example2:**

Syntax in Template

```handlebars
{{url_decode url is_url=false}}
```

Input sent to the template (JSON):

```json
{ 
  "url": "https%3A%2F%2Fdummyimage.com%2F600x400%2F000%2Ffff%26text%3Dhello%20world"
}
```

Generated Output:

```
https://dummyimage.com/600x400/000/fff&text=hello world
```

{% hint style="warning" %}
Encoding or decoding a URL depends on the value of the parameter 'is\_url'. If the value is true, only the query parameter part of the complete URL is encoded/decoded else, the whole of the URL is encoded/decoded.\
The Default value of is\_url is set as false.
{% endhint %}

## Rand

Rand will return a random value between the min and max values passed.

Syntax: `{{rand min max}}`

| Example                  | Input                     | Output                                                               |
| ------------------------ | ------------------------- | -------------------------------------------------------------------- |
| {{rand min max}}         | <p>min: 2<br>max: 500</p> | <p>could be any random number between 2 and 500<br>Ex: 436.89318</p> |
| {{round (rand min max)}} | <p>min: 2<br>max: 500</p> | <p>could be any random integer value</p><p>ex: 437</p>               |

{% hint style="info" %}
**rand** returns a decimal value between the given min and max. Use **round** along with **rand** to get an integer value.
{% endhint %}

## As Number

As Number converts any given input to a valid number.

Syntax: `{{as_number FieldName}}`

| Example                                                                                                                                                             | Input                                | Output                         |
| ------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------ | ------------------------------ |
| {{as\_number value}}                                                                                                                                                | value: "**23.000**"(string)          | **23**(numerical value)        |
| <p>{{#if (as\_number input\_value) "<=" 100}}<br><strong>Value is less than 100.</strong><br>{{else}}<br><strong>Value is greater than 100.</strong><br>{{/if}}</p> | input\_value: "**98.767**"(string)   | **Value is less than 100.**    |
| <p>{{#if (as\_number input\_value) "<=" 100}}<br><strong>Value is less than 100.</strong><br>{{else}}<br><strong>Value is greater than 100.</strong><br>{{/if}}</p> | input\_value: "**101.9876**"(string) | **Value is greater than 100.** |

## As String

As String converts any given input to a valid string.

Syntax: `{{as_string FieldName}}`

<table><thead><tr><th width="377.3333333333333">Example</th><th>Input</th><th>Output</th></tr></thead><tbody><tr><td>{{as_string value}}</td><td>value: <strong>234.987</strong> (numerical value)</td><td>"<strong>234.987</strong>" (String)</td></tr><tr><td>{{#if (as_string input_value) "==" "23.000"}}<br><strong>Success</strong><br>{{else}}<br><strong>Fail</strong><br>{{/if}}</td><td>input_value: "<strong>23.000</strong>"(string)</td><td><strong>Success</strong></td></tr><tr><td>{{#if (as_string input_value) "==" "23.000"}}<br><strong>Success</strong><br>{{else}}<br><strong>Fail</strong><br>{{/if}}</td><td>input_value: "<strong>23.00</strong>"(string)</td><td><strong>Fail</strong></td></tr></tbody></table>

## As Boolean

As Boolean converts any given input into Boolean values **0**(False) and **1**(True).

String: `{{as_boolean FieldName}}`

<table><thead><tr><th width="353.3333333333333">Example</th><th>Input</th><th>Output</th></tr></thead><tbody><tr><td>{{as_boolean value}}</td><td>value: <strong>348</strong></td><td><strong>1</strong>(True)</td></tr><tr><td>{{as_boolean input_value}}</td><td>input_value: <strong>0</strong></td><td><strong>0</strong>(False)</td></tr><tr><td>{{#if (as_boolean input_value)}}<br><strong>Input received.</strong><br>{{else}}<br><strong>Input is empty.</strong><br>{{/if}}</td><td>input_value: <strong>123.9</strong></td><td><strong>Input received</strong></td></tr></tbody></table>


# Numerical Calculations

Want to calculate the numerical value for a field based on merge tokens? You can do so by entering your mathematical equation in the format below.

| **Operation**       | Syntax with two variables    | Syntax with a variable & constant      |
| ------------------- | ---------------------------- | -------------------------------------- |
| Addition            | {{add x y}}                  | {{add x 10}}                           |
| Subtraction         | {{subtract x y}}             | {{subtract x 10}}                      |
| Multiply            | {{multiply x y}}             | {{multiply x 10}}                      |
| Divide              | {{divide x y}}               | {{divide x 10}}                        |
| Modulo              | {{modulo x y}}               | {{modulo x 10}}                        |
| Rounding of numbers |                              | {{ceil x}} / {{floor x}} / {{round x}} |
| calc                | {{calc "price \* quantity"}} | {{calc "price \* 5"}}                  |

## Numerical Calculation in Loops & Tables

You can also use Numerical Calculation in Loops & Tables.

{% code title="Example" %}

```
{{#each line_items}}

Name: {{Name}}
Qty: {{Qty}}
Price: {{Price}}
Total: {{multiply Qty Price}}

{{/each}}

```

{% endcode %}

### Incrementing @index in Loops & Tables

When iterating through a list, `@index` is useful for displaying the position of each element within the loop. By default, `@index` starts from 0. However, you can adjust it to start from 1 by using the addition operator.

**Syntax for Incrementing `@index`**

To increment `@index` so that numbering starts from 1, you can use the `add` operator like this: `{{add @index 1}}`.

**Example**

Here's how you can use `@index` in a loop to display a sequence number along with other item details in a table format:

{% code title="Example" %}

```
{{#each line_items}}
Sno: {{add @index 1}}
Name: {{Name}}
Qty: {{Qty}}
Price: {{Price}}
Total: {{multiply Qty Price}}
{{/each}}

```

{% endcode %}

#### Calculating Minimum, Maximum, and Average Values

When working with repeated data—like a list or table of products, invoice, or transactions—you can use **min**, **max**, and **avg** helpers to calculate the lowest, highest, and average values from that list.

**Syntax**

Minimum Value : `{{min ListName lookup="FieldName"}}`

Maximum Value : `{{max ListName lookup="FieldName"}}`

Average Value : `{{avg ListName lookup="FieldName"}}`

**Example**

Consider a list of products with their quantities and prices:

{% code title="Example Syntax" %}

```
{{#each Product}}

Name: {{Name}}
Qty: {{Qty}}
Price: {{Price}}
Total: {{multiply Qty Price}}

{{/each}}

Lowest Price: {{min Product lookup="Price"}}
Highest Price: {{max Product lookup="Price"}}
Average Price: {{avg Product lookup="Price"}}
```

{% endcode %}

In this case, the **min**, **max**, and **avg** helpers calculate the lowest, highest, and average prices respectively from all products and are printed after the loop.

{% hint style="info" %}
These helpers can be used inside other numerical calculations.

For example, to find the difference between min and max prices, you can do:

{{subtract (max Product lookup="Price") (min Product lookup="Price") }}
{% endhint %}

### Rounding of numbers

Rounding of the numbers can be done using the helpers **ceil**, **floor**, and **round**.

#### Ceil

The helper **ceil** will round off the number to the nearest positive number which is greater than or equal to the give input number.

|  Example syntax |  Input | Output |
| :-------------: | :----: | :----: |
| {{ceil number}} | 198.58 |   199  |
|  {{ceil input}} | 187.24 |   188  |

#### Floor

The helper **floor** will round off the number to the nearest positive number which is lesser than or equal to the given input number.

|  Example syntax  |  Input | Output |
| :--------------: | :----: | :----: |
| {{floor number}} | 198.58 |   198  |
|  {{floor input}} | 187.24 |   187  |

#### Round

**Round** helper will round of the given number in accordance with the value in it's decimal place. If the value in decimal places is greater than 50, then it will round of to the **succeding number**.

|  Example syntax  |  Input  | Output |
| :--------------: | :-----: | :----: |
| {{round number}} |  198.58 |   199  |
|  {{round input}} | -187.74 |  -188  |

### Using calc Helper for Simplified Calculations

The `calc` helper is designed to simplify calculations within templates, enabling direct numerical operations—such as addition, subtraction, multiplication, and division— and supports complex operations with a single syntax. This functionality allows for dynamic number processing, enhancing the efficiency of document automation.​

#### Syntax

You can use the \`calc\` helper with the following syntax:

{{calc "expression"}}

<table data-header-hidden><thead><tr><th valign="top">Operator</th><th width="321" valign="top">Syntax</th><th width="137" valign="top">Input</th><th valign="top">Output</th><th data-hidden valign="top">Description</th></tr></thead><tbody><tr><td valign="top"><strong>Operator</strong></td><td valign="top"><strong>Syntax</strong></td><td valign="top"><strong>Input</strong></td><td valign="top"><strong>Output</strong></td><td valign="top"><strong>Description</strong></td></tr><tr><td valign="top">Add</td><td valign="top">{{calc "price + tax"}}</td><td valign="top">price = 500<br>tax = 30</td><td valign="top">530</td><td valign="top">Displays the sum of `price` and `tax`.</td></tr><tr><td valign="top">Subtract</td><td valign="top">{{calc "price - discount"}}</td><td valign="top">price = 100<br>discount = 10</td><td valign="top">90</td><td valign="top">Displays the difference between `total_price` and `discount`.</td></tr><tr><td valign="top">Multiply</td><td valign="top">{{calc "price * quantity"}}</td><td valign="top">price = 50<br>quantity = 10</td><td valign="top">500</td><td valign="top">Displays the product of `unit_price` and `quantity`.</td></tr><tr><td valign="top">Divide</td><td valign="top">{{calc "price / quantity"}}</td><td valign="top">price = 100<br>quantity = 4</td><td valign="top">25</td><td valign="top">Displays the quotient of `total_price` and `quantity`.</td></tr><tr><td valign="top">Multiple operators</td><td valign="top">{{calc "price - (price * discount /100)"}}</td><td valign="top">price = 500<br>discount = 10</td><td valign="top">450</td><td valign="top">Division is performed first, then multiplication, followed by subtraction.</td></tr></tbody></table>

{% hint style="info" %}
*Note: Calculations follow standard mathematical precedence (BODMAS rules).*
{% endhint %}

### Using `calc` Helper for Advanced Calculations

The `calc` helper works seamlessly within dynamic placeholders and nested calculations, addressing more complex use-cases. Below are few examples of how you can use it.

#### Using \`calc\` in Conditional Logic

You can also perform calculations within conditions to make decisions based on calculated values.

```
{{#if ((calc "price * quantity") > 1000)}}
Discount Applied 
{{else}} 
No Discount 
{{/if}}
```

| **Input**                           | **Output**       |
| ----------------------------------- | ---------------- |
| <p>price = 100<br>quantity = 30</p> | Discount Applied |
| <p>price = 100<br>quantity = 3</p>  | No Discount      |

#### Using \`calc\` in Loops

You can use `calc` inside loops to dynamically compute values for repeating elements in templates.

<figure><img src="/files/q3XMprJTVA7G29BcbaQ4" alt=""><figcaption></figcaption></figure>

#### Using `calc` in manipulating numerical values

<table data-header-hidden><thead><tr><th valign="top">Description</th><th valign="top">Syntax</th><th valign="top">Input</th><th valign="top">Output</th><th data-hidden valign="top">Description</th></tr></thead><tbody><tr><td valign="top"><strong>Description</strong></td><td valign="top"><strong>Syntax</strong></td><td valign="top"><strong>Input</strong></td><td valign="top"><strong>Output</strong></td><td valign="top"><strong>Description</strong></td></tr><tr><td valign="top">Convert to Words</td><td valign="top">{{number_to_words (calc "price * quantity")}}</td><td valign="top">price = 10<br>quantity = 5</td><td valign="top">fifty</td><td valign="top">Converts the numerical calculation result into words.</td></tr><tr><td valign="top">Rounding (`round()`)</td><td valign="top">{{round (calc "price / quantity")}}</td><td valign="top">price = 50<br>quantity = 3</td><td valign="top">17</td><td valign="top">Rounds the result to the nearest whole number.</td></tr><tr><td valign="top">Ceiling (`ceil()`)</td><td valign="top">{{ceil (calc "price / quantity")}}</td><td valign="top">price = 50<br>quantity = 3</td><td valign="top">17</td><td valign="top">Rounds up to the next whole number.</td></tr><tr><td valign="top">Floor (`floor()`)</td><td valign="top">{{floor (calc "price / quantity")}}</td><td valign="top">price = 50<br>quantity = 3</td><td valign="top">16</td><td valign="top">Rounds down to the next whole number.</td></tr></tbody></table>


# Advanced usage

This section guides you to advanced usage of helpers.

## Nested helpers

Nested helpers refers to having a helper inside another, this enables you to use multiple helpers on a token. Nested helpers can be used to address requirements such as “*capitalizing the number converted to words*”, “*sorting comma-separated employee names*” and “*applying discount by percentage on invoice total*”.

Example 1:

`{{capitalize (number_to_words amount suffix="dollars" decimal_suffix="cents")}}`

| Input   | Output                                                  |
| ------- | ------------------------------------------------------- |
| 800.658 | Eight hundred dollars six hundred and fifty-eight cents |

Example 2:

`{{divide (subtract a b) c}}`

| Input                      | Output |
| -------------------------- | ------ |
| <p>a b c</p><p>50 10 5</p> | 8      |

Note that nested helpers should be written inside the parenthesis `()` and not inside curly braces `{{}}`.


# Content Library

Content Library helps you to reuse frequently used document sections—like Terms & Conditions, policy texts, legal clauses, or any repeatable content—across multiple templates

### **Creating a Content Block**

1. Navigate to **Content Library** from the dashboard.
2. Click on **Create Content Block**.
3. Select your preferred content block type. You can upload a Word document or create an Online Builder template. These content blocks can include merge tokens in it.
4. Set a unique **Key Name**. This will be used to reference the content block in your templates.

{% hint style="warning" %}
The **Key Name** can only be set when creating the content block and cannot be changed later.
{% endhint %}

### **Refer the Content Block in Templates**

* In any template, use the following syntax to embed the content: **`{{content_block "your_key_name"}}`**
* At the time of document generation, the content from the referenced content block will be included inline.

### Example Use Case

Let’s say you often include the same Terms and Conditions section in your Quotes and Proposals

* You can save that as a content block in the Content Library and set a unique Key Name (e.g., **tnc**) to reuse it across templates.

<figure><img src="/files/gsbObs9m5p0vgxoWC4Cq" alt="" width="563"><figcaption><p>Creating a Content Block</p></figcaption></figure>

* To include this content block in your templates, use the following syntax:

  **`{{content_block "tnc"}}`**

<figure><img src="/files/CVjNf04DmXkKdAL0TjII" alt="" width="563"><figcaption><p>Referring the content block in templates</p></figcaption></figure>

* Any updates to "Terms and conditions" in the Content Library will automatically reflect across all templates where it’s used—without having the need to edit each template individually.

### Supported Actions on Content Block

* **View linked templates:** Click the chevron (**>**) before to the content block name to view the list of linked templates.
* **Copy:** Duplicate a content block with a different Key Name.
* **Share:** Share access to a content block with Members in the same workspace.
* **Edit:** Allows to edit the Name and Description of the content block.
* **Delete:** Deletes the content block permanently.

{% hint style="warning" %}
You can only delete a content block if it is not used in any templates.
{% endhint %}

### Supported Template Types

This feature is supported for:

* Online Builder Templates
* Word (DOCX) Templates

> Note: Content blocks can only be inserted in Templates. A Content block cannot be inserted in another Content block

### When to Use the Content Library

Content Library is useful when:

* There's recurring content across templates (e.g., legal disclaimers or product descriptions).
* You want to manage and update shared content in one place.


# Test your document template

Once you have finished creating your template, you can test the same to ensure that the final document meets expectations.

To test your document, follow below steps:

* Click on the `Test` option located in the top right corner of the template details page.

![](/files/qPlMoDi1llXQ1WYRtMdg)

* A Test Form with fields detected from your template will be shown in a popup.

![Test form](/files/iHWozLykwDByVUiuCnWe)

* Click the `Fill Sample Data` button to auto-populate the form with sample data, then click **`Test Template`** to generate a Test document.

<figure><img src="/files/j5X8owYfReWS8NVaYT9D" alt=""><figcaption><p>Test form filled with Fill Sample Data option</p></figcaption></figure>

* Alternatively, you can enter sample data manually and click on `Test Template` button to generate the document.

<figure><img src="/files/Ld92kqEGg7Py6aXYJLqV" alt=""><figcaption><p>Test form filled with data manually</p></figcaption></figure>

* To test using JSON, click the `JSON` button at the top-right of the test form. You can then either enter your JSON data manually or click `Fill Sample Data` to auto-populate the form, then generate the document.

<figure><img src="/files/HZBH21UD5rjeoFxv1eiS" alt=""><figcaption><p>Test form using JSON</p></figcaption></figure>

* For quick testing, simply **Shift + Click** the `Test` button to generate document with the data used in previous tests.

<figure><img src="/files/ugNphcWUIMb9zDO8NE0h" alt=""><figcaption><p>Quick Testing</p></figcaption></figure>

{% hint style="info" %}
Document generated using test form will contain a watermark.

Any configured deliveries will not be executed.

This test data will be stored and can be reused for testing purposes.
{% endhint %}


# Deliveries

Deliveries allow you to send your generated document to the desired destination. Example, you can email your document, or send it to Zoho CRM, or store it in  Dropbox/Google Drive.

Once you have completed creating and testing your document, you can start with setting up delivery options.

\
Click on the `Deliveries` tab and choose desired delivery type to start with.

![](/files/nLeik4V2p49NNvkzqsU1)

### Use Cases

* Generate and Email PDF from Google Forms response
* Create and Email personalized Sales Documents When a Lead is Created in SalesForce
* Generate Documents and store in Google Drive or Dropbox for Backup & Audit
* Send generated documents to Docusign for e-Signing


# Email

Email deliveries are an efficient way to send created documents to your customers, colleagues, and other stakeholders. In email delivery, the final merged document is sent to recipients as an attachment. You can also customize the email subject and message to make it more personalised.

## Setup a new Email delivery

To set up an Email Delivery, choose the `Email` option from the list of deliveries available in the `Deliveries` tab.

All the configurations are explained as below:

![](/files/HxKWcQKCOVzDr6z0oInG)

| Configuration      | Description                                                                                                                                                                                                                                                                                                                                                |
| ------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Configuration      | Description                                                                                                                                                                                                                                                                                                                                                |
| Account            | The email account which should be used to send email. (more details on how to configure an email account are explained below)                                                                                                                                                                                                                              |
| From               | The email address of the sender. From address can only be customised when the Account with SMTP type is selected.                                                                                                                                                                                                                                          |
| To                 | <p>The email of the recipient(s). This field can take in multiple email addresses.</p><p><br>You can also add merge tokens to pass dynamic email addresses. Click on the <code>{{}}</code> button to get the list of already available merge fields -or- type new tokens (for example: <code>{{client\_email}}</code>, or <code>{{recipients}}</code>)</p> |
| CC                 | <p>Email addresses of carbon copy recipients.</p><p>You can configure dynamic email addresses similar to <code>TO</code> field.</p>                                                                                                                                                                                                                        |
| BCC                | <p>Email addresses of blind carbon copy recipients.</p><p>You can configure dynamic email addresses similar to <code>TO</code> field.</p>                                                                                                                                                                                                                  |
| Subject            | <p>The Subject for the email.<br><br>You can also add merge tokens to add dynamic values in Subject. Click on the <code>{{}}</code> button to get the list of already available merge fields or type new tokens (for example: <code>{{caseId}}</code>)</p>                                                                                                 |
| Message            | <p>Email content. Use the editor to draft email content that looks exactly like how it should look in a sent email.<br><br>You can also add merge tokens to add dynamic values by typing desired tokens.<br><br>For example:<br><code>Hello {{client\_name}}, please find the attached invoice {{invoice\_id}}</code></p>                                  |
| Static Attachments | Upload the files that should be attached to the email along with the generated documen&#x74;**.**                                                                                                                                                                                                                                                          |

{% hint style="info" %}
Email delivery supports up to 5 static attachments, with a total size limit (including the generated document) of 15 MB.
{% endhint %}

## Email Account

### System default account

All workspaces will have access to a system provided email account `no-reply@docupilot.app` which can be used to send up to 100 emails per day. Recipients of these emails will see that the email originated from Docupilot.

{% hint style="info" %}
If you need to send more than 100 emails per day, create an emial account by configuring your SMTP credentials or a DNS verified email account.
{% endhint %}

### SMTP email delivery

An SMTP email account facilitates the sending of emails using your own email server credentials. Configure SMTP credentials obtained from your email provider in an SMTP email account and configure your email deliveries to use this account.

Steps to Configure the SMTP Account:

1. Navigate to **Settings > Linked Accounts**

<figure><img src="/files/yFAt8vK81iQHBO3Ax93q" alt=""><figcaption><p>Linked Accounts module in Docupilot</p></figcaption></figure>

2. Select **Email** in the list of account types.

<figure><img src="/files/3MlEBh7jEieU1l49p6fk" alt=""><figcaption></figcaption></figure>

3. Select **SMTP Credentials** and enter the required details:
   1. Server Address - Address of your email host server
   2. Username - SMTP username (issued by your email provider, in most cases this will be your email address)
   3. Password - SMTP password (issued by your email provider, in most cases this will be your email password or a dedicated application password)
   4. Port - SMTP port ( in most cases it will be 25, 465, and 587)
   5. TLS/SSL - Choose desired encryption mode (TLS is preferred over SSL)

{% hint style="info" %}
Here are few references on how to obtain SMTP credentials from various email providers:

GMail - <https://support.google.com/a/answer/176600?hl=en>

Zoho Mail - <https://www.zoho.com/mail/help/zoho-smtp.html>

Office365 - <https://www.saleshandy.com/smtp/office-365-smtp-settings/>
{% endhint %}

<figure><img src="/files/VArhbZrhR6jt4xWVlWTS" alt=""><figcaption></figcaption></figure>

4. **Test Configuration**: Enter an email address and hit "Send Test Email" button to send a test email with the configured credentials.

<figure><img src="/files/E88rl6oKZ0O47EPHAjq1" alt=""><figcaption></figcaption></figure>

### DNS Validation

Instead of using an SMTP server, if you would like Docupilot to send emails using a custom from address, the ownership of the domain and the email address should be validated. This validation happens by verifying custom DNS records in your Domain's DNS management tool plus and OTP sent to your email inbox.

Configuring DNS Validation:

1. Navigate to **Settings > Linked Accounts**

<figure><img src="/files/yFAt8vK81iQHBO3Ax93q" alt=""><figcaption></figcaption></figure>

2. Select **Email** in the list of account types.

<figure><img src="/files/3MlEBh7jEieU1l49p6fk" alt=""><figcaption></figcaption></figure>

3. Select **DNS Validation** and enter the email address your would like to send emails from & click Proceed.

<figure><img src="/files/G5XgSrdHr3cCN42dVlGI" alt=""><figcaption></figcaption></figure>

4. Copy the DNS records shown and configure them in your DNS management console. Read more about [how to configure an SPF record](#what-is-an-spf-record-and-how-do-i-add-it).

<figure><img src="/files/37N4QZWvGhpCX7rMtTzI" alt=""><figcaption><p>Email Account - DNS records</p></figcaption></figure>

5. Try to verify the records after addition by clicking "Verify" button. It could take up to 48 hours for the DNS records to be propagated based on your DNS caching settings.
6. After successful verification, click Proceed.

<figure><img src="/files/oe1tKe7k9h8sJOZW6kSw" alt=""><figcaption><p>Email Account - DNS Records verified</p></figcaption></figure>

7. An OTP will be sent to the desired email address, enter the OTP here to complete addition of your email account.

<figure><img src="/files/KydzA6JKdL1wrMWcyJWb" alt=""><figcaption><p>Email Account - OTP Verification for DNS Account</p></figcaption></figure>

{% hint style="info" %}
Once your domain's DNS records are verified, you can add multiple email accounts with the same domain. You will be prompted to validate each new email address by entering an OTP, similar to step 7.
{% endhint %}

### What is an SPF Record and how do I add it?

**This article also answers:**

* Can I use my existing SPF record with Docupilot?
* Email notifications sent from Docupilot are marked as SPAM by my customer's email servers. How can I handle this?

Sometimes emails from Docupilot may be marked as SPAM by your customer’s email servers.\
\
This happens because your customer’s email server does not know that you are using Docupilot to send emails on your behalf. You can easily correct this by creating an SPF record (Sender Policy Framework record) in your DNS Server.\
\
In simple terms, by creating an SPF record you are authorizing Docupilot to send emails (notification emails) with @\<your-domain>.com email address.

**And here's how you do it:**

* Go to your domain registrar's website.
* Login to the domain control panel.
* Open your DNS configuration settings.
* Edit your ZONE File and look for TXT or SPF record.
* Specify the following value: **v=spf1 include:email.docupilot.app \~all** .
* Save your changes.

**But what if an SPF record already exists?**

You can just include the SPF in the same line as your existing record

**v=spf1 include:spf1.domain.com include:spf2.domain2.com include:email.docupilot.app \~all**

In case you are unable to get the SPF set up, here are more specific instructions with respect to each provider. Make sure you remember to use the right value before saving your changes.

* [GoDaddy](https://in.godaddy.com/help/manage-dns-zone-files-680)
* [Namecheap](https://www.namecheap.com/support/knowledgebase/article.aspx/317/78/how-do-i-add-spf-or-txt-records-for-my-domain)
* [Hover](https://help.hover.com/entries/21204757-how-to-edit-dns-records-a-cname-mx-txt-and-srv)

## Headers inside an email delivery

Besides default email headers, if you need to customise your email headers further, configure custom headers in the **Headers** section.

For example, if your from email address is `dave@example.com`, and you would like the replies to come back to `support@example.com`, configure a custom header with the following values:

* **Header Name:** `Reply-To`
* **Header Value:** `support@example.com`

![Custom Headers in Email Delivery](/files/SLbtC0C4kv2AwQwLm5d9)

Here's another example where `Reply-To` and `Priority` headers are customized:

![Email headers Sample Invoice](/files/loQmQBJ2TtcOBDhdGmzR)


# Webhook

Webhook is just a fancy word for initiating an HTTP request to another server every time an event occurs. **Docupilot** triggers a webhook every time we create a new document for you. You can send data & document for example to one of the supported CRM systems (Salesforce, Zoho CRM) or Zapier or to your own API. With WebHooks, you can send data and document to various services, say Zapier, or any or supported CRM system (Zoho CRM, Salesforce) or even to your own service for that matter.

To start with a webhook delivery, choose the `WebHook` option from the list of deliveries available in the `Deliveries` tab.

![](/files/-LMxaJFV4ZQxHZk2AwhR)

The various configurations available for the webhook delivery are listed below

| Configuration | Description                                                                                                                                                                          |
| ------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| Name          | The name of the Delivery                                                                                                                                                             |
| Post URL      | The POST URL that you want to be called, once there is a merge. This field takes merge variables for input. Click on the `{{}}` to get a list of possible variables that can be used |
| Headers       | The headers that needs to be sent with the HTTP POST request. This field takes merge variables for input.                                                                            |
| Data          | The data that needs to be sent with the HTTP POST request. This field takes merge variables for input.                                                                               |

{% hint style="info" %}
The webhook is sent as a **HTTP POST** **multipart**/**form**-**data** with **file** and **file\_name.**
{% endhint %}


# eSignature

Send generated documents for signing through Docupilot’s built-in signing solution.

With Docupilot’s built-in eSignature feature, you can seamlessly deliver documents for signing right after generation. Here’s how to set it up.

## Configuring eSignature Delivery

To add a new eSignature delivery, choose the `eSignature` option from the list of deliveries available in the `Deliveries` tab.

<figure><img src="/files/0ANu6zu05oLjdyJeMPhY" alt=""><figcaption><p>Configuring eSignature delivery fields</p></figcaption></figure>

**Name:** Give your delivery a name for easier identification on what this delivery does.

**Email Subject:** Set the subject line of the email your signer will receive. You can personalize this by adding dynamic tokens. Click on the `{{}}` button to get the list of already available tokens or type in a new new token (like `{{client_name}}`)

**Email Message**: Define the body of the email your signer will receive. You can also add dynamic tokens to personalize this message. This message will be included as part of a standard email template. For example:

```
Dear valued {{client_name}},

Please find the contract "Contract-AcmeCorp-{{client_company}}" as discussed
and sign it at the earliest possibility.
```

**Sender Mode:**

* **Smart Sender** – The logged-in user in your account who submits the form becomes the sender.\
  If the document is generated without a logged-in user (e.g., public form or un-authenticated API), document generation will fail.\
  This mode is recommended when documents are generated by logged-in users.
* **Fixed Sender** – always use the sender configured below for all envelopes. **Sender** is **mandatory** in this mode.

**Sender:**

Choose who should be considered as the sender for envelopes created from this template.

* You can only select yourself as the sender.
* Only the selected sender can track and manage the envelopes created.
* This option is only available when **Sender Mode** is set to **Fixed Sender**.
* Any user with write access to this Template can set themselves as the Sender.

**Recipients:**

This section allows you to configure the recipient details for signing the document. The recipient entries should match signature tags placed in your template. For example, if your template has `{{eSign 1}}` and `{{eSign 2}}` signature tags configured ([read more about how to add signature tags](#placing-signature-tags-in-document)), ensure there are 2 signers configured in your delivery.

* Enter the **Name** and **Email** of each signer who should receive the invite to sign.
* Click **Add another** to include multiple recipients.
* Enable the **Set Signing Order** option to control the signing sequence. Recipients will receive the document one after another, based on the order you specify.
* Add recipients in **CC** if needed.

#### **Optional Recipients**

Enable the optional recipients feature to **bypass invalid recipient entries**.

For instance, as illustrated below (screenshot), John sets up a generated lease agreement to be sent to new tenants. He configures three tenants and himself as signers. The tenant count may vary. If a property is leased to only two individuals, the data for `tenant_three_name` and `tenant_three_email` can be omitted. Without the optional recipients feature enabled, the delivery fails since Docupilot requires valid data for all recipients. When enabled, Docupilot omits sending invalid recipient details in the envelope, ensuring successful delivery.

<figure><img src="/files/2fFQOFkTAjdjzzRsl0k4" alt=""><figcaption><p>Enabling Optional Recipients</p></figcaption></figure>

#### **More options:**

<figure><img src="/files/jm8HQVjrqdzIV1XFQ6G7" alt=""><figcaption><p>Configuring Reminder Settings in Delivery</p></figcaption></figure>

**Reminder Settings** allow you to automate follow-ups with recipients to ensure timely signing of documents. You can choose to use your account’s default reminder configuration, or set custom preferences under `Reminder Settings`:

* **Expires in**: Number of days before the Envelope expires
* **First reminder in:** Days after which the first reminder will be sent to current signers
* **Remind Signer every:** Frequency of follow-up reminders to be sent to current signers
* **Expiry Warning before:** Days before expiry when a warning is triggered

#### **Advanced Settings (Optional)**

<figure><img src="/files/eaDAwv3mWMSduic0cgf6" alt=""><figcaption><p>Configuring Advanced Settings</p></figcaption></figure>

If you like to get notified on delivery errors, or on successful execution of deliveries, configure advanced settings to take advantage of integrations. Following advanced integration options are available:

* **On Success Callback URL:** Configure a Web-hook URL which will be invoked with data containing the Envelope ID once the Envelope is created. To configure additional settings for callback URL like setting custom Headers and Additional Payload use the **Advanced Configuration** section.
* **Emails to Notify on Delivery Failure:** Failed deliveries are typically notified to the workspace owner, workspace admins and workspace managers via email. You can configure additional email IDs here to receive notifications on delivery failures.

**Save Configuration**

Once all fields are set, click Save at the top right to finalize the eSignature delivery setup.

#### Removing Watermark

Documents generated in Test mode will include a watermark that reads:

*“For demo purpose only. Powered by Docupilot.”*

<figure><img src="/files/wxRsWQKmyKGUZSnNDc04" alt=""><figcaption><p>Removing watermark on documents for signing</p></figcaption></figure>

To remove this watermark, simply [activate the template](/document-template/template-preferences#template-status-active-vs-test). Once the template is in Active status, any documents generated from it will no longer display the watermark.

## **Placing Signature tags in Document**

Place customizable eSignature fields directly into your templates using special placeholder tokens. These tokens define where and how each signer interacts with the document—adding a signature, initials, date, plain text, or more.

Each signer needs to be assigned a Signer ID in sequential order. Use this ID consistently while placing signature tags to ensure correct field assignment.

### eSignature Placeholder Tokens

Following is the list of all supported eSignature tokens

<table><thead><tr><th width="138.2578125">Placeholder</th><th width="604.671875">Syntax</th></tr></thead><tbody><tr><td>Signature</td><td><pre><code>{{eSign signer_id req=&#x3C;bool> width=&#x3C;num> height=&#x3C;num>}}
</code></pre><p><em>signer_id<mark style="color:red;">*</mark></em> = ID of the signer (<code>1</code>, <code>2</code>, <code>3</code>, etc)</p><p>req = whether this field is mandatory (<code>true</code>/<code>false</code> Default value: <code>true</code> )</p><p><em>width</em> = width of the signature box (ex: <code>100</code>, <code>110</code> Default value: <code>85</code>)</p><p><em>height</em> = height of the signature box (ex: <code>40</code>, <code>50</code> Default value: <code>25</code>)</p></td></tr><tr><td>Initials</td><td><pre><code>{{eInitials signer_id req=&#x3C;bool> width=&#x3C;num> height=&#x3C;num>}}
</code></pre><p><em>signer_id<mark style="color:red;">*</mark></em> = ID of the signer (<code>1</code>, <code>2</code>, <code>3</code>, etc)</p><p><em>req</em> = whether this field is mandatory (<code>true</code>/<code>false</code> Default value: <code>true</code> )</p><p><em>width</em> = width of the initials box (ex: <code>40</code>, <code>50</code> Default value: <code>25</code>)</p><p><em>height</em> = height of the initials box (ex: <code>40</code>, <code>50</code> Default value: <code>25</code>)</p></td></tr><tr><td>Date Signed</td><td><pre><code>{{eDateSigned signer_id req=&#x3C;bool> width=&#x3C;num> height=&#x3C;num>}}
</code></pre><p><em>signer_id<mark style="color:red;">*</mark></em> = ID of the signer (<code>1</code>, <code>2</code>, <code>3</code>, etc)</p><p><em>req</em> = whether this field is mandatory (<code>true</code>/<code>false</code> Default value: <code>true</code> )</p><p><em>width</em> = width of the signed date (ex: <code>70</code>, <code>80</code> Default value: <code>67</code>)</p><p><em>height</em> = height of the signed date (ex: <code>12</code>, <code>15</code> Default value: <code>10</code>)</p></td></tr><tr><td>Date</td><td><pre><code>{{eDate signer_id req=&#x3C;bool> width=&#x3C;num> height=&#x3C;num>}}
</code></pre><p><em>signer_id<mark style="color:red;">*</mark></em> = ID of the signer (<code>1</code>, <code>2</code>, <code>3</code>, etc)</p><p><em>req</em> = whether this field is mandatory (<code>true</code>/<code>false</code> Default value: <code>true</code> )</p><p><em>width</em> = width of the date field (ex: <code>70</code>, <code>80</code> Default value: <code>67</code>)</p><p><em>height</em> = height of the date field (ex: <code>12</code>, <code>15</code> Default value: <code>10</code>)</p></td></tr><tr><td>Text Input</td><td><pre><code>{{eText signer_id label=&#x3C;fieldLabel> req=&#x3C;bool> width=&#x3C;num> height=&#x3C;num>}}
</code></pre><p><em>signer_id<mark style="color:red;">*</mark></em> = ID of the signer (<code>1</code>, <code>2</code>, <code>3</code>, etc)</p><p><em>label<mark style="color:red;">*</mark></em> = Label of the text field (<code>"Role"</code>, <code>"Company Name"</code>, etc)</p><p><em>req</em> = whether this field is mandatory (<code>true</code>/<code>false</code> Default value: <code>true</code> )</p><p><em>width</em> = width of the text field (ex: <code>100</code>, <code>120</code> Default value: <code>80</code>)</p><p><em>height</em> = height of the text field (ex: <code>12</code>, <code>15</code> Default value: <code>10</code>)</p></td></tr><tr><td>Dropdown</td><td><pre><code>{{eDropDown signer_id label req=&#x3C;bool> width=&#x3C;num> height=&#x3C;num> values=&#x3C;string>}}
</code></pre><p><em>signer_id<mark style="color:red;">*</mark></em> = ID of the signer (<code>1</code>, <code>2</code>, <code>3</code>, etc)</p><p><em>label<mark style="color:red;">*</mark></em> = Label of the text field (<code>"Country"</code>, <code>"State"</code>, etc)</p><p><em>req</em> = whether this field is mandatory (<code>true</code>/<code>false</code> Default value: <code>true</code> )</p><p><em>width</em> = width of the dropdown (ex: <code>100</code>, <code>120</code> Default value: <code>80</code>)</p><p><em>height</em> = height of the dropdown (ex: <code>12</code>, <code>15</code> Default value: <code>10</code>)</p></td></tr><tr><td>Checkbox</td><td><pre><code>{{eCheckbox signer_id label req=&#x3C;bool> width=&#x3C;num> height=&#x3C;num>}}
</code></pre><p><em>signer_id<mark style="color:red;">*</mark></em> = ID of the signer (<code>1</code>, <code>2</code>, <code>3</code>, etc)</p><p><em>label<mark style="color:red;">*</mark></em> = Label of the text field (<code>"Accept Terms"</code>, <code>"Consent to terms"</code>, etc)</p><p><em>req</em> = whether this field is mandatory (<code>true</code>/<code>false</code> Default value: <code>true</code> )</p><p><em>width</em> = width of the checkbox (ex: <code>12</code>, <code>13</code> Default value: <code>11</code>)</p><p><em>height</em> = height of the checkbox (ex: <code>12</code>, <code>13</code> Default value: <code>11</code>)</p></td></tr></tbody></table>

### Examples

Below examples show how the placeholders can be used in your template:

<table><thead><tr><th width="138.2578125">Placeholder</th><th>Example (signer 1)</th><th>Example (signer 2)</th></tr></thead><tbody><tr><td>Signature</td><td>{{eSign 1}}</td><td>{{eSign 2 req=false width=100 height=40}}</td></tr><tr><td>Initials</td><td>{{eInitials 1}}</td><td>{{eInitials 2 req=false width=40 height=40}}</td></tr><tr><td>Date Signed</td><td>{{eDateSigned 1}}</td><td>{{eDateSigned 2 req=false width=80 height=20}}</td></tr><tr><td>Date</td><td>{{eDate 1}}</td><td>{{eDate 2 req=false width=80 height=20}}</td></tr><tr><td>Text Input</td><td>{{eText 1 "Role"}}</td><td>{{eText 2 "Role" req=false width=120 height=20}}</td></tr><tr><td>Dropdown</td><td>{{eDropDown 1 "Country" values="US,UK,Australia,India"}}</td><td>{{eDropDown 2 "Country" req=false values="Canada,France,Germany,Italy,Greece" width=120 height=20}}</td></tr><tr><td>Checkbox</td><td>{{eCheckbox 1 "AcceptTerms"}}</td><td>{{eCheckbox 2 "Accept Terms" req=false width=13 height=13}}</td></tr></tbody></table>

### Sample Word template

Please see the attached document for guidance on placing signature tags in a Word template.

{% file src="/files/eqUvyVNTe3XzO80vrDeY" %}
Example usage of Signature tags in Word template
{% endfile %}

### Sample Excel template

Please refer to the attached document for guidance on placing signature tags in an Excel template

{% file src="/files/nhtP7FTruuRtWmrem5bQ" %}
Example usage of Signature tags in Excel template
{% endfile %}


# SFTP

Securely upload generated documents to your documents to your File Server

To start with a SFTP delivery, choose the `SFTP` option from the list of deliveries available in the `Deliveries` tab.

## Configuration

<figure><img src="/files/xhqKEu5Rys2oVPQEfq8f" alt=""><figcaption></figcaption></figure>

**Name:** Enter a name for your delivery configuration. This helps you identify the delivery setup, for example, "Upload to Team folder."

**Select Account:** Select the SFTP account you wish to use for the delivery. This will determine which SFTP server the files will be uploaded to. If no accounts are available, you can connect an SFTP account by clicking the link icon or add one by navigating to **Settings > Linked Accounts**.

**Folder:** Configure folder path to which the generated files needs to be uploaded. The folder path can be dynamic. For example, to upload customer contracts under a folder that includes customer's name, you can configure **Folder** as `Agreements/{{CustomerName}}`

Now when a contract is generated for CustomerName `AcmeCorp`, it will be uploaded to `Agreements/AcmeCorp`

#### **Advanced Settings**

If you like to get notified on delivery errors, or on successful execution of deliveries, configure advanced settings to take advantage of integrations. Following advanced integration options are available:

* **On Success Callback URL**\
  Configure a Web-hook URL which will be invoked with data containing the folder path to which the file was uploaded. To configure additional settings for callback URL like setting custom Headers and Additional Payload use the **Advanced Configuration** section.
* **Emails to Notify on Delivery Failure**\
  Failed deliveries are typically notified to the workspace owner, workspace admins and workspace managers via email. You can configure additional email IDs here to receive notifications on delivery failures.


# Dropbox

Store the generated documents to your Dropbox Account

To start with a Dropbox delivery, choose the `Dropbox` option from the list of deliveries available in the `Deliveries` tab.

![Adding a DropBox delivery in Docupilot](/files/sbHedmHQzlv0KoaRheIb)

## Configuration

<figure><img src="/files/5r2LLb0mXEbMeTe83IKC" alt=""><figcaption><p>Configuring the folder option</p></figcaption></figure>

Configuring delivery **Folder:** Configure folder path to which the generated files needs to be uploaded. The folder path can be dynamic. For example, to upload customer contracts under a folder that is named against the customer's name, you can configure **Folder** as `Contracts/{{CustomerName}}`

Now when a contract is generated for customer with name `AcmeCorp`, it will be generated and uploaded to `Contracts/AcmeCorp`

Handling **file name conflicts**: Docupilot offers flexibility by giving an option to choose from various delivery modes for generated documents. You could choose between the following options:

* **Create new file:** Allows you to upload the generated document as a new file in the selected Dropbox folder, ensuring no existing files are modified or replaced. For example, if a file with name `AcmeCorpContract.pdf` already exists in the destination folder and the generated document also has the same name, it may be uploaded as `AcmeCorpContract(1).pdf`
* **Overwrite:** Generated document replaces an existing file with the same name in the Dropbox folder. The older file that was replaced may be available under previous versions.
* **Do not deliver:** Can be used if the file name conflict should not be resolved. The delivery will be marked as failed in such scenario.


# Google Drive

Store the generated documents to your Google Drive Account

To start with a Google Drive delivery, choose the `Google Drive` option from the list of deliveries available in the `Deliveries` tab.

Connect a Google drive account and choose the folder to which you need to upload the generated documents.

![](/files/McVo5s0CDkVyXdtRHKkg)


# One Drive

Save the generated documents in your OneDrive account.

To add a OneDrive delivery, follow these steps:

* Navigate to the '**Deliveries**' tab located in the top panel.
* From the list of delivery options, select **OneDrive**.
* Enter a name for the delivery.
* Select your desired OneDrive account. If no OneDrive account is linked, click the "**+**" button and follow the on-screen instructions to add your OneDrive account.
* Enter the name of the folder where you would like the generated documents to be uploaded.

<figure><img src="/files/dIn9F7avD5U37OrNppEI" alt=""><figcaption><p>Adding a OneDrive delivery in Docupilot</p></figcaption></figure>

**Advanced Settings:**

If you like to get notified on delivery errors, or on successful execution of deliveries, configure advanced settings to take advantage of integrations. Following advanced integration options are available:

* **On Success Callback URL** - Configure a Webhook URL which will be invoked with data containing the folder path to which the file was uploaded.
* **Emails to notify on delivery failure** - Failed deliveries are typically notified to the workspace owner, workspace admins and workspace managers via email. You can configure additional email IDs here to receive notifications on delivery failures.

<figure><img src="/files/hmeDehXqTgnKFNBoQfLq" alt=""><figcaption><p>Advanced Settings.</p></figcaption></figure>


# DropboxSign (formerly Hellosign)

Send generated documents automatically for Signing.

To start with a DropboxSign (formerly Hellosign) delivery, choose the `Dropboxsign (formerly Hellosign)` option from the list of deliveries available in the `Deliveries` tab.

{% hint style="info" %}
You need a DropboxSign API plan for HelloSign Delivery. Please refer <https://www.hellosign.com/api>
{% endhint %}

![Adding a new Dropbox Sign (formerly hellosign) delivery in Docupilot](/files/0zrA1trHUUbQKoVDNESE)

## Adding a DropboxSign Account

![Adding a new Dropbox sign account](/files/E7qGtq1Q6m0eycP70lzr)

You can find your API Key here <https://app.hellosign.com/home/myAccount#api>

## Configuration

|                   |                                                                                                                                                                                                                                                                                                                                                   |
| ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Title             | The title you want to assign to the Signature Request.                                                                                                                                                                                                                                                                                            |
| Subject           | <p>The subject in the email that will be sent to the signers.<br></p>                                                                                                                                                                                                                                                                             |
| Message           | The custom message in the email that will be sent to the signers.                                                                                                                                                                                                                                                                                 |
| Signers Name      | The name of the signer.                                                                                                                                                                                                                                                                                                                           |
| Signers Email     | The email address of the signer                                                                                                                                                                                                                                                                                                                   |
| CC                | The email addresses that should be CCed.                                                                                                                                                                                                                                                                                                          |
| Use Text Tags     | Enable this if you wish to enable [Text Tags](https://app.hellosign.com/api/textTagsWalkthrough#TextTagIntro) parsing in your document                                                                                                                                                                                                            |
| Hide Text Tags    | Enable this if you wish to enable automatic Text Tag removal. It is preferred that you don't enable this, hide your tags with white text or something similar because the automatic removal system can cause unwanted clipping. See the [Text Tags](https://app.hellosign.com/api/textTagsWalkthrough#TextTagIntro) walkthrough for more details. |
| Sequenced Signing | Enable this if you wish to enable Sequenced Signing.                                                                                                                                                                                                                                                                                              |

## Using Text Tags Field Parsing

To enable Text Tags and make sure you enable **Use Text Tags**. Your Text Tags will be converted into UI components for the user to interact with. Keep in mind that by default **the tags themselves will remain on the page.** To hide the tags from the end user you can change the text color to match the background (such as white on white). Alternatively you can set **Hide Text Tags** although we don't recommend this because auto-removal can lead to unwanted clipping.

To begin and end a tag, use square brackets \[ ] in your document. Within the square brackets, use the pipe character | to divide the parts of the tag. The first part of the tag is the type. The second part indicates if it is required or not. The third part indicates which signer in the list of signers needs to complete the field. The last two parts are optional and are for setting a label and unique ID.

For example: **\[text|noreq|signer1|Label|UniqueId]**

![Using DropboxSign Text Tags in Docupilot Template](/files/-LpTUJi-zdMilQJwhqGH)

Text Tags let you specify which signer the field is for, what type of field it is, and if the field is required or not in addition to the relative size of the field. The types of fields available are the same as when you create a template:

| **TEXT TAG VALUE** | FIELD TYPE                                             |
| ------------------ | ------------------------------------------------------ |
| text               | Text field                                             |
| check              | Checkbox field                                         |
| date               | Date field                                             |
| initial            | Signer's initials field                                |
| sig                | Signer's signature field                               |
| text-merge         | A text field that has default text set by the api      |
| checkbox-merge     | A checkbox field that has default value set by the api |

The only valid values for field requirement are "**req**" and "**noreq**". The value defaults to "req" if the entry is not understood.

### Matching Signer

When you write a Text Tag you must assign it to somebody. The number N in "signerN" represents the signer index, For example with these two text tags:

* **\[sig|req|signer1|OptionalLabel|OptionalID]**
* **\[initial|req|signer2|OptionalLabel|OptionalID]**

You have specified that **signer\[1]** is required to sign and **signer\[2]** is required to initial.

{% hint style="warning" %}
If you text tags, you will need to configure the signers fields in the delivery configuration. The number of signers configured in the document using text tags must match the number of signers configured in the delivery.
{% endhint %}

### Optional Recipients

Enabling optional recipients in the DropboxSign delivery will skip **invalid signers** and **carbon copy** (cc) entries.

![Configuring Dropbox Sign delivery on Docupilot](/files/O5SH0nTWRKGVySvCHxx9)


# DocuSign

Send generated documents automatically for Signing.

Docusign is the world’s leading platform for digital agreements. You can now send the generated documents automatically to DocuSign for signing.

![DocuSign delivery configuration in Docupilot](/files/QIm07p5xpLtG54pPCrGs)

### Configuring a new DocuSign Delivery

In template details page, open **Deliveries -> DocuSign**. This opens DocuSign delivery configuration page.

1. Give your delivery a name for easier identification on what this delivery does
2. Select DocuSign Account. (Link one if not already linked by using the + icon beside the account selection dropdown)
3. Enter Email Subject and Email Message (optional):
   1. This information will be sent to recipients mailbox by Docusign
4. Configure Recipients:
   1. The recipient entries should match anchor tags placed in your template. For example, if your template has `\s1\` and `\s2\` anchor tabs configured ([read more about how to add anchor tabs](#place-automatic-anchor-text-in-a-document)), ensure there are 2 signers configured in your delivery.
   2. Recipient Roles:
      1. **Need to Sign** (Signers) - A recipient who must sign, initial, date, or add data to text tabs on the documents in the envelope.
      2. **Receives a Copy** (Carbon Copy) - a recipient who gets a copy of the envelope but don't need to sign, initial, date, or add information to any of the documents. This type of recipient can be used in any routing order. Copy recipients receive their copy when the envelope reaches the recipient's order in the process flow and when the envelope is completed.
      3. **Allowed to Edit** (Editors) - a recipient who has the same management and access rights for the envelope as the sender. They can make changes to the envelope as if they were using the DocuSign's "Correct" feature. This recipient can add name and email information, add or change the routing order, and set authentication options for the remaining recipients. Additionally, this recipient can edit signature/initial tabs and text tabs for the remaining recipients. The recipient must have a DocuSign account to be an editor.
   3. Both Email and SMS delivery can be configured for Signers and Copy recipients. (since Version 2.1. Older version supports only Email delivery)
   4. Only Email configuration is allowed for Editors.
5. Enable optional recipients, if necessary ([read more](#optional-recipients))
6. Configure Expiry (optional) - configure the expiry date of the envelope in days. After the expiry, the envelope status changes to **Voided** and it can no longer be viewed or signed by recipients [(read more)](https://support.docusign.com/s/document-item?language=en_US\&bundleId=pik1583277475390\&topicId=onc1583277380729.html&_LANG=enus)
7. Configure custom anchor tags (advanced, optional)

{% hint style="info" %}
You can get a sandbox account for testing purposes for free <https://developers.docusign.com/>
{% endhint %}

### Place Automatic Anchor Text in a Document

Automatic anchor text is a feature that allows text to be used in documents as a placeholder for signature, initial and other tags for a particular signer.

When creating or editing a document, type the automatic anchor text in the appropriate location in the document.

* After typing the anchor text, change the color of the anchor text to white or to the background color of the document. This way, the anchor text does not appear when the document is viewed, making the anchor text invisible to the recipients of the document.
* In the following example, anchor text is added to place an initial, signature, name, title, and date signed tags.The text has been highlighted so it can be viewed.

![](/files/-LZjaCekMZOExglDwcyH)

The following table shows the default automatic anchor text used for different DocuSign fields (formerly tags). This is the text typed in documents as a placeholder when creating and saving the documents.

| Field Type          | Signer1                                                                     | Signer2                                                                     |
| ------------------- | --------------------------------------------------------------------------- | --------------------------------------------------------------------------- |
| **Signature**       | \s1\\                                                                       | \s2\\                                                                       |
| **Initial**         | \i1\\                                                                       | \i2\\                                                                       |
| **Date Signed**     | \d1\\                                                                       | \d2\\                                                                       |
| **Name**            | \n1\\                                                                       | \n2\\                                                                       |
| **Title**           | \t1\\                                                                       | \t1\\                                                                       |
| Attachment          | \attachment1\<br>\attachment1\_2\<br>\attachment1\_3\</p>                   | \attachment2\<br>\attachment2\_2\<br>\attachment2\_3\</p>                   |
| Attachment Required | \attachment1\_req\<br>\attachment1\_2\_req\<br>\attachment1\_3\_req\</p>    | \attachment2\_req\<br>\attachment2\_2\_req\<br>\attachment2\_3\_req\</p>    |
| Text Box            | \tbx\_1\_text\<br>\tbx\_1\_2\_text\<br>\tbx\_1\_3\_text\</p>                | \tbx\_2\_text\<br>\tbx\_2\_2\_text\<br>\tbx\_2\_3\_text\</p>                |
| Text Box required   | \tbx\_1\_text\_req\<br>\tbx\_1\_2\_text\_req\<br>\tbx\_1\_3\_text\_req\</p> | \tbx\_2\_text\_req\<br>\tbx\_2\_2\_text\_req\<br>\tbx\_2\_3\_text\_req\</p> |

{% hint style="warning" %}
**IMPORTANT:** You MUST NOT use the automatic anchor text in ANY other location in the document, unless you want DocuSign to add the fields (formerly tags) in that text location.
{% endhint %}

{% hint style="warning" %}
**Note:** While using tags, please not to leave a space after the tag if it is at the end of the line. Backslash at the end of the tags interfere with the token in the next line leading to nullification the token as plain text.
{% endhint %}

{% hint style="info" %}
We will be supporting more field types in the next release.
{% endhint %}

### Optional Recipients

Activate the optional recipients feature in DocuSign delivery to **bypass invalid recipient entries**.

For instance, as illustrated below (screenshot), John Realtor sets up a generated lease agreement to be sent to new tenants. He configures three tenants and himself as signers. The tenant count may vary. If a property is leased to only two individuals, the data for `tenant_three_name` and `tenant_three_email` can be omitted. Without the optional recipients feature enabled, the delivery fails since DocuSign requires valid data for all recipients. When enabled, Docupilot omits sending invalid recipient details to DocuSign, ensuring successful delivery.

![Configuring optional recipients for Docusign in Docupilot](/files/em4iZlmRHLAyJTXFidtq)

### Upgrade to Version 2.1

All DocuSign deliveries that were created prior to Oct 18th, 2023 use a legacy integration (v2.0) and post that date use latest version.

> We recommend you to test thoroughly after migration and reach out to <support@docupilot.app> if you have any concerns regarding the upgrade

While most of the functionalities are backward compatible, here is one important change that needs to be considering during upgrade:

The signature placement by DocuSign has been corrected (moved up by 21 pixels) to work better with the new upgrade

<figure><img src="/files/5V5ZBpCUZKQPv9ajluVw" alt=""><figcaption><p>DocuSign Sign here tab (\s1\, \s2\, etc) alignment with legacy vs new version</p></figcaption></figure>

Similarly, the initials placement also has been updated (moved up by 16 pixels)

<figure><img src="/files/2ViwfvhVv3JDlBuSRoW1" alt=""><figcaption><p>DocuSign Initial here tab (\i1\, \i2\, etc) alignment with legacy vs new version</p></figcaption></figure>

Read more about the update from DocuSign [here](https://developers.docusign.com/docs/esign-rest-api/esign101/upgrading-v21/).


# SignNow

Send generated documents automatically for Signing.

SignNow is an award-winning e-signature solution known for its easy-to-use and comprehensive toolkit. Effortlessly sign documents using electronic signatures and make them legally binding in seconds!

To start with SignNow delivery, choose the `SignNow` option from the list of deliveries available in the `Deliveries` tab

![](/files/iaKuNagWDbfok0QNVUXI)

SignNow Simple Text Tags (Anchor Tags) are specially formatted text that can be placed anywhere within the content of your document specifying the location, size, type of fields such as signature, text, initial fields.

1\. To use text tags, you must add them to your document before uploading.

The full set looks like: **\\{{t:\[s/i/t/d/c];r:\[y/n];o:"Role";l:"date";w:width;l:length;v:"validator\_id";}}**

For example: Signature and Date field

Signature field: `\{{t:s;r:y;o:"Signer1";}}`

Date field: `\{{t:t;r:y;o:"Signer1";l:"Date";}}`

![Example Document with SignNow Text Tags](/files/LnPzlAiITzV4gmtoSNRe)

{% hint style="info" %}
Adjusting the size of the SignNow fields is as simple as adjusting the text tag font size; a larger font results in a larger field and vice versa.
{% endhint %}

For example, the text tags being used for the ‘Date’ line are the following:\
\&#xNAN;**\\{{t (for the Type of field): t (for Text): r (for Required): y (for Yes): o (for Role): “Signer1”; l (for Label): “Date”;}}**

The text tags being used on first the ‘Sign here’ line are the following:\
\&#xNAN;**\\{{t (for Type of field): s (for Signature); r (for Required): y (for Yes); o (for Role): “Signer1”;}}**

The text tags being used on the second ‘Sign here’ line are the following:\
\&#xNAN;**\\{{t (for Type of field): s (for Signature); r (for Required): y (for Yes); o (for Role): “Signer2”;}}**

The table below shows the most widely used text tags in SignNow along with the types of fields for which these text tags can be applied.

| KEY | What does it mean? | Accepted format & values                                                                                           | When fields need this KEY?         |
| --- | ------------------ | ------------------------------------------------------------------------------------------------------------------ | ---------------------------------- |
| t   | TYPE of the field  | <p>s (for signature)</p><p>i (for initials)</p><p>t (for text)</p><p>d (for dropdown)</p><p>c (for checkboxes)</p> | For every field                    |
| r   | REQUIRED           | <p>y (for required)</p><p>n (for optional)</p>                                                                     | For every field                    |
| o   | ROLE               | " "                                                                                                                | For every field                    |
| l   | LABEL              | ""                                                                                                                 | Only for Text and Drop down fields |
| dd  | DROPDOWN           | "option1, option2, option2, ...."                                                                                  | Only for Drop down fields          |
| f   | FILE               | " ".pdf"                                                                                                           | File attachment                    |
| w   | WIDTH              | w (width)                                                                                                          | For every field                    |
| h   | HEIGHT             | h (height)                                                                                                         | For every field                    |
| v   | VALIDATOR\_ID      | v (validator\_id)                                                                                                  | <p>Only for Text field<br></p>     |

{% hint style="info" %}
Here is the full documentation from SignNow, <https://www.signnow.com/features/add-text-tags-to-the-document>
{% endhint %}

{% hint style="warning" %}
Note that the text tags defined by SignNow do not have a leading `\`, but it is required by Docupilot as the double-curly syntax of SignNow interferes with double-curly syntax supported by Docupilot. A leading `\` before `{{` tells Docupilot not to treat that as a Docupilot token.
{% endhint %}

### Date format for signers

The default format for the date field is '**mm/dd/yyyy**'. This can be edited as per requirement by appending a validator key at the end of the Date Text Tag.

Sample Text Tags for a specific date format:

| Format                              | Text Tags (with validator)                                                        |
| ----------------------------------- | --------------------------------------------------------------------------------- |
| European Format (dd/mm/yyyy)        | `\{{t:t;r:y;o:"Signer1";l:"Date";v:"059b068ef8ee5cc27e09ba79af58f9e805b7c2b3";}}` |
| European Format (dd/mm/yy)          | `\{{t:t;r:y;o:"Signer1";l:"Date";v:"0b61eb6a696da953910f195b30c86e5131f3ae3e";}}` |
| Time Only (HH:MM)                   | `\{{t:t;r:y;o:"Signer1";l:"Date";v:"09d3bb6a5eb6598edb7bfad02b0143d8c68ad788";}}` |
| Written Format (MON DD, YYYY)       | `\{{t:t;r:y;o:"Signer1";l:"Date";v:"0f4827a308018f98b11ae3923104685ff0c03070";}}` |
| Written Format (DD-MON-YYYY)        | `\{{t:t;r:y;o:"Signer1";l:"Date";v:"07c1e60f3da1192b60aca6f7e72d9b17a44539e5";}}` |
| Date and Time (MM/DD/YYYY HH:MM:SS) | `\{{t:t;r:y;o:"Signer1";l:"Date";v:"06448a0d0eb6a71c7c116ec4754bcb04ebf11da5";}}` |

### Optional Recipients

Enabling optional recipients in the SignNow delivery will skip **invalid signers** and **carbon copy** (cc) entries.

![SignNow delivery configuration](/files/UzpG8SJvymGFuFoKj2f8)


# Xodo sign (formerly Eversign)

Send generated documents automatically for Signing.

Xodo sign (formerly Eversign) is all about boosting your business workflow and efficiency, and getting day-to-day tasks like scanning, printing and manually signing out of the way.

To start with Xodo sign (formerly Eversign) delivery, choose the `Xodo sign(formerly Eversign)`option from the list of deliveries available in the `Deliveries` tab

![](/files/6fu7wCJgzT5Ysha9e0eg)

![Xodo Sign (formerly Eversign) delivery configration](/files/-M5vdqJGJVyyJFkl5taS)

## Hidden Tags

Hidden Tags is a feature that allows text to be used in documents as a placeholder for signature, initial and other tags for a particular signer.

![](/files/-M5vdl_MwHl7YHrMnVBT)

### Usage

A hidden tag is a text element wrapped in square brackets `[ ]` containing a series of options in a specific order, all divided by `|` symbols. You can specify a total of 9 options, such as field type, signer ID, required/non-required, field label, field identifier, and more.

{% hint style="info" %}
Only the first three options are mandatory!\
\
Signer1

\[sig|req|signer1]\
Full Name \[text|req|signer1]\
Date \[date|req|signer1]\
\---------------------------------------------------------------\
Signer 2\
\
\[sig|req|signer2]\
Full Name \[text|req|signer2]\
Date \[date|req|signer2]
{% endhint %}

{% hint style="warning" %}
White-on-White:\
Since hidden tags should in fact be hidden on your document, they should be added in same color as the background of your document. In most cases, this is white-on-white.
{% endhint %}

**Example:** Here's a hidden tag using all available options:

```
[text|req|signer1|Name|name_1|Paul McSign|125|50|letters_only]
```

In the example above we are creating a required 125x50px text field, prefilled with the value "Paul McSign", with "letters\_only" field validation enabled. Additionally, the field label is set to "Name" and the field identifier is set to "name\_1".

**Options:** Below you will find all 9 available options explained:

| Order | Name                    | Description                                                                                                                                              |
| ----- | ----------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- |
| 1     | Field Type              | Enter your preferred field type. \[Example: `sig` for Signature]                                                                                         |
| 2     | Required / Non-Required | Enter `req` for required or `nonreq` for a non-required field.                                                                                           |
| 3     | Signer Number           | Enter `signerX` with `X` being the number/ID of the signer this field is for. \[Example: `signer1`]                                                      |
| 4     | Field Label             | Enter your field label. This will be displayed as the placeholder for text fields. \[Example: `Name`]                                                    |
| 5     | Field Identifier        | Enter your field identifier. \[Example: `signature_2`]                                                                                                   |
| 6     | Prefill Field Value     | Enter a value to prefill your field with. Different field types come with different prefill options                                                      |
| 7     | Field Width Override    | By default, your field will come with the same width as your hidden tag. You can override this width by entering a pixel width here. \[Example: `125`]   |
| 8     | Field Height Override   | By default, your field will come with the same height as your hidden tag. You can override this height by entering a pixel height here. \[Example: `50`] |
| 9     | Field Validation        | Enter your preferred field validation type, if any.                                                                                                      |

### **Field Types**

The following field types can be created using hidden tags. "Prefill Value" refers to the type of value your field can be prefilled with.

| Field Type | Context           | Prefill Value                      |
| ---------- | ----------------- | ---------------------------------- |
| `sig`      | Signature field   |                                    |
| `init`     | Initials field    |                                    |
| `text`     | Text field        | String                             |
| `date`     | Date Signed field |                                    |
| `check`    | Checkbox field    | 0 for un-checked and 1 for checked |

### **Field Validation**

There are 3 types of field validation that can be enabled:

* `letters_only` Requires the given field value to contain letters only.
* `numbers_only`: Requires the given field value to contain numbers only.
* `email_address`: Requires the given field value to be a syntactically valid email address.

{% hint style="info" %}
Skipping Options:\
In order to skip an option, simply leave it empty without making any changes to the order of other options. A field with a field identifier but without a field label would look like below.\
\&#xNAN;**\[text|req|signer1||name\_1|...]**
{% endhint %}

### Optional Recipients & Signers

Enabling optional recipients in the Xodo sign delivery will skip **invalid signers** and **carbon copy** (cc) entries.

![](/files/qXnZv8AmXQqkdT0v8R60)


# Signable

Send generated documents automatically for Signing.

Signable is a cloud-based electronic signature solution which enables a user(s) to send out documents electronically to be signed by one or more signers.

To set up an Signable Delivery, choose the `Signable` option from the list of deliveries available in the `Deliveries` tab.

<figure><img src="/files/TnpX77wc2q907vfjXgyA" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/DROyNpbt3FCjZj79Orx5" alt=""><figcaption><p>Signable delivery configuration</p></figcaption></figure>

## Signable Tags

Signable Tags is a feature that allows text to be used in documents as a placeholder for Signature, Date, Text, Upload and Checkbox. These tags will then be replaced with the relevant field.

One thing to remember when adding Tags to your template is to keep them on one line to ensure the Tag is retained. For example: `{signature:signer1:Please+Sign+Here}`

A tag has the following structure: **{WHAT:WHO:MESSAGE}**

{% hint style="warning" %}
Tags also do not support the use of characters other than A-Z, a-z, 0-9 E.g. “my+tag+name+/+label” is not valid.
{% endhint %}

{% hint style="warning" %}
Tags are ***Case-Sensitive***.
{% endhint %}

### Types of Signable Tags

Signable supports the following types of fields

* Signature
* Date
* Text
* Document Upload
* Checkbox

#### Signature:

Syntax: `{signature:who:message}`

Example:\
1\. {signature:signer1:please+sign+here}\
2\. {signature:signer2:please+sign+here}\
3\. {signature:signer3:please+sign+here}

<figure><img src="/files/gGYYVTJ5GiXqEZQZE78D" alt=""><figcaption><p>Signable signature field</p></figcaption></figure>

#### Date

Syntax: `{date:who:message}`

Example:\
1\. `{signature:signer1:select+date+here}`\
2\. `{signature:signer2:enter+date+here}`\
3\. `{signature:signer3:select+date+here}`

<figure><img src="/files/cAy137DPMZmbOBlry4S7" alt=""><figcaption></figcaption></figure>

#### Text:

Syntax: `{text:who:message}`

Example:\
1\. `{text:signer1:enter+name}`\
2\. `{text:signer2:enter+address+here}`\
3\. `{text:signer3:enter+phone+number+here}`

<figure><img src="/files/CdNmYhaCATwK5ds5GNpb" alt=""><figcaption><p><code>Signable text field</code></p></figcaption></figure>

#### Document Upload

Syntax: `{upload:who:message}`

Example:\
1\. `{upload:signer1:upload+file+here}`\
2\. `{upload:signer2:upload+document+here}`\
3\. `{upload:signer3:upload+here}`

<figure><img src="/files/Zd2XW9c5YDdBgezpVSyq" alt=""><figcaption><p>Signable upload document field</p></figcaption></figure>

#### Checkbox

Syntax: `{check:who:message}`

Example:\
1\. `{check:signer1:please+tick+if+appropriate}`\
2\. `{check:signer2:please+tick}`\
3\. `{check:signer3:please+tick+appropriate}`

<figure><img src="/files/6c5t5sFa1GuUTseDIvhe" alt=""><figcaption><p><code>Signable checkbox field</code></p></figcaption></figure>

### Optional Tags

A signable tag can be made optional by inserting a "?" after the first part of the tag.

Examples:

* `{text?:signer1:enter+name+here}`
* `{check?:signer2:Please+tick}`
* `{date?:signer3:select+date}`

### Adjusting the height and width of the tag

By default, the size of a tag is fixed to 10x100. This can be changed by mentioning the width and/or height of the tag while entering the tag.

Examples:

* `{text,w20,h30:signer1:enter+name+here}`
* `{check,w30:signer2:Please+tick}`
* `{signature,h40:signer3:sign+here}`

{% hint style="warning" %}
When providing both width and height for the tag, they shall be mentioned in the order of width and height only and not as height and width.\
\
Correct syntax: `{text,w20,h40:signer2:enter+age}`\
Wrong syntax: `{text,h40,w20:signer2:enter+age}`
{% endhint %}


# Yousign

Send generated documents automatically for Signing.

YouSign is an electronic signature solution that allows individuals and businesses to securely sign documents online, eliminating the need for physical signatures.

<figure><img src="/files/K6QqTPByLcCilvCz9Exa" alt=""><figcaption></figcaption></figure>

To create a Yousign delivery, select `Yousign` option from the list of available deliveries within the `Deliveries` tab.

{% hint style="info" %}
To integrate your Yousign account with Docupilot, you'll require an API key from your Yousign account. You can generate a new API key by visiting this link:

[https://yousign.app/auth/api/apikeys](https://yousign.app/auth/api/apikeys.)
{% endhint %}

## Adding a Yousign account

<figure><img src="/files/Erv4LmA9V7g1WwiHik4S" alt=""><figcaption><p>Adding an Yousign Account</p></figcaption></figure>

{% hint style="info" %}
Docupilot supports enabling the optional signers to skip **invalid signer, approver and follower entries.**
{% endhint %}

Yousign supports the following types of fields :

* Signature Field
* Mention Field (Date Field)
* Text Field (Text Input)
* Checkbox Field
* Radio Button Field

## Smart Anchors:

Yousign places the signing fields on the document at locations where smart anchor tags are inserted. Read below to learn more about how to insert various types of fields in your Docupilot template.

{% hint style="info" %}
The text anchor's will appear in the generated document as original text. To make the anchors invisible in the final document, **anchor text match with the background colour**.
{% endhint %}

## Signature Field:

Syntax: `\{{signer_index|signature|width|height}}`

Example: `\{{s1|signature|85|37}}`

<div><figure><img src="/files/LPjwuchtleogglsdNXGG" alt="" width="563"><figcaption><p>Docupilot Template with YouSign's signature field</p></figcaption></figure> <figure><img src="/files/6QR6P9k5ih8W7bZ0Trlj" alt="" width="563"><figcaption><p>Signature on the Generated Document after</p></figcaption></figure></div>

Read more about the Yousign Signature field [here](https://developers.yousign.com/docs/fields-creation-new#signature-field).

## Mention Field (Date Field):

Syntax: `\{{signer_index|mention|mention_content}}`

Example: `\{{s1|mention|Read and approved on the %date%}}`

<div><figure><img src="/files/BBXbGUDagiDMQTatZ8fs" alt="" width="375"><figcaption><p>Docupilot Template with YouSign's signature &#x26; date field</p></figcaption></figure> <figure><img src="/files/IwhMuPrMvEnabT5ok2Av" alt="" width="375"><figcaption><p>Signature &#x26; Date on the Generated Document after completing</p></figcaption></figure></div>

Read more about Yousign the Mention field [here](https://developers.yousign.com/docs/fields-creation-new#mention-field).

## Text Field (Text Input):

Syntax:`\{{signer_index|text|max_length|width|height|question|instruction|optional}}`

Example: `\{{s1|text|150|100|165|text field with specific width and height?|Important for us|t}}`

<div><figure><img src="/files/ke3okVVJbBY46XpfSPSy" alt="" width="375"><figcaption><p>Docupilot Template with YouSign's text field</p></figcaption></figure> <figure><img src="/files/9UfW5idNWn7uXM3eGdAY" alt="" width="375"><figcaption><p>Text added on the Generated Document after completing</p></figcaption></figure></div>

Read more about the Yousign Text field [here](https://developers.yousign.com/docs/fields-creation-new#text-field-text-input).

## CheckBox Field:

Syntax: `\{{signer_index|checkbox|size|optional|checked|name}}`

Example: `\{{s1|checkbox|24|t|f|Checkbox1}}`

Deprecated pattern: `\{{signer_index|checkbox|optional|checked|name}}`

<div><figure><img src="/files/TjQRbJoTr0GqwwgabheY" alt=""><figcaption><p>Docupilot Template with YouSign's checkbox field</p></figcaption></figure> <figure><img src="/files/epkcqHYoPwdrjBbKH50L" alt=""><figcaption><p>Checkbox is checked on the Generated Document after completing</p></figcaption></figure></div>

Read more about the Yousign Checkbox field [here](https://developers.yousign.com/docs/fields-creation-new#checkbox-field).

## Radio Button Field:

Syntax:`\{{signer_index|radio|size|group_name|optional}}`

Example: `\{{s1|radio|28|group_name_1|t}}`

<div><figure><img src="/files/EWkKXWk8CEXlelWQ3xjf" alt=""><figcaption><p>Docupilot Template with YouSign's radio button field</p></figcaption></figure> <figure><img src="/files/Xxs70cwncO8N2gFn9Jfi" alt=""><figcaption><p>Radio is selected on the Generated Document after completing</p></figcaption></figure></div>

Read more about the Yousign Radio button field [here](https://developers.yousign.com/docs/fields-creation-new#radio-button-field).

{% hint style="warning" %}
**Smart Anchors:**

To maintain performance, the usage of Smart Anchors is only possible on documents fitting the following criteria:

* 150 pages.
* 50 Mb
* Multiline anchors are not supported.
* If an anchor refers to a **non-existing Signer position** the **field** will **not be created.**
* **For better compatibility, Yousign recommends using the Arial font** when adding a Smart Anchor into a document.

If document has more than 150 pages, no error will be sent but the Smart Anchors won't be parsed. *Note that this will still use credits from your Docupilot Account as well as Yousign account.*
{% endhint %}


# Amazon S3

Saving created documents in AWS Simple Storage Services(S3).

Minimal IAM Permissions required for a smooth integration are as given below:

```
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": [
                "s3:PutObject",
                "iam:GetUser"
            ],
            "Resource": [
                "arn:aws:iam::<YOUR_ACCOUNT_ID>:user/<YOUR_IAM_USER_NAME>",
                "arn:aws:s3:::<YOUR_S3_BUCKET>/*"
            ]
        }
    ]
}
```

To start with a Amazon S3 delivery, choose the `AWS S3` option from the list of deliveries available in the `Deliveries` tab.

![Configuring Amazon S3 delivery](/files/ozwfUpAzZDkaCrcMcOJZ)

Your final file key will be File key prefix + name of the created document.

Example :

1. If the File key Prefix is `docupilot/docs/` and the name of the created file is `hello.pdf` , then the final file key shall be `docupilot/docs/hello.pdf`
2. If the file key prefix is `docupilot/docs` and the name of the created file is `hello.pdf`, then the final key shall be `docupilot/docshello.pdf`


# Azure Blob Delivery

Saving created documents in Azure Blob Storage.

To add Azure Blob delivery, choose the `Azure Blob` option from the list of deliveries available in the `Deliveries` tab.

### Linking **Azure Storage** A**ccount**

<figure><img src="/files/eXgOh517ouo7pxbDWFFk" alt=""><figcaption><p>Connecting Azure Storage Account</p></figcaption></figure>

To connect your Azure Storage account, follow the steps below:

1. Navigate to **Settings** in your Docupilot account.
2. Click on [**Linked Accounts**](/settings/linked-accounts) from the left side panel.
3. Select **Link Account**, then choose **Azure Storage** as the storage type.
4. Enter the following details and click **Save**:
   * **Azure Storage Account Name**
   * **Sas Token**

{% hint style="info" %}
**Sas** Token must be generated from your Azure Storage account. Navigate to **Security + networking > Access Keys** to create one.
{% endhint %}

### Granting Permissions

<figure><img src="/files/q0W4YEEEvQkRq4nyaWEE" alt=""><figcaption><p>Allowing Access Permissions to Container in Azure</p></figcaption></figure>

After linking your Azure Storage account, follow the steps below to grant the required permissions (if not already provided):

1. Go to your **Azure** **Storage Account**.
2. Navigate to **Security + Networking** > **Shared access signature**.
3. Under **Allowed services**, enable:
   * **Blob**
4. Under **Allowed resource types**, enable:
   * **Object**
5. Under **Allowed permissions**, enable:
   * **Read** *(required only when* [*using this account for inserting private images*](/settings/linked-accounts#use-a-linked-account-to-download-images) *on the document)*
   * **Write**

{% hint style="info" %}
If you want to update any permissions, or if your SAS token is expired, you must generate a new SAS token and use that to [reconnect](/settings/linked-accounts#reconnect-an-integration) your Azure Storage account.
{% endhint %}

To insert private images *(i.e. image files that are not available to download from a public URL)* from your Azure Storage account, make sure to enable the **"**[**Use a linked account to download private images**](/settings/linked-accounts#use-a-linked-account-to-download-images)**"** toggle for the connection under **Linked Accounts**.

## Configuration

<figure><img src="/files/AMR3b69VC58HilFx2LUR" alt=""><figcaption><p>Configuring Azure Blob Delivery</p></figcaption></figure>

**Name:** Enter a name for your delivery configuration. This helps you identify the delivery setup, for example, "Upload to My App folder".

**Select Account:** Select the Azure Blob account you wish to use for the delivery. If no accounts are available, you can connect an account by clicking the Link Account icon or by navigating to **Settings > Linked Accounts**.

**Container Name:** Specify the name of the existing container to which your documents need to be delivered.

**Folder Path:** Configure folder path to which the generated files needs to be uploaded. The folder path can be dynamic. For example, to upload customer contracts under a folder that includes customer's name, you can configure **Folder** as `Contract Agreements/{{CustomerName}}`

Now when a contract is generated with `AcmeCorp` as `CustomerName` it will be uploaded to `Agreements/AcmeCorp`

**Advanced Settings (Optional)**

If you like to get notified on delivery errors, or on successful execution of deliveries, configure advanced settings to take advantage of integrations. Following advTanced integration options are available:

* **On Success Callback URL :** Configure a Web-hook URL which will be invoked with data containing the folder path to which the file was uploaded. To configure additional settings for callback URL like setting custom Headers and Additional Payload use the **Advanced Configuration** section.
* **Emails to Notify on Delivery Failure :** Failed deliveries are typically notified to the workspace owner, workspace admins and workspace managers via email. You can configure additional email IDs here to receive notifications on delivery failures.


# Box Drive

Upload the generated documents to your Box Drive.

To integrate with Box Drive, choose the `Box Drive` option from the list of deliveries available in the `Deliveries` tab.

### Configuration

<figure><img src="/files/8rZ28M6uzcQvNjCcZbsj" alt=""><figcaption><p>Configuring Box Drive Delivery</p></figcaption></figure>

**Name:** Enter a name for your delivery configuration. This helps you identify the delivery setup, for example, "Upload to Team folder."

**Select Account:** Select the Box Drive account you wish to use for the delivery. If no accounts are available, you can connect an account by clicking the link icon or add one by navigating to **Settings >** [**Linked Accounts**](/settings/linked-accounts).

**Folder:** Select the folder path where the generated files should be uploaded. If no path is configured, the files will be uploaded to the root folder of the drive.

**Advanced Settings**

If you like to get notified on delivery errors, or on successful execution of deliveries, configure advanced settings to take advantage of integrations. Following advanced integration options are available:

* **On Success Callback URL** Configure a Web-hook URL which will be invoked with data containing the folder path to which the file was uploaded. To configure additional settings for callback URL like setting custom Headers and Additional Payload use the **Advanced Configuration** section.
* **Emails to Notify on Delivery Failure** Failed deliveries are typically notified to the workspace owner, workspace admins and workspace managers via email. You can configure additional email IDs here to receive notifications on delivery failures.

[<br>](https://help.docupilot.app/deliveries/azure-blob-delivery)


# Create document


# Data Capture Form

Generate Documents using Data Capture Form

Once you have tried and tested your document, you can finally start merging!

There are various options to do a merge. One of them is to fill a form with all the merge fields, similar to the test document phase.

### Creating a Data Capture Form

To start creating documents using a form, follow the steps listed below :

* Click on the **Create** tab to access the Create Document view.

<figure><img src="/files/8lU3lBfcahvvStCvFuEB" alt=""><figcaption><p>Accessing the Create Document view</p></figcaption></figure>

* Select the **Data Capture Form** on the left side (if it's not already selected), then click the **+ Create Link** button.

<figure><img src="/files/inqFrCspkxFUNelgSnTE" alt=""><figcaption><p>Creating a Data Capture Form</p></figcaption></figure>

* Click on the link under the heading "**Generate document by filling form**" to open a form

<figure><img src="/files/KHB3d1DuAe1yAEJZ7a5p" alt=""><figcaption><p>Accessing Data Capture Form URL</p></figcaption></figure>

* Once you complete the form and click the **Submit** button, the generated document will be delivered to all your configured deliveries. If no deliveries are configured, the document will be downloaded.

If you want to download the generated document along with triggering deliveries you use the Link under **"Download Form"** section or append a `?download=true` parameter in the URL.

### Populating Table data using a CSV

If your data capture form includes a table (i.e. if your template contains an array field), you can upload a CSV file to automatically populate the table —saving you from manually entering each record.

For example, if you need to fill a list of employees (role, name and experience), you can prepare a CSV like this:

<figure><img src="/files/z58FE0e0sgjz6oRkgT3T" alt="CSV data to be uploaded to data capture form"><figcaption></figcaption></figure>

Then upload the CSV to the corresponding table field in your data capture form.

{% hint style="warning" %}
**Note:** The CSV column headers must exactly match the template tokens used in the table for the import to work correctly.
{% endhint %}

<figure><img src="/files/P4ZM9jaYfXgslFn2h7Zn" alt="Upload CSV to data capture form"><figcaption></figcaption></figure>

### Deleting a Data Capture Form

To delete the link that opens Data Capture Form, click the **Delete** button available on the right side of the **Data Capture Form** section.

<figure><img src="/files/w6lam9qoR97CAM6yWegN" alt=""><figcaption><p>Deleting the Data Capture Form</p></figcaption></figure>

{% hint style="info" %}
To create or delete these links, users must have **Manage** or **Write** permissions on the templates. Please note that deleting the Data Capture Form link will also remove the link created for API Endpoint.
{% endhint %}


# API & Webhook Integration

Generate Documents using Webhooks & APIs

Docupilot allows you to simplify your document generation process by integrating with other systems through Unauthenticated **API endpoints** which can also be configured as **Webhooks** in other applications.

### Creating an API Endpoint

To create an API Endpoint, follow these steps:

* Click on the **Create** tab to access the **Create Document** view and select **API Integrations** from the left sidebar.

<figure><img src="/files/jQNtwWJ60r8Nr9bLXsZ3" alt=""><figcaption><p>Create an API Endpoint</p></figcaption></figure>

* Click on **Create API Endpoint** button to create the Url for document generation.

<figure><img src="/files/P5vbv94int7GRAgPuK3q" alt=""><figcaption><p>API Integration</p></figcaption></figure>

When data is sent to the API Endpoint, it generates a Document and sends it to configured delivery locations. If no deliveries are configured, then it will return a secure file URL to download the generated document. This secure URL is valid for 24 hours by default which can be customized under [Data Retention Preferences](/settings/workspace#data-retention).

If you want to download the generated document along with triggering deliveries you need to append `download=true` query parameter in the URL.

If you want to receive the generated document as a file in response, append `download=file` query parameter in the URL. This will include the secure file URL in the `Content-Location` response header. If you do not prefer the secure file URL to be created, send an additional query parameter `includeUrl=false`. This will not return the `Content-Location` header in the response.

### Using the API Endpoint

The API Endpoint can be configured in various locations – Ex: Configure it as a Webhook in your CRM, or configure it as a Webhook in your the Forms/Survey software you use, or configure this URL inside your custom built application, and send data to it.

For example, if this is your template:

{% code title="Sample Template" %}

```handlebars
Hello {{name}},

{{email}}
{{address}} {{state}} {{country}}
```

{% endcode %}

You should send a `POST` request to the API Endpoint, with `Content-Type` as `application/json` and body with JSON payload structured like in the example below:

{% code title="Sample Request" %}

```
Method: POST
URL: https://api.docupilot.app/documents/create/{org_unique}/{template_unique}/

Headers:
Content-Type: application/json

Body:
{
    "name":"John",
    "email":"johj@example.com",
    "address":"XYZ Street",
    "state":"CA",
    "country":"USA"
}
```

{% endcode %}

{% hint style="info" %}
Please note that the tokens (merge fields) defined in the template should match the keys in the webhook data.
{% endhint %}

Sample response when at-least 1 delivery configured:

```
{
    "status": "success",
    "data": null
}
```

Sample response with no deliveries configured -or- with `download=true` query parameter

```
{
    "status": "success",
    "data": {
        "file_url": "https://docupilot-documents.s3.amazonaws.com/temp/1a2cadd4-33f7-4f0c-9d9a-3e87803d3e7b/contract.pdf?AWSAccessKeyId=AKIAJTKZBQI56EOPGLFQ&Signature=BHG3mejXO3f1ymBcZVjMB04Sr6U%3D&Expires=1530277229",
        "file_name": "contract.pdf"
    }
}
```

Sample response when `download=file` query parameter is appended

<div><figure><img src="/files/OcUQnJXnuo2IxlT8MeHc" alt=""><figcaption><p>Returns the File in Body</p></figcaption></figure> <figure><img src="/files/tO5mY66otb6ClRHhzQpP" alt=""><figcaption><p>Response includes Content-Location in Header</p></figcaption></figure></div>

{% hint style="info" %}
To avoid creating the Secure file URL, add the `includeUrl=false` parameter to the API Endpoint, which will remove the `Content-Location` from the API response header.
{% endhint %}

### Quickstart with a CURL Script

The API Integration tab shows an example CURL request for the respective template.

<figure><img src="/files/PZ8soCFS5upAgfr8qsC7" alt=""><figcaption><p>Sample CURL Script</p></figcaption></figure>

### Python

```python
import requests

# update your API Endpoint URL here
api_endpoint = "https://api.docupilot.app/documents/create/46ac75c3/5e7d03ec"

payload = {
  "customer_name":"John",
  "customer_email":"john@example.com",
  "line_items":[
    {
      "description":"Design",
      "quantity":1,
      "price":"230"
    },
    {
      "description":"Development",
      "quantity":4,
      "price":"130"
    }
  ]
}
headers = {
  'Content-Type': "application/json"
}

response = requests.post(api_endpoint, data=payload, headers=headers)

print(response.text)
```

### Deleting the API Endpoint

To delete the API Endpoint, click the **Delete** button available on the right side of the **API Integrations** section.

<figure><img src="/files/ZcGKZt5o87R2hkIcSP30" alt=""><figcaption><p>Deleting API Endpoint</p></figcaption></figure>

{% hint style="info" %}
To create or delete these links, users must have **Manage** or **Write** permissions on the templates. Please note that deleting the API Endpoint link will also remove the link created for Data Capture Form.
{% endhint %}


# Bulk Create

Generating documents in bulk from an Excel or CSV

Data from a CSV file can be used to create numerous documents at once. For Bulk Merge to work, first [setup at-least one delivery](/deliveries) under your template. Follow below steps to create numerous documents at once using Bulk Merge.

* Navigate to the **`Create`** tab in template details page, then click on the **`Bulk Merge`** tab.
* Upload desired CSV file. Ensure that the first row of CSV contains column headers
* Once the file has been uploaded, tokens present in the template should be mapped to corresponding columns. If the column names are similar Docupilot will automatically map the fields for you. The mapping will be remembered across bulk-merge invocations so you wouldn't have to re-map every-time.
* The total number of documents that will be generated can be viewed under **Execution History**.
* Documents that are generated will be delivered to all the configured deliveries.

![Bulk Merge](/files/0acG8NRJ9z9bUMZs0FIg)

{% hint style="warning" %}
In test mode, documents will be generated only from the first 10 records and the generated documents will contain watermark on them.
{% endhint %}


# Integrate with Zapier

Generate Documents from Salesforce, Google Forms, Wufoo Forms, etc.

[Zapier](https://zapier.com/zapbook/docupilot) lets you connect Docupilot to 1,000+ other web services. Automated connections called Zaps, set up in minutes with no coding, can automate your day-to-day tasks and build workflows between apps that otherwise wouldn't be possible.

Each Zap has one app as the **Trigger**, where your information comes from and which causes one or more **Actions** in other apps, where your data gets sent automatically.

With Zapier integration, **Docupilot** now holds hands with your favorite applications to make your tasks simple and efficient.

**How do I connect Docupilot to Zapier?**

1. Log in to your [Zapier account](https://zapier.com/sign-up) or create a new account.
2. Navigate to "Connected Accounts" from the top menu bar.
3. Now click on "Connect new account" and search for "Docupilot"
4. Use your credentials to connect your Docupilot account to Zapier.
5. Once that's done you can start creating an automation! Use a pre-made Zap or create your own with the Zap Editor. Creating a Zap requires no coding knowledge and you'll be walked step-by-step through the setup.
6. Need inspiration? See everything that's possible with [Docupilot and Zapier](https://zapier.com/zapbook/docupilot).

### Create and Email Sales Documents When a Lead is Created

When a new lead is added in the CRM, you'll want to email a personalized proposal or any personalized sales document. Automatically generate a new document from the lead information and document template and email the generated document and save hours of precious time. Put proposals in front of your sales leads quickly before they go cold.

![Salesforce & Docupilot](/files/aV5TDds1SzhkoyPfJHP2)

### Generate and Email PDFs from Forms response

When a new user submit a response in your form like Google Forms, Wufoo, Typeform, FormStack, you will want send an email along with a generated PDF from the data of their response.

![Google Forms & Docupilot](/files/DnnqZ46AY33e7VvCiIZT)

![Wufoo Forms and Docupilot](/files/9YZKKh6lK7fOoEuR9tJy)

<br>


# Integrate with Make

Generate Documents using DropBox, JotForm, Google Sheets etc..

[Make](https://www.make.com/en/integrations/docupilot?fromImt=1) lets you connect Docupilot to 800+ other web services. Automated connections called Scenarios, set up in minutes with no coding, can automate your day-to-day tasks and build workflows between apps that otherwise wouldn't be possible.\
\
Each Scenario has one app as the **Trigger**, where your information comes from and which causes one or more **Actions** in other apps, where your data gets sent automatically.

With Make integration, **Docupilot** now holds hands with your favourite applications to make your tasks simple and efficient.\
\
**How do I connect Docupilot to Make?**

1. Log in to your [Make account](https://www.make.com/en) or create a new account.
2. Click on **Create a new scenario** on the top right corner.
3. Now search for **Docupilot**, select the application and press "Continue".
4. In the Scenario page click on **Docupilot** and select **Create a Document**.
5. Click on **Add** and paste **API Key** generated in **API settings** page in **Docupilot**.
6. Once that's done you can start creating an automation!creating a Scenario requires no coding knowledge and you'll be walked step-by-step through the setup.
7. Need inspiration? See everything that's possible with [Docupilot and Make](https://www.make.com/en/integrations/docupilot?fromImt=1)

### Create Invoices, Agreements and Contracts from online database

When a new record is added to online database services like Airtable, Knack, Zoho Creator, SmartSheet, etc. you'll want to create an agreement or a contract or generate an invoice. Automatically generate a new document from the information provided and save precious time and manual interventions so as to have a cleaner and more fluid work flow.

![Airtable & Docupilot](/files/rkj9CBjrO0tFQv5RMWzt)

### Create documents from Process Management and Workflow Management software

Create documents when a particular stage is reached in your process management software like Pipefy, etc.

![Pipefly & Docupilot](/files/b91KwHJQCcgmIFEDlXG5)

### Create and Email Sales Documents When a Lead is Created

When a new lead is added in the CRM, you'll want to email a personalized proposal or any personalized sales document, Automatically generate a new document from the lead information and document template and email the generated document and save precious time. Put proposals in front of your sales leads quickly before they go cold.

![Freshsales & Docupilot](/files/F8sZKqlwNPnFG65WmdJy)

### Generate and Email PDFs with data collected from a Form

When a new user submit's a response in your form like Google Forms, Wufoo, Typeform, FormStack, you will want send an email along with a generated PDF from the data of their response.

![Wufoo & Docupilot](/files/PLKlagfirQAblQSRPb4O)

### Generate Documents and store in Document Storage for Backup & Audit

Furthermore, push the created documents into Google Drive, Dropbox, Box for backup or audit purposes.

![Typeform & Docupilot](/files/H6ELXPdwFuemQHZcKzgi)


# Integrate with Zoho Flow

Generate Documents from Salesforce, Google Forms, Jot Forms, etc.

[Zoho Flow](https://www.zoho.com/flow/) enables connection of over 600+ web services with Docupilot. Automated connections called Flows, set up in minutes with no coding, can automate your day-to-day tasks and build workflows between various applications.

Each Flow has one app as the **Trigger**, where your information comes from and which causes one or more **Actions** in other apps, where your data gets sent automatically.

With Zoho Flow integration, **Docupilot** now holds hands with your favorite applications to make your tasks simple and efficient.

**How do I connect Docupilot to Zoho Flow?**

1. Log in to your [Zoho Flow account](https://www.zoho.com/flow/) or create a new account.
2. Navigate to **Connections** from the **Settings** bar.
3. Now click on **CREATE CONNECTION** and search for **Docupilot**.
4. Select **Docupilot** from the list below and press **Next**.
5. Paste the **API Key** from the **API settings** in **Settings** tab in your **Docupilot** account.
6. Once that's done you can start creating an automation! Use a pre-made Flow or create your own with the Flow Editor. Creating a Flow requires no coding knowledge and you'll be walked step-by-step through the setup.

### Generate and Email PDFs from Forms response

When a new user submit a response in your form like Google Forms, Wufoo, Typeform, FormStack, JotForm you will want send an email along with a generated PDF from the data of their response.

![JotForm & Docupilot.](/files/-M_RoUIwGR11EeTPAQzt)

### Create and Email Sales Documents When a Lead is Created

When a new lead is added in the CRM, you'll want to email a personalized proposal or any personalized sales document. Automatically generate a new document from the lead information and document template and email the generated document and save hours of precious time. Put proposals in front of your sales leads quickly before they go cold.

![SalesForce & Docupilot](/files/-M_deWB6n1z3IqirEGe7)


# Integrate with Integrately

Generate Documents from Google Docs, Salesforce, Jot Forms etc..

Integrately as the name suggests is an integration platform which enables Docupilot to connect third party web services. Automations can be set up in no time with no coding involved, these can automate your day-to-day tasks and establish workflows between apps.

Each Automation has one **Trigger**, this is where the information comes from and this information is sent to other apps automatically causing one or more **Actions**.

With the help of Integrately, **Docupilot** can now integrate with your favorite applications to make the tasks simple and efficient.

#### How do I connect Docupilot with Integrately?

1. Log in to your [Integrately account](https://app.integrately.com/login) or create a [new account](https://app.integrately.com/signup).
2. In the **Explore & Automate** page displayed, search for **Docupilot**.
3. Select any other app as the second app.
4. Scroll down and choose **Create document in Docupilot** under the **Do** section, while selecting a random under **When** section and press **Go**.
5. In the pop up press on **Yes**.
6. Now press on **Add Connection** under Docupilot and paste **API key** from **API Settings** in your **Docupilot** account.
7. Once this is done, you can start creating an automation.Use a pre-made automation or create your own. Creating an automation requires no coding knowledge and you'll be walked step-by-step through the setup.

### Create and Email Sales Documents When a Contact is Created

When a new contact is added in the CRM, you'll want to email a personalized proposal or any personalized sales document. Automatically generate a new document from the contact information and document template and email the generated document and save hours of precious time.

![](/files/-MaTpq3cKfvrV5BD7Xzj)

### Generate and Email PDFs from Forms response

When a new user submit a response in your form like Google Forms, Wufoo, Typeform, FormStack, JotForm you will want send an email along with a generated PDF from the data of their response.

![Google Forms & Docupilot.](/files/-M_QZmgaek865NUZzsGQ)

![Jot Form & Docupilot](/files/-M_QgVD-8CjVLaSDkRtB)


# Workflows

Build visual automations that collect data, generate documents, and deliver the results.

Workflows let you automate a multi-step document process on a visual canvas. A workflow can collect data, choose a path based on that data, generate documents, convert or combine files, and deliver the result.

## How a Workflow Works

Every workflow starts with one **Form** module. Select a published form from Extensions to define the information the workflow accepts, whether a run is started from the hosted form or through the API.

After the Form module, connect the modules that should process the data:

1. Collect information through the workflow form or API.
2. Evaluate conditions when the process has different paths.
3. Map submitted fields to a template and generate a document.
4. Convert or combine files when required.
5. End each path with a delivery module.

Supported delivery modules include Email Delivery, Webhook Delivery, and eSign Delivery.

{% hint style="info" %}
Create and publish the form from **Extensions**, then select it in the workflow's Form module.
{% endhint %}

## Workflow Terminology

* **Canvas**: The visual workspace where you build a workflow.
* **Module**: A step that performs an action, such as generating a document or sending an email.
* **Connection**: The link that determines which module runs next.
* **Branch**: A path selected by a Condition module.
* **Version**: A saved draft or published snapshot of a workflow.
* **Run**: One execution of a workflow, started by a form submission, API request, or test.

## Example: Sales Contract Workflow

Suppose a sales representative submits customer details and selects a package:

1. The Form module collects the customer and package information.
2. A Condition module selects the Standard or Premium path.
3. A Template module generates the correct agreement.
4. A Convert module creates a PDF.
5. An eSign Delivery module sends the agreement for signing.

The following guides use this example to explain the workflow editor.


# Create and Build a Workflow

Create a workflow, select its form, and connect modules on the canvas.

## Create a Workflow

1. Select **Workflows** from the left sidebar.
2. Open the folder where you want to create the workflow.
3. Select **Create workflow**.
4. Enter a workflow name and an optional description.
5. Select **Create**.

The workflow opens in the editor with an initial draft version.

## Create and Select a Form

The Form module is the required first module. The selected form defines the fields available to later modules and to callers using the workflow API.

Before configuring the workflow:

1. Open **Extensions** and create or select a form.
2. Add and arrange the required fields.
3. Configure the form fields and appearance.
4. Publish the form.

Then return to the workflow:

1. Select the **Form** module.
2. Select the published form.
3. Save the workflow.

For the sales contract example, the selected form could contain:

* Client Name
* Email
* Package

{% hint style="info" %}
Manage form fields and appearance from Extensions. After changing the form, publish it before publishing the workflow.
{% endhint %}

## Add and Connect Modules

1. Add a module from the module panel to the canvas.
2. Select the module and complete its configuration.
3. Connect the previous module's output to the new module's input.
4. Continue until every workflow path ends with a delivery module.
5. Select **Save workflow**.

Connections control execution order. A module can use data or files only from modules that run before it on the same path.

{% hint style="warning" %}
Disconnected modules and incomplete paths can be saved as a draft, but they prevent the workflow version from being published.
{% endhint %}

## Save While You Build

Saving stores the current draft, including the canvas, form, module settings, and connections. The editor displays **Findings** when a module is incomplete or a connection is invalid.

Select a finding to locate the affected module, correct its configuration, and save again.


# Workflow Modules and Mapping

Configure form, condition, document, file, and delivery modules in a workflow.

Each module performs one action. Select a module on the canvas to configure it.

| Module           | Purpose                                 | Main requirement                               |
| ---------------- | --------------------------------------- | ---------------------------------------------- |
| Form             | Collects data and starts the workflow   | Must be the first module                       |
| Condition        | Routes a run through different branches | Requires connected outcomes                    |
| Template         | Merges workflow data into a template    | Requires a selected template and token mapping |
| Convert          | Converts a generated document to PDF    | Requires one upstream document                 |
| PDF Append       | Combines files into one PDF             | Requires at least two supported inputs         |
| Email Delivery   | Sends files as email attachments        | Requires files and email settings              |
| Webhook Delivery | Posts output to a webhook endpoint      | Requires files and a valid endpoint            |
| eSign Delivery   | Sends PDF documents for signing         | Requires files, signers, and eSign settings    |

## Map Form Fields to Template Tokens

A Template module generates a document from a selected Docupilot template. Map each template token to the workflow value that should populate it.

1. Add and select a **Template** module.
2. Select a published template version.
3. Map the template tokens to fields from the Form module.
4. Review the mappings and save the workflow.

For example:

| Template token         | Form field  |
| ---------------------- | ----------- |
| `{{client_name}}`      | Client Name |
| `{{customer_email}}`   | Email       |
| `{{selected_package}}` | Package     |

If a field is unavailable, update and publish the selected form from Extensions, then return to the Template module.

## Add Conditions and Branches

A Condition module selects a path by evaluating submitted workflow data.

For the sales contract example:

* If **Package** is Standard, generate the standard agreement.
* If **Package** is Premium, generate the premium agreement.
* Use the default outcome when no configured rule matches.

To configure a condition:

1. Add and select a **Condition** module.
2. Add an outcome for each required path.
3. Add rules to every non-default outcome.
4. Connect each outcome to its next module.
5. Keep one default outcome and connect it to the appropriate fallback path.

## Convert Documents

Use a Convert module when a generated document must be a PDF before it can be appended or delivered.

1. Connect the Template module to a **Convert** module.
2. Select the upstream document.
3. Enter the output file name.

## Append Files

Use PDF Append to combine two or more supported PDF or PNG inputs into one PDF.

1. Connect the source modules to a **PDF Append** module.
2. Select the files to include.
3. Arrange the files in the required order.
4. Enter the combined output file name.

If an upstream document has an unsupported format, add a Convert module before PDF Append.

## Add Deliveries

Delivery modules are terminal modules: they send the final files and do not connect to another module.

* **Email Delivery** sends selected files as email attachments.
* **Webhook Delivery** posts workflow output to another system.
* **eSign Delivery** sends PDF documents to configured signers.

You can use form values in supported delivery fields, such as recipients, subjects, messages, or webhook values. Select the files produced earlier on the same path and complete every required delivery setting.

{% hint style="warning" %}
Every published workflow path must end in a delivery module. A delivery cannot use a file produced on an unrelated or later path.
{% endhint %}


# Test, Publish, and Version Workflows

Save drafts, run tests, publish versions, and understand workflow status.

## Save and Review Findings

Select **Save workflow** while building. Saving can preserve an incomplete draft, so review the **Findings** menu before testing or publishing.

Common findings include:

* a required module setting is missing
* a module is not connected
* a template token has an invalid mapping
* a condition outcome has no rule or connection
* a file is unavailable or unsupported
* a workflow path does not end in a delivery

## Test a Workflow

1. Open the draft version you want to test.
2. Resolve workflow errors and save your changes.
3. Select **Test Run**.
4. Enter test values in the workflow form.
5. Start the test and review the executed path.
6. Open **Workflow runs** and select **Test runs** to inspect the result later.

Test runs are kept separate from live runs. If a workflow is inactive, activate it before testing.

## Publish a Workflow

Before publishing, confirm that:

* the form contains all required fields
* the selected form is published
* every selected template version is published
* template mappings are complete
* condition outcomes and connections are valid
* document and file modules have valid inputs
* every path ends in a configured delivery module
* the workflow has been saved and tested

Select **Publish** to make the draft the active workflow version. Publishing is stricter than saving and is blocked until publish findings are resolved.

## Start the Workflow

Open **Trigger Options** after configuring the workflow:

* Use **Form** to copy or open the hosted form link.
* Use **API** to view the request information for starting the workflow programmatically.
* Select whether the link targets the published workflow or the latest draft when that option is available.

Use the published workflow link for live submissions.

## Workflow Statuses

The Workflows list displays the lifecycle of the workflow:

* **Draft**: The workflow has not been published.
* **Active**: The workflow has a published version and can accept runs.
* **Inactive**: The workflow is paused. Its published version is retained, but new runs and tests are disabled until it is activated.

## Workflow Versions

A workflow version is a snapshot of its canvas, selected resources, mappings, and module configuration.

* A new workflow starts with a draft version.
* A published version is read-only and continues to run until it is replaced.
* Selecting **Edit** on a published version creates a new draft.
* Changes to the new draft do not affect the published version.
* Publishing the draft makes it the active version.

Use **Workflow versions** in the editor to view and switch between available versions.


# Workflow Runs

Monitor workflow executions and inspect module inputs, outputs, and errors.

A workflow run records one execution of a workflow. Runs let you confirm what happened after a form submission, API request, or test.

## View Workflow Runs

1. Open a workflow.
2. Select **Workflow runs**.
3. Filter by status, run type, or date range, or search by run ID.
4. Select a run to open its execution view.

Use **Live runs** for real submissions and **Test runs** for executions started with Test Run.

## Workflow Run Statuses

* **Queued**: The run has been accepted and is waiting to start.
* **Running**: One or more modules are being processed.
* **Waiting**: Execution is temporarily waiting before it can continue.
* **Completed**: All modules on the selected path completed successfully.
* **Failed**: A module encountered an error that stopped its dependent path.
* **Cancelled**: The run was stopped before completion.

## Inspect a Run

The canvas highlights the path taken by the selected run. Select an executed module to review:

* module execution status
* input data received by the module
* output data produced by the module
* error details, when applicable

The submitted form values appear with the run and in the Form module's data. The run also records the workflow version used for that submission.

Modules can appear as skipped or blocked when their condition branch was not selected or a required upstream module failed. Independent branches can continue even when another branch fails.

## Investigate a Failed Run

1. Open the failed run.
2. Find the failed module on the canvas.
3. Select the module and read its error message.
4. Review its input data and the output from upstream modules.
5. Correct the workflow configuration or submitted data.
6. Save and test the updated draft.

When contacting support, include the workflow name, workflow version, run ID, failed module, and complete error message.


# Manage Workflows

Organize, rename, pause, restore, and delete workflows.

The Workflows page lets you search, organize, and control workflows in the current workspace.

## Organize Workflows with Folders

Create folders to group workflows by process, team, customer, or use case. You can create workflows in a folder or move existing workflows into one.

Deleting a folder does not delete its workflows. Workflows in that folder are moved to the Home folder.

## Rename a Workflow

Select the workflow name in the Workflows list, enter the new name, and confirm the change. Renaming changes the workflow's display name without creating a new workflow version.

## Activate or Pause a Workflow

An active workflow can accept new runs. Use the status action in the Workflows list to make an active workflow **Inactive** when it should be paused temporarily.

Activate the workflow again when it is ready to accept runs. The published version is preserved while the workflow is inactive.

## Move a Workflow to Trash

Move a workflow to Trash when it is no longer needed. Trashed workflows cannot be edited or run.

{% hint style="warning" %}
Workflows in Trash are automatically deleted after 30 days.
{% endhint %}

## Restore a Workflow

1. Open **Trash** from the workflow folder navigation.
2. Find the workflow you want to recover.
3. Select **Restore**.

The workflow returns to the Workflows list with its saved versions and configuration.


# Troubleshoot Workflows

Resolve common workflow building, publishing, testing, and execution problems.

Start with the **Findings** menu for build or publish problems. For execution problems, open **Workflow runs**, select the failed run, and inspect the failed module.

| Problem                             | What to check                                                                                                          |
| ----------------------------------- | ---------------------------------------------------------------------------------------------------------------------- |
| A form field is unavailable         | Update and publish the selected form from Extensions, then reopen the affected workflow module.                        |
| A template contains the wrong value | Confirm that the template token is mapped to the intended form field.                                                  |
| A branch does not run               | Check the condition field, operator, comparison value, and submitted data. Confirm the outcome is connected.           |
| A module does not run               | Confirm it is connected after the required upstream module and belongs to the selected condition path.                 |
| A file is unavailable               | Confirm the source module runs earlier on the same path and produces the selected file.                                |
| A file type is unsupported          | Add a Convert module or select a supported file output.                                                                |
| The workflow cannot be published    | Open Findings and resolve every error. Confirm templates are published and every path ends in a delivery.              |
| Test Run is disabled                | Save the workflow, clear errors, and activate the workflow if it is inactive.                                          |
| A delivery fails                    | Inspect the delivery module's inputs and error. Check recipients, endpoint, account authorization, and selected files. |

## Save Succeeds but Publish Fails

Saving is designed to preserve work in progress. Incomplete modules and connections can therefore be stored with findings.

Publishing validates the complete executable workflow. It can be blocked by missing connections, invalid mappings, an unpublished form or template, unsupported files, or incomplete deliveries.

## A Condition Uses the Wrong Path

1. Open the run and verify the value received by the Form module.
2. Select the Condition module and review each non-default outcome.
3. Confirm the field, operator, and expected value.
4. Confirm the default outcome is connected.
5. Save and start another test run.

## A Delivery Fails

Select the failed delivery module in the run and review:

* the file inputs received by the module
* recipient, signer, or endpoint values
* connected delivery account status
* the complete provider error

Some email, webhook, and eSign provider errors are returned directly by the provider. Reauthorize an expired account or correct the provider configuration before testing again.

## A Downstream Module Is Skipped

A module can be skipped because its condition branch was not selected or because a required upstream module failed. Fix the first failed module on that path; skipped descendants do not need to be corrected individually.

Independent branches may still complete successfully.


# eSignatures

Explore how Docupilot’s eSignature feature enables secure document signing, envelope tracking, and automated reminders.

## Getting Started with eSignatures in Docupilot

Docupilot’s **eSignatures** feature enables users to securely send, sign, and manage documents digitally. This guide walks you through how eSignatures work in Docupilot, the lifecycle of a document (Envelope), and the key roles, settings, and actions involved.


# Introduction to eSignatures

Learn about eSignatures and key terminologies

## What Are eSignatures?

**eSignatures**, or electronic signatures, allow individuals to sign documents digitally, eliminating the need for physical paperwork. They are legally recognized and secure.

Docupilot supports *Advanced Electronic Signatures (AES)*, which comply with legal standards and include added verification, audit trails, and signer authentication to ensure trust and validity.

## What Is an Envelope?

An *envelope* refers to a document or group of documents sent out for signing. It includes:

* the document(s) to be signed
* signer details
* signature fields
* reminder and expiry settings

Each envelope in Docupilot gets a unique identifier, which is used to track its progress from start to finish. This envelope ID appears on all pages of the document(s) sent for signing.

## What is an Audit Trail?

Audit Trail is a Document that shows the activity log of all the actions happened on an Envelope. For example, sent-viewed-signed-completed/declined, etc. This Audit log document bears the Envelope ID and acts as a proof of what stages Envelope has gone through.

## Type of Users for an Envelope

* **Sender**: The user who initiates and sends the document for signing.
* **Recipient**: The individual(s) who are required to sign or fill fields in the document.
* **CC (Carbon Copy)**: Individuals who receive a copy of the envelope for visibility, but do not participate in signing.


# Creating eSignatures

To create documents for eSignatures in Docupilot, follow this simple 3-step process:

## Step1: Add Signature Fields to Your Template

Start by placing signature placeholders in your document template. These signature placeholders (such as `{{eSign ...}}`, `{{eInitials ...}}` etc.) indicate the locations where signers will be prompted to sign or fill in information during a signing session.

For detailed instructions, refer to our guide: [Placing Signature fields in your template](/deliveries/esignature#placing-signature-tags-in-document).

## Step2: Configure eSignature Delivery

Once your template includes all required signature fields, set up the eSignature delivery. This configuration determines the recipients, signing order, reminders and other signing preferences.

Learn how to configure it here: [Configuring eSignature Delivery](/deliveries/esignature#configuring-esignature-delivery)

## Step3: Generate the Document

When you [generate a document](/create-document) using this setup, an eSignature Envelope will be created and the signing process will be initiated. [Signature Invitations](/esignatures/signature-invitation) will be sent to respective recipients via email to review and sign.

## Troubleshooting issues

If you do not see an Envelope listed under eSignatures tab, here are the potential solutions:

1. Only a sender can see the envelope.
2. If you are the sender, but you still can't see the Envelope, there might be an issue in creating the Envelope. Navigate to [reports tab](/reports) to find out the error message.
3. If you need further help, [Ask the community](https://community.docupilot.com/c/ask-the-community/7) or reach out to our support.


# Signature Invitation

### What Is a Signature Invite?

A signature invite is a secure email sent to each recipient, containing a unique signing link. It directs the recipient to their designated fields, allowing them to review and sign the document. Each invite is tracked to ensure accountability.

***

### Sending Invitations

When a document is generated from a template with an eSignature delivery configured, Docupilot automatically sends signature invites to all assigned recipients based on the envelope configuration.

### Signing Link Validity

Each recipient’s Signing link remains valid for up to 5 days or until the envelope is completed / voided / declined / expired. When a signing link expires, the recipient can request for a new signing link using the Resend Link button shown when they open the expired signing link. New Singing links are automatically sent if the reminders are configured for an envelope.

### Notifications

Docupilot sends automatic email notifications to keep all parties informed:

| User Type | Notification Triggered When…                                                                                                                                                                                                               |
| --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| Sender    | <ul><li>Envelope is Sent successfully to signer</li><li>Envelope sending to signer fails</li><li>Envelope is signed by a signer</li><li>Envelope is declined by a signer</li><li>Envelope is fully signed</li></ul>                        |
| Recipient | <ul><li>Invited to Sign (in case of ordered signing, a recipient will receive invite when it's their turn to sign)</li><li>Reminder emails to Sign an Envelope</li><li>Sender voids an Envelope</li><li>Envelope is fully signed</li></ul> |
| CC        | <ul><li>Envelope sending to signer fails</li><li>Envelope is voided by sender</li><li>Envelope is signed by a signer</li><li>Envelope is fully signed</li></ul>                                                                            |


# Reminder Settings

### Reminder Settings

To help ensure documents are signed promptly, Docupilot lets you set up reminder settings that notify recipients at regular intervals. You can choose to:

* Use the default reminder settings configured at the account level.
* Or, disable the default and define custom rules such as first reminder date, reminder frequency, and expiry warning.

If the envelope is in Pending status, you can update the reminder settings directly from the Signature Details Page. A Send Reminder button is also available beside the History icon for quick manual follow-up.

> Note that manually sending reminder will not affect the reminder workflow. Reminders scheduled to be sent based on First Reminder, Reminder Frequency and Expiry Warning will still be sent as scheduled.

### Configuring Expiry

Set how long an envelope is valid before it expires. Once expired, recipients can no longer access or sign the document. This is useful for time-sensitive agreements or approvals.

### Default Reminder & Expiry Settings

By default the reminder and expiry settings are as follows:

1. **First reminder:** 3 days from the date a recipient recieves an envelope for signing.
2. **Reminder frequency:** 2 days - current signer will receive a reminder to sign once every 2 days after the first reminder is sent.
3. **Warn before expiration:** 5 days - current signer will receive an email 5 days before the envelope expiration.
4. **Expiry:** 30 days - envelope will expire in 30 days after it is sent.


# Envelope Statuses

An envelope travels through different stages in its life-cycle from created to signed or voided. These statues are visible against each Envelope in eSignature module:

* **Created** – Envelope is created and is ready to be sent.
* **Pending** – Envelope has been sent out for signing and is awaiting signatures from one or more recipients.
* **Completed** – All required signatures collected; the document is finalized.
* **Declined** – A recipient rejected the document with a reason.
* **Voided / Expired** – The envelope was either manually voided or expired automatically.


# Envelope Actions

Various actions can be performed on an Envelope based on it's current status. Following actions are available from the Envelops list page and within envelope detail view:

* **View Document** – Preview the latest version of the documents sent for signing.
* **Send Reminder** – Reminds current recipients to sign the documents.
* **Download** – Download latest version of the documents.
* **Activity History** – View the audit log of all actions performed on the envelope.
* **Void** - Voids the envelope, no further operations can be performed on the envelope besides moving it to trash.
* **Email Document** - Send latest version of the documents via email to a specific email address.
* **Delete** – Voids and moves the envelope to trash. Envelope stays in trash for 30 days after which it will be deleted permanently.


# Signing & Declining an invite

### Signing an Envelope

A signer can sign the Envelope by opening the signing link sent via email. They need to fill out all the information required based on the signature fields configured (Sign, Initials, Text inputs, Date, etc).

Once all the information is filled, a signer can finish signing the envelope. Once the envelope is signed by a signer, relevant notifications will be sent out and envelope will move to next stage.

### Save Progress and Finish Later

A signer can partially fill the necessary singing fields and come back later to finish signing. They can re-use the existing signing link or request for a new link in case the singing link expire to complete the signing process.

### Downloading Documents

Signer has the option to download the document to review it offline. When they are ready to sign, they can open the same signing link and sign (or decline) the document.

### Declining an Envelope

A signer may decline an envelope by providing a reason if they do not wish to sign. Once declined:

* The envelope status will be set to **Declined**.
* Sender and CC recipients will be notified with the provided reason.
* This operation is irreversible. Once declined, the document cannot be re-signed.


# Integrations


# Google Forms

Generate/Populate/Merge PDF or Word Documents with data from your Google Forms Submission.

{% embed url="<https://www.youtube.com/watch?v=gBX4hGT-9Nw>" %}

Here is how you do it:

* Configure the Document Template and Email delivery in Docupilot. See building document templates and email delivery in the below links.

{% content-ref url="/pages/-LM7DRa8-sA-1cByfWX8" %}
[Building Templates](/document-template)
{% endcontent-ref %}

{% content-ref url="/pages/-LM7EatHIMWZIsdYhBgo" %}
[Deliveries](/deliveries)
{% endcontent-ref %}

{% embed url="<https://zapier.com/apps/docupilot/integrations/google-forms/36960/create-personalized-docupilot-documents-from-new-google-forms-responses>" %}

* You then need to set up Zapier - <https://zapier.com/apps/docupilot/integrations/google-forms>
* A trigger to look for Google Form submission responses.
* An action to send the submission response to Docupilot to create the document from template. Choose the correct document template, template variables will be listed, map the fields with the response from the trigger.
* Finally, turn on the Zap.

![Google Forms & Docupilot](/files/-LOEv2ck6rL-emovx2bM)


# Google Sheets

Generate/Populate/Merge PDF or Word Documents with every new row from your Google Sheets.

Here is how you do it:

* Configure the Document Template and Email delivery in Docupilot. See building document templates and email delivery in the below links.

{% content-ref url="/pages/-LM7DRa8-sA-1cByfWX8" %}
[Building Templates](/document-template)
{% endcontent-ref %}

{% content-ref url="/pages/-LM7EatHIMWZIsdYhBgo" %}
[Deliveries](/deliveries)
{% endcontent-ref %}

{% embed url="<https://zapier.com/apps/docupilot/integrations/google-sheets/36971/create-personalized-docupilot-documents-from-new-google-sheets-spreadsheet-rows>" %}

* You then need to set up Zapier - <https://zapier.com/apps/docupilot/integrations/google-sheets>
* A trigger to look for Google Sheets New Spreadsheet Row.
* An action to send the submission response to Docupilot to create the document from template. Choose the correct document template, template variables will be listed, map the fields with the response from the trigger.
* Finally, turn on the Zap.

![Google Sheets & Docupilot](/files/-LOIcnSFub0-0im-siQX)


# Airtable Extension

Generate/Populate/Merge documents from your Airtable records

Docupilot's Airtable extension allows you to create your Contracts, Sales/Purchase Orders, Invoices, Employment Offer Letters, Real Estate Agreements, Marketing material and many more professional documents in PDF, Word, Powerpoint, Excel and other formats.

<https://airtable.com/marketplace/blkTR72VkH3OEjvPX/docupilot>

## Installation Guide

### Step 1: Adding an extension to the base

In the Airtable base, click on the `Extensions` button present on the RHS. A dialogue box will be displayed. Now, click on the button `Add an extension` in the dialogue box.

<figure><img src="/files/VTKK48xpTiZL1GaEZIr9" alt=""><figcaption><p>Step 1 adding an extension to the base.</p></figcaption></figure>

### Step 2: Search Docupilot in the Market place

Once the button `Add an extension` is clicked, a pop-up of Airtable Marketplace will be displayed on the screen. In the pop-up search for Docupilot and click on it.

<figure><img src="/files/7ux29MsaR67zCxNkAddR" alt=""><figcaption><p>Step 2: Searching for Docupilot application in the Airtable Market place</p></figcaption></figure>

### Step 3: Selecting Docupilot as the extension

Once Docupilot is selected, the following will be displayed on the screen. Here click on `Add extension`. After doing so, a small pop-up will be displayed, click on `Add extension` button on the pop-up too.

<figure><img src="/files/X3VK902Egjt9dY1TL5sv" alt=""><figcaption><p>Step3: Selecting Docupilot extension from Marketplace</p></figcaption></figure>

### Step4: Setting up the API key

After clicking on `Add extension`, a pop-up of Docupilot will be displayed consisting of instructions to set up an API key and secret. Follow the steps and set up the key and secret on Docupilot after which click on `Get Started` button on the pop-up.

<figure><img src="/files/o1ctgMmsACFdERcklQKL" alt=""><figcaption><p>Step4: Instructions to setup API key in Docupilot</p></figcaption></figure>

### Step 5: Linking Docupilot and Airtable

On the following page, paste the API key and secret into their corresponding slots and click on save.

<figure><img src="/files/kboi8y6OFGkjP4cqvFhG" alt=""><figcaption><p>Step5: Linking Docupilot and Airtable</p></figcaption></figure>

Now the Docupilot extension is installed successfully onto the Airtable base.

## Document Generation

### Step 1: Record and Template selection

After the installation of the Airtable extension to the base, the first step towards document generation would be selecting the record(s) and the template.

<div align="center"><img src="/files/0vdc8TM6vY3LRrV8oRsP" alt="Record and template selection"></div>

<figure><img src="/files/izzvMBumkpf4f7f6fxbl" alt=""><figcaption><p>Multiple records selection</p></figcaption></figure>

### Step 2: Field Mapping

Once the record and the template have been chosen, we can see that a few fields will be pre-mapped based on the field name and the token name.

The remaining fields need to be mapped manually.

![Field Mapping](/files/DsnX7FmCgJfdDYNaRWkh)

### Step 3: Document Generation

After all the fields are mapped, clicking on the Generate document button will start document generation and one document will be generated for each record selected.

For example, if 5 records are selected then 5 documents will be generated.

<figure><img src="/files/cHdau4pAWBbfOUD9HknF" alt=""><figcaption><p>Selecting attachment field to upload the generated document</p></figcaption></figure>

![Document Generation](/files/bo85dG8V1aTQHZ4APkwd)

The generated document can either be saved into an attachment row in the Airtable base or can be delivered using the mode of delivery that is assigned to the template.

{% hint style="info" %}
Once the mapping is done for a template inside a base, it will be saved and when a new record is selected, the mapping will be done automatically.
{% endhint %}

## Automating Document Generation using Airtable Automations

To be able to automatically generate documents as part of your Airtable Automation setup, you can use the custom script generated by our Extension in "Run a Script" step.

To generate the code:

1. Select a record from your Airtable base
2. Select desired template from the Extension
3. Configure attachment field if desired
4. Map the fields
5. Click on the "**Generate Automation Code**" ( `< >` ) button to generate the automation script

<figure><img src="/files/Asyj05y5QoN45wxTGnpC" alt=""><figcaption><p>Generate Airtable Automation code to automate document generation using Docupilot's Extension</p></figcaption></figure>

Use generated code in automations:

1. Copy the generated script
2. Paste it in your automation "**Run a Script**" step
3. Add an input variable "**recordURL**" and map it to "**Base Record URL**"

<figure><img src="/files/S3xtF8VFQu6fUbLGt2Zr" alt=""><figcaption><p>Utilizing a generated script in Airtable Automation to generate documents using Docupilot's Extension</p></figcaption></figure>

## Append PDFs

You can append up to 10 PDFs using the "Append PDF" option available in Docupilot's Airtable extension.

### Step 1: **Select Rows and Open the Extension**

In Airtable, select the row(s) containing the PDFs you want to append. Then, navigate to the **Append PDF** tab in the Docupilot extension.

<figure><img src="/files/RwyssbqUD5hgRtOy2Yu4" alt=""><figcaption><p>Select the row(s) with PDFs and open the Append PDFs tab</p></figcaption></figure>

### Step 2: **Choose Attachment Field for Upload**

From the dropdown, select the attachment field where the appended PDF should be uploaded.

<figure><img src="/files/qqCNT9pEj9EJOkagSC85" alt=""><figcaption><p>Choose the attachment field from the dropdown to upload the appended PDF.</p></figcaption></figure>

### Step 3: **Select Columns**

If you have multiple attachment fields, select all the columns from which the attachments are to be appended.

<figure><img src="/files/haoGagWMsm6Ct8gct7Jo" alt=""><figcaption><p>Select the columns containing the attachments to be appended.</p></figcaption></figure>

<sup>*Please note that the order of your selection will determine the sequence in which the files are appended.*</sup>

### Step 4: **Append the Documents**

Click **Append Documents**. This will combine all selected files and place a single document in the chosen column of the respective row.

<figure><img src="/files/z4OUnNqo5IBGTIhcNGfH" alt=""><figcaption><p>Appended document is uploaded to destination attachment field</p></figcaption></figure>


# Microsoft Word Add-In

Docupilot's MS Word Add-in makes it easier than ever to download, edit, and upload templates directly from Microsoft Word. Below is a quick guide to help you make the most of this powerful tool:

{% hint style="info" %}
Currently the add-in is in Beta phase. Kindly report any feedback to <support@docupilot.app>
{% endhint %}

### Installing the Docupilot Word Add-in (Beta)

Or, you can install from MS Word:

1. Open Microsoft Word and go to the Home tab.
2. Click on Add-ins in the toolbar.
3. Click on "Find more add-ins at Microsoft AppSource".
4. Search for "Docupilot," click Get it now, and if asked, confirm your details to install the Add-In.
5. Alternatively, install directly from [Microsoft AppSource](https://appsource.microsoft.com/en-us/product/office/WA200008450?tab=Overview).

<figure><img src="/files/N2TxTNQXBG6sGme8USrr" alt=""><figcaption><p>Installing Word Add in from Microsoft AppSource</p></figcaption></figure>

{% hint style="info" %}
If you are an Administrator of an Organization in your Microsoft account, you can install the Add-In for yourself, all users or to a group of users.
{% endhint %}

### Link Your Account

Open Microsoft Word, click on the **Add-ins** button in the toolbar and select **Docupilot**. On the right side, click **Login** to link your account. Once you login you will be asked to choose your workspace.

*If necessary you can switch to other workspaces under settings tab.*

<figure><img src="/files/LAWn1EH3FF6c5e31lMS7" alt=""><figcaption><p>Linking Your Docupilot Account</p></figcaption></figure>

### Creating Templates

To create a new template with the opened document, click the + button under Linked Templates. Fill in the template details and click **Create**.

<figure><img src="/files/Ueq3i1fJ6NcVAqEHxFkH" alt=""><figcaption><p>Create a New Template from Word Add in</p></figcaption></figure>

### Downloading a template

To Download a template from your Docupilot account to your Word:

1. Open a blank word document
2. Select the template under **Linked Template**
3. Click on the **Download your Document ↙** button

The template from your Docupilot account will be loaded into the blank word document. You can make changes and upload this document back to your account.

### Updating an existing Docupilot Template

1. Either Download an existing Docupilot template as mention above -or- open a word document that you want to upload to Docupilot.
2. In the Docupilot Add-In, if your template is not already selected, select the Docupilot Template you want to update.
3. Click on the **Update your Document ↗** button to update the Document on your Docupilot account.

<figure><img src="/files/UYDLL3rmF3L7KRMbiBwC" alt=""><figcaption><p>Update your template from Word Add in</p></figcaption></figure>

You can enable **Auto Sync** in **Settings**, which will automatically update any local changes to your Docupilot account.

<figure><img src="/files/u1sYQoGeUNnaQtgiG83B" alt=""><figcaption><p>Auto Sync Document from Word Add-In</p></figcaption></figure>

### Update with AI

Use AI to effortlessly enhance your template. Select the text, enter your prompt, and let Docupilot’s AI process and populate it with the appropriate tokens or data.

<figure><img src="/files/9szWCo56Ybvo7prnV0FC" alt=""><figcaption><p>Use Docupilot's AI for templatizing your document content within MS Word</p></figcaption></figure>


# Account Setup & Administration

Managing your Docupilot account — setup your organization, create workspaces, invite users, setup security, and overall account administration.


# Setting Up Your Account

To get started with Docupilot, the first step is to create an Organization.

## What is an Organization in Docupilot?

An Organization in Docupilot serves as the primary entity overseeing workspaces and users. It facilitates centralized management of user access and security, streamlining operations for seamless management.

## **Create your account**

1. **Sign Up for an account at** [**https://docupilot.app/signup/**](https://docupilot.app/signup/)
2. **Add Your Organization Details:**&#x45;nter your Organization Name, Subdomain and optionally Upload your company logo. This subdomain should be used to login to your organization later on.
3. **Create Your Account Details:** Enter your Name, setup a secure **password**. and click **Sign Up** to create your account.

<figure><img src="/files/vRfCGDLIaeRovVOhmbOk" alt=""><figcaption><p>Setting up an Organization(Account)</p></figcaption></figure>

## **Manage your Organization**

### Updating basic details of the Organization:

Navigate to **Organization** from the left-side menu, where you can update the **Organization Name**, **Sub Domain** and **Logo** by clicking the respective edit buttons.

{% hint style="info" %}
⚠️ I**mportant Notes Before Changing the Subdomain:**

* All users will be logged out and prompted to log in using the new organization URL.
* The old organization URL will no longer be accessible; all users must use the updated URL.
* Any activation or reset password links tied to the old URL will stop functioning.
* This change is permanent and cannot be undone.
  {% endhint %}

<figure><img src="/files/lfP7WdiOliePeUO8mdfj" alt=""><figcaption><p>Managing an Organization</p></figcaption></figure>

## **Enforcing MFA across all users**

Secure your workspace by enabling **Multi-Factor Authentication** (MFA) for all users in your organization.

* Use the toggle button to enforce MFA across your organization.
* To configure, navigate to the **Multi-Factor Authentication** page from the left-side menu and click **Enable MFA.**

For more detailed instructions, including the different types of MFA available, refer to the [MFA Settings](/account-setup-and-administration/user-profile-and-account-security#types-of-mfa) help page.

<figure><img src="/files/hKs6Dn0A78o0g5u6Kkcq" alt=""><figcaption><p>MFA settings</p></figcaption></figure>

## Deleting an Organization

Before deleting your Organization, ensure that all associated workspaces have been removed. Once the workspaces are deleted, navigate to the **Danger Zone** on the **Organization** page and click **Delete** to proceed.

For security purposes, a **One-Time Password** (OTP) will be sent to your registered email. Enter the OTP to confirm and finalize the deletion.

{% hint style="info" %}
Only the Organization Owner can to delete an organization.
{% endhint %}

For instructions on deleting workspaces, refer to the [**Workspace Deletion**](/settings/workspace#deleting-workspace) help page.

<figure><img src="/files/bIUGcCTK5k7IVTVDDQY9" alt=""><figcaption><p>Deleting an Organization</p></figcaption></figure>

## Creating an Additional Organization

If you are a service provider, you may want to work with different customers, and it is a best practice to create another org for that customer. Signup afresh to create a new Organization by following the instructions here [#create-your-account](#create-your-account "mention"). You can transfer ownership of the organization to your client at a later point in time.


# Creating Workspaces

Workspace is where you create and manage your document templates, deliveries, eSignatures and team members. Each workspace operates independently, allowing teams to work autonomously within the same organization.

For example, you can create a workspace for different departments like *HR*, *Marketing*, and *Support*.

## **Create Your Workspace**:

* From the left-side menu, go to the **Home** page.
* Click **Create Workspace**, provide a Workspace Name, and click on **Create Worksapce** to create it.

<figure><img src="/files/ovQ7mavbfxNy2Tlfrx4U" alt=""><figcaption><p>Creating a new Workspace</p></figcaption></figure>

* To create more workspaces, return to the **Home** page, and repeat above steps.

## **Accessing your workspace**

All workspaces in your organization can be viewed from the **Home** page. To access a workspace, select the desired workspace.

## **Managing a Workspace**

Inside your workspace navigate to **Settings > Workspace**

<figure><img src="/files/mBlqq0UMdbnrqkWkQAsx" alt=""><figcaption><p>Managing a Workspace</p></figcaption></figure>

For more details on configuration and customization, refer to the [**Workspace Settings**](/settings/workspace) help page.


# Managing your Org

This section explains about how you can configure and manage access to your Organization on Docupilot by Inviting and managing users, setting up SSO, SCIM, etc.


# User Management

Invite, Transfer ownership, Deactivate Users at Organization level.

## Inviting Users to the Organization/Workspace

You can invite new users to your organization and assign them role-based access to a specific workspace. To do this, go to the **Organization > Users > Invite User**.

<figure><img src="/files/4rwTh3DHQlMv9slhvBKD" alt=""><figcaption><p>Inviting a User to Organization</p></figcaption></figure>

For more information on the User roles in a Workspace, refer to [Invite users](/collaborating-with-multiple-users/invite-users) page.

{% hint style="info" %}
To view pending invitations, use the dropdown filter and select **Invited Users**.
{% endhint %}

## Accepting Invitation

An invitation will be sent to the invited user’s email address. By clicking **Accept Invitation** and following the on-screen instructions, the user can successfully join the Organization and the Workspace.

If the user is already part of the Organization, they can review the invitation details and choose either:

* Join – to accept and become part of the workspace, or
* Dismiss – to decline the invitation

<div><figure><img src="/files/Fh5RV7htGpyKFrl27qMm" alt="" width="375"><figcaption><p>Reviewing the Invitation</p></figcaption></figure> <figure><img src="/files/ybyIoGche8sA2Fw9gGlO" alt="" width="375"><figcaption><p>Joining the Workspace</p></figcaption></figure></div>

{% hint style="info" %}
Once the User has accepted to Join the Workspace, they will be moved to Active User's list
{% endhint %}

## Transfer Ownership

You can transfer the ownership of your Organization to any active user within the organization.

* Once the ownership is transferred, the new owner will automatically gain access to all workspaces.
* The current owner will be moved to an Admin role and will continue to have access to the workspaces they were already a part of.

{% hint style="info" %}
Ownership can be transferred even if the selected member is not part of all workspaces in the organization.
{% endhint %}

<figure><img src="/files/EoSbZB4EUUp6VrzGxHRC" alt=""><figcaption></figcaption></figure>

## Deactivating a User

You can deactivate a user to remove their access to the organization.

1. Go to the **Users** tab under your organization.
2. Hover over an active user to see the **Deactivate** option appear.
3. Click the **Deactivate icon** and then confirm by selecting the **Deactivate** button.

{% hint style="info" %}
Only the Organization Owner has the permission to deactivate users.
{% endhint %}

<figure><img src="/files/TcGj50LtxzFx2qjE23xt" alt=""><figcaption></figcaption></figure>

## Re-Activating a User

You can restore access for deactivated users by reactivating them.

1. In the **Users** list, filter the dropdown to display *Deactivated Users*.
2. Hover over a deactivated user — you’ll see the **Activate** option appear.
3. Click the **Activate icon** and then confirm by selecting the `Activate` button.

For more details on managing users, refer to the [**User Settings**](/collaborating-with-multiple-users) help page.


# Verified Domains

Add and verify your company's email domains to enhance workspace security and enable Single Sign-On (SSO).

Verified domains help your organization establish ownership of your company’s domain (e.g., yourcompany.com) within Docupilot. Once verified, your domain can be used to streamline user management, set-up and enforce Single Sign-On (SSO), and ensure secure access across your workspace.

#### Why Verify a Domain?

Verifying your domain ensures:

* Administrators can **enable SSO** for existing and new users under the verified domain.
* Only users with emails from verified domains can **join your Docupilot Organization via SSO**.
* Your organization maintains control over who can access Docupilot using your company domain.

#### How to Verify a Domain?

* Go to **Organization > Domains** in your org dashboard.
* Click **Add Domain** and enter your domain name (e.g., yourcompany.com).
* Copy the **TXT record** displayed on screen.
* Configure the TXT record in your DNS console (GoDaddy, Cloudflare, Name Cheap, etc).
* Once configured, return to Docupilot and click **Verify**.

  > *It could take up to 48 hours for the DNS records to be propagated based on your DNS caching settings.*

<figure><img src="/files/Z4TxzXP3JdNARiY1pxV8" alt=""><figcaption></figcaption></figure>

#### Locking a domain

After verification, you can **lock** the domain to prevent unauthorized account creation using your company’s email domain.

When a domain is locked:

* Only **Organization Admins** can invite users with emails from the locked domain.
* New sign-ups using that domain are blocked.
* If someone tries to create a new Organization using the same domain, it will **not be allowed**.


# Login Methods

Configure login methods such as Password based, SSO, etc to provide secure and seamless access for all users in your organization.

As an Organization Owner, you can configure how users can login to access your Organization and Workspaces.

### Password based login

Allow users to login to your Organization by entering their registered **Email** and **Password**. Multi-factor authentication settings if enabled will be applicable for Password based login.

Password based login is enabled by default on all accounts and this can be disabled if other methods are enabled.

<div align="center"><img src="/files/3Y0fSyb80bSxLq3SfiBd" alt="enable or disable password login"> <img src="/files/vQlpxid2rB31m9CdVYaj" alt="Login to Docupilot with email and password"></div>

### Single Sign-On (SSO)

**Single Sign-On (SSO)** is an authentication method that allows users to securely access multiple applications with a single set of login credentials. Docupilot's SSO integrates with identity providers like **Microsoft Entra ID (Azure AD), Google Workspace, Okta**, and more to centralize and simplify access management across your organization.

Using SSO will:

* Improve security by enforcing unified login policies
* Make onboarding and offboarding fast and easy
* Reduce IT overhead by avoiding password resets
* Give admins full control over who can access Docupilot
* Deliver a seamless, secure login experience for users

Ensure you have at-least one [domain configured and verified](/account-setup-and-administration/managing-your-org/verified-domains) on your account to proceed with SSO setup.

Follow guidelines from provider specific SSO setup pages:

1. [Microsoft Entra ID (Azure AD)](/account-setup-and-administration/managing-your-org/login-methods/microsoft-entra-id-sso)
2. *Google Workspace (coming up)*
3. *SAML (coming up)*
4. *Okta (coming up)*

> Looking for other providers? *Let us know your preferred AD provider integration by dropping an email to* [*support@docupilot.app*](mailto:support@docupilot.app)


# Microsoft Entra ID SSO

Set up Microsoft Entra ID (formerly Azure AD) as your SAML SSO provider for Docupilot.

## Prerequisites

* Ensure you have a verified domain added to your Docupilot Organisation. Learn more on adding a [Verified Domain here](/account-setup-and-administration/managing-your-org/verified-domains).
* To enable SAML Single Sign-On (SSO) with Microsoft Entra ID, you need to be the organization owner in Docupilot.

## Configuring Microsoft Entra ID SSO

To enable Single Sign-On (SSO) on Docupilot using Microsoft Entra ID, follow the steps below:

### Step 1: Connect Microsoft Entra ID in Docupilot

<figure><img src="/files/E7pwE1HTcpPxNRaq2mHL" alt="Connect SSO on your Docupilot account"><figcaption><p>Configuring Microsoft Entra ID SSO</p></figcaption></figure>

1. Navigate to **Login Methods** tab in your **Organization** settings.
2. Click **Connect SSO** under **SSO Login method**, and select **Microsoft Entra ID** from the list.
3. Enter a display name for this SSO connection.
4. Click **Add method**.

<figure><img src="/files/yBcofUwYIOmCZ1bd0y2U" alt=""><figcaption><p>Adding Microsoft Entra ID SSO Login Method</p></figcaption></figure>

### Step 2: Configure SAML SSO in Microsoft Entra ID

#### **A. Create an Application**

1. Log in to your Microsoft Entra admin center.
2. Navigate to the **Enterprise Applications**, click **New Application.**
3. Select **Create your own application** and enter a name for the application (ex: *Docupilot*).
4. Choose the option **Integrate any other application you don’t find in the gallery (Non-gallery)** and click on **Create.**

   <figure><img src="/files/cihJCZqbKndkt5ClxPui" alt=""><figcaption><p>Creating Application in Microsoft Entra ID</p></figcaption></figure>
5. Once created, select **Single sign-on** from the Manage section and select the **SAML** based sign-on method.<br>

   <figure><img src="/files/NhvfbT57Kl4XYGfrJ4re" alt=""><figcaption><p>Selecting SAML Sign On method</p></figcaption></figure>

#### **B. Copy metadata from Docupilot to Entra ID**

In the **SAML** configuration:

1. Click **Edit** under **Basic SAML Configuration.**<br>

   <figure><img src="/files/djKyiMPCpIFGbmBeDnkh" alt=""><figcaption><p>Editing Basic SAML Configuration in Azure</p></figcaption></figure>
2. From Docupilot **copy** **Identifier** and **Reply** URL.<br>

   <figure><img src="/files/ue898saed2Opk59lRyFn" alt=""><figcaption><p>Copy Basic Configuration from Docupilot</p></figcaption></figure>
3. **Paste** them in respective fields in Microsoft Entra ID. **Save** the settings.

<figure><img src="/files/8yH7kLcf8JdYgSwrxW5W" alt=""><figcaption><p>Save Basic SAML Configuration in Microsoft Entra ID</p></figcaption></figure>

#### **C. Copy Metadata from Entra ID to Docupilot**

1. Click on **Edit** option in **SAML Certificates** section and select the **Signing option** as **Sign SAML response and assertion**. **Save** the change&#x73;**.**<br>

   <div align="center" data-full-width="true"><figure><img src="/files/InyACtU5Cu08IBGh9PPa" alt=""><figcaption><p>Selecting Signing options in Microsoft Entra ID</p></figcaption></figure></div>
2. In the **SAML Certificates** section copy **App Federation Metadata Url** and **paste** it in the respective field in Docupilot

   <div><figure><img src="/files/5c3DkZGWkr6r6UpZLY1n" alt=""><figcaption><p>Copy Metadata URL from Microsoft Entra ID</p></figcaption></figure> <figure><img src="/files/8d8CLmL4uOYnZPyASM8e" alt=""><figcaption><p>Paste Metadata in Docupilot</p></figcaption></figure></div>
3. **Save Configuration** in Docupilot.
4. **Enable** the SSO Configuration to activate it.

<figure><img src="/files/E1NO6OweTsv11iwbI2sF" alt=""><figcaption><p>Enabling Microsoft Entra ID SSO</p></figcaption></figure>

### Step 3: Login via Microsoft Entra ID

Add users to your Microsoft Entra ID Enterprise Application. Read [Invite, assign and unassign users](https://learn.microsoft.com/en-us/entra/identity/enterprise-apps/assign-user-or-group-access-portal?pivots=portal) for detailed steps. Once assigned, users can log in to Docupilot using Microsoft Entra ID SSO from the Organization Login page. If a user doesn't already have an account under your organization, one will be created automatically upon first login.

<figure><img src="/files/DLYbOnuCIW3QMGTUB2ya" alt=""><figcaption><p>Login option with Microsoft Entra ID SSO</p></figcaption></figure>

## Deleting SSO Login Method

To delete the configured SSO Login method:

1. Navigate to **Login Methods** tab in your **Organization** page
2. Select the SSO method and click on **Delete Configuration.**

<figure><img src="/files/zy8okC23yaPtENRCr6ET" alt=""><figcaption><p>Deleting Microsoft Entra ID SSO Login Method</p></figcaption></figure>


# Okta SSO

Set up Okta as your SAML SSO provider for Docupilot.

## Prerequisites

* Ensure you have a verified domain added to your Docupilot Organisation. Learn more on adding a [Verified Domain here](/account-setup-and-administration/managing-your-org/verified-domains).
* To enable SAML Single Sign-On (SSO) with Okta, you need to be the organization owner in Docupilot.

## Configuring Okta SSO

To enable Single Sign-On (SSO) on Docupilot using Okta, follow the steps below:

### Step 1: Connect Okta in Docupilot

<figure><img src="/files/E7pwE1HTcpPxNRaq2mHL" alt="Connect SSO on your Docupilot account"><figcaption><p>Configuring Okta SSO</p></figcaption></figure>

1. Navigate to **Login Methods** tab in your **Organization** settings.
2. Click **Connect SSO** under **SSO Login method**, and select **Okta** from the list.
3. Enter a display name for this SSO connection (for your own reference).
4. Click **Add method**.<br>

   <figure><img src="/files/J6RybLPI9f2Jf0AIidFN" alt=""><figcaption><p>Adding Okta SSO Method</p></figcaption></figure>

### Step 2: Configure SAML SSO in Okta

#### **A. Adding Docupilot App Integration**

1. Log in to your **Okta** **Admin Console**.
2. Navigate to the **Applications,** click **Browse App Catalog** and search for **Docupilot.**
3. Select the **Docupilot** card and click on **Add Integration.**<br>

   <div align="center" data-full-width="true"><figure><img src="/files/USgdXnqYdCRhE4LbyaLQ" alt=""><figcaption><p>Search for Docupilot on Okta</p></figcaption></figure> <figure><img src="/files/5d8yqRUsoXWP83Jnxitx" alt=""><figcaption><p>Adding Docupilot Integration on Okta</p></figcaption></figure></div>

#### **B. Copy metadata from Docupilot to Okta**

In the newly added integration,

1. Under **General Settings** set a desired **Application label** *(ex: Docupilot)*
2. From Docupilot, **copy** the **Unique ID** from the set up window and **paste** it in the respective field in **Okta.**<br>

   <div align="center" data-full-width="true"><figure><img src="/files/6IVoBmO3csQgnzSu9v4t" alt=""><figcaption><p>Copy Unique ID for new Okta SSO Integration</p></figcaption></figure> <figure><img src="/files/4HYfSnlevqaHluHbKeFa" alt=""><figcaption><p>Paste the Unique ID from Docupilot into Okta</p></figcaption></figure></div>

#### **C. Copy metadata from Okta to Docupilot**

1. In Okta, under the newly created application, navigate to **Sign On** tab and copy the **Metadata URL**.<br>

   <div align="center" data-full-width="true"><figure><img src="/files/2WsEKpZ6GTjRdARMBSL0" alt=""><figcaption><p>Copy <strong>Metadata URL</strong> from Okta</p></figcaption></figure></div>
2. Paste **Metada URL** in Docupilot and click **Save Configuration**<br>

   <div align="center" data-full-width="true"><figure><img src="/files/atjfDUhIT463slPaca0a" alt=""><figcaption><p>Paste <strong>Metada URL</strong> in Docupilot and <strong>Save Configuration</strong></p></figcaption></figure></div>
3. **Enable** the newly added SSO Configuration in Docupilot to activate it.

<figure><img src="/files/gcgVEvpseNbJ1UYobx9H" alt=""><figcaption></figcaption></figure>

### Step 3: Login via Okta

Add users to your Docupilot Application in Okta. Read [Assign applications to users](https://help.okta.com/en-us/content/topics/users-groups-profiles/usgp-assign-apps.htm) for detailed steps. Once assigned, users can log in to Docupilot using Okta SSO from the Organization Login page. If a user doesn't already have an account under your organization, one will be created automatically upon first login.

<figure><img src="/files/N9XJySg084qd1jVauD9Y" alt=""><figcaption><p>Login option with Okta SSO</p></figcaption></figure>

## Supported Features

Docupilot supports the following **SAML** features:

* IdP-initiated SSO
* SP-initiated SSO
* Just-In-Time (JIT) provisioning

## Supported SAML Attributes

Docupilot supports the following SAML attributes. These attributes are preconfigured in the Okta integration.

| Attribute     | Okta Mapping   | Required |
| ------------- | -------------- | -------- |
| Email address | user.userName  | Yes      |
| First name    | user.firstName | No       |
| Last name     | user.lastName  | No       |

{% hint style="info" %}
• The Okta username (user.userName) must be a valid email address.

• The email address is used as the unique user identifier in Docupilot.
{% endhint %}

## Deleting SSO Login Method

To delete the configured SSO Login method:

1. Navigate to **Login Methods** tab in your **Organization** page
2. Select the SSO method and click on **Delete Configuration**

<figure><img src="/files/YyCk4dHNI5jjO8eaojX6" alt=""><figcaption></figcaption></figure>


# User Profile & Account Security

This section guides you through editing your profile, changing your password, and enabling/disabling Multi-Factor Authentication (MFA).

## Profile Management

To access your profile from a workspace:

1. Click your name/avatar at the bottom of the side navigation.
2. Click **View Profile**.
3. Select **Profile** in the left side menu from your Organization's Home page.

<figure><img src="/files/3GVWjfVN8wpUsxIb4iuT" alt="" width="563"><figcaption><p>View your Profile</p></figcaption></figure>

### Updating your profile

1. On your profile page, click **Edit** to update your personal details.
2. You can modify your **Name**, interface **Language**, and **Timezone**.

<figure><img src="/files/Oi8S3GcRRVC7YlqKjDw1" alt="" width="563"><figcaption><p>Updating your Profile</p></figcaption></figure>

### Changing your Email address:

1. Click **Change Email.**
2. Enter your **new email address** and **account password.** Click on **Change**.
3. A verification link will be sent to your new email.
4. Click the link to confirm the change.

<figure><img src="/files/VGT5n0LUTY8g3dBEyI4Z" alt="" width="563"><figcaption><p>Changing your Email address</p></figcaption></figure>

## Security

### Updating your password

1. Go to the **Security** page from the left-side menu.
2. Enter your **Current Password**, **New Password**, and re-enter the New Password under Confirm Password.
3. Check the "Logout from all other devices" option to delete all your active sessions.
   1. Only active sessions linked to registered email and current organization will be logged out.
   2. If you have active sessions from same email address but a different organization they will not be logged out.
4. Click **Update**.

<figure><img src="/files/7yujCxbkuQuYWK8mKAC5" alt="" width="563"><figcaption><p>Updating the Password</p></figcaption></figure>

## Multi - Factor Authentication (MFA)

### Enabling MFA

1. Navigate to **Multi-Factor Authentication** in the left-side menu.
2. Click **Enable MFA**.
3. By default, Email OTP will be enabled and set as your primary MFA method. *Read more about Email OTP in the next section.*

<figure><img src="/files/Iu51Ua78NZrVDlkFt8tC" alt="" width="563"><figcaption><p>Enable MFA</p></figcaption></figure>

### Types of MFA

#### Email OTP

1. When Email OTP MFA is enabled, a **One-Time Password (OTP)** will be sent to your email during login.
2. Enter that OTP to login to your account successfully.

<figure><img src="/files/egfYGuu73F2Vhtjw4886" alt="" width="563"><figcaption><p>Email Authentication</p></figcaption></figure>

#### Time-Based One-Time Password (TOTP)

To use TOTP for Multi-Factor Authentication (MFA), follow these steps:

1. Click `Setup Now` under **OTP Authenticator.**
2. Configure your Authenticator:
   1. Open an authenticator app on your mobile device (e.g., **Google Authenticator**) and scan the **QR code** displayed in your account.\
      — OR —
   2. Open a password manager (e.g., **LastPass**), click the **eye icon** to reveal the **Secret Key**, and manually enter it as the **TOTP secret key** in your password manager.
3. Enter the **OTP** generated by the authenticator app to complete the setup.

Optionally, you can now set TOTP as your primary authentication method by clicking **Make Primary**.

<figure><img src="/files/EowzBRjop5sQ5iyL3zry" alt="" width="563"><figcaption><p>MFA using TOTP method</p></figcaption></figure>

#### MFA recovery codes

1. If you lose access to your device or email, recovery codes can help you log in.
2. Click `Generate Recovery Codes` and store them securely.
3. If necessary, click **Generate new Codes** to replace old codes with new ones.

{% hint style="info" %}
*Note:*

1. *Each recovery code can be used only once.*
2. *If you run out of recovery codes, you can always Generate new Codes.*
3. *Old codes will be invalidated once the new codes are generated.*
   {% endhint %}

<figure><img src="/files/dmp1FoJyJPKQygQuMgQ9" alt=""><figcaption><p>MFA recovery codes</p></figcaption></figure>

### Disabling MFA

1. Toggle MFA from **Enabled** to **Disabled** to disable MFA.
2. Enter the MFA OTP generated from your primary MFA method (Email OTP or TOTP) to disable MFA on your account.

<figure><img src="/files/aaYrkuXWPRPEBTR4FhUh" alt="" width="563"><figcaption><p>Disabling MFA</p></figcaption></figure>


# Collaborating with multiple users

Multi-user collaboration in Docupilot is tailored to enhance teamwork in automating document generation workflows. It optimizes the process, enabling team members to work on different parts of the document creation simultaneously, boosting efficiency and conserving time. Role-based access control further ensures that access to resources in your workspace is correctly allocated, preserving both security and integrity.

#### Getting Started with User Collaboration:

1. **Invite Your Team:** Begin by easily adding team members to your project with a few simple steps.
2. **Assign Roles:** Assign user roles to meet the specific needs of your team.

To access user module, navigate to the "**Settings"** menu and click on "**Users**”

<figure><img src="/files/agB7koahQiym2ZJU67E3" alt=""><figcaption><p>User Collaboration</p></figcaption></figure>


# Invite users

Invite users to collaborate within your Docupilot workspace.

The Owner/Admin/Manager of the workspace can invite new users. To create an invitation:

1. Click the **Invite user** button.
2. Enter the **Email address** and assign one of the roles: Admin, Manager, Billing Manager, or Member. See below for explanation about each Role and its Privileges it has.

<table><thead><tr><th width="191">Role Name</th><th>Privileges</th></tr></thead><tbody><tr><td>Owner</td><td>User who created the workspace is called Owner. There can be only one Owner in a workspace. Owner has full control over workspace.</td></tr><tr><td>Admin</td><td>Admin can perform all operations that an Owner can, except for removing the Owner from the workspace and Deleting the workspace.</td></tr><tr><td>Manager</td><td>A manager can manage all folders &#x26; templates and has the ability to invite and manage users with Member role.<br>A manager can also view workspace details, but cannot change workspace preferences.</td></tr><tr><td>Billing Manager</td><td>Can manage subscription and billing. Can view list of users in the workspace.</td></tr><tr><td>Member</td><td>A user who can access only folders and templates shared with them or created by them.</td></tr></tbody></table>

<figure><img src="/files/GtaNmJ8YnWTbYAEG8p3R" alt=""><figcaption><p>Inviting a user</p></figcaption></figure>

### Pending Invite

Under "Pending Invitations," all outstanding invites will be visible. Each invite will automatically expire after three days.

<figure><img src="/files/wPNZuDsNr7aMYdW8yyii" alt=""><figcaption><p>Pending Invitations</p></figcaption></figure>

### Resend Invite

To resend an invitation, navigate to the "Pending Invitations" section, then click on the specific invitation you wish to resend.

<figure><img src="/files/V9xDiBUjKTyfOdOouLlm" alt=""><figcaption><p>Resend Invite from Pending invites.</p></figcaption></figure>

### Accepting an Invite

As soon as an invitation is sent out, invitee will receive an email invitaion with a link to join the workspace. Upon visiting the link, user will be asked to create a new Docupilot account or log-in to existing Docupilot account.

Upon successfully logging in to the account, click on **Join workspace** button.

<figure><img src="/files/fnTURnDy4jGm4eIdwlc5" alt=""><figcaption><p>Accepting invitation</p></figcaption></figure>

{% hint style="info" %}
Note: The email address on invitee's Docupilot account should be same as the email to which invitation was sent. Invitation cannot be accepted by a user with different email address.

For example, an invite sent to <ana@example.com> cannot be accepted from a Docupilot account with email <carl@example.com>
{% endhint %}


# Manage & delete users

Change a user's role or delete users within a workspace

### Updating User roles

To modify a user's role, navigate to **Settings > Users** section. Find the user whose role needs to be changed in the list of users and select a new role for that user in the role dropdown.

When updating user roles within your workspace, it's important to understand who has the capability to make changes.

* The Owner has full control and can change role of all users other then self
* An Admin can perform following changes
  * Admin -> Manager
  * Admin -> Member
  * Manager -> Member
  * Member -> Manager
  * Member -> Admin
  * Manager -> Admin
* A Manager has the capability to perform following changes:
  * Manager -> Member
  * Member -> Manager
* A Member and Billing Manager has no control on user role assignments

<figure><img src="/files/nHxBrjvd5RGfP3mpqdQO" alt=""><figcaption><p>Updating the User roles.</p></figcaption></figure>

### Deleting a user

To remove a user from your workspace, navigate to the “**User Management**” section, select the desired user, and click on the **Delete** option.

{% hint style="info" %}
Note that only the Owner can perform this action, and once deleted, it cannot be undone or recovered.
{% endhint %}

<figure><img src="/files/88EZ3t7oUlHlJkxoWJbO" alt=""><figcaption><p>Deleting the user.</p></figcaption></figure>


# Reports

You will be able to access the Reports section of your account from the Dashboard by clicking on `Reports` present on the left side menu.

![Accessing Reports section](/files/aBgmEYIpEYv60wKIPtrk)

### Filters

Choose between different filters available:

1. Select a template to see usage for that template
2. Select status to see how many deliveries are in that state
3. To see history from a custom range, select the date range from "Period" popup

![Using Filters to access templates](/files/DlJQWOYcqQhFRQhSs3ce)

### Accessing the Generated document and Data used to generate the document

The data passed to the template and the generated document can be viewed and downloaded from each entry in the reports list. This will be helpful in understanding better if there are any issues with the generated document.

![View merge data and download generated document from reports section](/files/h754ULFi69Sc9pRa5Wws)

Click on the download icon on the right side to download the generated document. Click on the eye icon to view the merge data that is used to generate the document.


# Settings


# Workspace

On this page, you have the ability to modify and adjust the configuration settings of your workspace as needed. Workspace can also be deleted if necessary.

To access your **Workspace Preferences**, navigate to the Dashboard and click on the **Settings icon** located in the left side menu.

<figure><img src="/files/B4VFRci7XCLrvwTotDVK" alt=""><figcaption><p>Workspace page</p></figcaption></figure>

### Workspace Details

In this section, you can see both the Workspace ID and Workspace name. You can also update the Workspace name here.

To modify the workspace name, enter the new name into the provided workspace input and click on the "**Update**" button.

<figure><img src="/files/hvVG1rG1rbJcZMLW5WfY" alt=""><figcaption><p>Workspace Settings</p></figcaption></figure>

### Data Retention

Data retention settings let you specify how long data or documents should be stored, aiding in effective data management and compliance. You can set the time from as short as 30 minutes to a maximum of 3 days.

Follow these steps to adjust the data retention period:

1. Navigate to **Settings > Workspace**.
2. Choose the **desired retention periods** for storing data and generated documents.
3. Click the "**Update**" button to save your changes.

<figure><img src="/files/65RFNwEWYK6IVfgcfLfO" alt=""><figcaption><p>Data Retention Settings</p></figcaption></figure>

{% hint style="info" %}
Configuring Data Retention Preferences are supported only on Business and higher plans.
{% endhint %}

### Security

To enforce Multi-Factor Authentication (MFA) for all users in the workspace, click on the **Enable** toggle switch.

<figure><img src="/files/tbQWlkc70tF32UMqC08X" alt=""><figcaption><p>Enabling Multi Factor Authentication</p></figcaption></figure>

### Deleting Workspace

To delete the workspace and all the data associated with it, click on the **Delete Workspace** button available on the bottom right of the page and follow on-screen instructions.

<figure><img src="/files/Y31eRATUzd6e4F686g3z" alt=""><figcaption><p>Deleting the Workspace</p></figcaption></figure>

{% hint style="info" %}
Deleting workspace is permanent and it cannot be un-done. This will not delete your User Account, you will still have access other workspaces or your user account. If you wish to delete your User Account, [see instructions here](broken://pages/L6bd1Cni2uJbEJvsD5TS#deleting-your-account).
{% endhint %}


# API Settings

API keys are essential for integrating third-party applications such as Zapier. In this section, you can create and manage your API keys to ensure smooth integration.

To access the API settings:

1. Navigate to the Dashboard.
2. Click on the **Settings** icon in the left-side menu.
3. Then, select "**API Settings**"

<figure><img src="/files/obUwV2WSNh0Beuqrnh1P" alt=""><figcaption><p>API Settings</p></figcaption></figure>

### Create an API Key

To create an API key, follow these steps:

1. Click the "**Add API Key**" button located on the right side.
2. Enter the name for the API token (for example: *Zapier*, *MyApp1*, etc) and click “**Generate**.”
3. Once the API Key and API secret are generated, you can **Download** them to your device for future use.

<figure><img src="/files/5rD9VA82UxS6wGzkxpyX" alt=""><figcaption><p>Create an API Key</p></figcaption></figure>

{% hint style="info" %}
Securely store the API Secret as it is only available once for further use.
{% endhint %}

### Delete an API Key

To delete an API Key, first, click the trash button situated beside the API Key you wish to delete. Then, click the "**Delete**" button from the popup.

<figure><img src="/files/0EYAxUx8cysCl1DqPSdj" alt=""><figcaption><p>Delete an API Key</p></figcaption></figure>

{% hint style="info" %}
Once an API key has been deleted, it cannot be restored.
{% endhint %}


# Manage Subscription

## Subscribe to Docupilot

* Go to the "Settings" menu and select "Billing and Usage"
* Choose the specific plan you want to switch to
* Proceed to the checkout page
* Provide your Account, Billing address, and Payment details
* Click on "Pay & Subscribe" to finalise the subscription process

<figure><img src="/files/TQ7OOsG51j8Zt5GgI3XY" alt=""><figcaption><p>New subscription</p></figcaption></figure>

#### How to Apply a Coupon

* Click Subscribe on your preferred plan
* Use Apply Coupon to enter code and check discount.
* Select Proceed to Checkout to move ahead with the subscription.

The discount will be applied to your invoice accordingly.

<figure><img src="/files/xfHbjuKaatnl3rvegxaK" alt=""><figcaption><p>Applying Discount Coupon</p></figcaption></figure>

## Upgrade or Downgrade your subscription

* Go to the "Settings" menu and select "Billing and Usage".
* Choose the specific plan you want to switch to
* Proceed to the checkout page by clicking on the relevant option
* Finalise the switch by clicking on "Pay & Subscribe" on the checkout page

<figure><img src="/files/1lWC7MDKwi6Hsc5qVkTM" alt=""><figcaption><p>Upgrade the Subscription</p></figcaption></figure>

<figure><img src="/files/qBSB3pGGmKdqQZqCawJw" alt=""><figcaption><p>Downgrade the subscription</p></figcaption></figure>

{% hint style="info" %}
As part of the upgrade process, you will be invoiced for the remaining credits necessary to accommodate the new plan.
{% endhint %}

{% hint style="info" %}
When initiating a downgrade, there will be no immediate charges. Instead, the remaining credits will be adjusted accordingly in the subsequent billing cycle.
{% endhint %}

## Buy Addons and Apply Coupon

* Go to the "Settings" menu and select "Billing and Usage"
* Select "Manage Billing" and choose your current plan
* Click "Edit Subscription" and select "Add Addons" under your current subscribed plan.
* Select your preferred Addon and specify the quantity
* If you have a Discount Coupon, click on "Apply Coupon" to enter code and hit `→` button to check discount.
* Click on "Update Subscription →" to proceed with purchase.

<figure><img src="/files/Uhw9h1R8Rrp1P4X3UF0R" alt=""><figcaption></figcaption></figure>

## Update your Billing Details

* Go to the "Settings" menu and select "Billing and Usage"
* Choose "Manage Billing" and click “Payment methods”
* Locate your card and click the “Edit Payment method”
* Enter your updated payment information and billing address. Click “Update”.

<figure><img src="/files/iO0dD2RHgYrMRS5Vi0Is" alt=""><figcaption><p>Updating your Billing Address</p></figcaption></figure>

## **Download your subscription invoice**

To download an invoice,

* Go to the **Dashboard > Settings**
* Navigate to **Billing and Usage > Manage Billing** and click on **Billing History** to view past invoices
* Find the desired invoice and click the "Download" button

<figure><img src="/files/cDd0ldghkflGsgaKNrFd" alt=""><figcaption><p>Download an invoice</p></figcaption></figure>

## **Cancel your subscription**

* Navigate to the "Settings" menu
* Select "Billing and Usage" from the options
* Choose "Manage Billing" to access your billing information
* Locate and click on your current subscription details
* Look for the "Cancel subscription" button and click on it to initiate the cancellation process

<figure><img src="/files/8VdtVOqXdRbgjx02UQDa" alt=""><figcaption></figcaption></figure>

{% hint style="info" %}
If you cancel your subscription before the end of your billing cycle, you will still have access to the service until the end of the current billing cycle.
{% endhint %}

**Modifying a Scheduled Subscription Cancellation**

To cancel a scheduled subscription cancellation:

* Navigate to **Settings** and select **Billing and Usage**.
* Click **Manage Billing** to open your billing dashboard.
* Locate and click on your current subscription details.
* Click **Remove Scheduled Cancellation**, then confirm the action.

<figure><img src="/files/IsBSJO4fuwsbgRkvhU3K" alt=""><figcaption><p>Modify a Scheduled cancellation</p></figcaption></figure>


# Linked Accounts

In this section, you can view all the accounts you have integrated with third-party applications for deliveries. You can also manage all your linked accounts from here.

To access the Linked Accounts:

1. Navigate to the Dashboard.
2. Click on the **Settings** icon in the left-side menu.
3. Then, select "**Linked Accounts**."

<figure><img src="/files/P6kEiHCAPvAWHspYk2D9" alt=""><figcaption><p>Linked Accounts</p></figcaption></figure>

### Link Account

You can easily connect supported third-party apps by clicking the **"Link account**" button. Then, select your desired app from the list and proceed with on-screen instructions to link your account.

<figure><img src="/files/OJTnvy6AybcsAVHQmkay" alt=""><figcaption><p>Setup an integration account</p></figcaption></figure>

### Reconnect an integration

When account authorization expires for various reasons, this option allows you to securely reconnect the linked account, ensuring that ongoing deliveries remain uninterrupted. Click the "**Reconnect**" button besides an expired account and follow on-screen instructions to re-establish the link.

<figure><img src="/files/Wu3YFz6FruDjAuYPVY7k" alt=""><figcaption><p>Reconnect a broken integration</p></figcaption></figure>

### Use a linked account to download images

<figure><img src="/files/ztskDKbrptVo31UWtydA" alt=""><figcaption></figcaption></figure>

When you link a cloud storage account (**Google Drive** or **Azure Storage**), you’ll see a **"Use this for images"** toggle next to the connection. Enabling this option allows Docupilot to use the Linked Account as Authorization mechanism to download the images from private image URLs and insert on the document.

### Revoke Access

If you wish to remove a linked account, you can use this option. This action will revoke Docupilot's access to your integrated account, and all deliveries associated with that account will be deleted.

<figure><img src="/files/dD1XbdkLadbWF8Toq7IH" alt=""><figcaption><p>Revoke access for an Linked Accounts</p></figcaption></figure>

{% hint style="info" %}
Note: Once this operation is executed, it is irreversible, and any deleted data cannot be recovered.
{% endhint %}


# Folders & Templates management

This section will explain how to edit, delete and manage templates and folders


# Manage Folders

### Create a New folder

To create a new folder,

1. Navigate to Templates list page.
2. In the folder section, click the "**+**" button.
3. In the "New Folder" popup, enter your desired folder name.
4. Click "Save" to create the new folder.

<figure><img src="/files/8wc1GXKRPSt0VvI73fc9" alt=""><figcaption><p>Create a new folder</p></figcaption></figure>

### Rename a Folder

To rename a folder, click the **⋯** (ellipsis) button on the folder, select **Edit**, enter the new name in the pop-up, and click **Save**.

<figure><img src="/files/biRaUQTkrcoExhTRthcL" alt=""><figcaption><p>Rename a Folder</p></figcaption></figure>

### Delete a Folder

To delete a Folder, first, click the ⋯ ellipsis button situated beside the folder name you wish to delete. Then, click "**Delete**" button from the popup.

<figure><img src="/files/MQCLIJlR9MiJ01Oo5KXJ" alt=""><figcaption><p>Delete a folder</p></figcaption></figure>


# Manage Templates

### Replicating a Template

To create a copy of a template,

1. In the Template List View, locate the template you want to duplicate and Click the Copy button on that template.
2. In the dialog box that appears, enter a name for the new template and Click the Copy template button.

<figure><img src="/files/JcHdBTEEJbZfhd8gYFWt" alt=""><figcaption><p>Replicating a Template</p></figcaption></figure>

{% hint style="info" %}
The Template will be copied along with preferences and deliveries.
{% endhint %}

### Deleting a template

To move a Template to trash: Click the Delete button on the template, then select **Delete Template** from the pop-up.

<figure><img src="/files/ZCLamyyc5ChHpk2ZJ7od" alt=""><figcaption><p>Deleting a Template</p></figcaption></figure>

#### To permanently delete a template:

1. Navigate to Trash by clicking the Trash button at the bottom of the folders list.
2. Find the template you want to delete, click the **Delete Permanently button** on that template, then confirm by selecting Delete in the pop-up.

<figure><img src="/files/ZFlWKyBnyyksvkUTLOcB" alt=""><figcaption><p>Delete a template permanently</p></figcaption></figure>

{% hint style="info" %}
Templates in Trash will be permanently deleted 30 days after they are moved to Trash.
{% endhint %}

### Restoring a deleted template

If you need to recover a deleted template, you can easily do so:

1. Navigate to Trash by clicking the Trash button, located at the bottom of folders list.
2. Find the template you want to restore, click the Restore button on that template, then confirm by selecting **Restore** in the pop-up.

<figure><img src="/files/PeKI4rF6n4hcy3erWQQ5" alt=""><figcaption><p>Restoring a deleted template</p></figcaption></figure>


# Share Templates & Folders

Share templates and folders with members to explicitly grant Read, Write or Manage access to a template or a folder.

Once a user is added as Member in a Workspace, they can be granted access to view, edit or manage specific Templates or Folders.

### Template & Folder sharing Permissions

By default, **Owners**, **Admins** and **Managers** can manage all Templates and Folders. A **Member** can be granted Manage access for a specific Folder or a Template.

A user who has Manage access to a Template/Folder can share it with a **Member** by assigning one of the following permissions:

* Read Only Permission
* Edit Permission
* Manage Permission

#### Read Only Permission

Members with this permission can:

* View the contents of the folder or template
* Generate documents from the template

#### Edit Permission

Members with this permission can perform every action on a Template/Folder that a Manager, Admin, or Owner can, which includes:

* Edit a Template/Folder name
* Update Template preferences
* Upload a new version of the template
* Manage deliveries (create, update, delete)
* Generate test documents from template
* Create or Delete Data Capture and API Integration link
* Perform bulk merges

{% hint style="info" %}
Granting Edit permission does not allow the Member to share Templates or Folders with other users.
{% endhint %}

#### Manage Permission

In addition to **Read Only** and **Edit** permissions, members with this permission can also **share the template or folder** with other users.

### Sharing a template with member:

1. Click on the Share Button in templates list view against desired Template.
2. Search for users who should be given access to that Template.
3. Choose desired permission and click on Share button.

<figure><img src="/files/J0saSVgLxEZMJkCltqxX" alt=""><figcaption><p>Sharing a template with a Member granting Write permission</p></figcaption></figure>

### Sharing a folder with member:

1. Click on the `⋯` ellipsis button on the folder and select share to open Folder Sharing Settings.
2. Search for users who should be given access to that folder.
3. Choose desired permission and click on Share button.

<figure><img src="/files/otqTmI8QwEzPQ0Qsa4eG" alt=""><figcaption><p>Sharing the Forms folder with Write permission to a Member</p></figcaption></figure>

### Update sharing permissions

Only users with Manage access to a Template or Folder can update its sharing settings. These users can modify permissions, such as changing from Read to Write or Manage.

#### To change a members permission:

1. Open Template/Folder's sharing settings.
2. Find the User whose access needs to be updated under **"Shared Access".**
3. Select a new value from the dropdown to update the permission automatically. No need to click save.

<figure><img src="/files/GvrcFpDgcPjAODfExvjF" alt=""><figcaption><p>Updating access permissions of a Folder from Write to Read.</p></figcaption></figure>

#### To revoke access to Template/Folder for a Member:

1. Open Template/Folder sharing settings.
2. Find the User whose access needs to be removed under **"Shared Access"**. Users under **"Inherited access"** cannot be removed.
3. Click on the **Delete** button from the dropdown to remove access.

<figure><img src="/files/SMrqVxzPpYXzMH7vJKre" alt=""><figcaption><p>Revoking access to a folder.</p></figcaption></figure>

{% hint style="info" %}
A Member's **Inherited Access** on a Template can be **removed** by removing their access from Folder sharing settings.
{% endhint %}


# Frequently Asked Questions (FAQs)

**What is a document credit?**

Document credit refers to the credits issued for your subscription based on the chosen plan.

To generate documents, you need to have active credits in your workspace. For example subscribing to a 29$ monthly plan issues 100 document credits for every billing cycle.

Generating a document and delivering it to each configured delivery consumes one document credit. For instance, if you generate an invoice and send it via email to recipients while also uploading it to Google Drive, it will use 2 credits.

Downloading generated document also consumes 1 credit. If you configure your workflow to download the generated document (using Download mode) and also send it to Docusign, it will consume 2 credits.

**Can I integrate Docupilot with other software or systems?**

Yes, Docupilot provides integration options to connect with popular tools and platforms, such as CRM systems, cloud storage, and more, to simplify your document generation process.

**Is my data secure with Docupilot?**

Yes, Data security is a top priority for Docupilot. Your data is securely stored and transmitted, with the platform adhering to industry best practices to ensure the protection of your information. Read more on our [Security page](https://www.docupilot.com/security).

**What is the pricing?**

Our plans start at 29$ per month. You can more details on our [Pricing page](https://www.docupilot.com/pricing).

**I’m new to Docupilot. How do I start a trial account?**

You can begin your 30-day free trial today without requiring a credit card, commitment, or agreement by [signing up here](https://dashboard.docupilot.app/signup).

### BILLING FAQs:

**How can I upgrade to a paid plan from a trial plan?**

To upgrade to a paid plan, go to the Billing and Usage section within the settings page. From there, choose your desired plan and provide your credit card information to finalize the transaction.

<figure><img src="/files/IgVeTpgbg5MsScTgREOO" alt="" width="175"><figcaption><p>Settings</p></figcaption></figure>

**What types of payment do you accept?**

We Accept Visa, Mastercard, American Express, Discover, Diners Club, JCB, Alipay, Apple Pay, Google Pay, iDEAL, ACH Direct Debit and China UnionPay payments.<br>

**Can I change plans any time?**

You have the flexibility to switch between plans at any time. When you modify your plan, the monthly payments will be automatically adjusted starting from the next billing cycle. In case of an upgrade, you can immediately take advantage of the additional quota.

**What happens when I upgrade my subscription?**

You will be charged only a pro-rated amount for the current billing cycle and you can use additional quota right away.

**What happens if I hit my Usage Limit?**

We will notify you when you consume 80%, 90% and 100% of credits. You will not be able to generate documents once you have hit 100% limit. You can upgrade your account to a higher plan to continue generating the documents.

**Is there a cancellation fee?**

No, there is no cancellation fee. You have the flexibility to cancel, upgrade, or downgrade at any time.

**I need a custom plan for my needs. How can I reach out?**

Drop us an email with your requirements to <support@docupilot.app>.

**Where can I download my invoices for my subscription?**

To obtain the download, navigate to **Settings** -> **Billing and Usage** -> **Manage Billing**, from there, access the billing history and download the required invoice.

<div><figure><img src="/files/LEwFRWQS8pD4U5IQey9U" alt=""><figcaption><p>Billing History</p></figcaption></figure> <figure><img src="/files/j0giGdr4MUsU3vmgvuxP" alt=""><figcaption><p>Invoices History Download</p></figcaption></figure></div>


# API Overview

## Introduction

Docupilot API allows you to perform most of the operations that you do with our web application. Our APIs are designed based on HTTP REST Architectural pattern and follow OpenAPI Specification.

Interactive documentation of Docupilot's V2 APIs is available at `https://<YOUR_SUBDOMAIN>.docupilot.app/~/dashboard/api-docs/swagger-ui/`

### V2 API Authentication

APIs can be accessed using a combination of API Key and Secret created from your **API Settings** section.

1. Go to **Settings > API Settings** to create a new API key.
2. Copy the Key & Secret - download the copy if needed. The secret cannot be retrieved again.
3. base64 encoded value of **key:secret** will be your API key

Use the following command to base64 encode your **key:secret**

```bash
// create the base64 encoded string
echo -n YOUR_API_KEY:YOUR_API_SECRET | base64
```

Use the following curl command to make an API request using the base64 encoded string generated from previous step.

```bash
// making an API request
curl -X GET \
  https://api-us1.docupilot.app/accounts/user/me/ \
  -H 'Authorization: Bearer <Base64 encoded API credentials>'
```

#### X-Workspace Header

The `X-Workspace` header is required to be sent for all the APIs that interact with your Workspace (ex: Templates, etc). This header holds the ID of your workspace for which the request is being made.

You can locate your **Workspace ID** on the Workspace details page. Navigate to the Dashboard and click on the **Settings** icon in the left side menu to access the Workspace details page.

<figure><img src="/files/jBDc1y6DXWJtCJmPVWqU" alt=""><figcaption><p>Workspace ID</p></figcaption></figure>


