PandaDoc
Document automation for contracts, proposals, and e-signatures
PandaDoc
Connect to PandaDoc for document creation, e-signatures, and contract automation.
Overview
PandaDoc is a document automation platform. The integration supports:
- Templates - List and use document templates
- Documents - Create, send, and track documents
- E-signatures - Send for signature and track status
- Folders - Organize documents
- Contacts - Manage recipient contacts
Prerequisites
- PandaDoc account (Free trial, Essentials, Business, or Enterprise)
- API access enabled
- OAuth app or API key configured
Authentication
PandaDoc uses OAuth 2.0 for authentication via Nango.
curl "http://localhost:3000/api/v1/connections/pandadoc/auth-url" \
-H "x-api-key: YOUR_API_KEY"Available Actions
Template Actions
listTemplates
List available templates.
{
"action": "pandadoc.listTemplates",
"config": {
"q": "Sales Contract",
"tag": "sales",
"folderId": "folder-uuid",
"count": 50,
"page": 1
}
}Parameters:
| Field | Type | Description |
|---|---|---|
q | string | Search query |
tag | string | Filter by tag |
folderId | string | Filter by folder |
count | number | Results per page (default: 50) |
page | number | Page number |
deleted | boolean | Include deleted |
getTemplate
Get template details.
{
"action": "pandadoc.getTemplate",
"config": {
"templateId": "{{input.templateId}}"
}
}Document Actions
createDocument
Create a document from a template.
{
"id": "create-contract",
"type": "action",
"action": "pandadoc.createDocument",
"config": {
"templateId": "{{input.templateId}}",
"name": "Contract - {{input.companyName}}",
"recipients": [
{
"email": "{{input.signerEmail}}",
"first_name": "{{input.signerFirstName}}",
"last_name": "{{input.signerLastName}}",
"role": "signer",
"signing_order": 1
},
{
"email": "{{input.ccEmail}}",
"first_name": "{{input.ccFirstName}}",
"last_name": "{{input.ccLastName}}",
"role": "cc"
}
],
"tokens": [
{ "name": "Company.Name", "value": "{{input.companyName}}" },
{ "name": "Contract.Amount", "value": "{{input.amount}}" },
{ "name": "Contract.Date", "value": "{{input.contractDate}}" }
],
"pricingTables": [
{
"name": "Products",
"sections": [
{
"title": "Services",
"rows": [
{
"options": { "qty_editable": false },
"data": {
"Name": "Professional Services",
"Price": 5000,
"QTY": 1
}
}
]
}
]
}
],
"folderId": "{{input.folderId}}",
"tags": ["sales", "q1-2024"],
"metadata": {
"opportunity_id": "{{input.opportunityId}}",
"source": "workflow"
}
}
}Parameters:
| Field | Type | Required | Description |
|---|---|---|---|
templateId | string | Yes | Template UUID |
name | string | Yes | Document name |
recipients | array | No | Document recipients |
recipients[].email | string | Yes | Recipient email |
recipients[].first_name | string | No | First name |
recipients[].last_name | string | No | Last name |
recipients[].role | string | No | Role from template |
recipients[].signing_order | number | No | Signing order |
tokens | array | No | Template variable values |
tokens[].name | string | Yes | Token name |
tokens[].value | string | Yes | Token value |
pricingTables | array | No | Pricing table data |
folderId | string | No | Folder UUID |
tags | array | No | Document tags |
metadata | object | No | Custom metadata |
getDocument
Get document details.
{
"action": "pandadoc.getDocument",
"config": {
"documentId": "{{input.documentId}}"
}
}getDocumentStatus
Get document status (lighter endpoint for status checks).
{
"action": "pandadoc.getDocumentStatus",
"config": {
"documentId": "{{steps.create.output.id}}"
}
}Document Statuses:
| Status | Description |
|---|---|
document.draft | Draft, not yet sent |
document.sent | Sent for signature |
document.completed | All signatures collected |
document.viewed | Viewed by recipient |
document.waiting_approval | Awaiting internal approval |
document.approved | Internally approved |
document.rejected | Rejected |
document.waiting_pay | Awaiting payment |
document.paid | Payment received |
document.voided | Voided |
document.declined | Declined by recipient |
document.external_review | External review in progress |
listDocuments
List documents with filters.
{
"action": "pandadoc.listDocuments",
"config": {
"status": "document.sent",
"templateId": "{{input.templateId}}",
"q": "Contract",
"tag": "sales",
"folderId": "{{input.folderId}}",
"createdFrom": "2024-01-01",
"createdTo": "2024-12-31",
"orderBy": "date_created",
"count": 50,
"page": 1
}
}sendDocument
Send a document for signature.
{
"id": "send-for-signature",
"type": "action",
"action": "pandadoc.sendDocument",
"config": {
"documentId": "{{steps.create-contract.output.id}}",
"subject": "Please sign: {{input.documentName}}",
"message": "Hi {{input.recipientName}},\n\nPlease review and sign the attached document at your earliest convenience.\n\nThank you!",
"silent": false,
"forwarding_allowed": true
}
}Parameters:
| Field | Type | Description |
|---|---|---|
documentId | string | Document UUID |
subject | string | Email subject |
message | string | Email message |
silent | boolean | Send without email (default: false) |
forwarding_allowed | boolean | Allow forwarding (default: true) |
createDocumentLink
Create a sharing/signing link.
{
"action": "pandadoc.createDocumentLink",
"config": {
"documentId": "{{input.documentId}}",
"recipient": "{{input.recipientEmail}}",
"lifetime": 3600
}
}Parameters:
| Field | Type | Description |
|---|---|---|
documentId | string | Document UUID |
recipient | string | Recipient email (for specific recipient link) |
lifetime | number | Link lifetime in seconds (default: 3600) |
Response:
{
"id": "session-uuid",
"expires_at": "2024-01-15T11:30:00Z",
"link": "https://app.pandadoc.com/s/..."
}downloadDocument
Get document download URL.
{
"action": "pandadoc.downloadDocument",
"config": {
"documentId": "{{input.documentId}}",
"watermark": false,
"separateFiles": false
}
}deleteDocument
Delete a document.
{
"action": "pandadoc.deleteDocument",
"config": {
"documentId": "{{input.documentId}}"
}
}updateDocumentStatus
Update document status (void, mark complete, etc.).
{
"action": "pandadoc.updateDocumentStatus",
"config": {
"documentId": "{{input.documentId}}",
"status": "document.voided",
"note": "Voided per customer request",
"notifySigner": true
}
}Valid Status Transitions:
| From | To |
|---|---|
document.draft | document.sent |
document.sent | document.voided |
document.viewed | document.voided |
document.waiting_approval | document.approved, document.rejected |
Folder Actions
listFolders
List folders.
{
"action": "pandadoc.listFolders",
"config": {
"parentId": "{{input.parentFolderId}}",
"count": 50,
"page": 1
}
}createFolder
Create a new folder.
{
"action": "pandadoc.createFolder",
"config": {
"name": "Q1 2024 Contracts",
"parentId": "{{input.parentFolderId}}"
}
}renameFolder
Rename a folder.
{
"action": "pandadoc.renameFolder",
"config": {
"folderId": "{{input.folderId}}",
"name": "Q1 2024 Contracts - Archived"
}
}Contact Actions
listContacts
List contacts.
{
"action": "pandadoc.listContacts",
"config": {
"email": "{{input.email}}"
}
}createContact
Create a new contact.
{
"action": "pandadoc.createContact",
"config": {
"email": "{{input.email}}",
"firstName": "{{input.firstName}}",
"lastName": "{{input.lastName}}",
"company": "{{input.companyName}}",
"jobTitle": "{{input.title}}",
"phone": "{{input.phone}}",
"streetAddress": "{{input.address.street}}",
"city": "{{input.address.city}}",
"state": "{{input.address.state}}",
"postalCode": "{{input.address.zip}}",
"country": "{{input.address.country}}"
}
}updateContact
Update a contact.
{
"action": "pandadoc.updateContact",
"config": {
"contactId": "{{input.contactId}}",
"company": "{{input.newCompanyName}}",
"jobTitle": "{{input.newTitle}}"
}
}deleteContact
Delete a contact.
{
"action": "pandadoc.deleteContact",
"config": {
"contactId": "{{input.contactId}}"
}
}Webhook Triggers
PandaDoc webhooks trigger workflows on document events.
{
"trigger": {
"type": "webhook",
"provider": "pandadoc",
"events": ["document_state_changed", "recipient_completed"]
}
}Event Types:
| Event | Description |
|---|---|
document_state_changed | Document status changed |
recipient_completed | Recipient completed their actions |
document_completed | All recipients completed |
document_paid | Payment received |
document_viewed | Document was viewed |
document_deleted | Document was deleted |
Example Workflow
Complete contract workflow:
{
"name": "Send Contract on Deal Close",
"trigger": {
"type": "webhook",
"provider": "hubspot",
"events": ["deal.propertyChange"]
},
"steps": [
{
"id": "check-stage",
"type": "condition",
"config": {
"conditions": {
"left": "{{input[0].propertyName}}",
"operator": "eq",
"right": "dealstage"
},
"then": ["check-closed"],
"else": []
}
},
{
"id": "check-closed",
"type": "condition",
"config": {
"conditions": {
"left": "{{input[0].propertyValue}}",
"operator": "eq",
"right": "closedwon"
},
"then": ["get-deal"],
"else": []
}
},
{
"id": "get-deal",
"type": "action",
"action": "hubspot.getDeal",
"config": {
"dealId": "{{input[0].objectId}}",
"properties": ["dealname", "amount", "closedate"]
}
},
{
"id": "get-contact",
"type": "action",
"action": "hubspot.getAssociations",
"config": {
"objectType": "deals",
"objectId": "{{input[0].objectId}}",
"toObjectType": "contacts"
}
},
{
"id": "create-contract",
"type": "action",
"action": "pandadoc.createDocument",
"config": {
"templateId": "contract-template-uuid",
"name": "Service Agreement - {{steps.get-deal.output.properties.dealname}}",
"recipients": [
{
"email": "{{steps.get-contact.output.results[0].email}}",
"role": "signer"
}
],
"tokens": [
{ "name": "Deal.Name", "value": "{{steps.get-deal.output.properties.dealname}}" },
{ "name": "Deal.Amount", "value": "{{steps.get-deal.output.properties.amount}}" }
]
}
},
{
"id": "wait-for-processing",
"type": "wait",
"config": {
"duration": 5000
}
},
{
"id": "send-contract",
"type": "action",
"action": "pandadoc.sendDocument",
"config": {
"documentId": "{{steps.create-contract.output.id}}",
"subject": "Service Agreement Ready for Signature",
"message": "Please review and sign the attached service agreement."
}
},
{
"id": "notify-team",
"type": "action",
"action": "slack.sendMessage",
"config": {
"channel": "#sales",
"text": "Contract sent for {{steps.get-deal.output.properties.dealname}}"
}
}
]
}Rate Limits
| Limit | Value |
|---|---|
| API calls | 50/minute (standard) |
| API calls | 300/minute (enterprise) |
| Document creation | 100/hour |
| Bulk operations | 10 concurrent |
Troubleshooting
Common Errors
| Error | Cause | Solution |
|---|---|---|
document_not_found | Invalid document ID | Verify document exists |
template_not_found | Invalid template ID | Verify template ID |
invalid_recipients | Missing required recipient data | Check email format |
rate_limit_exceeded | Too many requests | Implement backoff |
Document Processing
Documents take time to process after creation:
- Create document (status:
document.draft) - Wait 3-5 seconds for processing
- Send document (status:
document.sent)
Use a wait step between creation and sending.