Sign In

Webhooks

Send and receive webhooks to integrate Buildorado with any external service.

Webhooks let you connect Buildorado with any external service that supports HTTP callbacks, giving you unlimited integration possibilities beyond the 30+ built-in integrations. Outgoing webhooks send data from your workflows to external APIs when events occur -- a form is submitted, a payment is processed, or a workflow completes. Incoming webhooks let external services trigger Buildorado workflows by sending HTTP requests to a unique endpoint. Combined with the Respond to Webhook node, you can build complete request-response APIs on top of Buildorado's workflow engine. Whether you are syncing data to a custom CRM, triggering workflows from Stripe events, or connecting to Zapier, webhooks are the universal integration layer.

Outgoing Webhooks

Outgoing webhooks send HTTP requests from your Buildorado workflow to an external URL when a specific step in the workflow executes. Use them to push form submission data to your backend, notify third-party services, or call any REST API.

Configuration

Add an HTTP Request or Webhook action node to your workflow canvas and configure the following settings:

SettingDescription
URLThe endpoint to call (must be HTTPS in production)
MethodGET, POST, PUT, PATCH, or DELETE
HeadersCustom HTTP headers as key-value pairs
BodyJSON payload with {{variableName.property}} template variables
AuthenticationNone, Bearer token, API key (header or query), or Basic auth
TimeoutMaximum wait time in milliseconds (default: 30,000ms, max: 120,000ms)

Request Body with Dynamic Variables

Compose the JSON body using template variables from upstream form fields and nodes:

{
  "name": "{{form.name}}",
  "email": "{{form.email}}",
  "company": "{{form.company}}",
  "budget": {{form.budget}},
  "source": "buildorado",
  "workflow_id": "{{workflow.id}}",
  "submission_id": "{{submission.id}}",
  "submitted_at": "{{submission.createdAt}}"
}

All {{variableName.property}} references are resolved at execution time with the actual values from the current workflow run.

Authentication Options for Outgoing Requests

Auth TypeConfiguration
NoneNo authentication header is added
Bearer TokenSends Authorization: Bearer <token> header
API Key (Header)Sends a custom header with your API key (e.g., X-API-Key: your-key)
API Key (Query)Appends the API key as a query parameter (e.g., ?api_key=your-key)
Basic AuthSends Authorization: Basic <base64(username:password)> header

Store sensitive values like API keys and tokens in your workflow's credential configuration rather than hardcoding them in the node. Buildorado encrypts stored credentials with AES-256 using AWS KMS.

Retry Behavior

If the outgoing webhook fails (network error, 5xx response, or timeout), Buildorado retries the request with exponential backoff:

AttemptDelay
1st retry5 seconds
2nd retry30 seconds
3rd retry2 minutes

After 3 failed retries, the node is marked as failed. If you have an error handler node connected, it catches the failure and can trigger fallback logic -- such as sending an alert to Slack or logging the error.

Timeout Configuration

The default timeout is 30 seconds. If your external service needs more time to process (e.g., a slow API or heavy computation), increase the timeout up to 120 seconds. If the request exceeds the timeout, it is treated as a failure and enters the retry cycle.

For long-running operations, consider having your external service respond immediately with a 202 Accepted and then call back to Buildorado via an incoming webhook when processing completes.

Response Handling

The outgoing webhook node captures the HTTP response and makes it available as output variables for downstream nodes:

Output VariableDescription
statusCodeHTTP status code (e.g., 200, 201, 404)
bodyResponse body parsed as JSON (if valid JSON)
headersResponse headers as key-value pairs

You can reference these in downstream nodes. For example, if your API returns a record ID:

New record created: {{httpRequest.body.id}}

Use conditional logic to branch on the status code:

[HTTP Request] → [Branch: Status Code]
  → statusCode == 200 → [Email: Success confirmation]
  → statusCode != 200 → [Slack: #errors "Webhook failed with {{httpRequest.statusCode}}"]

Incoming Webhooks (Triggers)

Incoming webhooks let external services start a Buildorado workflow by sending an HTTP request. This turns your workflow into an API endpoint that processes incoming data.

Setting Up an Incoming Webhook

  1. Open or create a workflow in the visual canvas.
  2. Add a Webhook Trigger node as the starting node of your workflow.
  3. Buildorado generates a unique webhook URL (e.g., https://api.buildorado.io/webhooks/wh_abc123def456).
  4. Copy this URL and configure your external service to send events to it.
  5. Publish the workflow to activate the webhook endpoint.

The webhook URL is unique to each workflow and does not change when you edit or republish the workflow. Draft (unpublished) workflows do not accept incoming webhooks.

Supported HTTP Methods

The webhook trigger accepts POST, PUT, and PATCH requests by default. GET requests are supported for simple triggers that do not include a body.

Payload Parsing

Buildorado automatically parses the incoming request body based on the Content-Type header:

Content-TypeParsing
application/jsonParsed as JSON -- fields are available as {{webhook.fieldName}}
application/x-www-form-urlencodedParsed as form data
text/plainAvailable as {{webhook.body}} (raw string)
multipart/form-dataForm fields and file uploads are parsed

Accessing Webhook Data in Your Workflow

After the webhook trigger fires, all fields from the parsed payload are available as template variables throughout the workflow:

// Incoming payload:
{
  "event": "order.created",
  "customer_email": "[email protected]",
  "amount": 149.99,
  "items": [
    { "name": "Widget", "qty": 3 }
  ]
}

Reference these fields in downstream nodes:

Customer: {{webhook.customer_email}}
Amount: ${{webhook.amount}}
First item: {{webhook.items[0].name}}

Authentication for Incoming Webhooks

Incoming webhooks support three authentication modes to ensure only authorized services can trigger your workflows:

No Authentication

Accepts any request. Suitable for testing but not recommended for production. Any service or person with the webhook URL can trigger the workflow.

Secret Header

Validate a shared secret in a custom HTTP header. Configure the header name and expected value in the Webhook Trigger node settings.

SettingExample
Header NameX-Webhook-Secret
Expected Valueyour-secret-value-here

The incoming request must include the header with the exact value. Requests without the header or with an incorrect value receive a 401 Unauthorized response.

JWT (JSON Web Token)

Validate a JSON Web Token passed in the Authorization: Bearer <token> header. Configure the JWT secret or public key in the Webhook Trigger node. Buildorado verifies the token signature and checks expiration (exp) and not-before (nbf) claims.

This is the most secure option and is recommended for production integrations where the calling service supports JWT.

Respond to Webhook Node

The Respond to Webhook logic node lets you send a custom HTTP response back to the service that triggered the incoming webhook. Without this node, Buildorado responds with a default 200 OK and a generic JSON acknowledgment. With it, you control the status code, headers, and body.

Configuration

SettingDescription
Status CodeHTTP status code to return (e.g., 200, 201, 400)
HeadersCustom response headers (e.g., Content-Type: application/json)
BodyJSON or text response body with {{variableName.property}} variables

Example: Return Processed Data

// Respond to Webhook configuration:
Status Code: 200
Body:
{
  "status": "success",
  "record_id": "{{salesforce.recordId}}",
  "message": "Lead created in Salesforce"
}

The calling service receives this response instead of the default acknowledgment. This is useful when the caller needs to know the result of the workflow processing.

Important: Placement in Workflow

The Respond to Webhook node should be placed at the point in your workflow where you want to send the response. Any nodes after it continue executing asynchronously. This means you can respond quickly (within seconds) and then perform long-running operations (AI processing, multiple API calls) without making the caller wait.

[Webhook Trigger] → [Validate Data] → [Respond to Webhook: 200 OK]
                                          → [CRM: Create Lead]
                                          → [Slack: Notify Team]
                                          → [Email: Welcome Email]

Webhook Signatures

Verifying Outgoing Webhook Signatures

Every outgoing webhook from Buildorado includes a signature header that lets you verify the request is authentic and has not been tampered with. The signature is an HMAC-SHA256 hash of the request body using your webhook secret.

HeaderValue
X-Buildorado-Signaturesha256=<hex-encoded HMAC-SHA256 hash>
X-Buildorado-TimestampUnix timestamp of when the webhook was sent

Verification Code Examples

JavaScript (Node.js)

const crypto = require('crypto');

function verifyWebhookSignature(body, signature, secret) {
  const expectedSignature = 'sha256=' +
    crypto.createHmac('sha256', secret)
      .update(body, 'utf8')
      .digest('hex');

  return crypto.timingSafeEqual(
    Buffer.from(signature),
    Buffer.from(expectedSignature)
  );
}

// In your Express handler:
app.post('/webhook', (req, res) => {
  const signature = req.headers['x-buildorado-signature'];
  const body = req.rawBody; // raw request body as string

  if (!verifyWebhookSignature(body, signature, process.env.WEBHOOK_SECRET)) {
    return res.status(401).json({ error: 'Invalid signature' });
  }

  // Process the webhook...
  const data = JSON.parse(body);
  console.log('Verified webhook:', data);
  res.status(200).json({ received: true });
});

Python

import hmac
import hashlib

def verify_webhook_signature(body: bytes, signature: str, secret: str) -> bool:
    expected = 'sha256=' + hmac.new(
        secret.encode('utf-8'),
        body,
        hashlib.sha256
    ).hexdigest()

    return hmac.compare_digest(signature, expected)

# In your Flask handler:
from flask import Flask, request, jsonify

app = Flask(__name__)

@app.route('/webhook', methods=['POST'])
def handle_webhook():
    signature = request.headers.get('X-Buildorado-Signature')
    body = request.get_data()

    if not verify_webhook_signature(body, signature, WEBHOOK_SECRET):
        return jsonify({'error': 'Invalid signature'}), 401

    data = request.get_json()
    print(f'Verified webhook: {data}')
    return jsonify({'received': True}), 200

PHP

function verifyWebhookSignature(
    string $body,
    string $signature,
    string $secret
): bool {
    $expected = 'sha256=' . hash_hmac('sha256', $body, $secret);
    return hash_equals($expected, $signature);
}

// In your endpoint:
$body = file_get_contents('php://input');
$signature = $_SERVER['HTTP_X_BUILDORADO_SIGNATURE'] ?? '';

if (!verifyWebhookSignature($body, $signature, $webhookSecret)) {
    http_response_code(401);
    echo json_encode(['error' => 'Invalid signature']);
    exit;
}

$data = json_decode($body, true);
// Process the webhook...
http_response_code(200);
echo json_encode(['received' => true]);

Timestamp Validation

To prevent replay attacks, check the X-Buildorado-Timestamp header and reject requests older than 5 minutes:

const timestamp = parseInt(req.headers['x-buildorado-timestamp'], 10);
const fiveMinutesAgo = Math.floor(Date.now() / 1000) - 300;

if (timestamp < fiveMinutesAgo) {
  return res.status(401).json({ error: 'Webhook expired' });
}

Common Webhook Patterns

Zapier Integration

Connect Buildorado to Zapier to access thousands of additional integrations:

  1. In Zapier, create a new Zap with a Webhooks by Zapier trigger (Catch Hook).
  2. Copy the Zapier webhook URL.
  3. In your Buildorado workflow, add an outgoing webhook node with the Zapier URL.
  4. Send test data from Buildorado so Zapier can detect the payload structure.
  5. Add Zapier actions (e.g., create a Mailchimp subscriber, add a Trello card, update an Asana task).

This lets you use any of Zapier's 5,000+ integrations without waiting for a native Buildorado connector.

Custom CRM Sync

Push form submissions to a custom CRM or internal database:

[Form: Lead Capture]
  → [HTTP Request: POST to CRM API]
    URL: https://api.yourcrm.com/v1/contacts
    Headers: Authorization: Bearer {{credential.crmApiKey}}
    Body: {
      "first_name": "{{form.first_name}}",
      "last_name": "{{form.last_name}}",
      "email": "{{form.email}}",
      "phone": "{{form.phone}}",
      "source": "buildorado_form",
      "notes": "Submitted on {{submission.createdAt}}"
    }
  → [Branch: CRM Response]
    → 201 Created → [Email: Welcome]
    → Error → [Slack: #errors "CRM sync failed for {{form.email}}"]

Stripe Event Processing

Receive Stripe webhook events and trigger Buildorado workflows:

  1. Create a Buildorado workflow with a Webhook Trigger node.
  2. Copy the webhook URL.
  3. In Stripe Dashboard > Developers > Webhooks, add the URL and select events (e.g., invoice.paid, customer.subscription.deleted).
  4. Process the event in your workflow:
[Webhook Trigger: Stripe Events]
  → [Branch: Event Type]
    → "invoice.paid" → [Google Sheets: Log payment] → [Slack: #payments]
    → "customer.subscription.deleted" → [Email: Cancellation survey]
    → "charge.disputed" → [Slack: #finance "Dispute on {{webhook.data.object.id}}"]

GitHub / CI-CD Triggers

Trigger workflows from GitHub events like pull request merges or issue creation:

  1. Set up a Buildorado webhook trigger with secret header authentication.
  2. In GitHub, go to your repository Settings > Webhooks and add the Buildorado webhook URL.
  3. Set the Content type to application/json and add your secret.
  4. Select the events you want to trigger on (e.g., Pull requests, Issues).

Two-Way Sync Pattern

For services that need to both send and receive data:

Outgoing: [Buildorado Form] → [Webhook: POST to External Service]
Incoming: [External Service] → [Webhook Trigger: Buildorado] → [Update Records]

This creates a bidirectional data sync where Buildorado pushes new submissions to the external service and the external service pushes updates back to trigger follow-up workflows.

Debugging Webhooks

Outgoing Webhook Debugging

  1. Check the execution log -- In your Buildorado dashboard, open the workflow's execution history. Each execution shows the request URL, headers, body, response status, and response body for every webhook node.
  2. Use a request inspector -- Services like webhook.site or RequestBin provide a temporary URL that logs all incoming requests. Point your outgoing webhook to a request inspector to see exactly what Buildorado sends.
  3. Verify URL accessibility -- Ensure the target URL is reachable from the internet. Buildorado cannot call localhost or private network addresses (blocked by SSRF protection).
  4. Check response codes -- A 4xx response means the target rejected the request (check authentication, headers, or payload format). A 5xx response means the target server had an error.

Incoming Webhook Debugging

  1. Publish the workflow -- Incoming webhooks only work on published workflows. Draft workflows do not accept webhook requests.
  2. Send a test request -- Use curl or Postman to send a test payload:
curl -X POST https://api.buildorado.io/webhooks/wh_abc123def456 \
  -H "Content-Type: application/json" \
  -H "X-Webhook-Secret: your-secret" \
  -d '{"test": true, "name": "Test User"}'
  1. Check the execution log -- After sending the test, check the workflow execution history to verify the webhook triggered and the data was parsed correctly.
  2. Verify authentication -- If using secret header auth, ensure the header name and value match exactly. Header names are case-insensitive but values are case-sensitive.

Security Best Practices

For Outgoing Webhooks

  • Always use HTTPS for production webhook URLs. HTTP endpoints expose data in transit.
  • Authenticate requests using Bearer tokens, API keys, or Basic auth. Never send sensitive data to unauthenticated endpoints.
  • Validate responses -- branch on status codes to detect and handle failures.
  • Set appropriate timeouts -- do not let a slow external service block your workflow indefinitely.
  • Store credentials securely -- use Buildorado's credential store instead of hardcoding secrets in webhook configurations.

For Incoming Webhooks

  • Enable authentication -- use secret header or JWT validation for all production webhooks. Never leave incoming webhooks unauthenticated in production.
  • Validate the payload -- use branch nodes to check for required fields before processing.
  • Keep webhook URLs private -- treat your webhook URL like a password. Do not publish it in public repositories or documentation.
  • Use the Respond to Webhook node -- return appropriate status codes (200 for success, 400 for bad requests) so calling services can detect issues.
  • Monitor for abuse -- check your workflow execution logs for unexpected triggers that might indicate your webhook URL has been leaked.

For Webhook Signatures

  • Always verify signatures in your receiving endpoint for outgoing Buildorado webhooks.
  • Use timing-safe comparison functions (crypto.timingSafeEqual in Node.js, hmac.compare_digest in Python, hash_equals in PHP) to prevent timing attacks.
  • Check timestamps to reject replayed requests older than 5 minutes.
  • Rotate secrets periodically and update both sides (Buildorado and your receiving endpoint).

Frequently Asked Questions

What happens if my external service is down when Buildorado sends a webhook?

Buildorado retries failed outgoing webhooks up to 3 times with exponential backoff (5 seconds, 30 seconds, 2 minutes). If all retries fail, the webhook node is marked as failed. You can attach an error handler node to catch failures and trigger fallback logic, such as queueing the data for manual review or sending an alert to Slack.

Can I send webhooks to localhost or internal network addresses?

No. Buildorado blocks requests to private IP ranges (10.x.x.x, 172.16-31.x.x, 192.168.x.x) and localhost as an SSRF protection measure. For development, use a tunneling service like ngrok to expose your local server with a public URL, or use a request inspector service like webhook.site.

How do I test incoming webhooks without publishing the workflow?

You need to publish the workflow for the incoming webhook endpoint to be active. However, you can publish the workflow in a non-discoverable state (no public link) and send test requests using curl or Postman. Check the execution logs in the dashboard to verify the data was received and processed correctly.

Can I use webhooks with Zapier, Make (Integromat), or n8n?

Yes. Any automation platform that supports sending or receiving webhooks can integrate with Buildorado. For outgoing webhooks, configure the target URL in the webhook node. For incoming webhooks, copy the Buildorado webhook URL and paste it into the automation platform's webhook action. See the Zapier integration pattern above for a step-by-step example.

On this page

Webhooks | Buildorado