Skip to main content
Set up webhook endpoints to receive real-time notifications about document events in your Documenso workspace.

Prerequisites

  • A publicly accessible HTTPS endpoint to receive webhook requests
  • Team owner or admin role in Documenso
  • Access to the team settings page

Creating a webhook

1

Navigate to team settings

Go to your team settings and select the Webhooks tab.Webhooks settings page
2

Create a new webhook

Click Create Webhook to open the webhook configuration dialog.Create webhook dialog
3

Configure webhook settings

Fill in the webhook configuration:
  • Webhook URL: Your endpoint URL (must be publicly accessible)
  • Secret: Optional shared secret for signature verification
  • Event Triggers: Select which events to subscribe to
  • Enabled: Toggle to enable/disable the webhook
Example configuration:
{
  "webhookUrl": "https://your-app.com/webhooks/documenso",
  "secret": "your-secret-key",
  "eventTriggers": [
    "DOCUMENT_SIGNED",
    "DOCUMENT_COMPLETED"
  ],
  "enabled": true
}
4

Test your webhook

After creating the webhook, use the Test button to send a sample payload.Test webhook triggerThis helps verify your endpoint is configured correctly before real events occur.

Webhook endpoint requirements

Your webhook endpoint must:
  • Accept POST requests with JSON payload
  • Return a 2xx status code for successful delivery
  • Respond within 30 seconds
  • Handle duplicate deliveries (implement idempotency)
Endpoints that consistently fail or timeout may be automatically disabled to prevent performance issues.

Example endpoint implementation

const express = require('express');
const app = express();

app.post('/webhooks/documenso', express.json(), async (req, res) => {
  const { event, payload, createdAt } = req.body;
  const secret = req.headers['x-documenso-secret'];

  // Verify secret (see Security page for full implementation)
  if (secret !== process.env.DOCUMENSO_WEBHOOK_SECRET) {
    return res.status(401).json({ error: 'Invalid secret' });
  }

  // Process the webhook event
  console.log(`Received ${event} event for document ${payload.id}`);

  try {
    // Handle different event types
    switch (event) {
      case 'DOCUMENT_COMPLETED':
        await handleDocumentCompleted(payload);
        break;
      case 'DOCUMENT_SIGNED':
        await handleDocumentSigned(payload);
        break;
      default:
        console.log(`Unhandled event type: ${event}`);
    }

    // Always return 200 for successful processing
    res.status(200).json({ received: true });
  } catch (error) {
    console.error('Webhook processing error:', error);
    res.status(500).json({ error: 'Processing failed' });
  }
});

app.listen(3000);

Managing webhooks

View webhook details

Click on any webhook to view its configuration, event history, and recent calls. Webhook detail page

View webhook call logs

Each webhook call is logged with:
  • Request timestamp
  • Event type
  • HTTP status code
  • Response body and headers
  • Request payload
Webhook call logs
Use webhook logs to debug delivery issues and inspect the exact payload sent for each event.

Manually retry webhooks

If a webhook delivery fails, you can manually retry it from the webhook call details page. This resends the exact same payload to your endpoint.

Edit webhook configuration

You can update webhook settings at any time:
  • Change the webhook URL
  • Update the secret
  • Add or remove event subscriptions
  • Enable or disable the webhook

Delete a webhook

Deleting a webhook immediately stops all event deliveries. This action cannot be undone.

Testing webhooks locally

For local development, use tools like ngrok or localtunnel to expose your local server to the internet.
1

Start your local server

Run your webhook endpoint locally:
node server.js
# or
python app.py
2

Expose your local server

Use ngrok to create a public URL:
ngrok http 3000
Copy the HTTPS forwarding URL (e.g., https://abc123.ngrok.io).
3

Configure webhook in Documenso

Use the ngrok URL as your webhook URL:
https://abc123.ngrok.io/webhooks/documenso
4

Test the webhook

Trigger events in Documenso or use the test button to verify your local endpoint receives webhooks.

Best practices

Respond with a 200 status code as soon as you receive the webhook. Process the event asynchronously to avoid timeouts.
app.post('/webhooks/documenso', async (req, res) => {
  // Immediately acknowledge receipt
  res.status(200).json({ received: true });
  
  // Process asynchronously
  processWebhookAsync(req.body).catch(console.error);
});
Store processed webhook IDs to avoid processing the same event twice:
const processedWebhooks = new Set();

app.post('/webhooks/documenso', async (req, res) => {
  const webhookId = req.body.payload.id + req.body.createdAt;
  
  if (processedWebhooks.has(webhookId)) {
    return res.status(200).json({ received: true, duplicate: true });
  }
  
  processedWebhooks.add(webhookId);
  // Process webhook...
});
Keep detailed logs of webhook receipts and processing for debugging:
console.log({
  timestamp: new Date().toISOString(),
  event: req.body.event,
  documentId: req.body.payload.id,
  status: 'received'
});
Never hardcode webhook secrets in your code:
const WEBHOOK_SECRET = process.env.DOCUMENSO_WEBHOOK_SECRET;

if (!WEBHOOK_SECRET) {
  throw new Error('DOCUMENSO_WEBHOOK_SECRET not configured');
}

Next steps

Event reference

Explore all available events and their payloads

Security

Implement webhook signature verification

Build docs developers (and LLMs) love