{
  "schema": "aaes/capability-pack/1",
  "provider": "pandadoc",
  "version": "1.0.0",
  "description": "Read PandaDoc documents, templates, and contacts; create documents from templates or uploaded files, and send draft documents for signature. Sending can email recipients a signing link.",
  "notes": "Every capability in this pack targets PandaDoc's real shared API host api.pandadoc.com, so no host substitution is required; the only placeholder is DOCUMENT_ID in the send path, an UPPERCASE path segment the deployment binds to a concrete document before enabling. This pack registers only endpoints verified against the official PandaDoc API reference at developers.pandadoc.com: listing documents, listing templates, listing contacts, creating a document, and sending a document.\n\nAll reads are collection reads only — single-record paths (document details, template details, contact details) are not registered. Consequential effects: PandaDoc documents that sending a document emails the recipients a link to view and sign it, so document send is declared send at the minimum R3 tier — send is one of the designated actions requiring human approval, a sent document cannot be recalled after delivery.\n\nOn supported AAES-mediated execution paths, irreversible actions require approval by an authorized person; this does not prevent calls through bypass or observation-only paths. Document creation is declared create at the minimum R2 tier: it brings a new document into existence but does not itself notify recipients — PandaDoc documents that a created document sits in document.uploaded and then document.draft status until a separate send call.\n\nDocumented exclusions, framed as what this pack does not register: document update and document status change (PATCH, including voiding a sent document), document delete and bulk delete, document download and export, document recipient/field/section/attachment management, manual reminders (a further send surface), document ownership update and transfer-all-ownership (a transfer effect), template creation/update/duplication/deletion, content library items, forms, contact create/update/delete, catalog items and quotes, notary requests, webhook subscriptions, workspace/user/member administration, and API-key creation.\n\nAuthentication: PandaDoc documents two methods, an Authorization: 'API-Key <key>' header (documented as legacy, maintained for backwards compatibility) and OAuth 2.0 bearer tokens (documented as recommended for all new integrations); see the credential note for what the stored value must be. This pack registers the OAuth method only: the reviewed documentation does not establish the legacy API key's issuance, expiry or revocation contract, so that credential option was removed (see the credential note).\n\nCredential review completed on 2026-09-21 for an OAuth access token held in the customer's vault and refreshed by an external process. The requirements and limits are below.\n\nIssuance authority and delegation: tokens are minted by PandaDoc's OAuth server through the authorization-code flow — the authorization code is one-time-use — and PandaDoc documents OAuth 2.0 as the recommended authentication method for all new integrations, with the 'API-Key' header a legacy method whose issuance, expiry and revocation contract the reviewed documentation does not establish.\n\nScope: PandaDoc documents two scopes, 'read' (view templates and document details) and 'write' (create, send, delete and download documents), with 'read+write' deprecated in favor of 'read write'; this pack needs 'read write' when the create and send capabilities are enabled, and 'write' also authorizes document deletion, which this pack excludes — a limitation of the vendor's scope model.\n\nAudience: no audience mechanism is documented — the bearer value authorizes against api.pandadoc.com, and audience binding beyond that is not established. TTL: the access token's expires_in is 31,535,999 seconds (one year) as currently documented — read expires_in rather than hard-coding a duration — and an expired token returns 401.\n\nRefresh ownership: the client secret stays with the external process, which owns minting and refresh (the stored refresh_token is exchanged at POST /oauth2/access_token with grant_type=refresh_token) and writes the fresh header value into the vault; the executor injects the stored value verbatim and performs no token lifecycle itself, and a stale value fails closed.\n\nRevocation: the retrieved reference documents no token-revocation endpoint and no refresh-token rotation or lifetime semantics — the completed review documents this gap: the cut-off path is an account-side administrative action the deployment must confirm with PandaDoc, and this pack makes no stronger claim.\n\nExecutor access and replay/exposure: the executor reads only the vault reference; the token is a bearer credential replayable for up to its documented one-year TTL with no vendor revocation endpoint — so vault-only storage and the executor hygiene bar are the controlling mitigations.\n\nAlternate access paths: the PandaDoc web app and any legacy API-Key integrations retain access outside this pack, and ending this integration's access closes only this path. The credential review is complete. Assign accountable owners before deployment.",
  "credential": {
    "secret_ref_id": "secret-ref-pandadoc-api-credential",
    "custody": "customer_vault",
    "inject": "header",
    "inject_name": "Authorization",
    "note": "A PandaDoc OAuth 2.0 access token, held in the client's own secret manager. The stored material must be the complete Authorization header value: the scheme 'Bearer', one separating space, then the access token — 'Bearer <access_token>'. PandaDoc documents OAuth 2.0 as the recommended authentication method for all new integrations and the 'API-Key' header as a legacy method maintained for backwards compatibility with existing integrations.\n\nThis pack registers only the OAuth credential: the official documentation retrieved for this review does not establish the API key's issuance, expiry or revocation contract, so the API-key option was removed rather than registered on an unresolved custody model — a deployment that wants the legacy key must complete that review itself. customer_vault is the only generally-supported production custody model here — identity_federation and customer_broker are refused at startup and inline is lab-only.\n\nToken lifecycle, per PandaDoc's Create/Refresh Access Token reference: the authorization code is one-time-use; the access token's expires_in is 31,535,999 seconds (one year) as currently documented — read expires_in rather than hard-coding a duration — and an expired token returns 401; the stored refresh_token is then exchanged for a new access token at POST /oauth2/access_token with grant_type=refresh_token.\n\nThe client secret stays with the external process, which must own minting and refresh and write the fresh header value into the vault — the executor injects the stored value verbatim and performs no token lifecycle itself, and a stale value fails closed.\n\nThe retrieved reference documents no token-revocation endpoint and no refresh-token rotation or lifetime semantics, so the completed custody review documents revocation and refresh-token expiry as unresolved vendor-side properties: the cut-off path is an account-side administrative action the deployment must confirm with PandaDoc, and this pack makes no stronger claim.\n\nLeast privilege: PandaDoc documents two scopes, 'read' (view templates and document details) and 'write' (create, send, delete and download documents), and documents 'read+write' as deprecated in favor of 'read write'. This pack needs 'read write' when the create and send capabilities are enabled — note that 'write' also authorizes document deletion, which this pack excludes; that residual breadth is a documented trade-off of the vendor's scope model, not an oversight.\n\nExecutor hygiene: the value must live only in executor memory for the lifetime of a call, must never be written to logs, traces or diagnostics, and must not appear in crash dumps; a deployment that cannot meet that bar must not enable the pack."
  },
  "capabilities": [
    {
      "capability_id": "pandadoc.documents.read",
      "version": "1.0.0",
      "kind": "tool",
      "risk_tier": "R0",
      "owner": "REPLACE-WITH-ACCOUNTABLE-HUMAN",
      "data_class": "pii",
      "egress_allowlist": [
        "api.pandadoc.com"
      ],
      "endpoint": "https://api.pandadoc.com/public/v1/documents",
      "method": "GET",
      "connector": "http",
      "custody": "customer_vault",
      "secret_ref_id": "secret-ref-pandadoc-api-credential",
      "inject": "header",
      "inject_name": "Authorization",
      "actions": [
        "read"
      ],
      "resource_id": "pandadoc-documents",
      "description": "List and search documents in the workspace: document names, statuses, recipients and metadata, which identify named individuals, so the read is classified as pii (personal data). The registered path covers the collection read only — single-document reads (GET /public/v1/documents/{id}/details) are not registered by this pack.",
      "requires_review": true
    },
    {
      "capability_id": "pandadoc.templates.read",
      "version": "1.0.0",
      "kind": "tool",
      "risk_tier": "R0",
      "owner": "REPLACE-WITH-ACCOUNTABLE-HUMAN",
      "data_class": "internal",
      "egress_allowlist": [
        "api.pandadoc.com"
      ],
      "endpoint": "https://api.pandadoc.com/public/v1/templates",
      "method": "GET",
      "connector": "http",
      "custody": "customer_vault",
      "secret_ref_id": "secret-ref-pandadoc-api-credential",
      "inject": "header",
      "inject_name": "Authorization",
      "actions": [
        "read"
      ],
      "resource_id": "pandadoc-templates",
      "description": "List templates in the workspace: template names, tags and versioning, which are internal authoring material. The registered path covers the collection read only — single-template reads (template details) are not registered by this pack.",
      "requires_review": true
    },
    {
      "capability_id": "pandadoc.contacts.read",
      "version": "1.0.0",
      "kind": "tool",
      "risk_tier": "R0",
      "owner": "REPLACE-WITH-ACCOUNTABLE-HUMAN",
      "data_class": "pii",
      "egress_allowlist": [
        "api.pandadoc.com"
      ],
      "endpoint": "https://api.pandadoc.com/public/v1/contacts",
      "method": "GET",
      "connector": "http",
      "custody": "customer_vault",
      "secret_ref_id": "secret-ref-pandadoc-api-credential",
      "inject": "header",
      "inject_name": "Authorization",
      "actions": [
        "read"
      ],
      "resource_id": "pandadoc-contacts",
      "description": "List the contacts associated with the workspace: names, emails and company details of counterparties, which are personal data. The registered path covers the collection read only — single-contact reads (contact details) are not registered by this pack.",
      "requires_review": true
    },
    {
      "capability_id": "pandadoc.documents.create",
      "version": "1.0.0",
      "kind": "tool",
      "risk_tier": "R2",
      "owner": "REPLACE-WITH-ACCOUNTABLE-HUMAN",
      "data_class": "pii",
      "egress_allowlist": [
        "api.pandadoc.com"
      ],
      "endpoint": "https://api.pandadoc.com/public/v1/documents",
      "method": "POST",
      "connector": "http",
      "custody": "customer_vault",
      "secret_ref_id": "secret-ref-pandadoc-api-credential",
      "inject": "header",
      "inject_name": "Authorization",
      "actions": [
        "create"
      ],
      "resource_id": "pandadoc-documents",
      "description": "Create a document from a template or an uploaded file, naming recipients and pre-filling fields — recipient names and emails are personal data. Declared create at the minimum R2 tier: creation brings a new document into existence, and PandaDoc documents that a created document remains in document.uploaded then document.draft status and is not delivered to anyone until the separate send endpoint is called, so creation alone is not a send.",
      "requires_review": true
    },
    {
      "capability_id": "pandadoc.documents.send",
      "version": "1.0.0",
      "kind": "tool",
      "risk_tier": "R3",
      "owner": "REPLACE-WITH-ACCOUNTABLE-HUMAN",
      "data_class": "pii",
      "egress_allowlist": [
        "api.pandadoc.com"
      ],
      "endpoint": "https://api.pandadoc.com/public/v1/documents/DOCUMENT_ID/send",
      "method": "POST",
      "connector": "http",
      "custody": "customer_vault",
      "secret_ref_id": "secret-ref-pandadoc-api-credential",
      "inject": "header",
      "inject_name": "Authorization",
      "actions": [
        "send"
      ],
      "resource_id": "pandadoc-documents",
      "description": "Send an existing draft document to its recipients. This operation sends a document that was created earlier (by this pack's create capability or otherwise); it does not create another document, so the declared action is send alone, at the minimum R3 tier.\n\nPandaDoc documents that the send emails each recipient a link to view and sign the document (unless the silent parameter suppresses notifications for an alternative delivery channel), so the documented effect is transmission outside AAES's control — send is one of the designated actions requiring human approval and a sent document cannot be recalled after delivery.\n\nPandaDoc documents that only a document in document.draft status can be sent. DOCUMENT_ID is a placeholder the deployment binds to a concrete document before enabling.",
      "requires_review": true
    }
  ],
  "resources": [
    {
      "resource_id": "pandadoc-documents",
      "kind": "api",
      "locator": "https://api.pandadoc.com/public/v1/documents",
      "data_class": "pii",
      "owner": "REPLACE-WITH-ACCOUNTABLE-HUMAN"
    },
    {
      "resource_id": "pandadoc-templates",
      "kind": "api",
      "locator": "https://api.pandadoc.com/public/v1/templates",
      "data_class": "internal",
      "owner": "REPLACE-WITH-ACCOUNTABLE-HUMAN"
    },
    {
      "resource_id": "pandadoc-contacts",
      "kind": "api",
      "locator": "https://api.pandadoc.com/public/v1/contacts",
      "data_class": "pii",
      "owner": "REPLACE-WITH-ACCOUNTABLE-HUMAN"
    }
  ],
  "review": {
    "state": "library",
    "date": "2026-09-22",
    "sources": [
      "https://developers.pandadoc.com/reference/list-documents (retrieved 2026-09-21)",
      "https://developers.pandadoc.com/reference/list-templates (retrieved 2026-09-21)",
      "https://developers.pandadoc.com/reference/list-contacts (retrieved 2026-09-21)",
      "https://developers.pandadoc.com/reference/create-document (retrieved 2026-09-21)",
      "https://developers.pandadoc.com/reference/send-document (retrieved 2026-09-21)",
      "https://developers.pandadoc.com/docs/send-document (retrieved 2026-09-21)",
      "https://developers.pandadoc.com/reference/authentication (retrieved 2026-09-21)",
      "https://developers.pandadoc.com/reference/access-token (retrieved 2026-09-21)"
    ],
    "reviewer_id": "aaes-eng"
  }
}
