> **Building with AI coding agents?** Install the authstack plugin with one command. This equips your agent with accurate Scalekit implementation patterns.
>
> **Recommended** (the `-y` flags skip prompts, so the command runs without an interactive terminal):
> ```bash
> npx -y @scalekit-inc/cli setup -y
> ```
>
> Global:
> ```bash
> npm install -g @scalekit-inc/cli
> scalekit setup -y
> ```
>
> Supports Claude Code, Cursor, GitHub Copilot, Codex + skills for other Agent Skills-compatible agents in `~/.agents/skills`.
> Skills: integrate-agentkit, implement-saaskit, add-mcp-oauth, implement-sso, implement-scim.
> [Full setup guide](https://docs.scalekit.com/dev-kit/build-with-ai/)

---

# Connect AI agents to the Pandadoc MCP server

The Pandadoc MCP connector routes your AI agent's tool calls to Pandadoc's own MCP server through Scalekit. Each user signs in to Pandadoc once, and Scalekit stores and refreshes their tokens, so your agent never handles credentials. It comes with 22 tools.

**Authentication:** OAuth 2.1/DCR
**Categories:** Productivity, Automation, Files & Documents
**Tools:** 22: 11 read, 8 write, 3 destructive
**Users sign in with:** OAuth
**OAuth app:** Scalekit's or your own
**Built by:** Vendor MCP
**Try it:** [Playground in the Scalekit dashboard](https://app.scalekit.com/ws/signup?sk_intent=playground&provider=PANDADOCMCP)

## What you can do

- **Create documents**: build a document from a PandaDoc template, from markdown content, or from a PDF/DOCX file URL
- **Send for signature**: send a draft to its recipients with a custom subject and message, control email notifications, and set forwarding and approval options
- **Manage recipients**: add CC recipients, edit a recipient's details, reassign a signer to another contact, or remove a recipient
- **Track status and history**: check document status, retrieve the full audit trail, and manually mark a document Completed, Paid, Expired, or Declined
- **Find and read documents**: list with status, folder, tag, sorting and date-range filters, full-text search, and pull content, details, summaries, or metadata (single or batched across up to 40 documents)
- **Work with templates**: list templates, inspect a template's roles, fields, tokens and pricing tables, or create a new template from a PDF URL

## Setup

1. ### Install the SDK

   **Node.js**

   ```bash
   npm install @scalekit-sdk/node dotenv
   ```

   **Python**

   ```bash
   pip install scalekit-sdk-python python-dotenv
   ```

2. ### Set your credentials

   Add your Scalekit credentials to your `.env` file. Find values in **[app.scalekit.com](https://app.scalekit.com)** > **Developers** > **API Credentials**.

   ```sh title=".env"
   SCALEKIT_ENVIRONMENT_URL=<your-environment-url>
   SCALEKIT_CLIENT_ID=<your-client-id>
   SCALEKIT_CLIENT_SECRET=<your-client-secret>
   ```

3. ### Create the Pandadoc MCP connection

   In **AgentKit > Connections**, create a Pandadoc MCP connection. The name you give it is the `connection_name` your code passes. See [Configure connections](/agentkit/connections/).

   Scalekit credentials are available for Pandadoc MCP server, so you don't need to register an OAuth app.

4. ### Authorize a user and make your first call

   **Node.js** (`quickstart.mts`)

   ```typescript
   import { ScalekitClient } from '@scalekit-sdk/node'
   import 'dotenv/config'
   import { createInterface } from 'node:readline/promises'

   const scalekit = new ScalekitClient(
     process.env.SCALEKIT_ENVIRONMENT_URL,
     process.env.SCALEKIT_CLIENT_ID,
     process.env.SCALEKIT_CLIENT_SECRET,
   )
   const actions = scalekit.actions

   const connector = 'pandadocmcp'
   const identifier = 'user_123'

   // Generate an authorization link for the user
   const { link } = await actions.getAuthorizationLink({ connectionName: connector, identifier })
   console.log('Authorize Pandadoc MCP:', link)
   const rl = createInterface({ input: process.stdin, output: process.stdout })
   await rl.question('Press Enter after authorizing...')
   rl.close()

   // Make your first call
   const result = await actions.executeTool({
     connector,
     identifier,
     toolName: 'pandadocmcp_documents_list',
     toolInput: {},
   })
   console.log(result)
   ```

   ```bash
   npx tsx quickstart.mts
   ```

   **Python** (`quickstart.py`)

   ```python
   import os
   from scalekit import ScalekitClient
   from dotenv import load_dotenv
   load_dotenv()

   scalekit_client = ScalekitClient(
       env_url=os.getenv("SCALEKIT_ENVIRONMENT_URL"),
       client_id=os.getenv("SCALEKIT_CLIENT_ID"),
       client_secret=os.getenv("SCALEKIT_CLIENT_SECRET"),
   )
   actions = scalekit_client.actions

   connection_name = "pandadocmcp"
   identifier = "user_123"

   # Generate an authorization link for the user
   link_response = actions.get_authorization_link(
       connection_name=connection_name,
       identifier=identifier,
   )
   print("Authorize Pandadoc MCP:", link_response.link)
   input("Press Enter after authorizing...")

   # Make your first call
   result = actions.execute_tool(
       tool_input={},
       tool_name="pandadocmcp_documents_list",
       connection_name=connection_name,
       identifier=identifier,
   )
   print(result)
   ```

   ```bash
   python quickstart.py
   ```

   Each user signs in once. See [Authorize a user](/agentkit/tools/authorize/) for the full flow and statuses.

## Tools

Pass the exact name to `execute_tool`, with an input like each tool's example. To ask for a tool that's missing, use the [request form](https://scalekitsupport.portal.usepylon.com/forms/request-a-connector-tool).

**Node.js**

```typescript
const result = await actions.executeTool({
  toolName: 'pandadocmcp_documents_audit_trail_get',
  toolInput: {
    document_id: '<document_id>',
  },
  connector: 'pandadocmcp',
  identifier: 'user_123',
})
```

**Python**

```python
result = actions.execute_tool(
    tool_name="pandadocmcp_documents_audit_trail_get",
    tool_input={
        "document_id": "<document_id>",
    },
    connection_name="pandadocmcp",
    identifier="user_123",
)
```

`result.data` is the app's response as JSON, and `result.execution_id` (`executionId` in Node.js) is the ID of the call.

### `pandadocmcp_documents_audit_trail_get`

Documents Audit Trail Get · Read-only

Retrieve the full audit trail for a document, showing all events including views, signatures, and status changes.

Read only: yes. Destructive: no. Idempotent (safe to retry): yes.

Inputs:

- `document_id` (`string`, required): Document ID

Example input: `{"document_id":"<document_id>"}`

### `pandadocmcp_documents_content_get`

Documents Content Get · Read-only

Get the content of a document in HTML or PDF format by document ID.

Read only: yes. Destructive: no. Idempotent (safe to retry): yes.

Inputs:

- `content_format` (`string`, required): Content format to return. Must be one of: 'plaintext' or 'markdown'. One of: `plaintext`, `markdown`.
- `document_id` (`string`, required): Document ID

Example input: `{"content_format":"plaintext","document_id":"<document_id>"}`

### `pandadocmcp_documents_details_get`

Documents Details Get · Read-only

Retrieve full details for a document including metadata, recipients, fields, and status.

Read only: yes. Destructive: no. Idempotent (safe to retry): yes.

Inputs:

- `document_id` (`string`, required): Document ID

Example input: `{"document_id":"<document_id>"}`

### `pandadocmcp_documents_list`

Documents List · Read-only

List documents with filters for status, folder, tag, free-text search, sorting, and created/completed date ranges. Returns paginated results.

Read only: yes. Destructive: no. Idempotent (safe to retry): yes.

Inputs:

- `completed_from` (`string`, optional): Only documents completed on or after this ISO-8601 datetime.
- `completed_to` (`string`, optional): Only documents completed before this ISO-8601 datetime.
- `count` (`string`, optional): Limits the size of the response. Default is 50 documents, maximum is 100 documents.
- `created_from` (`string`, optional): Only documents created on or after this ISO-8601 datetime, e.g. ``2026-03-01T00:00:00Z``.
- `created_to` (`string`, optional): Only documents created before this ISO-8601 datetime, e.g. ``2026-03-31T23:59:59Z``.
- `folder_uuid` (`string`, optional): UUID of the folder to list from (folder_uuid, NOT folder_id).
- `page` (`string`, optional): Paginates the search result. Increase value to get the next page of results.
- `q` (`string`, optional): Filters documents by name or reference number (stored on the template level).
- `sort_by` (`string`, optional): Field to sort documents by. Defaults to date_status_changed when omitted.
- `sort_order` (`string`, optional): Sort direction, ascending when omitted. Keep consistent across pages of the same query.
- `status` (`string`, optional): Filters documents by status. Valid values: Draft, Sent, Completed, Uploaded, Error, Viewed, Waiting for Approval, Approved, Rejected, Waiting for Payment, Paid, Expired, Declined, External Review, Scheduled.
- `tag` (`string`, optional): Filters documents by tag.

Example input: `{}`

### `pandadocmcp_documents_metadata_batch_get`

Documents Metadata Batch Get · Read-only

Retrieve metadata for 1-40 documents in one request. Preferred over calling Get Document Metadata in a loop; a failure for one document does not fail the batch.

Read only: yes. Destructive: no. Idempotent (safe to retry): yes.

Inputs:

- `document_ids` (`array`, required): 1-40 document IDs to fetch metadata for. Duplicates are rejected by the server.
- `field_keys` (`string`, optional): Optional case-sensitive filter on metadata field `key` (the human-readable name returned as `results[].key` by the single-document endpoint, e.g. `Contract value`). Unknown keys are silently ignored. When omitted, every populated field is returned per document.

Example input: `{"document_ids":[]}`

### `pandadocmcp_documents_metadata_get`

Documents Metadata Get · Read-only

Get AI-extracted metadata fields from a document, combining document and content data into structured key-value pairs.

Read only: yes. Destructive: no. Idempotent (safe to retry): yes.

Inputs:

- `document_id` (`string`, required): Document ID
- `limit` (`string`, optional): Maximum number of fields to return in one response. Omit for API default (100). Max 100.
- `offset` (`string`, optional): Number of fields to skip before starting to collect the result set. For predictable paging, use multiples of `limit`.

Example input: `{"document_id":"<document_id>"}`

### `pandadocmcp_documents_search`

Documents Search · Read-only

Full-text search across documents with optional filters for status, date range, and pagination.

Read only: yes. Destructive: no. Idempotent (safe to retry): yes.

Inputs:

- `query` (`string`, required): Full-text search string (matches document content and metadata).
- `count` (`string`, optional): Page size: public API ``count`` query param. Omit for default (30). Max 100.
- `date_filter_column` (`string`, optional): Which document timestamp the date window applies to. If you set any date filter, set **all three** of ``date_filter_column``, ``from_date``, and ``to_date``. Allowed values: ``date_created``, ``date_expiration``, ``last_modified``, ``signature_date``, ``effective_date``.
- `from_date` (`string`, optional): Inclusive window start (ISO-8601), e.g. ``2026-03-01T00:00:00Z``. Use together with ``date_filter_column`` and ``to_date``.
- `page` (`string`, optional): Page number (1-based). Omit to use API default (1).
- `status` (`string`, optional): Restrict hits to documents with these statuses (omit to ignore status). Valid values: Draft, Sent, Completed, Uploaded, Error, Viewed, Waiting for Approval, Approved, Rejected, Waiting for Payment, Paid, Expired, Declined, External Review, Scheduled. Example: ["Sent", "Completed"].
- `to_date` (`string`, optional): Inclusive window end (ISO-8601), e.g. ``2026-03-31T23:59:59Z``. Use together with ``date_filter_column`` and ``from_date``.

Example input: `{"query":"<query>"}`

### `pandadocmcp_documents_status_get`

Documents Status Get · Read-only

Get the current status of a document by ID.

Read only: yes. Destructive: no. Idempotent (safe to retry): yes.

Inputs:

- `document_id` (`string`, required): Document ID

Example input: `{"document_id":"<document_id>"}`

### `pandadocmcp_documents_summary_get`

Documents Summary Get · Read-only

Get an AI-generated or standard summary for a document by ID.

Read only: yes. Destructive: no. Idempotent (safe to retry): yes.

Inputs:

- `document_id` (`string`, required): Document ID
- `summary_type` (`string`, required): Summary granularity to return. Must be one of: 'detailed', 'short', or 'headline'. One of: `detailed`, `short`, `headline`.

Example input: `{"document_id":"<document_id>","summary_type":"detailed"}`

### `pandadocmcp_templates_details_get`

Templates Details Get · Read-only

Get full details for a template including roles, fields, tokens, and pricing tables.

Read only: yes. Destructive: no. Idempotent (safe to retry): yes.

Inputs:

- `template_id` (`string`, required): Template ID

Example input: `{"template_id":"<template_id>"}`

### `pandadocmcp_templates_list`

Templates List · Read-only

List templates with optional filters for search, tags, folder, and shared/deleted status.

Read only: yes. Destructive: no. Idempotent (safe to retry): yes.

Inputs:

- `count` (`string`, optional): Specify how many templates to return.
- `deleted` (`string`, optional): Returns only the deleted templates.
- `fields` (`string`, optional): A comma-separated list of additional fields to include in the response.
- `folder_uuid` (`string`, optional): UUID of the folder where the templates are stored.
- `page` (`string`, optional): Specify which page of the dataset to return.
- `q` (`string`, optional): Search query. Filter by template name.
- `shared` (`string`, optional): Returns only the shared templates.
- `tag` (`string`, optional): Search tag. Filter by template tag.
- `template_id` (`string`, optional): Specify template ID.

Example input: `{}`

### `pandadocmcp_documents_create`

Documents Create · Write

Create a document from a template, markdown content, or a PDF/DOCX file URL. Pass a single 'request' object whose 'source' selects the creation mode; each source accepts only its own parameters. Creation is asynchronous - poll Get Document Status until the document is Draft or Error. IMPORTANT for pricing_tables: row/column field names (e.g. 'name', 'price', 'qty') are defined per-template, not fixed globally. Before populating pricing_tables, call templates_details_get on the target template_uuid and read the real column names from its pricing.tables[].items[] / merged_data - do not guess casing or names from examples.

Read only: no. Destructive: no. Idempotent (safe to retry): no.

Inputs:

- `request` (`string`, required): Document to create. Set `source` to `template` (create from a PandaDoc template), `markdown` (create from markdown content), or `file` (create from a PDF/DOCX file URL). Each source accepts only its own parameters.

Example input: `{"request":"<request>"}`

### `pandadocmcp_documents_fields_assign`

Documents Fields Assign · Write

Assign, reassign, or unassign document fields to recipients. Document must be in draft status.

Read only: no. Destructive: no. Idempotent (safe to retry): yes.

Inputs:

- `assignments` (`array`, required): List of field-to-recipient assignments. Each item maps a field UUID to a recipient UUID (or null to unassign).
- `document_id` (`string`, required): Document ID

Example input: `{"assignments":[],"document_id":"<document_id>"}`

### `pandadocmcp_documents_send`

Documents Send · Write

Send a draft document to recipients for review and signature with optional message, subject, and CC settings.

Read only: no. Destructive: no. Idempotent (safe to retry): no.

Inputs:

- `document_id` (`string`, required): Document ID
- `forwarding_settings` (`string`, optional): Settings for document and signature forwarding. Controls whether recipients can forward the document or reassign their fields to another person.
- `message` (`string`, optional): A message that will be sent by email with a link to the document to sign.
- `reply_to` (`string`, optional): Email address used as reply-to for the document. Must be enabled for the account by support.
- `selected_approvers` (`string`, optional): Configuration for selecting approvers from approval workflow groups. Copy 'steps' from the 'approval_execution' section of Document Details and set 'is_selected' to true for the desired approver.
- `sender` (`string`, optional): Set a sender of a document as an email or membership_id.
- `silent` (`string`, optional): If true, disables email notifications for document recipients and the sender. Also disables scheduled reminders. Does not affect 'Approve document' email notification.
- `skip_unfilled_variables` (`boolean`, optional): Must be false by default. Only set to true when the user has explicitly chosen to send with empty variables. Default: `false`.
- `subject` (`string`, optional): Value that will be used as the email subject.

Example input: `{"document_id":"<document_id>"}`

### `pandadocmcp_documents_update`

Documents Update · Write

Update a draft document — name, recipients, fields, tokens, images, pricing tables, and metadata. Document must be in draft status.

Read only: no. Destructive: no. Idempotent (safe to retry): no.

Inputs:

- `document_id` (`string`, required): Document ID
- `fields` (`string`, optional): Document fields as key-value pairs
- `images` (`string`, optional): Images
- `metadata` (`string`, optional): Document metadata as key-value pairs
- `name` (`string`, optional): Document name
- `pricing_tables` (`string`, optional): Pricing tables to populate by name
- `recipients` (`string`, optional): List of recipients. Each should have email, first_name, last_name, etc.
- `tables` (`string`, optional): Tables to populate by name
- `tags` (`string`, optional): Document tags
- `texts` (`string`, optional): List of text blocks to update. Each item should have 'name' and 'data' fields
- `tokens` (`string`, optional): Document tokens (variables). Each should have name and value.
- `url` (`string`, optional): Document URL

Example input: `{"document_id":"<document_id>"}`

### `pandadocmcp_recipients_add_cc`

Recipients Add Cc · Write

Add a CC (non-signing) recipient to a document using an existing contact ID. Cannot add to expired or declined documents.

Read only: no. Destructive: no. Idempotent (safe to retry): yes.

Inputs:

- `contact_id` (`string`, required): Contact UUID to add as CC.
- `document_id` (`string`, required): Document UUID
- `kind` (`string`, optional): 'contact' or 'contact_group'. One of: `contact`, `contact_group`. Default: `contact`.

Example input: `{"contact_id":"<contact_id>","document_id":"<document_id>"}`

### `pandadocmcp_recipients_edit`

Recipients Edit · Write

Update a recipient's details such as email, name, phone, company, address, or redirect. A signer's email cannot be changed after they have signed.

Read only: no. Destructive: no. Idempotent (safe to retry): yes.

Inputs:

- `document_id` (`string`, required): Document UUID
- `recipient_id` (`string`, required): Recipient UUID from document details.
- `city` (`string`, optional): City.
- `company` (`string`, optional): Company name.
- `country` (`string`, optional): Country.
- `delivery_methods` (`string`, optional): Delivery methods (email/sms).
- `email` (`string`, optional): New email address.
- `first_name` (`string`, optional): First name.
- `job_title` (`string`, optional): Job title.
- `last_name` (`string`, optional): Last name.
- `phone` (`string`, optional): Phone number.
- `postal_code` (`string`, optional): Postal / ZIP code.
- `redirect` (`string`, optional): Post-signing redirect (is_enabled, url).
- `state` (`string`, optional): State or region.
- `street_address` (`string`, optional): Street address.

Example input: `{"document_id":"<document_id>","recipient_id":"<recipient_id>"}`

### `pandadocmcp_recipients_reassign`

Recipients Reassign · Write

Replace a signer with another contact, transferring all assigned fields to the new signer. Cannot reassign recipients who have already signed.

Read only: no. Destructive: no. Idempotent (safe to retry): no.

Inputs:

- `document_id` (`string`, required): Document UUID
- `new_contact_id` (`string`, required): Contact UUID of the new signer.
- `recipient_id` (`string`, required): Recipient UUID of the signer to replace.
- `kind` (`string`, optional): 'contact' or 'contact_group'. One of: `contact`, `contact_group`. Default: `contact`.

Example input: `{"document_id":"<document_id>","new_contact_id":"<new_contact_id>","recipient_id":"<recipient_id>"}`

### `pandadocmcp_templates_create`

Templates Create · Write

Create a new template from a publicly accessible PDF URL with optional name, folder, tokens, and owner.

Read only: no. Destructive: no. Idempotent (safe to retry): no.

Inputs:

- `url` (`string`, required): Secure (HTTPS) and publicly accessible URL to the PDF document
- `folder_uuid` (`string`, optional): Folder ID where the created template should be stored
- `metadata` (`string`, optional): Arbitrary key-value data to associate with the template
- `name` (`string`, optional): The name of the template
- `owner_email` (`string`, optional): Owner email for the template
- `owner_membership_id` (`string`, optional): Owner membership_id for the template
- `tokens` (`string`, optional): CUSTOM variables as list of {name, value} pairs

Example input: `{"url":"<url>"}`

### `pandadocmcp_documents_archive`

Documents Archive · Destructive

Archive a document by ID to remove it from active lists without permanently deleting it.

Read only: no. Destructive: yes. Idempotent (safe to retry): yes.

Inputs:

- `document_id` (`string`, required): Document ID to archive

Example input: `{"document_id":"<document_id>"}`

### `pandadocmcp_documents_status_change`

Documents Status Change · Destructive

Manually change a document's status. Only Completed, Paid, Expired, and Declined are settable; other statuses are managed automatically by PandaDoc.

Read only: no. Destructive: yes. Idempotent (safe to retry): no.

Inputs:

- `document_id` (`string`, required): Document ID
- `status` (`string`, required): Target status. Valid values: Completed, Paid, Expired, Declined.
- `note` (`string`, optional): Optional note for the status change
- `notify_recipients` (`boolean`, optional): Whether to notify recipients of the status change. Default: `false`.

Example input: `{"document_id":"<document_id>","status":"<status>"}`

### `pandadocmcp_recipients_delete`

Recipients Delete · Destructive

Remove a recipient from a document. Signers can only be removed while the document is in draft; CC recipients can be removed in any status except expired or declined.

Read only: no. Destructive: yes. Idempotent (safe to retry): yes.

Inputs:

- `document_id` (`string`, required): Document UUID
- `recipient_id` (`string`, required): Recipient UUID to remove.

Example input: `{"document_id":"<document_id>","recipient_id":"<recipient_id>"}`

## Related

Other Productivity connectors ([all 103](/agentkit/connectors/?category=productivity)):

- [Slack](/agentkit/connectors/slack/): Scalekit connector, OAuth, 96 tools
- [Microsoft 365](/agentkit/connectors/microsoft365/): Scalekit connector, OAuth, 317 tools
- [Notion](/agentkit/connectors/notion/): Scalekit connector, OAuth, 51 tools


---

## More Scalekit documentation

| Resource | What it contains | When to use it |
|----------|-----------------|----------------|
| [/llms.txt](/llms.txt) | Structured index with routing hints per product area | Start here — find which documentation set covers your topic before loading full content |
| [/llms-full.txt](/llms-full.txt) | Complete documentation for all Scalekit products in one file | Use when you need exhaustive context across multiple products or when the topic spans several areas |
| [sitemap-0.xml](https://docs.scalekit.com/sitemap-0.xml) | Full URL list of every documentation page | Use to discover specific page URLs you can fetch for targeted, page-level answers |
