Your webhook endpoint must be publicly accessible.
Setup
import { KadoaClient } from "@kadoa/node-sdk";
const client = new KadoaClient({ apiKey: "YOUR_API_KEY" });
await client.notification.setupForWorkflow({
workflowId: "YOUR_WORKFLOW_ID",
events: ["workflow_data_change"],
channels: {
WEBHOOK: {
name: "my-webhook",
webhookUrl: "https://api.example.com/webhooks/kadoa",
httpMethod: "POST",
},
},
});
from kadoa_sdk import KadoaClient, KadoaClientConfig
from kadoa_sdk.notifications import SetupWorkflowNotificationSettingsRequest
client = KadoaClient(KadoaClientConfig(api_key="YOUR_API_KEY"))
client.notification.setup_for_workflow(
SetupWorkflowNotificationSettingsRequest(
workflow_id="YOUR_WORKFLOW_ID",
events=["workflow_data_change"],
channels={
"WEBHOOK": {
"name": "my-webhook",
"webhookUrl": "https://api.example.com/webhooks/kadoa",
"httpMethod": "POST",
}
},
)
)
Dashboard Setup
- Go to Notifications in the sidebar
- Click Add Channel → Webhook
- Enter your endpoint URL
- Save changes

Authentication
Add custom headers for webhook authentication:// POST /v5/notifications/channels
{
"channelType": "WEBHOOK",
"name": "Authenticated Webhook",
"config": {
"webhookUrl": "https://api.example.com/webhooks/kadoa",
"httpMethod": "POST",
"auth": {
"type": "HEADER",
"headers": {
"Authorization": "Bearer your-secret-token",
"X-Custom-Header": "custom-value"
}
}
}
}
Request Format
Every webhook request includes:| Header | Description |
|---|---|
Content-Type | application/json |
X-Kadoa-Event | Event type (e.g., workflow_data_change) |
Payload Reference
All payloads follow this structure:{
"eventType": "event_name",
"timestamp": "2025-01-15T10:30:00Z",
"data": { /* event-specific data */ }
}
{
"eventType": "workflow_data_change",
"timestamp": "2025-01-15T10:30:00Z",
"data": {
"id": "change_123",
"workflowId": "wf_123",
"data": [
{ "id": "record-1", "name": "Product A", "price": 29.99 }
],
"differences": [
{
"type": "changed",
"fields": [
{ "key": "price", "value": 29.99, "previousValue": 24.99 }
]
},
{
"type": "added",
"fields": [
{ "key": "id", "value": "record-2" },
{ "key": "name", "value": "New Product" }
]
}
],
"url": "https://monitored-page.com",
"createdAt": "2025-01-15T10:30:00Z",
"metadata": {
"workflowName": "Product Monitor",
"tags": ["pricing"]
}
}
}
{
"eventType": "workflow_finished",
"timestamp": "2025-01-15T10:30:00Z",
"data": {
"id": "wf_123",
"jobId": "job_456",
"source": "scheduler"
}
}
{
"eventType": "workflow_failed",
"timestamp": "2025-01-15T10:30:00Z",
"data": {
"workflowId": "wf_123",
"workflowName": "Product Monitor",
"source": "Product Monitor",
"sourceUrl": "https://monitored-page.com",
"url": "https://monitored-page.com",
"reason": "Access blocked by bot protection",
"action": "No action needed. We'll email you when the workflow recovers."
}
}
{
"eventType": "workflow_recovered",
"timestamp": "2025-01-15T10:45:00Z",
"data": {
"workflowId": "wf_123",
"workflowName": "Product Monitor",
"source": "Product Monitor",
"sourceUrl": "https://monitored-page.com",
"url": "https://monitored-page.com"
}
}
{
"eventType": "workflow_data_quality_change",
"timestamp": "2025-01-15T10:30:00Z",
"data": {
"workflowId": "wf_123",
"jobId": "job_456",
"previousJobId": "job_455",
"workflowName": "Product Monitor",
"createdAt": "2025-01-15T10:30:00Z",
"dataQualityIssues": { "current": 4, "previous": 2 },
"rowViolations": { "current": 4, "previous": 2 },
"currentSummary": {
"schemaValidation": {
"rowViolationCount": 4,
"rules": null,
"columns": [
{ "name": "price", "violations": [{ "kind": "ROW_COUNT", "ruleKey": "presence", "count": 4 }] }
]
},
"completeness": { "score": 90, "actualRowCount": 48, "expectedRowCount": 52, "signalCount": 2, "cappedByLimit": false },
"semanticPlausibility": { "score": 98, "flaggedColumns": [] }
},
"previousSummary": {
"schemaValidation": {
"rowViolationCount": 2,
"rules": null,
"columns": [
{ "name": "price", "violations": [{ "kind": "ROW_COUNT", "ruleKey": "presence", "count": 2 }] }
]
},
"completeness": { "score": 96, "actualRowCount": 50, "expectedRowCount": 52, "signalCount": 2, "cappedByLimit": false },
"semanticPlausibility": { "score": 98, "flaggedColumns": [] }
}
}
}
workflow_failed fields: required workflowId, source, reason, action; optional workflowName, sourceUrl, url.
workflow_recovered fields: required workflowId, workflowName, source; optional sourceUrl, url.
| Event | Description |
|---|---|
workflow_data_change | Monitored data changes. Difference types: changed, added, removed |
workflow_finished | Workflow completes successfully |
workflow_failed | Workflow fails. Includes reason and a human-readable action. |
workflow_recovered | Workflow recovers after failure. Sent via workflow_failed subscription; suppressed if workflow_finished is also configured. |
workflow_data_quality_change | Data quality issues of a run change. Formerly workflow_validation_anomaly_change. |
Error Handling
Kadoa retries failed webhook deliveries with exponential backoff:| Attempt | Delay |
|---|---|
| 1st retry | 1 second |
| 2nd retry | 2 seconds |
| 3rd retry | 4 seconds |
2xx status code to acknowledge receipt.