HiStruct Webhook Integration - HiStructClient/femcad-doc GitHub Wiki
HiStruct Webhook Integration Tutorial
Table of Contents
- What is a Webhook?
- HiStruct Webhook Overview
- Event Types
- Webhook Payload Structure
- Integration Examples
- Best Practices
- 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:
- Setup: You provide a URL endpoint that can receive HTTP POST requests
- Registration: You register this URL with the service (HiStruct) for specific events
- Event Occurs: When the registered event happens, the service sends an HTTP POST to your URL
- Processing: Your application receives and processes the webhook payload
- 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 submittedcomponent.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 callwebhook_subscription_id
: ID of the webhook subscription that triggered this callwebhook_subscription_account_id
: Account identifier for the webhook subscriptionevent_timestamp
: ISO 8601 timestamp of when the event occurredevent_type
: The type of event that triggered the webhookmessage_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 nameProspect_Company_VATID
: VAT identification number
-
Contact Information:
Prospect_PersonName
: Contact person's last nameProspect_Phone
: Phone numberProspect_Email
: Email address
-
Address Information:
BuildingAddress_Street
: Street addressBuildingAddress_City
: CityBuildingAddress_Zip
: Postal codeBuildingAddress_Country
: CountryBuildingAddress_GpsCoordinates
: GPS coordinates
-
Project Information:
Project_Note
: Additional project notes
-
Additional Data:
ContactName2
: First nameCountryKey
: Country classificationCountrySelect
: Country code (e.g., "CZ")BuildingUsage
: Building type/usageBuildingUsageKey
: Building usage codeBuildingPurposeText
: 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:
- Trigger: HTTP Request (When an HTTP request is received)
- Parse JSON: Parse the HiStruct webhook payload
- Condition: Check if event_type equals "component.report.published"
- Create Record: Add new record to Dynamics 365 or SharePoint
- 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.