Webhooks

    Webhooks let you receive real-time HTTP notifications whenever important events happen in your deals — files uploaded, request statuses changed, team members added, and more. Use them to integrate Vetting Vault with your existing tools and automate deal workflows.

    Paid feature

    Webhooks require an active Vetting Vault subscription. Only deal creators and admins who subscribe can create webhook endpoints. All deal contributors continue to generate events that trigger webhooks — only the endpoint management requires a subscription.

    Overview

    Instead of polling the platform for changes, webhooks push event data to your server the moment something happens. This is useful for a wide range of integrations:

    • CRM updates — Automatically update your CRM when a deal request status changes or a new file is uploaded.
    • Slack or Teams notifications — Post a message to a channel whenever a team member is added or a question is answered.
    • Compliance logging — Stream all deal activity to an external audit system for regulatory recordkeeping.
    • Custom dashboards — Feed live deal progress data into your own reporting tools.
    • Workflow automation — Trigger downstream processes (approvals, checklists, notifications) in tools like Zapier, Make, or your own backend.

    Vetting Vault follows the Standard Webhooks specification for signing and delivery, so if your team has worked with webhooks from Stripe, GitHub, or similar platforms, the patterns will be familiar.

    Creating a Webhook Endpoint

    To start receiving webhook events, create an endpoint in your account settings under the Webhooks section. You will need to provide:

    1. URL — The HTTPS URL where Vetting Vault will POST event payloads.
    2. Description (optional) — A human-readable label to help you identify the endpoint (e.g., “Production CRM sync” or “Slack deal alerts”).
    3. Event types — Choose which event types this endpoint should receive. You can select specific types or leave it open to receive all events.
    4. Deal subscriptions — Select which deals should send events to this endpoint. You must have owner or admin access to a deal to subscribe it.

    Once created, the endpoint is active immediately and will begin receiving events for the deals and event types you selected.

    Endpoint URL Requirements

    Your endpoint URL must meet the following requirements:

    • Must use HTTPS (HTTP is not accepted)
    • Must be publicly reachable from the internet
    • Must not resolve to a private or internal IP address (SSRF protection)
    • Must respond within 30 seconds
    • Must return a 2xx status code to acknowledge receipt

    Signing Secret

    When you create a webhook endpoint, Vetting Vault generates a unique signing secret. This secret is displayed once at creation time — copy it immediately and store it securely. The secret is used to verify that incoming webhook payloads genuinely originated from Vetting Vault and have not been tampered with.

    Signing secrets use the whsec_ prefix followed by a base64-encoded key, for example: whsec_MfKQ9r8GKYqrTwjUPD8ILPZIo2LaLaSw.

    Save your secret immediately

    The signing secret is only shown once when the endpoint is created. If you lose it, you will need to rotate the secret, which generates a new one and invalidates the old one. See the Rotating Secrets section below.

    Event Types

    Vetting Vault emits events across every major area of deal activity. Each event type follows a resource.action naming convention. You can filter which types each endpoint receives, or subscribe to all of them.

    Deal Events

    Event TypeDescription
    deal.updatedDeal settings changed (name, description, etc.)
    deal.lockedDeal locked or unlocked
    deal.archivedDeal archived

    Team Events

    Event TypeDescription
    team_member.addedMember added to the deal
    team_member.removedMember removed from the deal
    team_member.role_changedMember’s role changed

    Project & Section Events

    Event TypeDescription
    project.createdNew project created
    project.updatedProject updated
    project.deletedProject deleted
    section.createdNew section created within a project
    section.updatedSection updated

    Request Events

    Event TypeDescription
    request.createdNew file request or question created
    request.status_changedRequest status updated (e.g., submitted, approved, to discuss)
    request.assignedRequest assigned to a team member
    request.updatedRequest details changed

    File Events

    Event TypeDescription
    file.uploadedFile uploaded to a request
    file.deletedFile deleted from a request

    Comment & Q&A Events

    Event TypeDescription
    comment.createdComment added to a request
    question.createdQuestion posted in Q&A
    question.answeredAnswer submitted to a question
    question.updatedQuestion or answer edited

    Chat Events

    Event TypeDescription
    chat.message_sentChat message sent in deal chat
    Event TypeDescription
    guest_link.createdGuest view link created
    guest_submission.receivedGuest uploaded a file through a guest link

    Other Events

    Event TypeDescription
    written_response.savedWritten response saved on a request
    sync.completedFile synced to external cloud storage
    sync.failedCloud storage sync failed

    Start with the events you need

    You don’t have to subscribe to every event type. Start with the events most relevant to your integration — for example, request.status_changed and file.uploaded for a CRM sync, or team_member.added for an onboarding automation. You can always add more event types later.

    Deal Subscriptions

    Each webhook endpoint is subscribed to specific deals. When an event occurs in a subscribed deal, and the event type matches the endpoint’s filter, Vetting Vault delivers the event payload to your URL.

    To subscribe an endpoint to a deal, you must have owner or admin access to that deal. This ensures that only authorized users can configure event delivery for a deal’s data.

    You can update deal subscriptions at any time. Adding a new deal starts delivering events for that deal immediately. Removing a deal stops delivery going forward — previously delivered events are not affected.

    A single endpoint can be subscribed to up to 50 deals. If you need to monitor more deals from one integration, create additional endpoints.

    Delivery & Retry Logic

    Vetting Vault is designed for reliable delivery. Every event is persisted in the database before any delivery attempt, so events are never lost even if your server is temporarily unavailable.

    Payload Format

    Every webhook delivery is an HTTP POST with a JSON body. The payload follows a consistent envelope structure:

    {
      "id": "evt_a1b2c3d4-e5f6-7890-abcd-ef1234567890",
      "type": "request.status_changed",
      "version": "1",
      "occurred_at": "2026-04-06T14:30:00.000Z",
      "deal_id": 42,
      "deal_name": "Acme Corp Acquisition",
      "data": {
        "request_id": 185,
        "request_title": "3 Years of Tax Returns",
        "old_status": "submitted",
        "new_status": "approved",
        "changed_by": "jane@example.com"
      }
    }

    The data field contains event-specific information. Its shape varies by event type, but always includes enough context to identify the affected resource.

    Delivery Headers

    Each delivery includes Standard Webhooks headers for verification:

    HeaderDescription
    webhook-idUnique event identifier (matches the id in the payload)
    webhook-timestampUnix timestamp (seconds) when the delivery was signed
    webhook-signatureHMAC-SHA256 signature in v1,<base64> format
    Content-Typeapplication/json
    User-AgentVettingVault-Webhooks/1.0

    Retry Schedule

    If your server returns a non-2xx response or the connection fails, Vetting Vault retries the delivery with exponential backoff. Each delivery is attempted up to 15 times over approximately 3 days:

    AttemptDelay After Failure
    11 minute
    22 minutes
    35 minutes
    415 minutes
    530 minutes
    61 hour
    72 hours
    84 hours
    96 hours
    108 hours
    11–1212 hours
    13–1524 hours

    A small amount of random jitter (up to 20%) is added to each retry delay to prevent thundering-herd scenarios when your server recovers.

    Permanent failures: If your server responds with a 4xx status code (except 429 Too Many Requests), the delivery is immediately moved to the dead-letter queue without further retries. A 429 response is treated as a temporary failure and retried normally.

    After all 15 attempts are exhausted, the delivery is moved to the dead-letter queue (DLQ). You can manually retry DLQ deliveries from the delivery history in your settings.

    Auto-Disable

    If an endpoint accumulates 50 consecutive failures across all its deliveries, Vetting Vault automatically disables it to prevent wasting resources. You will see the disabled reason in your endpoint settings.

    To re-enable a disabled endpoint, fix the underlying issue with your server, then click “Enable” in the webhook settings. The failure counter resets when you re-enable, and you can send a test ping to verify the endpoint is working before live events resume.

    Managing Webhooks

    Delivery History

    Every webhook endpoint has a delivery history that shows each event delivery and its outcome. For each delivery you can see:

    • The event type and deal that triggered it
    • Current delivery status — pending, delivered, failed, or dlq
    • Number of delivery attempts and the timestamp of each
    • HTTP status code returned by your server
    • Error messages for failed attempts
    • Response latency for each attempt

    You can filter the delivery history by status to quickly find failed deliveries that need attention. Failed or DLQ deliveries can be manually retried with one click.

    Testing with Ping

    Before subscribing an endpoint to live deals, use the Ping feature to send a test event. A ping sends a small test payload to your endpoint URL and reports whether the delivery succeeded:

    {
      "id": "ping_1712412345678",
      "type": "ping",
      "version": "1",
      "occurred_at": "2026-04-06T14:30:00.000Z",
      "deal_id": null,
      "deal_name": null,
      "data": {
        "message": "Webhook endpoint verification"
      }
    }

    If the ping succeeds (your server returns a 2xx response), the endpoint is confirmed active. If it fails, you will see the HTTP status code or error message to help you debug.

    Rotating Secrets

    If you need to change your endpoint’s signing secret — for example, if the secret was accidentally exposed or as part of a regular rotation policy — you can rotate it from the endpoint settings.

    When you rotate a secret:

    1. A new whsec_ secret is generated and shown to you once.
    2. The old secret is immediately invalidated.
    3. You should update your consumer to use the new secret within 24 hours.

    Update your consumer promptly

    After rotating a secret, your consumer must be updated with the new secret. Any deliveries signed with the new secret will fail verification if your consumer is still using the old secret.

    Limits

    The following limits apply to webhook configuration:

    ResourceLimit
    Endpoints per user10
    Deal subscriptions per endpoint50
    Event types per endpoint30
    Delivery attempts per event15
    API rate limit60 requests per minute
    Response timeout30 seconds
    Consecutive failures before auto-disable50

    Events API

    In addition to push-based webhooks, Vetting Vault provides a cursor-paginated Events API for each deal. This is useful for:

    • Catch-up — If your consumer was down for a period, query the Events API to retrieve events you may have missed.
    • Backfill — When setting up a new integration, pull historical events to populate your system.
    • Verification — Cross-reference webhook deliveries against the Events API to confirm you received everything.

    Any accepted deal member can query the Events API for that deal. You can filter by event type and paginate through results using a cursor. Results are returned in chronological order, up to 100 events per page.

    Security

    Verifying Signatures

    Every webhook delivery is signed using HMAC-SHA256 with your endpoint’s signing secret. To verify a delivery is authentic:

    1. Extract the headers — Read webhook-id, webhook-timestamp, and webhook-signature from the request.
    2. Build the signature input — Concatenate the message ID, timestamp, and raw request body with periods: {webhook-id}.{webhook-timestamp}.{body}
    3. Compute the HMAC — Decode the base64 portion of your whsec_ secret and compute the HMAC-SHA256 of the signature input.
    4. Compare signatures — The computed signature should match the value after the v1, prefix in the webhook-signature header. Always use a timing-safe comparison to prevent timing attacks.

    Here is an example in Node.js:

    const crypto = require('crypto');
    
    function verifyWebhook(payload, headers, secret) {
      const msgId = headers['webhook-id'];
      const timestamp = headers['webhook-timestamp'];
      const signature = headers['webhook-signature'];
    
      // Strip the whsec_ prefix and decode
      const secretBytes = Buffer.from(
        secret.replace('whsec_', ''),
        'base64'
      );
    
      // Build the signed content
      const signedContent = `${msgId}.${timestamp}.${payload}`;
    
      // Compute expected signature
      const expected = crypto
        .createHmac('sha256', secretBytes)
        .update(signedContent)
        .digest('base64');
    
      // Compare using timing-safe equality
      const expectedSig = `v1,${expected}`;
      const receivedBuf = Buffer.from(signature.split(' ')[0]);
      const expectedBuf = Buffer.from(expectedSig);
    
      if (receivedBuf.length !== expectedBuf.length) return false;
      return crypto.timingSafeEqual(receivedBuf, expectedBuf);
    }

    Check the timestamp too

    To protect against replay attacks, verify that the webhook-timestamp is within an acceptable window (e.g., 5 minutes) of your server’s current time. Reject deliveries with timestamps that are too old or too far in the future.

    Best Practices

    • Always verify signatures — Never process a webhook payload without verifying its signature first. This prevents spoofed events from being acted upon.
    • Respond quickly, process later — Return a 200 status code as soon as you receive and verify the payload. Do any heavy processing asynchronously. If your server takes too long to respond, Vetting Vault may treat it as a timeout and retry.
    • Handle duplicates — In rare cases (network issues, retries), you may receive the same event more than once. Use the webhook-id header or the id field in the payload to deduplicate.
    • Store your secret securely — Keep the signing secret in an environment variable or a secrets manager. Never commit it to source control or expose it in client-side code.
    • Monitor your delivery history — Periodically check the delivery history in your settings to catch failures early. Set up your own alerting if deliveries start failing.
    • Use the Events API for catch-up — If your consumer goes down, don’t rely solely on retries. Query the Events API to backfill any events that may have been missed or moved to the dead-letter queue.
    • Rotate secrets periodically — Even if your secret has not been compromised, rotating it on a regular cadence (e.g., quarterly) is a good security practice.