Webhooks API
Complete API reference for webhook endpoints.
Overview
Webhooks allow you to receive real-time notifications when events occur in Archivus. Configure webhooks to be notified of document processing, chat messages, and other events.
Create Webhook
Create a new webhook endpoint.
POST /api/v1/webhooks
Request
{
"url": "https://yourapp.com/webhooks/archivus",
"events": [
"document.processed",
"document.failed",
"chat.message.created"
],
"secret": "your-webhook-secret"
}
Example
curl -X POST https://api.archivus.app/api/v1/webhooks \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-H "X-Tenant-Subdomain: your-tenant" \
-H "X-CSRF-Token: YOUR_CSRF_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"url": "https://yourapp.com/webhooks/archivus",
"events": ["document.processed", "document.failed"],
"secret": "your-webhook-secret"
}'
Response
{
"id": "webhook_abc123",
"url": "https://yourapp.com/webhooks/archivus",
"events": ["document.processed", "document.failed"],
"status": "active",
"created_at": "2025-12-16T10:30:00Z"
}
List Webhooks
Get all webhooks for your account.
GET /api/v1/webhooks
Example
curl "https://api.archivus.app/api/v1/webhooks" \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-H "X-Tenant-Subdomain: your-tenant"
Response
{
"webhooks": [
{
"id": "webhook_abc123",
"url": "https://yourapp.com/webhooks/archivus",
"events": ["document.processed"],
"status": "active",
"created_at": "2025-12-16T10:30:00Z"
}
]
}
Update Webhook
Update webhook configuration.
PUT /api/v1/webhooks/:id
Request
{
"url": "https://yourapp.com/webhooks/archivus-v2",
"events": ["document.processed", "chat.message.created"],
"status": "active"
}
Example
curl -X PUT https://api.archivus.app/api/v1/webhooks/webhook_abc123 \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-H "X-Tenant-Subdomain: your-tenant" \
-H "X-CSRF-Token: YOUR_CSRF_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"events": ["document.processed", "document.failed", "chat.message.created"]
}'
Delete Webhook
Delete a webhook.
DELETE /api/v1/webhooks/:id
Example
curl -X DELETE https://api.archivus.app/api/v1/webhooks/webhook_abc123 \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-H "X-Tenant-Subdomain: your-tenant" \
-H "X-CSRF-Token: YOUR_CSRF_TOKEN"
Webhook Events
Available Events
| Event | Description |
|---|---|
document.processed |
Document processing completed |
document.failed |
Document processing failed |
document.uploaded |
Document uploaded |
chat.message.created |
New chat message created |
chat.session.created |
New chat session created |
Event Payload
All webhook events include:
{
"id": "event_abc123",
"type": "document.processed",
"timestamp": "2025-12-16T10:30:00Z",
"data": {
"document_id": "doc_abc123",
"status": "completed"
}
}
Webhook Verification
Verify webhook requests using the signature header.
Signature Header
Archivus includes a signature in the X-Archivus-Signature header:
X-Archivus-Signature: sha256=abc123def456...
Verification Example
Python:
import hmac
import hashlib
def verify_webhook(payload, signature, secret):
expected_signature = hmac.new(
secret.encode(),
payload.encode(),
hashlib.sha256
).hexdigest()
return hmac.compare_digest(f"sha256={expected_signature}", signature)
# Usage
payload = request.data
signature = request.headers.get('X-Archivus-Signature')
secret = 'your-webhook-secret'
if verify_webhook(payload, signature, secret):
# Process webhook
pass
JavaScript:
const crypto = require('crypto');
function verifyWebhook(payload, signature, secret) {
const expectedSignature = crypto
.createHmac('sha256', secret)
.update(payload)
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(`sha256=${expectedSignature}`),
Buffer.from(signature)
);
}
// Usage
const payload = JSON.stringify(req.body);
const signature = req.headers['x-archivus-signature'];
const secret = 'your-webhook-secret';
if (verifyWebhook(payload, signature, secret)) {
// Process webhook
}
Webhook Handler Example
Python Flask
from flask import Flask, request, jsonify
import hmac
import hashlib
app = Flask(__name__)
WEBHOOK_SECRET = 'your-webhook-secret'
@app.route('/webhooks/archivus', methods=['POST'])
def archivus_webhook():
# Verify signature
signature = request.headers.get('X-Archivus-Signature')
payload = request.get_data(as_text=True)
expected = hmac.new(
WEBHOOK_SECRET.encode(),
payload.encode(),
hashlib.sha256
).hexdigest()
if not hmac.compare_digest(f"sha256={expected}", signature):
return jsonify({"error": "Invalid signature"}), 401
# Process webhook
event = request.json
event_type = event['type']
event_data = event['data']
if event_type == 'document.processed':
document_id = event_data['document_id']
# Handle document processed
print(f"Document {document_id} processed")
return jsonify({"status": "ok"}), 200
Node.js Express
const express = require('express');
const crypto = require('crypto');
const app = express();
const WEBHOOK_SECRET = 'your-webhook-secret';
app.post('/webhooks/archivus', express.raw({ type: 'application/json' }), (req, res) => {
const signature = req.headers['x-archivus-signature'];
const payload = req.body.toString();
const expectedSignature = crypto
.createHmac('sha256', WEBHOOK_SECRET)
.update(payload)
.digest('hex');
if (signature !== `sha256=${expectedSignature}`) {
return res.status(401).json({ error: 'Invalid signature' });
}
const event = JSON.parse(payload);
const { type, data } = event;
if (type === 'document.processed') {
const { document_id } = data;
// Handle document processed
console.log(`Document ${document_id} processed`);
}
res.json({ status: 'ok' });
});
Best Practices
Security
- Always verify signatures - Never process unverified webhooks
- Use HTTPS - Webhook URLs must use HTTPS
- Rotate secrets - Regularly rotate webhook secrets
- Validate events - Verify event types before processing
Reliability
- Return 200 quickly - Respond within 5 seconds
- Handle failures - Implement retry logic
- Idempotency - Handle duplicate events
- Logging - Log all webhook events
Performance
- Async processing - Process webhooks asynchronously
- Queue system - Use a queue for webhook processing
- Rate limiting - Implement rate limiting on your endpoint
Error Responses
Invalid URL
Status: 400 Bad Request
{
"error": "invalid_url",
"code": "INVALID_URL",
"message": "Webhook URL must use HTTPS"
}
Invalid Event
Status: 400 Bad Request
{
"error": "invalid_event",
"code": "INVALID_EVENT",
"message": "Invalid event type"
}
Next Steps
- Error Handling - Handle webhook errors
- Rate Limits - Understand rate limits
- Webhook Guide - Learn about webhooks
Questions? Check the FAQ or contact support@ubiship.com