Create a Document from Template
Automate repeated document creation from a template. Reference: https://developers.pandadoc.com/reference/create-document-from-pandadoc-template
Template
A PandaDoc template is a document template created and edited in the PandaDoc web application. Our help center has further information on PandaDoc templates.
We have prepared a sample PandaDoc template that you can use to test the request. You can find it in the Templates section of your account or download it here:
After downloading, the system will create a document from this template. The browser will redirect you to this document. Return to the templates page to find the template_id
that you can use in Postman. Look for it in your browser's address bar: https://app.pandadoc.com/a/#/templates/{ID}/content
.
Asynchronous document creation
Document creation is a non-blocking (asynchronous) operation
The document creation process may take some time.
With a successful request, you receive a response with the created document's ID and status
document.uploaded
. After processing completes on our servers, usually a few seconds, the document moves to thedocument.draft
status. Please wait for the webhook call or check this document's status before proceeding.The change of status from
document.uploaded
to another status signifies the document is ready for further processing. Attempting to use a newly created document before PandaDoc servers process it will result in a "404 document not found" response.
Date fields
Specify date formatting in the PandaDoc template date field settings. Pass the date field value in the following way: "fields": {"Date": {"value": "2019-02-21T00:00:00.000Z"}}
Signing order
Set a signing order of recipients for documents created from templates via API.
In addition, we allow overriding a signing order in the document creation request.
"recipients": [
{
"email": "[email protected]",
"first_name": "Josh",
"last_name": "Ron",
"role": "user",
"signing_order": 1
}
]
Create on member's behalf
Create documents on your colleagues' behalf when it's needed. Simply add an additional owner
section in the document creation request.
You can set an owner of a document as an email
or membership_id
. Unique member's identifier you may find in the List Members.
"owner":{
"email":"[email protected]"
}
"owner":{
"membership_id":"radQBiBkU7MBk59NSgaGfd"
}
Prefilled fields
You can't prefill a Signature field.
If you want to prefill a particular field, you need to map a template Merge Field to the API field:
- Open your template on the web view
- Open field properties
- Scroll down to Merge Field and give your field a meaningful name:
- Use this name in your request body, like in the example on the right panel:
"fields": { "Favorite.Color": { "value": "PandaDoc green" }, "Delivery": { "value": "Same Day Delivery" }, "Like": { "value": true }, "Date": { "value": "2019-12-31T00:00:00.000Z" } },
Images
Upload images to Image blocks when creating a new document from a template. Please note the image blocks in the template should be pre-set before creating a document.
Link an image to a particular image block in your template by its name. For example, if there is an image block named "Image 1" in your template, uploading an image with the name "Image 1" via API places this image in this block.
Upload an image as a URL parameter inside a JSON request body in the following format:
"images": [
{
"name": "Image 1",
"urls": [
"https://s3.amazonaws.com/pd-static-content/public-docs/pandadoc-panda-bear.png"
]
}
]
Image formats supported: GIF, JPG, PNG. Editor 2.0 allows only one image per block and doesn't allow images in text blocks.
Content Placeholder
With API, you can replace the Content Placeholder with content library items. In addition, it's possible to prefill fields/variables values, add items to the pricing table, and assign recipients to roles from the content library item.
See a detailed guide on how to use a content placeholder.
Content Placeholder can be accessed via Block ID
which automatically generates upon placeholder creation in the template. You can easily change it in the template.
"content_placeholders": [
{
"uuid": "305eca46-f5be-435b-bbb4-f4dacf3896f5",
"block_id": "Content Placeholder 1",
"description": "Click here to add content library items"
}
]
As mentioned above, you can replace a placeholder with a few content library items each and you can be pass them as an array of content library items in the API document creation request.
"content_placeholders": [
{
"block_id": "{{block_id}}",
"content_library_items": [
{
"id": "{{cli_id}}",
"pricing_tables": [
{
"name": "Pricing Table 1",
"sections": [
{
"title": "Sample Section",
"default": true,
"rows": [
{
"options": {
"optional": true,
"optional_selected": true,
"qty_editable": true
},
"data": {
"name": "Placeholder Panda",
"price": 10,
"qty": 3
}
}
]
}
]
}
]
},
{
"id": "{{cli_id_2}}",
"recipients": [
{
"email": "[email protected]",
"first_name": "John",
"last_name": "Roe",
"role": "Signer"
}
],
"fields": {
"Date": {
"value": "2019-12-31T00:00:00.000Z"
}
}
}
]
}
Content placeholders restrictions:
- Content placeholder must be replaced with at least 1 content library item.
- You can add up to 10 content library items in one content placeholder.
- Content library item must be unique in the content placeholder. You can use the same one for different placeholders.
Pricing table
Section types
There are two types of sections in the pricing table (PT):
- Default sections won't have a section Header in the resulting document. Set the
"default"
parameter as "true" to mark a section as default. - Non-default sections will have a Header and should be added with
"default": false
option.
You can set a multiple-choice section in the "sections" description inside a JSON request body in the format: "multichoice_enabled": true
. Use the parameter "multichoice_selected"
set as true to select the row, while other rows should be deselected in the row description.
Here is a code example of a "Multiple choice section" where the second item in the section is selected below:
"sections": [
{
"title": "First Section",
"default": false,
"multichoice_enabled": true,
"rows": [
{
"options": {
"multichoice_selected": false
},
"data":{
"name": "Toy Panda",
"price": 20,
"qty": 2
}
},
{
"options": {
"multichoice_selected": true
},
"data":{
"name": "Toy Panda",
"price": 10,
"qty": 3
}
}
]
Multiple-choice section restrictions
If you don't mark any row as selected in the "Multiple choice section,” the first row in the section will be selected. If you mark several rows, only the first one will be selected.
It is not possible to set rows as optional in the "Multiple choice section.”
Column types
Column type | JSON example |
---|---|
Text | "Name": "Toy Panda", "Description": "Fluffy!" |
Tax | "Tax": { "value": 7.5, "type": "percent" } |
Discount | "Discount": { "value": 7.5, "type": "percent" } |
Fee | "Fee": { "value": 7.5, "type": "percent" } |
Additional multiplayer | "Multiplayer": 1.5 |
Price | "Price": 15.0 |
Quantity | "QTY": 15 |
Taxes
Your document can have several taxes. To apply several taxes successfully, you must use these names: tax_first
, tax_second
.
For a global tax in your pricing table (PT), follow these steps:
- Add a Tax column to the PT in your template. You can hide it if you don't really need it there.
- Edit the PT section in your payload to match the following example:
"pricing_tables":
[
{
"name": "Pricing Table 1",
"data_merge": true,
"options":
{
"currency": "EUR",
"Tax":
{
"name": "Tax",
"type": "percent",
"value": 19
}
},
"sections":
[
{
"title": "Pricing Section",
"default": true,
"rows":
[
{
"options":
{
"optional": false,
"optional_selected": false,
"qty_editable": false
},
"data":
{
"Name": "Meta Conversion Advertising",
"Price": 6000,
"QTY": 6,
"Description": "Conversion Kampagnen Management \n+ Performance Design",
"Unit": "Monatlich",
"Tax":
{
"type": "percent",
"value": 0
}
}
}
]
}
]
}
]
Data merge
Frequently, our customers need to name columns in the pricing table according to names in their system and that's where data merge may help. The data merge feature is available by default and the only thing you need to do is enable it in API as well.
Here is how you can check what names your columns have with the data merge feature by default and change them.
To use these column names instead of default ones you need to add the data_merge
boolean parameter as true
(false
by default) into the pricing table object of the document creation request body and use them in the data
section.
"pricing_tables": [
{
"name": "Pricing Table 1",
"data_merge":true,
"options": {
"discount": {
"type": "absolute",
"name": "Discount",
"value": 2.26
}
},
"sections": [
{
"title": "Sample Section",
"default": true,
"rows": [
{
"options": {
"optional": true,
"optional_selected": true,
"qty_editable": true
},
"data": {
"Name": "Toy Panda",
"Description": "Fluffy!",
"Price": 10,
"QTY": 3,
"SKU":"TEST1",
"Tax": {
"value": 7.5,
"type": "percent"
},
"CustomText":"testcolumn"
},
"custom_fields": {
"Fluffiness": "5 / 5"
}
}
]
}
]
}
]
As a result, all values from the document creation request will be properly matched with columns in the pricing table of the newly created document.
For more information on how to add and set your pricing table, visit our help center. You will also discover ways your recipients can interact with the pricing table. This is a fun feature you’ll want to explore more!
Variables in titles
The name
parameter is optional for the documents created from a template. Here's how you dynamically populate the document name:
Set document name to include a variable
- Set the template name to include a variable on the UI.
- Create a document from the template via API:
- For name, pass a variable enclosed in square brackets, like this: Proposal for [Company.Name]. Set the optional
detect_title_variables
parameter totrue
. - Title variable only works if you have either set it on the UI or passed it in the
tokens
section of the payload. Otherwise, it is presented as plain text in square brackets.
- For name, pass a variable enclosed in square brackets, like this: Proposal for [Company.Name]. Set the optional
{
"name": "Proposal for [Company.Name]",
"detect_title_variables": true,
"template_uuid": "RWVafhmMWniwA5FWnEQVvg",
...
"tokens": [
{
"name": "Company.Name",
"value": "Panda"
}
}
Updated 10 months ago