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

  1. Always verify signatures - Never process unverified webhooks
  2. Use HTTPS - Webhook URLs must use HTTPS
  3. Rotate secrets - Regularly rotate webhook secrets
  4. Validate events - Verify event types before processing

Reliability

  1. Return 200 quickly - Respond within 5 seconds
  2. Handle failures - Implement retry logic
  3. Idempotency - Handle duplicate events
  4. Logging - Log all webhook events

Performance

  1. Async processing - Process webhooks asynchronously
  2. Queue system - Use a queue for webhook processing
  3. 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


Questions? Check the FAQ or contact support@ubiship.com