Webhooks
Webhooks allow you to receive real-time HTTP notifications when events occur in your document processing pipelines. Instead of polling the API for status updates, you can configure hooks to automatically push data to your endpoints when executions complete, fail, or update.
Overview
The Cambrion Hooks API provides:
- Event-driven notifications - Receive updates on status changes and observation updates
- Flexible payload formats - Choose from raw, JSON, or custom transformations
- Multipart form support - Include processed documents in webhook deliveries
- Custom headers - Authenticate webhook requests with your own tokens
- Status filtering - Trigger hooks only for specific execution statuses
API Endpoints
| Method | Endpoint | Description |
|---|---|---|
POST | /hooks | Create a new hook |
GET | /hooks | List all configured hooks |
GET | /hooks/{hookId} | Retrieve a specific hook |
PUT | /hooks/{hookId} | Update an existing hook |
DELETE | /hooks/{hookId} | Delete a hook |
POST | /executions/{executionId}/submit | Trigger SUBMIT-type hooks |
Hook Configuration
Hook Object Properties
| Property | Type | Required | Description |
|---|---|---|---|
hookId | string | No | Unique identifier (auto-generated if omitted) |
name | string | No | Human-readable name for the hook |
eventType | string | Yes | Event that triggers the hook |
hookType | string | Yes | Delivery mechanism (currently WEBHOOK) |
endpoint | string | Yes | Target URL for webhook delivery |
headers | object | No | Custom HTTP headers for authentication |
statusFilter | array | No | Filter by execution status (for STATUS_CHANGE events) |
payloadType | string | Yes | Format of the webhook payload |
transform | string | Conditional | JSONata expression (required for TRANSFORM/FORM_TRANSFORM) |
formPayloadKey | string | No | Form field name for JSON payload (default: payload) |
formDocumentKey | string | No | Form field name for documents (default: documents) |
enabled | boolean | No | Whether the hook is active (default: true) |
createdAt | timestamp | No | Auto-set creation timestamp |
Event Types
Hooks can be triggered by three types of events:
STATUS_CHANGE
Triggered when an execution's status changes. Use statusFilter to limit notifications to specific statuses.
{
"eventType": "STATUS_CHANGE",
"statusFilter": ["COMPLETED", "ERROR"]
}
Available statuses: PENDING, PROCESSING, COMPLETED, ERROR, CANCELLED
OBSERVATION_UPDATE
Triggered when extraction results are generated or modified during processing.
{
"eventType": "OBSERVATION_UPDATE"
}
SUBMIT
Triggered only when explicitly calling the submit endpoint. Useful for manual control over webhook delivery.
{
"eventType": "SUBMIT"
}
Payload Types
The payloadType determines how the observation data is formatted and delivered.
RAW
Sends the raw observation data with minimal processing:
{
"executionId": "exec-123",
"eventType": "STATUS_CHANGE",
"status": "COMPLETED",
"data": {
// Raw observation data
}
}
JSON
Applies the JSON transformation service for structured output:
{
"executionId": "exec-123",
"eventType": "STATUS_CHANGE",
"status": "COMPLETED",
"data": {
// Transformed observation data
}
}
TRANSFORM
Applies a custom JSONata expression for flexible data transformation:
{
"payloadType": "TRANSFORM",
"transform": "{ \"invoice_number\": data.invoice_id, \"total\": data.amount }"
}
FORM_TRANSFORM
Delivers payload as multipart/form-data, combining transformed JSON with binary document files:
{
"payloadType": "FORM_TRANSFORM",
"transform": "{ \"id\": executionId, \"results\": data }",
"formPayloadKey": "payload",
"formDocumentKey": "documents"
}
The webhook request will include:
payloadfield: The transformed JSON datadocumentsfield(s): Binary files (PDF, images, etc.)
For multiple documents, array notation is used: documents[0], documents[1], etc.
Getting Started
Creating Your First Hook
Create a webhook that notifies you when document processing completes:
curl -X POST https://api.cambrion.io/v1/hooks \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_API_KEY" \
-d '{
"hookId": "completion-webhook",
"name": "Processing Complete Notification",
"eventType": "STATUS_CHANGE",
"hookType": "WEBHOOK",
"endpoint": "https://your-server.com/webhooks/cambrion",
"statusFilter": ["COMPLETED"],
"payloadType": "JSON"
}'
Response:
{
"hookId": "completion-webhook",
"name": "Processing Complete Notification",
"eventType": "STATUS_CHANGE",
"hookType": "WEBHOOK",
"endpoint": "https://your-server.com/webhooks/cambrion",
"statusFilter": ["COMPLETED"],
"payloadType": "JSON",
"enabled": true,
"createdAt": "2026-02-03T10:00:00Z"
}
Attaching Hooks to Executions
Hooks can be attached to executions in several ways:
Via Extraction Configuration
When creating an extraction, include the hook IDs:
{
"extractionId": "invoice-extraction",
"schema": { ... },
"hookIds": ["completion-webhook", "error-webhook"]
}
All executions using this extraction will automatically trigger the specified hooks.
Via Execution Request
Attach hooks directly when creating an execution:
curl -X POST https://api.cambrion.io/v1/executions \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_API_KEY" \
-d '{
"executionId": "exec-001",
"media": [
{
"mediaId": "doc-1",
"url": "https://storage.example.com/invoice.pdf"
}
],
"hookIds": ["completion-webhook"]
}'
Via Pipeline Execution
curl -X POST https://api.cambrion.io/v1/pipelines/my-pipeline/execute \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_API_KEY" \
-d '{
"executionId": "exec-002",
"hookIds": ["completion-webhook", "error-webhook"]
}'
Examples
Example 1: Error Notification with Custom Headers
Set up a webhook that notifies your monitoring system when processing fails:
curl -X POST https://api.cambrion.io/v1/hooks \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_API_KEY" \
-d '{
"hookId": "error-alert",
"name": "Error Alert to Slack",
"eventType": "STATUS_CHANGE",
"hookType": "WEBHOOK",
"endpoint": "https://hooks.slack.com/services/YOUR/SLACK/WEBHOOK",
"headers": {
"X-Custom-Source": "cambrion-production"
},
"statusFilter": ["ERROR"],
"payloadType": "TRANSFORM",
"transform": "{ \"text\": \"Document processing failed for execution \" & executionId & \". Status: \" & status }"
}'
Example 2: Custom JSON Transformation
Transform extraction results into your own data format:
curl -X POST https://api.cambrion.io/v1/hooks \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_API_KEY" \
-d '{
"hookId": "erp-integration",
"name": "ERP System Integration",
"eventType": "STATUS_CHANGE",
"hookType": "WEBHOOK",
"endpoint": "https://erp.company.com/api/documents",
"headers": {
"Authorization": "Bearer ERP_TOKEN",
"X-API-Version": "2.0"
},
"statusFilter": ["COMPLETED"],
"payloadType": "TRANSFORM",
"transform": "{ \"document_id\": executionId, \"vendor\": data.supplier_name, \"invoice_number\": data.invoice_id, \"amount\": data.total_amount, \"currency\": data.currency, \"due_date\": data.payment_due_date }"
}'
Example 3: Multipart Form Delivery with Documents
Send extracted data along with the original documents to an archive system:
curl -X POST https://api.cambrion.io/v1/hooks \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_API_KEY" \
-d '{
"hookId": "archive-upload",
"name": "Document Archive",
"eventType": "SUBMIT",
"hookType": "WEBHOOK",
"endpoint": "https://archive.company.com/api/upload",
"headers": {
"Authorization": "Bearer ARCHIVE_TOKEN"
},
"payloadType": "FORM_TRANSFORM",
"transform": "{ \"execution_id\": executionId, \"status\": status, \"extracted_data\": data }",
"formPayloadKey": "metadata",
"formDocumentKey": "files"
}'
When triggered, this sends a multipart/form-data request:
POST /api/upload HTTP/1.1
Host: archive.company.com
Content-Type: multipart/form-data; boundary=----WebKitFormBoundary
------WebKitFormBoundary
Content-Disposition: form-data; name="metadata"
Content-Type: application/json
{"execution_id":"exec-123","status":"COMPLETED","extracted_data":{...}}
------WebKitFormBoundary
Content-Disposition: form-data; name="files"; filename="document.pdf"
Content-Type: application/pdf
[binary PDF data]
------WebKitFormBoundary--
Example 4: Manual Submission with Payload Inspection
Use the submit endpoint to manually trigger hooks and inspect the payloads:
curl -X POST https://api.cambrion.io/v1/executions/exec-123/submit \
-H "Authorization: Bearer YOUR_API_KEY"
Response:
{
"hookPayloads": [
{
"hookId": "archive-upload",
"hookName": "Document Archive",
"endpoint": "https://archive.company.com/api/upload",
"payload": {
"execution_id": "exec-123",
"status": "COMPLETED",
"extracted_data": { ... }
},
"delivered": true,
"error": null
}
]
}
Managing Hooks
List All Hooks
curl -X GET https://api.cambrion.io/v1/hooks \
-H "Authorization: Bearer YOUR_API_KEY"
Get a Specific Hook
curl -X GET https://api.cambrion.io/v1/hooks/completion-webhook \
-H "Authorization: Bearer YOUR_API_KEY"
Update a Hook
Disable a hook temporarily:
curl -X PUT https://api.cambrion.io/v1/hooks/completion-webhook \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_API_KEY" \
-d '{
"hookId": "completion-webhook",
"name": "Processing Complete Notification",
"eventType": "STATUS_CHANGE",
"hookType": "WEBHOOK",
"endpoint": "https://your-server.com/webhooks/cambrion",
"statusFilter": ["COMPLETED"],
"payloadType": "JSON",
"enabled": false
}'
Delete a Hook
curl -X DELETE https://api.cambrion.io/v1/hooks/completion-webhook \
-H "Authorization: Bearer YOUR_API_KEY"
JSONata Transformation Reference
The transform field uses JSONata, a powerful JSON query and transformation language. Here are some useful patterns:
Basic Field Mapping
{
"id": executionId,
"result": data.extracted_value
}
String Concatenation
{
"message": "Execution " & executionId & " completed with status " & status
}
Conditional Logic
{
"priority": status = "ERROR" ? "high" : "normal"
}
Array Operations
{
"line_items": data.items.({"sku": product_id, "qty": quantity})
}
Aggregation
{
"total": $sum(data.items.amount),
"item_count": $count(data.items)
}
Webhook Delivery
Request Format
All webhooks are delivered as HTTP POST requests:
- Timeout: 30 seconds
- Content-Type:
application/json(ormultipart/form-dataforFORM_TRANSFORM) - Custom Headers: Included as specified in hook configuration
Supported Media Types
When using FORM_TRANSFORM, the following file types are automatically detected:
| Extension | Content-Type |
|---|---|
.pdf | application/pdf |
.png | image/png |
.jpg, .jpeg | image/jpeg |
.gif | image/gif |
.webp | image/webp |
.tiff, .tif | image/tiff |
Error Handling
Webhook delivery errors are logged but do not affect execution processing. The submit endpoint returns delivery status for each hook:
{
"hookPayloads": [
{
"hookId": "my-hook",
"delivered": false,
"error": "Connection timeout"
}
]
}
Best Practices
- Use status filters - Avoid unnecessary webhook traffic by filtering for specific statuses
- Implement idempotency - Your webhook endpoint should handle duplicate deliveries gracefully
- Validate payloads - Always validate incoming webhook data before processing
- Use HTTPS - Always use HTTPS endpoints for webhook delivery
- Authenticate webhooks - Use custom headers to verify webhook authenticity
- Handle timeouts - Respond quickly to webhook requests (under 30 seconds)
- Test with submit - Use the submit endpoint to test webhook configurations before enabling automatic triggers
Troubleshooting
Webhooks Not Firing
- Verify the hook is enabled (
enabled: true) - Check that the hook ID is attached to the execution
- Confirm the event type matches the expected trigger
- For
STATUS_CHANGE, verify the status is instatusFilter
Payload Transformation Errors
- Validate your JSONata expression at try.jsonata.org
- Ensure required fields (
transform) are provided forTRANSFORM/FORM_TRANSFORMtypes - Check that the observation data structure matches your transformation expectations
Delivery Failures
- Verify the endpoint URL is accessible
- Check that custom headers are correctly formatted
- Ensure your server responds within 30 seconds
- Review server logs for authentication or validation errors