Webhooks

Webhooks

Receive real-time notifications about system events and integrate with your existing workflows.

Overview

Webhooks provide a way for your applications to receive real-time notifications when specific events occur in Sapphire Legal AI. This enables seamless integration with external systems and automated workflows.

Core concepts

How webhooks work

  1. You register a webhook endpoint URL with Sapphire Legal AI
  2. When an event occurs, we send an HTTP POST request to your endpoint
  3. Your endpoint processes the webhook payload and takes appropriate action
  4. You return a 2xx status code to acknowledge receipt

Event types

Webhooks are triggered by various system events:

  • Case events: Case created, updated, status changed, assigned
  • Document events: Document uploaded, processed, updated, deleted
  • User events: User login, logout, permission changes
  • System events: Backup completed, maintenance scheduled, errors
  • AI events: AI processing started, completed, failed

Webhook configuration

Creating a webhook

POST /api/v1/admin/webhooks
Authorization: Bearer <admin_jwt_token>
Content-Type: application/json

{
  "name": "Case Notifications",
  "url": "https://your-app.com/webhooks/sapphire",
  "events": ["case.created", "case.updated", "case.status_changed"],
  "secret": "your_webhook_secret",
  "active": true,
  "retry_policy": {
    "max_attempts": 5,
    "backoff_multiplier": 2,
    "initial_delay": 60
  }
}

Webhook settings

SettingTypeDescriptionRequired
namestringHuman-readable name for the webhookYes
urlstringHTTPS endpoint to receive webhooksYes
eventsarrayList of events to subscribe toYes
secretstringSecret for signature verificationYes
activebooleanWhether webhook is activeNo

Webhook payloads

Standard payload format

{
  "id": "webhook_1234567890abcdef",
  "event": "case.created",
  "timestamp": "2025-01-20T10:30:00Z",
  "data": {
    "case_id": "case_1234567890abcdef",
    "title": "Smith v. Johnson",
    "case_number": "CV-2025-001",
    "status": "active",
    "created_by": "user_1234567890abcdef"
  },
  "metadata": {
    "webhook_id": "webhook_1234567890abcdef",
    "attempt": 1,
    "delivery_id": "delivery_1234567890abcdef"
  }
}

Case created event

{
  "id": "webhook_1234567890abcdef",
  "event": "case.created",
  "timestamp": "2025-01-20T10:30:00Z",
  "data": {
    "case_id": "case_1234567890abcdef",
    "title": "Smith v. Johnson",
    "case_number": "CV-2025-001",
    "case_type": "litigation",
    "jurisdiction": "federal",
    "client_name": "John Smith",
    "status": "active",
    "priority": "high",
    "created_by": "user_1234567890abcdef",
    "created_at": "2025-01-20T10:30:00Z"
  }
}

Document uploaded event

{
  "id": "webhook_1234567890abcdef",
  "event": "document.uploaded",
  "timestamp": "2025-01-20T10:30:00Z",
  "data": {
    "document_id": "doc_1234567890abcdef",
    "case_id": "case_1234567890abcdef",
    "title": "Complaint",
    "document_type": "pleading",
    "file_size": 1048576,
    "file_type": "application/pdf",
    "uploaded_by": "user_1234567890abcdef",
    "uploaded_at": "2025-01-20T10:30:00Z"
  }
}

Security and verification

Signature verification

Each webhook includes a signature header that you can use to verify the request authenticity:

X-Sapphire-Signature: t=1234567890,v1=abc123def456...
X-Sapphire-Timestamp: 1234567890

Verification process

  1. Extract the timestamp and signature from headers
  2. Concatenate the timestamp and request body
  3. Create HMAC SHA256 using your webhook secret
  4. Compare the computed signature with the received signature

Example verification (Node.js)

const crypto = require('crypto');

function verifyWebhookSignature(payload, signature, timestamp, secret) {
  const expectedSignature = crypto
    .createHmac('sha256', secret)
    .update(timestamp + '.' + payload)
    .digest('hex');
    
  return crypto.timingSafeEqual(
    Buffer.from(signature),
    Buffer.from(expectedSignature)
  );
}

Retry policy

Automatic retries

If your webhook endpoint fails to respond or returns an error, we automatically retry delivery:

  • Retry attempts: Up to 5 attempts by default
  • Backoff strategy: Exponential backoff with jitter
  • Initial delay: 60 seconds
  • Maximum delay: 1 hour
  • Total timeout: 24 hours

Retry conditions

Webhooks are retried when your endpoint:

  • Returns a 4xx or 5xx HTTP status code
  • Doesn't respond within 30 seconds
  • Returns a malformed response
  • Is unreachable (network errors)

Dead letter queue

After all retry attempts are exhausted, failed webhooks are moved to a dead letter queue for manual investigation and processing.

Best practices

Webhook endpoint design

  • Idempotency: Handle duplicate webhooks gracefully
  • Quick response: Return 2xx status immediately, process asynchronously
  • Error handling: Log errors and return appropriate status codes
  • Security: Always verify webhook signatures
  • Monitoring: Track webhook delivery success and failures

Performance considerations

  • Process webhooks asynchronously when possible
  • Use connection pooling for database operations
  • Implement proper timeout handling
  • Monitor endpoint response times
  • Scale your webhook endpoint as needed

Testing webhooks

Test endpoint

Use our test endpoint to verify your webhook configuration:

POST /api/v1/admin/webhooks/{webhook_id}/test
Authorization: Bearer <admin_jwt_token>
Content-Type: application/json

{
  "event_type": "case.created",
  "test_data": {
    "case_id": "test_case_123",
    "title": "Test Case"
  }
}

Local testing

For local development, use tools like ngrok to expose your local endpoint:

# Install ngrok
npm install -g ngrok

# Expose local endpoint
ngrok http 3000

# Use the ngrok URL as your webhook endpoint
https://abc123.ngrok.io/webhooks/sapphire
Tip
Pro tip: Use webhook signatures to ensure you're only processing legitimate requests from Sapphire Legal AI.

What's next