Skip to content
ParseFlow

Webhook Documentation

Receive real-time HTTP notifications when events happen in your ParseFlow account. Webhooks eliminate the need for polling and enable event-driven workflows.

Overview

Webhooks send HTTP POST requests to your specified URL when events occur. This is ideal for:

  • Triggering downstream workflows when documents are processed
  • Receiving batch completion notifications
  • Monitoring quota usage in real-time
  • Building event-driven integrations with tools like Zapier or n8n

Plan requirement: Webhooks are available on Pro and Enterprise plans. Upgrade your plan to get started.

Setup

Register a webhook endpoint using the API:

curl -X POST https://parseflow.dev/api/webhooks/notifications \
  -H "X-API-Key: dm_live_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://your-app.com/webhooks/parseflow",
    "events": ["extraction.completed", "extraction.failed"]
  }'

Response

{
  "id": "wh_a1b2c3d4e5f6g7h8",
  "url": "https://your-app.com/webhooks/parseflow",
  "events": ["extraction.completed", "extraction.failed"],
  "secret": "whsec_AbCdEfGhIjKlMnOpQrStUvWxYz123456",
  "isActive": true,
  "createdAt": "2026-04-14T10:00:00Z"
}

Save the secret securely — it is only shown once and is used to verify webhook signatures.

Events

Subscribe to one or more of these event types:

EventDescription
extraction.completedFired when a single document extraction finishes successfully.
extraction.failedFired when a document extraction fails (corrupt file, unsupported format).
batch.completedFired when all documents in a batch have been processed.
batch.failedFired when a batch processing job fails.
quota.warningFired when usage reaches 80% of monthly quota.
quota.exceededFired when monthly quota is exceeded.

Payload Format

Every webhook sends a JSON POST request with this structure:

{
  "event": "extraction.completed",
  "timestamp": "2026-04-14T10:05:00Z",
  "data": {
    "id": "ext_7f3a2b1c-4d5e-6f78-9a0b-cdef12345678",
    "status": "completed",
    "documentType": "invoice",
    "confidence": 0.94,
    "data": { ... },
    "metadata": {
      "fileName": "invoice.pdf",
      "fileSize": 145230,
      "mimeType": "application/pdf"
    },
    "processingTimeMs": 1240
  }
}

Headers

HeaderDescription
Content-Typeapplication/json
X-ParseFlow-SignatureHMAC-SHA256 signature of the request body
X-ParseFlow-EventThe event type (e.g., extraction.completed)
X-ParseFlow-DeliveryUnique delivery ID for deduplication

Verification

Always verify webhook signatures to ensure requests are from ParseFlow. Compute an HMAC-SHA256 of the raw request body using your webhook secret:

// Node.js verification example
const crypto = require('crypto');

function verifyWebhook(body, signature, secret) {
  const expected = crypto
    .createHmac('sha256', secret)
    .update(body, 'utf8')
    .digest('hex');
  return crypto.timingSafeEqual(
    Buffer.from(signature),
    Buffer.from(expected)
  );
}

// In your webhook handler:
app.post('/webhooks/parseflow', (req, res) => {
  const signature = req.headers['x-parseflow-signature'];
  const isValid = verifyWebhook(
    JSON.stringify(req.body),
    signature,
    'whsec_your_webhook_secret'
  );

  if (!isValid) {
    return res.status(401).json({ error: 'Invalid signature' });
  }

  // Process the webhook event
  const { event, data } = req.body;
  console.log(`Received: ${event}`);

  res.status(200).json({ received: true });
});

Retry Policy

If your endpoint returns a non-2xx status code, ParseFlow retries with exponential backoff:

AttemptDelay
1st retry30 seconds
2nd retry2 minutes
3rd retry15 minutes
4th retry1 hour
5th retry (final)4 hours

After 5 failed attempts, the webhook is marked as failing. It will be automatically disabled after 3 consecutive days of failures.

Managing Webhooks

List Webhooks

curl https://parseflow.dev/api/webhooks/notifications \
  -H "X-API-Key: dm_live_your_api_key"

Delete a Webhook

curl -X DELETE "https://parseflow.dev/api/webhooks/notifications?id=wh_a1b2c3d4e5f6g7h8" \
  -H "X-API-Key: dm_live_your_api_key"

Example Integration

Complete Python example using Flask to receive and process webhook events:

import hmac
import hashlib
from flask import Flask, request, jsonify

app = Flask(__name__)
WEBHOOK_SECRET = "whsec_your_webhook_secret"

@app.route('/webhooks/parseflow', methods=['POST'])
def handle_webhook():
    # 1. Verify signature
    signature = request.headers.get('X-ParseFlow-Signature', '')
    expected = hmac.new(
        WEBHOOK_SECRET.encode(),
        request.data,
        hashlib.sha256
    ).hexdigest()

    if not hmac.compare_digest(signature, expected):
        return jsonify({"error": "Invalid signature"}), 401

    # 2. Process event
    payload = request.json
    event = payload['event']

    if event == 'extraction.completed':
        doc_id = payload['data']['id']
        doc_type = payload['data']['documentType']
        # Save to your database, trigger next step, etc.
        print(f"Extraction complete: {doc_id} ({doc_type})")

    elif event == 'quota.warning':
        # Send alert to team
        print("Quota warning: 80% usage reached")

    return jsonify({"received": True}), 200