Webhook Integrations

Send signed real-time event data to external systems when actions happen in CE Pro.

IntermediateUpdated 2026-03-18

Webhook Integrations

Webhooks let you push real-time event data from CE Pro to external systems whenever something meaningful happens. Use them to connect CE Pro to your CRM, project management tool, accounting software, warehouse, or automation platform. Go to Settings --> Integrations --> Webhooks to get started.

Screenshot placeholder
Webhooks page showing the list of configured webhook endpoints with status indicators and Add Webhook button

How Webhooks Work

A webhook is an HTTP POST request that CE Pro sends to a URL you provide whenever a specific event occurs. Instead of polling CE Pro for changes, your system receives a push notification with the relevant data the moment something happens.

For example, when a customer accepts a proposal, CE Pro sends a POST request containing the proposal details to your configured endpoint. Your server processes the data and takes action -- creating a project in your PM tool, adding a row to a spreadsheet, or triggering a downstream workflow.

Webhooks are a developer-oriented feature. You need a server or service capable of receiving HTTP POST requests. No-code platforms like Zapier, Make, and n8n can receive webhooks without custom code.


Available Events

CE Pro supports webhooks for the following event types:

EventDescription
lead.createdA new lead is created.
lead.status_changedA lead changes status.
estimate.createdA new estimate is created.
estimate.acceptedA customer accepts an estimate.
job.createdA job is created.
job.completedA scheduled job is marked complete.
invoice.createdA new invoice is created.
invoice.paidAn invoice is fully paid through the approved payment flow.
proposal_createdA legacy internal proposal is generated.
proposal_sentA legacy internal proposal is delivered.
proposal_acceptedA legacy internal proposal is accepted.
proposal_declinedA legacy internal proposal is declined.
estimate_createdA legacy estimate-created event for older integrations.
job_completedA legacy job-completed event for older integrations.
bug_report_createdA bug report is submitted through the in-app reporting flow.

Each event includes a JSON payload with the relevant data. You can subscribe a single endpoint to multiple events, or create separate endpoints for different events.


Setting Up a Webhook

  1. Go to Settings --> Integrations --> Webhooks.
  2. Click the Add Webhook button.
  3. Fill in the configuration fields:
  • URL -- The full HTTPS endpoint that will receive the webhook POST requests. HTTP URLs are not accepted, and CE Pro rejects localhost, private-network, and other internal-only addresses.
  • Events -- Check one or more event types you want to listen for.
  • Active -- Toggle on to enable the webhook immediately.
  1. Click Save.
Screenshot placeholder
Add Webhook form with fields for URL, event type checkboxes, active toggle, and Save button

Use the Send Test action after saving to send a sample webhook to your endpoint. Your endpoint should return a 2xx response so you can confirm the URL, auth, and payload handling are correct.

If the test fails before CE Pro can reach your endpoint, the UI now keeps the error short and actionable. You may see setup errors like Webhook config not found or Webhook URL must be an external HTTPS endpoint. Other remote delivery failures return a generic Webhook test failed message while still showing the HTTP status and response body for debugging.


Payload Format

Every webhook request includes a JSON body with a consistent structure:

{
  "event": "proposal_accepted",
  "timestamp": "2026-03-08T14:30:00Z",
  "data": {
    "id": "prop_xyz789",
    "client_name": "Jane Smith",
    "client_email": "jane@example.com",
    "total": 2500.00,
    "status": "accepted",
    "accepted_at": "2026-03-08T14:29:45Z"
  }
}

Top-Level Fields

  • event -- The event type string (matches the values in the table above).
  • timestamp -- ISO 8601 timestamp of when the event occurred.
  • data -- An object containing the event-specific details. The fields inside data vary by event type.

Request Headers

Each webhook request includes the following headers:

  • Content-Type: application/json
  • X-Webhook-ID -- The delivery id for dedupe and tracing.
  • X-Webhook-Signature -- The HMAC-SHA256 signature for verification (see below).
  • X-Webhook-Event -- The event type.
  • X-Webhook-Timestamp -- The delivery timestamp.
  • X-Webhook-Attempt -- Which delivery attempt this is.

Testing Webhooks

Before configuring a webhook in CE Pro, verify that your endpoint works correctly.

Using a Request Inspector

  1. Go to a service like Webhook.site or RequestBin.
  2. Copy the generated URL.
  3. Paste it into the CE Pro webhook URL field.
  4. Save the webhook, then use Send Test. CE Pro sends a sample delivery to the endpoint.
  5. Check the request inspector to see the payload.

Testing in Development

If you are building a custom integration:

  1. Use a tunneling tool like ngrok to expose your local server to the internet.
  2. Start your local server.
  3. Copy the ngrok HTTPS URL and add your webhook path (for example, https://abc123.ngrok.io/webhooks/cepro).
  4. Configure the webhook in CE Pro with this URL.
  5. Trigger an event (create a test estimate, for example) and check your server logs.

Test Delivery Payload

The sample test delivery uses this format:

{
  "event": "estimate.created",
  "timestamp": "2026-03-08T14:30:00Z",
  "data": {
    "test": true,
    "message": "This is a test webhook from CleanEstimate Pro",
    "estimate_id": "00000000-0000-0000-0000-000000000000",
    "estimate_number": "TEST-001",
    "customer_name": "Test Customer",
    "total": 250.0
  }
}

Security and Signature Verification

CE Pro signs every webhook request using HMAC-SHA256. This lets you verify that the request genuinely came from CE Pro and was not tampered with in transit.

How Signing Works

  1. When you create a webhook, CE Pro generates a signing secret. Copy it immediately and store it securely. It is shown only once.
  2. For each webhook delivery, CE Pro computes an HMAC-SHA256 hash of the raw request body using your signing secret.
  3. The hash is sent in the X-Webhook-Signature header.

Verifying the Signature on Your Server

Compute the HMAC-SHA256 hash of the raw request body using your stored signing secret. Compare the result to the value in the X-Webhook-Signature header. If they match, the request is authentic.

Node.js example:

const crypto = require('crypto');

function verifyWebhookSignature(rawBody, signatureHeader, secret) {
  const expectedSignature = crypto
    .createHmac('sha256', secret)
    .update(rawBody)
    .digest('hex');
  const expectedBuffer = Buffer.from(expectedSignature);
  const receivedBuffer = Buffer.from(signatureHeader);
  return (
    expectedBuffer.length === receivedBuffer.length &&
    crypto.timingSafeEqual(expectedBuffer, receivedBuffer)
  );
}

Python example:

import hmac
import hashlib

def verify_webhook_signature(raw_body, signature_header, secret):
    expected = hmac.new(
        secret.encode(),
        raw_body.encode(),
        hashlib.sha256
    ).hexdigest()
    return hmac.compare_digest(expected, signature_header)

Warning: Always verify webhook signatures in production. Without verification, anyone who discovers your endpoint URL can send fake events to your system.

Best Practices for Signing Secrets

  • Store the signing secret in an environment variable, not in your source code.
  • Rotate your signing secret periodically by deleting and re-creating the webhook.
  • Use constant-time comparison functions (like timingSafeEqual in Node.js or compare_digest in Python) to prevent timing attacks.

Retry Logic

If your endpoint returns an error (any HTTP status code other than 2xx) or does not respond within 10 seconds, CE Pro queues the delivery and retries it automatically. Retries follow this backoff schedule:

AttemptDelay After Previous Failure
Retry 1about 10 seconds
Retry 2about 60 seconds
Retry 3about 300 seconds

After the final retry, the delivery is marked as failed. Failed deliveries remain visible in the delivery log for troubleshooting.

Tip: If your endpoint is consistently failing, CE Pro may automatically disable the webhook after a sustained period of failures. Check the delivery log and fix the issue, then re-enable the webhook.


Delivery Logging

CE Pro logs every webhook delivery attempt. View the log by clicking on a webhook endpoint in the list. The log shows:

  • Event Type -- The event that triggered the delivery.
  • Timestamp -- When the delivery was attempted.
  • Status Code -- The HTTP response code your endpoint returned.
  • Response Time -- How long your endpoint took to respond (in milliseconds).
  • Outcome -- Success, Failed, or Retrying.
  • Attempt -- Which attempt number (1 through 3).
Screenshot placeholder
Webhook delivery log showing recent deliveries with status codes, response times, and outcomes

Click on any delivery entry to see the full request payload and response body. Use this to debug issues with your integration.

Manual Retry

For any failed delivery, click the Retry button to resend the webhook immediately. This is useful when your endpoint was temporarily down and you need to replay missed events.

Screenshot placeholder
Failed delivery entry in the log with a Retry button

Managing Webhooks

Edit a Webhook

  1. Go to Settings --> Integrations --> Webhooks.
  2. Click on the webhook you want to modify.
  3. Update the URL, subscribed events, or active status.
  4. Click Save.

Disable a Webhook

Toggle the Active switch off to stop deliveries without deleting the webhook. This preserves your configuration and delivery history.

Delete a Webhook

  1. Click on the webhook.
  2. Click Delete.
  3. Confirm the deletion.

Deleting a webhook removes the endpoint and all delivery history permanently.


Tips

  • Test your webhook endpoint with a request inspector before configuring it in CE Pro.
  • Keep your endpoint response time low. CE Pro gives each delivery about 10 seconds before it counts as a failed attempt.
  • Use the delivery log to debug integration issues. A string of 500 errors usually means your endpoint is crashing.
  • Store your signing secret in an environment variable, never in source code.
  • If you use Zapier or Make, use their "Webhooks" trigger to receive CE Pro events without writing any code.
  • Subscribe only to the events you need. Unnecessary events create noise and consume processing resources on your server.
  • Implement idempotency on your server using X-Webhook-ID. Network issues and retries can produce repeat deliveries.

Was this article helpful?

Still need help? Contact support