Webhooks
Webhooks deliver real-time HTTP POST notifications when events occur in your Intufind account — products indexed, chat messages sent, handoff requests, and more.
Available Events
| Event | Description |
|---|---|
product.created | A new product was indexed |
product.updated | A product was updated |
product.deleted | A product was deleted |
post.created | A new post was indexed |
post.updated | A post was updated |
post.deleted | A post was deleted |
chat.message_sent | A chat message was sent |
chat.conversation_started | A new conversation began |
feedback.submitted | User feedback was submitted |
handoff.requested | Customer requested live agent handoff |
handoff.accepted | Agent accepted the handoff |
handoff.resolved | Handoff conversation was resolved |
contact.submitted | Customer submitted contact info |
Creating a Webhook
curl -X POST https://api.intufind.com/webhooks \
-H "Authorization: Bearer if_sk_xxx" \
-H "Content-Type: application/json" \
-d '{
"name": "My Webhook",
"url": "https://your-app.com/webhooks/intufind",
"events": ["product.created", "product.updated", "chat.message_sent"],
"secret": "your-webhook-secret"
}'
import { createClient, createWebhook } from '@intufind/ai-sdk';
const client = createClient({
baseUrl: 'https://api.intufind.com',
auth: process.env.INTUFIND_SECRET_KEY!,
});
const { data } = await createWebhook({
client,
body: {
name: 'My Webhook',
url: 'https://your-app.com/webhooks/intufind',
events: ['product.created', 'product.updated', 'chat.message_sent'],
secret: 'your-webhook-secret',
},
});
Payload Format
All webhook payloads follow this structure:
{
"id": "evt_abc123",
"event_type": "product.created",
"created_at": "2026-01-15T10:30:00Z",
"data": {
"id": "product-123",
"name": "Wireless Headphones",
"price": 199.99,
"categories": ["Electronics", "Audio"]
}
}
contact.submitted
Triggered when a customer submits contact information (typically when live agents are unavailable):
{
"id": "evt_ghi789",
"event_type": "contact.submitted",
"created_at": "2026-01-15T18:45:00Z",
"data": {
"thread_id": "web_1234567890_abc",
"name": "Jane Doe",
"email": "jane@example.com",
"phone": "+1-555-123-4567",
"message": "I need help with my recent order #12345"
}
}
Use this event to add leads to your CRM, create support tickets, or trigger email/SMS alerts.
Signature Verification
Webhooks include a signature header for verification:
X-Webhook-Signature: sha256=abc123...
Node.js
import crypto from 'crypto';
function verifyWebhookSignature(
payload: string,
signature: string,
secret: string
): boolean {
const expected =
'sha256=' +
crypto.createHmac('sha256', secret).update(payload).digest('hex');
return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(expected)
);
}
PHP
function verifyWebhookSignature(
string $payload,
string $signature,
string $secret
): bool {
$expected = 'sha256=' . hash_hmac('sha256', $payload, $secret);
return hash_equals($expected, $signature);
}
$payload = file_get_contents('php://input');
$signature = $_SERVER['HTTP_X_WEBHOOK_SIGNATURE'] ?? '';
if (!verifyWebhookSignature($payload, $signature, $secret)) {
http_response_code(401);
exit('Invalid signature');
}
$event = json_decode($payload, true);
Retry Policy
If your endpoint returns a non-2xx response or times out, Intufind retries with increasing delays:
| Attempt | Delay |
|---|---|
| 1 | Immediate |
| 2 | 1 minute |
| 3 | 5 minutes |
| 4 | 30 minutes |
| 5 | 2 hours |
After 5 failed attempts the webhook is marked as failed and you receive an email notification.
Testing
Send a Test Event
curl -X POST https://api.intufind.com/webhooks/{webhook-id}/test \
-H "Authorization: Bearer if_sk_xxx" \
-H "Content-Type: application/json" \
-d '{
"test_payload": {
"event_type": "product.created",
"data": {"id": "test-123", "name": "Test Product"}
}
}'
Local Development
Use a tunneling service like ngrok for local testing:
ngrok http 3000
Then register the ngrok URL (https://abc123.ngrok.io/webhooks/intufind) as your webhook endpoint.
Best Practices
- Always verify signatures to ensure requests originate from Intufind
- Respond quickly (under 30 seconds) to avoid timeouts
- Process asynchronously — queue webhook payloads for background processing
- Handle duplicates — use the event
idfor idempotency - Monitor failures — set up alerts for repeated webhook failures
Next Steps
- API Reference — Full webhook endpoint documentation
- Authentication — API key setup