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
- You register a webhook endpoint URL with Sapphire Legal AI
- When an event occurs, we send an HTTP POST request to your endpoint
- Your endpoint processes the webhook payload and takes appropriate action
- 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
| Setting | Type | Description | Required |
|---|---|---|---|
name | string | Human-readable name for the webhook | Yes |
url | string | HTTPS endpoint to receive webhooks | Yes |
events | array | List of events to subscribe to | Yes |
secret | string | Secret for signature verification | Yes |
active | boolean | Whether webhook is active | No |
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
- Extract the timestamp and signature from headers
- Concatenate the timestamp and request body
- Create HMAC SHA256 using your webhook secret
- 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
What's next
- SDKs & Libraries - Use official client libraries
- System Configuration - Configure webhook settings
- API Endpoints - Explore other API capabilities