Flowgrammer

PandaDoc E-Signature Automation

Verify PandaDoc webhooks with HMAC hex in the signature query parameter, Event-Id dedupe, and pdf_ready before you file.

— Craig Major

Verify a PandaDoc webhook on the exact raw POST body. Compute HMAC-SHA256 with the subscription shared value. Hex-encode the digest. Compare it to the signature query parameter. ACK any status below 400 inside 20 seconds, then queue PDF work. The published E-Signature Automation guide owns the shared Signing Control Plane. This page is the PandaDoc adapter: document id, X-PandaDoc-Webhook-Event-Id, JSON array payloads, and document_completed_pdf_ready before you file. The PandaDoc Webhook Verification Pack gives you fiction fixtures for those checks.

Start from the Signing Workflow Requirements Workbook if you still need the shared field list. If you already verify DocuSign Connect, keep the published DocuSign E-Signature Automation page for that raw-body HMAC and Base64 header. If you already acknowledge Dropbox Sign callbacks, keep the published Dropbox Sign E-Signature Automation page for that event_hash. If you already echo Acrobat Sign Application IDs, keep the published Adobe Acrobat Sign Automation page for that CLIENTID check. Those checks are not interchangeable. If the missing job is a named approve, reject, or request-changes decision, use the published Document Approval Workflow. PandaDoc Submit for approval is not that decision.

Who this is for

Use this when documents already go out through PandaDoc and the missing piece is a verified webhook listener. You need a named sender, one document family, and a place to keep SignatureEvidence. Confirm a public HTTPS URL, a webhook subscription in that workspace, and the shared value from the Developer Dashboard before you promise a listener to a team.

You do not need this page if you are still choosing a first workflow. Start with Document Processing Automation. You also do not need it if the job is an internal approve, reject, or request-changes decision. That job stays on the published Document Approval page.

The download includes:

  • HMAC hex tests against the signature query parameter
  • Raw-body versus re-serialized JSON
  • X-PandaDoc-Webhook-Event-Id replay cases
  • JSON array payloads with mixed event types
  • ACK below 400 versus an accidental 410
  • Three automatic retries and the seven-day soft-deactivate window
  • document_state_changed versus document_completed_pdf_ready versus recipient_completed
  • Download-protected 200 versus 202 Retry-After
  • SX01 through SX12 plus SX-PD-01 through SX-PD-10
  • A forbidden-downstream sheet

Brand search for PandaDoc is navigational. It does not prove workflow demand. This page survives on webhook depth. Later alternatives and later DocuSign versus PandaDoc pages are unfinished and are not linked.

What this adapter owns

The hub already defined send, remind, void, decline, complete, and download. It already named SignatureEvidence. It already blocked payment, bank-detail change, final accounting, auto-renew, and auto-terminate.

This page adds the PandaDoc surfaces:

  • Document data.id as signature_request_id
  • X-PandaDoc-Webhook-Event-Id as event_id
  • HMAC-SHA256 hex on the raw body versus the signature query parameter
  • Any HTTP status below 400 as the delivery ACK
  • A 20-second read timeout and a 5-second connection timeout
  • JSON array payloads that may carry more than one event
  • document_completed_pdf_ready as the filing signal

Do not clone the hub and swap the product name. Do not reuse the DocuSign Base64 header check. Do not reuse the Dropbox Sign ack string. Do not reuse Acrobat Sign CLIENTID echo. If a field is shared, keep the hub name. If a field is PandaDoc-only, say so.

Webhook verification

Official PandaDoc authenticity guidance, accessed 9 September 2026:

  1. Each delivery is a POST to your registered HTTPS URL.
  2. PandaDoc appends a signature query parameter. Official pages say that parameter is always sent.
  3. Compute HMAC-SHA256 over the exact raw HTTP body with the subscription shared value.
  4. Hex-encode the digest.
  5. Compare it to the query value with a timing-safe compare.
  6. On failure, return HTTP 403 and do not process the body.

The shared value lives on the webhook subscription in the Developer Dashboard. Treat it like a password. Official sample snippets show language-specific helpers. This page and the test pack use original fixtures and fiction values only.

Re-serializing JSON changes the body. Pretty-print, key reordering, and UTF-8 recoding are different bytes. SX03 and SX-PD-09 fail those paths.

Official verification documents the query parameter. Do not assume a header will be present. Prove the signature query value you actually received.

Acknowledgement and retries

Official setup and events guidance, accessed the same day:

  • Return any HTTP status below 400. Prefer 200.
  • Status 400 or higher, or a timeout, counts as failure.
  • HTTP 410 immediately deactivates the subscription. Reserve it for a permanent unsubscribe.
  • Connection timeout is 5 seconds. Read timeout is 20 seconds.
  • Heavy work must leave the request thread.

PandaDoc retries failed deliveries 3 times with exponential backoff. The Developer Dashboard can retry the same delivery by hand. This page does not invent a minute table.

If a subscription sees only unsuccessful deliveries for 7 days, it is soft-deactivated. One successful status below 400 in that window keeps it alive.

SX-PD-03 records a 21-second sync handler as ack_timeout. SX-PD-04 records the seven-day window. SX-PD-05 records an accidental 410 as a dead subscription.

Event identity

Official deduplication guidance: read X-PandaDoc-Webhook-Event-Id case-insensitively. The value is a UUID for that delivery. Automatic retries and Dashboard retries reuse the same id. Different event types from one document change get different ids.

Do not dedupe on document id alone. You will drop a sibling document_state_changed when you already stored document_updated.

If the header is missing, reject or quarantine the request. Do not process it as a normal delivery. SX-PD-08 covers a stripped header. SX02 and SX-PD-10 keep write_count at 1.

Array payloads

Official setup and events pages: the POST body is application/json and is an array. One delivery can carry more than one {event, data} item. Iterate every item. Verify the raw body once. Then walk the array.

SX-PD-01 sends document_state_changed and document_updated together. Each sibling type is processed once. Retries of the same Event-Id are ignored.

Timing honesty

Official events catalog, accessed 9 September 2026:

  • document_state_changed tracks status. It is not a promise that a completed PDF is stored.
  • document_completed_pdf_ready means a PDF was generated and saved. Use that event to download.
  • recipient_completed means one recipient finished. It does not mean the document is complete.

artifact_ready stays no until document_completed_pdf_ready arrives and the download you chose succeeds. SX07 waits on a state-changed complete. SX-PD-07 records recipient-only progress.

The events table also names a paid status as one possible document state. That vendor catalog line is not permission to pay a supplier from a webhook.

Download-protected retrieval

Official Download Protected Document guidance: the completed-file endpoint needs a Production API key. A Sandbox key returns 401. The same endpoint may return 202 with Retry-After when the file is not ready.

Official Production API key guidance: that key is an Enterprise plan category plus team activation. Confirm the screens you see. No seat prices appear here.

SX-PD-06 files only after a 200. A 202 stays pdf_not_ready_202.

Plan, admin, and limit classes

Official setup and events pages still document a maximum of 300 webhook subscriptions per workspace, accessed 9 September 2026. Subscriptions are workspace-scoped. Multiple workspaces need multiple subscriptions.

Official Limits pages publish per-user RPM categories, including a Download Protected Document category. Cite the category. Do not invent a finer quota or a seat price.

Webhook subscriptions can be created in the Developer Dashboard or through the API. Confirm which path your tenant actually has.

Approve-before-send wall

Official PandaDoc Help, accessed 9 September 2026, places a Submit for approval step on a template before Send document. Statuses include To approve, Approved, and Rejected. Conditional approvals are a Business add-on or Enterprise category.

That is a vendor-hosted pre-send gate. It is not Flowgrammer Document Approval DecisionEvidence. Recipient order is also not that decision.

SX11 and SX-PD-02 open the published Document Approval page when an org decision is still required.

Forbidden downstream

These writes stay blocked after a verified complete:

  • Payment
  • Supplier bank-detail change
  • Final accounting post
  • Auto-renew
  • Auto-terminate
  • A legal-validity conclusion as an automation outcome

Use invoice processing automation when money is the job. Use the contract tracker when renewal or termination is the job. Use intelligent document processing when extraction is the job.

Worked example

Fictional Cedar & Quay Fabrication Ltd sends DOC-CQ-SIGN-014 through PandaDoc.

  • Named sender: Jordan Hale
  • Signer: Morgan Reid
  • Human gate: Avery Chen
  • Fiction document: FICTION-CQ-PD-DOC-014
  • Fiction Event-Id: FICTION-CQ-PD-EVT-014
  • Shared document family: DOC-CQ-SIGN-014

The listener verifies the query signature on the raw array, ACKs 200 in under 20 seconds, and queues retrieval. It waits for document_completed_pdf_ready. Avery confirms the notify. SX09 tries to pay the supplier. The write is blocked.

Workflow

  1. Jordan confirms the template version and sends DOC-CQ-SIGN-014.
  2. If policy still needs an org decision, stop and use Document Approval before send.
  3. PandaDoc POSTs a JSON array to the HTTPS URL with a signature query value and an Event-Id header.
  4. The listener verifies HMAC hex on the raw body.
  5. The listener records the Event-Id, ACKs below 400, and queues work.
  6. On recipient_completed, store partial progress only.
  7. On document_completed_pdf_ready, retrieve with a Production key and handle 202.
  8. Write SignatureEvidence once. Avery decides the notify.

Decision table

Situation Automatic Review Human-only
Query signature matches raw body Verify pass Re-serialized body
Event-Id already stored Ignore second write
Work that needs the signed PDF Enqueue Sync download in the request
Status below 400 inside 20s ACK 410 on a timeout
recipient_completed only Partial progress File as final
document_completed_pdf_ready plus download 200 SignatureEvidence row Avery confirms notify or file Payment, bank, accounting, renew, terminate
Download 202 Wait / retry-after Sandbox key
Submit for approval Record the vendor gate Org DecisionEvidence

Human gates

A named person confirms the HTTPS URL, shared value, and workspace. A named person reviews HMAC failures, missing Event-Id, ack_timeout, subscription_deactivated, and pdf_not_ready_202. A named person decides any post-sign notify or file action.

Automation may ACK quickly and queue work. It may not invent a winner, legal validity, org approval, payment, bank-detail change, final accounting, auto-renew, or auto-terminate.

Failure paths

  • HMAC on parsed or pretty-printed JSON
  • Missing Event-Id header
  • Duplicate Event-Id written twice
  • Sync PDF work that exceeds 20 seconds
  • Accidental 410
  • Seven-day soft deactivate after only failed deliveries
  • Filing on document_state_changed or recipient_completed
  • Sandbox key on download-protected
  • Auto-pay or auto-renew
  • Submit for approval treated as DecisionEvidence

Test cases

Case Input Wrong outcome Acceptance
SX01 Verified pdf_ready plus download 200 No SignatureEvidence One row; ACK below 400
SX02 Replay of the same Event-Id Two writes write_count 1
SX03 Bad query signature Body processed HTTP 403; hmac_invalid
SX04 Decline payload Filed as signed Declined; no completed PDF
SX05 Void after partial Silent complete Voided
SX06 Stale template version Send proceeds Exception
SX07 State changed before pdf_ready Final PDF filed Wait
SX08 Unexpected workspace Write Exception
SX09 Auto-pay on complete Payment write Blocked
SX10 Auto-renew on complete Renewal write Blocked
SX11 Org approval still open Sign treated as SoR Link Document Approval
SX12 Sequential versus parallel recipients Surprise free-form Record routing_policy
SX-PD-01 Mixed array events Sibling type dropped Each Event-Id once
SX-PD-02 Submit for approval DecisionEvidence Vendor gate only
SX-PD-03 Sync work at 21 seconds Treated as live ack_timeout
SX-PD-04 Seven days of failures Assumed still live Soft-deactivate note
SX-PD-05 Accidental 410 Transient retry Subscription dead
SX-PD-06 pdf_ready then 202 File anyway Wait
SX-PD-07 recipient_completed alone Document complete Partial only
SX-PD-08 Missing Event-Id Processed Reject or quarantine
SX-PD-09 Re-serialized JSON HMAC pass Fail
SX-PD-10 Dashboard Retry Second write write_count 1

What to measure

Record verified deliveries, HMAC failures, Event-Id replays, 410 traps, pdf_ready waits, and blocked downstream attempts. Keep those as definitions. Do not invent a benchmark, accuracy rate, or ROI figure.

There is no live production PandaDoc metric here, and no Flowgrammer customer signing case.

How to use the pack

Download the PandaDoc Webhook Verification Pack. It is an original pack, not a Marketplace listing.

  1. Read README.md, then markdown/setup.md.
  2. Walk csv/hmac-query-tests.csv. Raw body passes. Re-serialized JSON fails.
  3. Walk csv/idempotency-table.csv. Replay stays at write_count 1.
  4. Confirm ACK below 400 and a 21-second sync handler fails.
  5. Walk SX01 through SX12, then SX-PD-01 through SX-PD-10.
  6. Keep markdown/forbidden-downstream.md next to any post-sign handoff.

The useful rules also sit on this page so the download is not the only answer.

Realistic limitations

  • This page designs PandaDoc signing control. It does not certify legal validity in any jurisdiction.
  • Shared values, API webhooks, Production keys, and approve-before-send can be plan-gated or admin-gated. Confirm the screens you see. No seat prices appear here.
  • Official pages still document 300 subscriptions per workspace. Recheck that ceiling if your tenant shows a different limit.
  • Exact automatic retry intervals are not published here.
  • This system does not approve a document for the organization, extract fields, pay anyone, or change supplier bank details.
  • This guide does not rank vendors and is not a pricing page.
  • Later alternatives and DocuSign versus PandaDoc pages are unfinished and are not linked.
  • This page is operational guidance, not legal advice and not a compliance certification.

Next step

Download the PandaDoc Webhook Verification Pack for HMAC vectors, Event-Id cases, and the twenty-two fixtures.

Keep the published E-Signature Automation hub nearby for the shared model. Keep the Document Approval Status and Role Matrix nearby when an org decision is required.

If webhook enablement, shared values, or the event log are still unclear, start with an AI Success Audit. If those pieces are already named, book a fit call to scope an AI Automation Systems build.

Sources

Frequently asked questions

What is PandaDoc workflow automation on this page?

It is a named send, query-signature HMAC check, ACK-then-queue path, Event-Id honesty, and a SignatureEvidence write after `document_completed_pdf_ready`. It is not a generic document-processing pillar.

Is PandaDoc approval workflow the same as Document Approval?

No. Submit for approval is a vendor-hosted pre-send gate. Use the published [Document Approval Workflow](/insights/document-approval-workflow) when an org decision is required.

Do I HMAC the parsed JSON?

No. Official authenticity guidance uses the raw HTTP body. Pretty-printed or re-encoded JSON is a different body.

Is a completed document the same as a downloadable PDF?

No. Wait for `document_completed_pdf_ready`, then retrieve. `recipient_completed` is one signer, not the document.

Does this page cover DocuSign, Dropbox Sign, or Adobe Acrobat Sign?

Those published adapters are live and use different checks. Keep each vendor page for its listener. This page does not score them.

Does document completion renew a contract or pay a supplier?

No. Those writes stay blocked. Use the [contract tracker](/insights/contract-tracker) or [invoice processing automation](/insights/invoice-processing-automation).