Webhooks Guide
Get real-time notifications when documents are generated.
What are Webhooks?
Webhooks are HTTP callbacks that DocGenLab sends to your server when a document generation completes. Perfect for:
- Asynchronous workflows
- Integration with other systems
- Real-time notifications
- Event-driven architectures
How Webhooks Work

Setting Up Webhooks
Configure Organization Webhook
- Navigate to Settings → Developer
- Enter your webhook URL (e.g.,
https://your-app.com/webhooks/docgenlab) - Click Test Webhook to verify
- Click Save Webhook URL
Use a tool like webhook.site to test and inspect webhook payloads during development.
Webhook Payload
When a document completes, DocGenLab sends a POST request:
{
"event": "document.generated",
"job_id": "abc-123-def-456",
"status": "completed",
"download_url": "https://storage.googleapis.com/...",
"metadata": {
"template_id": "template-xyz",
"created_at": "2024-01-15T10:30:00Z",
"error_message": null
}
}
Download URL
The download_url is a signed URL that:
- Is valid for 24 hours
- Allows direct download without authentication
- Bypasses API rate limits
Implementing a Webhook Handler
Python (Flask)
from flask import Flask, request, jsonify
import requests
app = Flask(__name__)
@app.route('/webhooks/docgenlab', methods=['POST'])
def handle_webhook():
payload = request.json
if payload['status'] == 'completed':
# Download the document
doc_url = payload['download_url']
response = requests.get(doc_url)
# Save or process the file
with open(f"document_{payload['job_id']}.pdf", 'wb') as f:
f.write(response.content)
# Send notification, update database, etc.
print(f"Document {payload['job_id']} ready!")
return jsonify({'status': 'ok'}), 200
Node.js (Express)
const express = require('express');
const axios = require('axios');
const fs = require('fs');
const app = express();
app.use(express.json());
app.post('/webhooks/docgenlab', async (req, res) => {
const payload = req.body;
if (payload.status === 'completed') {
// Download the document
const response = await axios.get(payload.download_url, {
responseType: 'arraybuffer'
});
// Save the file
fs.writeFileSync(`document_${payload.job_id}.pdf`, response.data);
console.log(`Document ${payload.job_id} ready!`);
}
res.status(200).json({ status: 'ok' });
});
app.listen(3000);
Best Practices
Security
1. Validate the Webhook
Always validate that the webhook came from DocGenLab:
# Option 1: IP Whitelist
DOCGENLAB_IPS = ['34.123.45.67']
if request.remote_addr not in DOCGENLAB_IPS:
return jsonify({'error': 'unauthorized'}), 403
2. Use HTTPS
Always use HTTPS endpoints:
- Correct:
https://your-app.com/webhooks/docgenlab - Incorrect:
http://your-app.com/webhooks/docgenlab
Reliability
1. Return 200 Quickly
Process webhooks asynchronously:
@app.route('/webhooks/docgenlab', methods=['POST'])
def handle_webhook():
payload = request.json
# Queue for background processing
queue.enqueue(process_document, payload)
# Return immediately
return jsonify({'status': 'ok'}), 200
def process_document(payload):
# Download and process in background
pass
2. Handle Retries
DocGenLab retries failed webhooks:
- 1st retry: after 1 minute
- 2nd retry: after 5 minutes
- 3rd retry: after 15 minutes
Make your endpoint idempotent (safe to call multiple times):
def handle_webhook():
payload = request.json
job_id = payload['job_id']
# Check if already processed
if redis.exists(f'processed:{job_id}'):
return jsonify({'status': 'already_processed'}), 200
# Process...
# Mark as processed
redis.set(f'processed:{job_id}', 1, ex=86400)
return jsonify({'status': 'ok'}), 200
Testing Webhooks
Test Button
Use the Test Webhook button in Settings to send a test payload:
{
"event": "webhook.test",
"message": "This is a test webhook from DocGenLab"
}
Local Development
Use ngrok to expose your local server:
ngrok http 3000
# Use the ngrok URL in DocGenLab settings
# Example: https://abc123.ngrok.io/webhooks/docgenlab
FAQ
Q: When are webhooks triggered?
Only for API-generated documents, not UI-generated. This prevents unnecessary webhook calls during manual testing.
Q: What if my webhook endpoint is down?
DocGenLab retries up to 3 times. After that, the webhook is dropped (but the document is still available via API).
Q: Can I use different webhooks for different templates?
Yes! Pass webhook_url in the API request to override the org-level setting (coming soon).