HiStruct Webhook Integration - HiStructClient/femcad-doc GitHub Wiki

HiStruct Webhook Integration Tutorial

Table of Contents

  1. What is a Webhook?
  2. HiStruct Webhook Overview
  3. Event Types
  4. Webhook Payload Structure
  5. Integration Examples
  6. Best Practices
  7. Troubleshooting

What is a Webhook?

A webhook is a way for an application to provide other applications with real-time information. Unlike traditional APIs where you need to poll for data, webhooks deliver data to your application as soon as an event occurs.

Key Characteristics of Webhooks:

  • Push-based: Data is sent to you automatically when events happen
  • Real-time: No delays from polling intervals
  • HTTP-based: Uses standard HTTP POST requests
  • Event-driven: Triggered by specific actions or state changes
  • Reliable: Can include retry mechanisms and delivery confirmations

How Webhooks Work:

  1. Setup: You provide a URL endpoint that can receive HTTP POST requests
  2. Registration: You register this URL with the service (HiStruct) for specific events
  3. Event Occurs: When the registered event happens, the service sends an HTTP POST to your URL
  4. Processing: Your application receives and processes the webhook payload
  5. Response: Your endpoint responds with an HTTP status code to confirm receipt

HiStruct Webhook Overview

HiStruct enables webhook notifications for various component events. When specific events occur in your HiStruct application, the system will automatically send a POST request to your configured endpoint with relevant data.

Supported Event Types

HiStruct supports webhook notifications for the following event types:

  • component.inquiry.sent - Triggered when an inquiry component is submitted
  • component.report.published - Triggered when a report is published

Event Types

component.inquiry.sent

This event is triggered when a user submits an inquiry through a HiStruct component. The webhook will contain all the form data and contact information.

component.report.published

This event is triggered when a report is generated and published. The webhook includes inquiry data and optionally report page links.

Webhook Payload Structure

All HiStruct webhooks follow a consistent structure. Here's the anatomy of a webhook request:

HTTP Headers

POST / HTTP/1.1
Host: your-webhook-endpoint.com
Content-Type: application/json; charset=utf-8
Accept: application/json
Authorization: Bearer your-secret-token
Content-Length: 951

Webhook Metadata

Every webhook payload includes these standard fields:

{
  "webhook_invocation_id": "d0833cc51be649cc88a52131dc12433f",
  "webhook_subscription_id": "40708c1144c3453b916ae67e57a31a46", 
  "webhook_subscription_account_id": "histruct-testing-webhook",
  "event_timestamp": "2025-06-12T09:05:47.6484545+00:00",
  "event_type": "component.report.published",
  "message_data": {
    // Event-specific data here
  }
}

Field Descriptions:

  • webhook_invocation_id: Unique identifier for this specific webhook call
  • webhook_subscription_id: ID of the webhook subscription that triggered this call
  • webhook_subscription_account_id: Account identifier for the webhook subscription
  • event_timestamp: ISO 8601 timestamp of when the event occurred
  • event_type: The type of event that triggered the webhook
  • message_data: Event-specific payload data

Example: Complete Webhook Payload

Here's a real example of a component.report.published webhook:

{
  "webhook_invocation_id": "d0833cc51be649cc88a52131dc12433f",
  "webhook_subscription_id": "40708c1144c3453b916ae67e57a31a46",
  "webhook_subscription_account_id": "histruct-testing-webhook",
  "event_timestamp": "2025-06-12T09:05:47.6484545+00:00",
  "event_type": "component.report.published",
  "message_data": {
    "inquiry_contact_data": {
      "Prospect_Company_Name": "FemCAD solutions",
      "Prospect_Company_VATID": "FemCAD solutions",
      "Prospect_PersonName": "Cocker",
      "Prospect_Phone": "777111222",
      "Prospect_Email": "[email protected]",
      "BuildingAddress_Street": "",
      "BuildingAddress_City": "",
      "BuildingAddress_Zip": "",
      "BuildingAddress_Country": "",
      "BuildingAddress_GpsCoordinates": "",
      "Project_Note": "And another test",
      "AdditionalData": {
        "ContactName2": "Joe",
        "CountryKey": "Ausland",
        "CountryZip": "",
        "BuildingUsage": "Industrie-Gewerbebau",
        "BuildingUsageTag": "",
        "CountrySelect": "CZ",
        "BuildingUsageKey": "IGB",
        "BuildingPurposeText": "Maschinenhalle"
      }
    },
    "report_page_links": null
  }
}

Contact Data Fields

The inquiry_contact_data object contains:

  • Company Information:

    • Prospect_Company_Name: Company name
    • Prospect_Company_VATID: VAT identification number
  • Contact Information:

    • Prospect_PersonName: Contact person's last name
    • Prospect_Phone: Phone number
    • Prospect_Email: Email address
  • Address Information:

    • BuildingAddress_Street: Street address
    • BuildingAddress_City: City
    • BuildingAddress_Zip: Postal code
    • BuildingAddress_Country: Country
    • BuildingAddress_GpsCoordinates: GPS coordinates
  • Project Information:

    • Project_Note: Additional project notes
  • Additional Data:

    • ContactName2: First name
    • CountryKey: Country classification
    • CountrySelect: Country code (e.g., "CZ")
    • BuildingUsage: Building type/usage
    • BuildingUsageKey: Building usage code
    • BuildingPurposeText: Specific building purpose

Integration Examples

1. Basic Node.js/Express Webhook Receiver

const express = require('express');
const app = express();

app.use(express.json());

app.post('/histruct-webhook', (req, res) => {
  const {
    webhook_invocation_id,
    event_type,
    event_timestamp,
    message_data
  } = req.body;

  console.log(`Received webhook: ${event_type} at ${event_timestamp}`);
  
  if (event_type === 'component.report.published') {
    const contactData = message_data.inquiry_contact_data;
    
    // Process the contact data
    console.log(`New inquiry from: ${contactData.Prospect_Email}`);
    console.log(`Company: ${contactData.Prospect_Company_Name}`);
    
    // TODO: Save to database, send to CRM, etc.
  }
  
  // Always respond with 200 to acknowledge receipt
  res.status(200).json({ 
    received: true, 
    invocation_id: webhook_invocation_id 
  });
});

app.listen(3000, () => {
  console.log('Webhook receiver listening on port 3000');
});

2. Salesforce Integration Example

// Salesforce integration using jsforce
const jsforce = require('jsforce');

async function handleHiStructWebhook(webhookData) {
  const conn = new jsforce.Connection({
    loginUrl: 'https://your-instance.salesforce.com'
  });
  
  await conn.login(username, password);
  
  if (webhookData.event_type === 'component.report.published') {
    const contactData = webhookData.message_data.inquiry_contact_data;
    
    // Create a new Lead in Salesforce
    const leadData = {
      FirstName: contactData.AdditionalData.ContactName2,
      LastName: contactData.Prospect_PersonName,
      Email: contactData.Prospect_Email,
      Phone: contactData.Prospect_Phone,
      Company: contactData.Prospect_Company_Name,
      Street: contactData.BuildingAddress_Street,
      City: contactData.BuildingAddress_City,
      PostalCode: contactData.BuildingAddress_Zip,
      Country: contactData.BuildingAddress_Country,
      Description: contactData.Project_Note,
      LeadSource: 'HiStruct Website'
    };
    
    const result = await conn.sobject('Lead').create(leadData);
    console.log(`Created Salesforce Lead: ${result.id}`);
  }
}

3. Microsoft Power Automate Integration

You can create a Power Automate flow that:

  1. Trigger: HTTP Request (When an HTTP request is received)
  2. Parse JSON: Parse the HiStruct webhook payload
  3. Condition: Check if event_type equals "component.report.published"
  4. Create Record: Add new record to Dynamics 365 or SharePoint
  5. Send Email: Notify sales team of new inquiry

Best Practices

1. Security

  • Verify the source: Always validate that webhooks come from HiStruct
  • Use HTTPS: Ensure your webhook endpoint uses SSL/TLS
  • Implement authentication: Use the Authorization header to verify requests
  • Rate limiting: Implement rate limiting to prevent abuse

2. Reliability

  • Idempotency: Handle duplicate webhook deliveries gracefully using webhook_invocation_id
  • Quick response: Respond with HTTP 200 quickly (under 30 seconds)
  • Async processing: Process webhook data asynchronously if it takes time
  • Error handling: Return appropriate HTTP status codes for different scenarios

3. Monitoring

  • Log all webhooks: Keep logs of all webhook deliveries for debugging
  • Monitor failures: Track and alert on webhook processing failures
  • Health checks: Implement health check endpoints for your webhook receiver

Example Webhook Receiver with Best Practices

const express = require('express');
const crypto = require('crypto');
const app = express();

// Middleware for webhook verification
function verifyWebhookSignature(req, res, next) {
  const authHeader = req.headers.authorization;
  
  if (!authHeader || !authHeader.startsWith('Bearer ')) {
    return res.status(401).json({ error: 'Missing or invalid authorization header' });
  }
  
  // In production, verify the token
  const token = authHeader.substring(7);
  // TODO: Verify token against your expected webhook secret
  
  next();
}

// Store processed webhook IDs to prevent duplicates
const processedWebhooks = new Set();

app.use(express.json());
app.use('/webhook', verifyWebhookSignature);

app.post('/webhook/histruct', async (req, res) => {
  const { webhook_invocation_id, event_type } = req.body;
  
  // Check for duplicate delivery
  if (processedWebhooks.has(webhook_invocation_id)) {
    console.log(`Duplicate webhook ignored: ${webhook_invocation_id}`);
    return res.status(200).json({ received: true, duplicate: true });
  }
  
  // Mark as processed immediately
  processedWebhooks.add(webhook_invocation_id);
  
  try {
    // Process webhook asynchronously
    setImmediate(() => processWebhookAsync(req.body));
    
    // Respond immediately
    res.status(200).json({ 
      received: true, 
      invocation_id: webhook_invocation_id 
    });
    
  } catch (error) {
    console.error('Webhook processing error:', error);
    res.status(500).json({ error: 'Internal server error' });
  }
});

async function processWebhookAsync(webhookData) {
  try {
    // Your actual webhook processing logic here
    console.log(`Processing webhook: ${webhookData.event_type}`);
    
    // Add to CRM, send notifications, etc.
    
  } catch (error) {
    console.error('Async webhook processing failed:', error);
    // TODO: Implement retry logic or dead letter queue
  }
}

Troubleshooting

Common Issues

1. Webhook not received

  • Check your endpoint URL is accessible from the internet
  • Verify your server is running and responding to POST requests
  • Check firewall settings

2. Authentication failures

  • Verify you're checking the Authorization header correctly
  • Ensure your webhook secret is configured properly

3. Timeouts

  • Ensure your webhook endpoint responds within 30 seconds
  • Move heavy processing to async operations

4. Duplicate processing

  • Use webhook_invocation_id to implement idempotency
  • Consider using a database to track processed webhooks

Testing Your Webhook Endpoint

You can test your webhook endpoint using tools like:

  • ngrok: For local development and testing
  • Postman: To simulate webhook payloads
  • curl: For command-line testing

Example curl command:

curl -X POST https://your-endpoint.com/webhook \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer your-test-token" \
  -d '{"webhook_invocation_id":"test-123","event_type":"component.report.published","message_data":{"inquiry_contact_data":{"Prospect_Email":"[email protected]"}}}'

Conclusion

HiStruct webhooks provide a powerful way to integrate real-time event data into your existing systems. By following the patterns and best practices outlined in this tutorial, you can build reliable, secure webhook integrations that automatically process inquiries and reports as they occur in your HiStruct applications.

Remember to always handle webhooks asynchronously, implement proper error handling, and monitor your webhook endpoints to ensure reliable data processing.