Skip to main content

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

MethodEndpointDescription
POST/hooksCreate a new hook
GET/hooksList 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}/submitTrigger SUBMIT-type hooks

Hook Configuration

Hook Object Properties

PropertyTypeRequiredDescription
hookIdstringNoUnique identifier (auto-generated if omitted)
namestringNoHuman-readable name for the hook
eventTypestringYesEvent that triggers the hook
hookTypestringYesDelivery mechanism (currently WEBHOOK)
endpointstringYesTarget URL for webhook delivery
headersobjectNoCustom HTTP headers for authentication
statusFilterarrayNoFilter by execution status (for STATUS_CHANGE events)
payloadTypestringYesFormat of the webhook payload
transformstringConditionalJSONata expression (required for TRANSFORM/FORM_TRANSFORM)
formPayloadKeystringNoForm field name for JSON payload (default: payload)
formDocumentKeystringNoForm field name for documents (default: documents)
enabledbooleanNoWhether the hook is active (default: true)
createdAttimestampNoAuto-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:

  • payload field: The transformed JSON data
  • documents field(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 (or multipart/form-data for FORM_TRANSFORM)
  • Custom Headers: Included as specified in hook configuration

Supported Media Types

When using FORM_TRANSFORM, the following file types are automatically detected:

ExtensionContent-Type
.pdfapplication/pdf
.pngimage/png
.jpg, .jpegimage/jpeg
.gifimage/gif
.webpimage/webp
.tiff, .tifimage/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

  1. Use status filters - Avoid unnecessary webhook traffic by filtering for specific statuses
  2. Implement idempotency - Your webhook endpoint should handle duplicate deliveries gracefully
  3. Validate payloads - Always validate incoming webhook data before processing
  4. Use HTTPS - Always use HTTPS endpoints for webhook delivery
  5. Authenticate webhooks - Use custom headers to verify webhook authenticity
  6. Handle timeouts - Respond quickly to webhook requests (under 30 seconds)
  7. Test with submit - Use the submit endpoint to test webhook configurations before enabling automatic triggers

Troubleshooting

Webhooks Not Firing

  1. Verify the hook is enabled (enabled: true)
  2. Check that the hook ID is attached to the execution
  3. Confirm the event type matches the expected trigger
  4. For STATUS_CHANGE, verify the status is in statusFilter

Payload Transformation Errors

  1. Validate your JSONata expression at try.jsonata.org
  2. Ensure required fields (transform) are provided for TRANSFORM/FORM_TRANSFORM types
  3. Check that the observation data structure matches your transformation expectations

Delivery Failures

  1. Verify the endpoint URL is accessible
  2. Check that custom headers are correctly formatted
  3. Ensure your server responds within 30 seconds
  4. Review server logs for authentication or validation errors