API recipes
Recipe 1: WordPress webhook receiver
Receive AskVault events in WordPress for custom handling:
<?php// In your WP theme or pluginadd_action('rest_api_init', function() { register_rest_route('askvault/v1', '/webhook', [ 'methods' => 'POST', 'callback' => 'askvault_webhook_handler', 'permission_callback' => '__return_true', ]);});
function askvault_webhook_handler($request) { $signature = $request->get_header('X-AskVault-Signature'); $timestamp = $request->get_header('X-AskVault-Timestamp'); $body = $request->get_body(); $secret = get_option('askvault_webhook_secret');
$expected = 'sha256=' . hash_hmac('sha256', $timestamp . '.' . $body, $secret); if (!$signature || !hash_equals($expected, $signature)) { return new WP_Error('invalid_signature', 'Bad signature', ['status' => 401]); }
$data = json_decode($body, true); // Process based on $data['event'] return ['status' => 'received'];}Add the endpoint as a webhook subscription in AskVault.
Recipe 2: Slack alerts on knowledge gaps
Notify your content team in Slack when a question the bot can't answer keeps recurring. This event fires once per new knowledge-gap suggestion and only when auto-train is set to Suggest or Auto; its fields are top-level, not inside data:
from flask import Flask, request, jsonifyimport requests
app = Flask(__name__)SLACK_WEBHOOK = 'https://hooks.slack.com/services/...'
@app.route('/askvault-webhook', methods=['POST'])def webhook(): event = request.json if event['event'] == 'knowledge.gap_detected': message = f":mag: Knowledge gap: '{event['question']}' asked {event['occurrences']}x" requests.post(SLACK_WEBHOOK, json={'text': message}) return jsonify({'status': 'ok'})
if __name__ == '__main__': app.run(port=5000)Run as your webhook endpoint.
Recipe 3: Zendesk ticket auto-create
Create a Zendesk ticket when a conversation is escalated. The conversation.escalated payload carries conversation_id, channel_type and message_count, so the ticket links back to the chat rather than copying it:
const express = require('express');const fetch = require('node-fetch');const app = express();app.use(express.json());
const ZENDESK_SUBDOMAIN = 'yourco';const ZENDESK_TOKEN = 'xxx';
app.post('/askvault-webhook', async (req, res) => { const event = req.body; if (event.event === 'conversation.escalated') { const conv = event.data; await fetch(`https://${ZENDESK_SUBDOMAIN}.zendesk.com/api/v2/tickets.json`, { method: 'POST', headers: { 'Authorization': 'Basic ' + Buffer.from(`${ZENDESK_USER}:${ZENDESK_TOKEN}`).toString('base64'), 'Content-Type': 'application/json', }, body: JSON.stringify({ ticket: { subject: `AskVault chat needs a person (${conv.channel_type})`, comment: { body: `Conversation ${conv.conversation_id}, ${conv.message_count} messages. Open it in the AskVault inbox.` }, external_id: conv.conversation_id, } }) }); } res.json({ status: 'ok' });});
app.listen(5000);Recipe 4: HubSpot lead sync
Push captured leads to HubSpot Contacts:
from flask import Flask, request, jsonifyimport requests
app = Flask(__name__)HUBSPOT_KEY = 'xxx'
@app.route('/askvault-webhook', methods=['POST'])def webhook(): event = request.json if event['event'] == 'lead.captured': lead = event['data'] requests.post( 'https://api.hubapi.com/crm/v3/objects/contacts', headers={'Authorization': f'Bearer {HUBSPOT_KEY}'}, json={ 'properties': { 'email': lead['email'], 'firstname': lead['name'].split()[0] if lead.get('name') else '', 'lead_source': 'AskVault Chat', } } ) return jsonify({'status': 'ok'})Common patterns
Every receiver should:
- Verify the signature over the
X-AskVault-Timestampvalue, a dot and the raw body (see webhooks). Recipes 2 to 4 leave it out for brevity; add it before going live. - Filter by event type and ignore the rest.
- Drop duplicates using the
X-AskVault-Deliveryheader. - Return 2xx once accepted. A 5xx is retried; a 4xx is not.
Limits
- Webhook delivery timeout. 10 seconds.
- Attempts. Up to 3, on 5xx or timeout only, with the pause doubling up to 30 seconds.
Common pitfalls
Recipe runs but ticket not created. Check upstream (Zendesk) credentials.
Slack message not arriving. Check incoming-webhook URL valid.
Duplicate tickets created. Store each X-AskVault-Delivery id and skip repeats.
FAQ
Can I customize these?
Yes. They're starting points; adapt to your workflow.
Will the AskVault team review my custom recipe?
Support can help with questions about AskVault's side, such as payloads and signatures.
Are these recipes open-source?
The patterns are. Your specific implementation is yours.