Skip to main content

Create Webhooks

To create webhooks, follow the instructions below. Step 1: Navigate to the “Webhooks” section from the sidebar under the “Configure” menu.
Image
Step 2: In the “New webhook” section, enter the destination URL where you want to receive the webhook notifications in the “Destination URL” field.
Download
Step 3: Optionally, click the “Test URL” button to ensure that your destination URL is correctly set up and can receive test data. Step 4: Provide a meaningful name for your webhook in the “Webhook Name” field. For example, “Employee data.” Step 5: Under “Webhook Type,” select the environment for which you want to receive webhook alerts.
Webhook TypeReceives alerts forRecommended use
ProductionProduction connectorsLive customer integrations
DevelopmentDevelopment connectorsTesting and development connectors
Note: Production and Development webhooks are environment-specific. This means a Production webhook will only receive alerts for connectors created in the Production environment, while a Development webhook will only receive alerts for connectors created in the Development environment.
Step 6: Choose the events for which you want to receive notifications by selecting the appropriate checkboxes:
  • Sync start: Receive an alert when a connector’s sync starts.
  • Sync error: Get notified when a connector sync fails.
  • Sync completed: Get notified when a connector sync job is successful.
  • Employee model change: Receive an alert when any employee data is modified.
  • Data model change: Receive an alert when any data model is modified.
Step 7: Once you have filled in all the required fields and selected the notification triggers, click the “Create webhook” button to save your webhook configuration.

Payload Properties

  • webhook: Information about the webhook that was triggered.
  • connector: Information about the connector associated with the event.
  • data: The affected connector sync status data.
  • sync: Information about the sync job that triggered the event. This object is included in all webhook payloads.
  • error: Information about the sync failure. This object is included only in the connector_sync_error webhook.

Sync information

All webhook payloads include a top-level sync object in the following format:
{
  "sync_id": "019f146e-8396-7c6d-aff3-c5760bf5eefe",
  "sync_type": "AUTOMATED",
  "sync_name": "#13"
}
FieldDescription
sync_idThe unique identifier of the sync job.
sync_typeHow the sync was triggered. Possible values:MANUAL and AUTOMATED.
sync_nameThe name assigned to the sync job.

Sync error information

The connector_sync_error webhook includes a top-level error object in the following format:
{
  "failed_at": "2026-07-07T11:21:35.837448+00:00",
  "message": "A runtime error occurred during the sync process. Bindbee team has been notified.",
  "detail": {}
}
FieldDescription
failed_atThe timestamp at which the sync job failed.
messageA summary of the sync job error.
detailAdditional details about the error. This is returned as an empty object ({}) when no additional details are available.

Webhook event types

  • Connector Sync Started
  • Connector Synced
  • Connector Sync Error
  • Employee Data Changed
  • Connector Data Modified

Sample payload for webhook events

Receive an alert when the connector sync starts.
{
    "webhook": {
        "webhook_id": "10c9a6b1-4ea8-476e-bdb0-193001a94a8d",
        "url": "https://webhook-test.com/8e771727c78e3a4017f374fb745313b6",
        "event": "connector_sync_started"
    },
    "connector": {
        "id": "018f99e2-ed3a-7f4c-ae97-83d619bdf95c",
        "display_name": "BreatheHR",
        "integration_slug": "breathehr",
        "categories": [
        "HRIS"
        ],
        "org_name": "Test Org",
        "origin_id": "user_123",
        "connector_status": "COMPLETE",
        "end_user_name": "John Doe",
        "end_user_email": "abc@xyz.com"
    },
    "data": {
        "id": "018f99e7-886b-7c9f-a63a-f6fbc9da1f83",
        "integration_name": "breathehr",
        "category": "HRIS",
        "display_status": "Syncing",
        "last_sync_start_time": "2024-07-22T09:49:30.478384+00:00"
    },
    "sync": {
      "sync_id": "019f146e-8396-7c6d-aff3-c5760bf5eef8",
      "sync_type": "AUTOMATED",
      "sync_name": "#13"
    }
}

Retry Mechanism

When a webhook event is triggered, Bindbee sends a POST request to your configured destination URL. If the request fails due to a request or network-layer issue, Bindbee automatically retries the delivery up to 4 times within 60 seconds. Each delivery attempt has a timeout of 10 seconds. Your server should respond within this window to avoid the request being treated as timed out.

Retry behavior

PropertyValue
Maximum retriesUp to 4 retries
Retry windowWithin 60 seconds
Request timeout10 seconds per attempt
Request methodPOST
Retry triggerRequest/network-layer failures and all non-2xxresponses

Failures that trigger retries

Retries are triggered only for request or network-layer failures, including:
Failure categoryExamples
Timeout errorsConnection timeout, read timeout, write timeout, connection pool timeout
Connection errorsConnection error, read error, write error, close error
Protocol errorsLocal protocol error, remote protocol error, unsupported protocol error
Other request errorsProxy error, response decoding error, too many redirects

Security

To secure your API endpoint, ensure it verifies that POST requests are genuinely from Bindbee and not from a malicious source, and that payloads haven’t been tampered with during transit. You can achieve this by checking if the X-Bindbee-Webhook-Signature field in the request header matches an encoded combination of your organization’s unique webhook signature and the payload of the incoming request. In the Webhooks configuration page, you should find a Security section where you can access your signature key. This key is unique to your organization and can be regenerated if it becomes known to an unauthorized party. Webhook Security
import base64
import hashlib
import hmac

# Replace 'YOUR_WEBHOOK_SIGNATURE_KEY' with the actual key from:
# https://app.bindbee.dev/webhooks

signature_key = "YOUR_WEBHOOK_SIGNATURE_KEY"
request_body = request.body

# Ensure the presence of a signature header in the request
if "X-Bindbee-Webhook-Signature" not in request.headers:
    print('Signature header missing; request may not be from Bindbee.')
    raise

# Retrieve the signature header from the request
received_signature = request.headers["X-Bindbee-Webhook-Signature"]

# Convert the key and request body to bytes
key_bytes = signature_key.encode("utf-8")
body_bytes = request_body.encode("utf-8")

# Create an HMAC digest using SHA-256
hmac_digest = hmac.new(key_bytes, body_bytes, hashlib.sha256).digest()

# Encode the digest to base64
encoded_digest = base64.urlsafe_b64encode(hmac_digest).decode()

# Use `hmac.compare_digest` to compare the computed digest with the received signature
signature_valid = hmac.compare_digest(encoded_digest, received_signature)
require 'base64'
require 'openssl'
require 'json'

# Replace 'YOUR_WEBHOOK_SIGNATURE_KEY' with the actual key from:
# https://app.bindbee.dev/webhooks

secret_key = 'YOUR_WEBHOOK_SIGNATURE_KEY'
request_body = request.raw_post
received_signature = request.env['X-Bindbee-Webhook-Signature']

unless received_signature
  raise "Signature header missing; request may not be from Bindbee."
end

# Ensure the payload is properly encoded in UTF-8
request_body.force_encoding('UTF-8')

# Compute HMAC digest using SHA-256
hmac_digest = OpenSSL::HMAC.digest(OpenSSL::Digest.new('sha256'), secret_key, request_body)

# Base64 encode the HMAC digest
encoded_digest = Base64.urlsafe_encode64(hmac_digest)

# Use secure comparison to validate the signature
valid_signature = ActiveSupport::SecurityUtils.secure_compare(encoded_digest, received_signature)
const crypto = require("crypto");
const express = require("express");
const app = express();

// Replace 'YOUR_WEBHOOK_SIGNATURE_KEY' with the actual key from:
// https://app.bindbee.dev/webhooks

// Middleware to capture raw body for HMAC verification
app.use(
  express.json({
    verify: (req, res, buf) => {
      req.rawBody = buf.toString();
    },
  }),
);

const webhookSecret = "YOUR_WEBHOOK_SIGNATURE_KEY";
const rawRequestBody = request.rawBody;

const receivedSignature = request.headers["X-Bindbee-Webhook-Signature"];

if (!receivedSignature) {
  console.log("Missing webhook signature; request may not be from Bindbee.");
}

// Ensure the request body is properly encoded
const utf8Body = Buffer.from(rawRequestBody, "utf-8").toString();

// Create an HMAC digest using SHA-256
const hmacDigest = crypto
  .createHmac("sha256", webhookSecret)
  .update(utf8Body)
  .digest("base64")
  .replace(/\+/g, "-")
  .replace(/\//g, "_");

// Use crypto.timingSafeEqual to compare the signatures securely
const expectedSignature = Buffer.from(receivedSignature, "utf-8");
const calculatedSignature = Buffer.from(hmacDigest, "utf-8");

const isSignatureValid =
  Buffer.byteLength(expectedSignature) ===
    Buffer.byteLength(calculatedSignature) &&
  crypto.timingSafeEqual(expectedSignature, calculatedSignature);

console.log(isSignatureValid);

Webhook Visibility

The webhook logs are easily visible on the webhooks tab at Bindbee dashboard. The specific webhook logs will be visible on the individual webhook page.