Webhooks
Webhooks enable Anava to send detection data to your custom applications, automation platforms, or third-party services via HTTP POST requests.
Use Cases
| Integration | Example |
|---|---|
| Custom Applications | Send detection data to your security dashboard |
| Automation | Trigger IFTTT, Zapier, or n8n workflows |
| Access Control | Lock doors when threats detected |
| Lighting | Activate lights on person detection |
| Messaging | Post to Slack, Teams, or Discord |
Webhook Payload
When a detection occurs, Anava sends a JSON payload to your endpoint:
{
"eventType": "detection",
"version": "1.0",
"timestamp": "2024-12-23T10:30:00.000Z",
"device": {
"id": "B8A44F45D624",
"name": "Warehouse-Cam-01",
"groupId": "warehouse-north"
},
"profile": {
"id": "intrusion-detection",
"name": "Intrusion Detection"
},
"skill": {
"id": "weapon-detection",
"name": "Weapon Detection"
},
"session": {
"id": "ses_abc123def456",
"url": "https://anava.ai/sessions/ses_abc123def456"
},
"analysis": {
"objects": [
{
"name": "Person",
"detected": true,
"confidence": 0.95,
"boundingBox": {"x": 100, "y": 200, "width": 150, "height": 300}
}
],
"questions": [
{
"id": 1,
"name": "is_authorized",
"text": "Is the person authorized?",
"answer": false,
"type": "bool"
},
{
"id": 2,
"name": "description",
"text": "Describe what you see",
"answer": "Adult male in dark clothing near the emergency exit",
"type": "string"
}
],
"summary": "Unauthorized person detected near emergency exit"
},
"imageUrl": "https://storage.googleapis.com/anava-frames/ses_abc123/frame.jpg"
}
Configuring Webhooks
Step 1: Create Webhook Endpoint
In your application, create an endpoint to receive POST requests:
// Example: Express.js endpoint
app.post('/anava-webhook', (req, res) => {
const detection = req.body;
console.log('Detection received:', detection);
// Process the detection
if (detection.analysis.objects.some(o => o.name === 'Weapon')) {
triggerEmergencyResponse(detection);
}
// Return 200 to acknowledge receipt
res.status(200).send('OK');
});
Step 2: Configure in Anava
- Navigate to Settings → Integrations → Webhooks
- Click + Add Webhook
- Enter your endpoint URL
- Configure options (below)
- Save and test
Webhook Configuration Options
| Option | Description | Default |
|---|---|---|
| URL | Your HTTPS endpoint | Required |
| Method | HTTP method | POST |
| Headers | Custom headers | None |
| Secret | Signing key for verification | None |
| Retry | Retry on failure | 3 attempts |
| Timeout | Request timeout | 10 seconds |
Step 3: Test Webhook
- Click Test Webhook in configuration
- Verify your endpoint receives the test payload
- Check for 200 OK response
Security
HTTPS Required
Webhooks must use HTTPS endpoints. HTTP endpoints are rejected for security.
Signature Verification
When a secret is configured, Anava signs requests using HMAC-SHA256:
X-Anava-Signature: sha256=abc123...
X-Anava-Timestamp: 1703325000
Verify the signature in your endpoint:
const crypto = require('crypto');
function verifySignature(body, signature, timestamp, secret) {
const payload = `${timestamp}.${JSON.stringify(body)}`;
const expected = crypto
.createHmac('sha256', secret)
.update(payload)
.digest('hex');
return `sha256=${expected}` === signature;
}
app.post('/anava-webhook', (req, res) => {
const signature = req.headers['x-anava-signature'];
const timestamp = req.headers['x-anava-timestamp'];
if (!verifySignature(req.body, signature, timestamp, SECRET)) {
return res.status(401).send('Invalid signature');
}
// Process verified request
// ...
});
IP Allowlisting
Anava webhook requests originate from these IP ranges:
- GCP Cloud Functions IPs (varies by region)
- Check current IPs in your Anava dashboard
Retry Policy
Failed webhook deliveries are retried automatically:
| Attempt | Delay |
|---|---|
| 1 | Immediate |
| 2 | 30 seconds |
| 3 | 2 minutes |
| 4 | 10 minutes |
| Final | 1 hour |
After all retries fail, the event is logged for manual review.
Filtering Webhooks
Configure which events trigger webhooks:
By Detection Type
{
"filter": {
"objects": ["Person", "Weapon"],
"minConfidence": 0.9
}
}
By Group/Device
{
"filter": {
"groups": ["high-security", "entrances"],
"devices": ["B8A44F45D624"]
}
}
By Time
{
"filter": {
"schedule": "outside_business_hours"
}
}
Integration Examples
Slack Notification
const axios = require('axios');
app.post('/anava-webhook', async (req, res) => {
const detection = req.body;
await axios.post(SLACK_WEBHOOK_URL, {
text: `*Alert:* ${detection.analysis.summary}`,
attachments: [{
color: 'danger',
fields: [
{ title: 'Camera', value: detection.device.name },
{ title: 'Time', value: new Date(detection.timestamp).toLocaleString() }
],
image_url: detection.imageUrl
}]
});
res.status(200).send('OK');
});
Home Assistant
# configuration.yaml
automation:
- alias: "Anava Person Detection"
trigger:
platform: webhook
webhook_id: anava_detection
condition:
- condition: template
value_template: "{{ trigger.json.analysis.objects | selectattr('name', 'eq', 'Person') | list | length > 0 }}"
action:
- service: light.turn_on
target:
entity_id: light.outdoor_lights
IFTTT
- Create IFTTT Webhooks applet
- Use your IFTTT webhook URL as Anava endpoint
- Configure IFTTT to trigger desired actions
Zapier
- Create Zap with Webhooks by Zapier trigger
- Use custom webhook URL from Zapier
- Configure actions (email, SMS, sheets, etc.)
Troubleshooting
Webhook Not Received
-
Check endpoint is reachable
- Test with curl:
curl -X POST https://your-endpoint.com/webhook - Verify SSL certificate is valid
- Test with curl:
-
Check firewall rules
- Allow inbound HTTPS from Anava IPs
- Check any WAF rules
-
Check Anava logs
- View webhook delivery status in dashboard
- Check for error responses
Signature Verification Failing
-
Check secret configuration
- Ensure same secret on both sides
- Check for whitespace issues
-
Check timestamp
- Ensure server clock is synchronized
- Allow some timestamp tolerance
Timeout Issues
-
Optimize endpoint
- Return 200 immediately
- Process async if needed
-
Check network latency
- Consider endpoint closer to GCP region
Best Practices
Respond Quickly
Return 200 immediately, process async:
app.post('/anava-webhook', (req, res) => {
// Acknowledge immediately
res.status(200).send('OK');
// Process async
processDetection(req.body).catch(console.error);
});
Handle Duplicates
Use session ID for idempotency:
const processed = new Set();
app.post('/anava-webhook', (req, res) => {
const sessionId = req.body.session.id;
if (processed.has(sessionId)) {
return res.status(200).send('Already processed');
}
processed.add(sessionId);
// Process...
});
Monitor Webhook Health
- Track success/failure rates
- Alert on repeated failures
- Log payloads for debugging