Webhooks & Events API
Outgoing webhooks, incoming webhooks, event subscriptions, and real-time event streaming.
Overview
The Webhooks & Events system provides both outgoing webhooks (push notifications to your servers) and incoming webhooks (receive data from external services). The event system allows fine-grained subscriptions, event tracing, and workflow triggers.
Outgoing Webhooks
Outgoing webhooks send HTTP POST requests to your endpoints when events occur in Arcanflows.
List Webhooks
GET /api/v1/webhooks
Query Parameters:
| Parameter | Type | Description |
|---|---|---|
page | integer | Page number (default: 1) |
per_page | integer | Items per page (default: 20) |
active | boolean | Filter by active status |
Create Webhook
POST /api/v1/webhooks
Request Body:
| Field | Type | Required | Description |
|---|---|---|---|
url | string | Yes | HTTPS endpoint URL |
events | string[] | Yes | Event types to subscribe to |
active | boolean | No | Enable immediately (default: true) |
description | string | No | Human-readable description |
headers | object | No | Custom headers to include |
bashcurl -X POST /api/v1/webhooks \ -H "Authorization: Bearer your_api_key" \ -H "Content-Type: application/json" \ -d '{ "url": "https://your-server.com/webhook", "events": ["agent.chat.completed", "workflow.execution.completed"], "description": "Production webhook", "active": true }'
Response:
json{ "id": "wh_abc123", "url": "https://your-server.com/webhook", "events": ["agent.chat.completed", "workflow.execution.completed"], "active": true, "secret": "whsec_a1b2c3d4e5f6...", "description": "Production webhook", "created_at": "2026-01-15T10:00:00Z" }
Important: The
secretis only returned on creation. Store it securely for signature verification.
Get Webhook
GET /api/v1/webhooks/:id
Update Webhook
PUT /api/v1/webhooks/:id
Delete Webhook
DELETE /api/v1/webhooks/:id
Send Test Event
POST /api/v1/webhooks/:id/test
Sends a test event to the webhook endpoint to verify connectivity.
bashcurl -X POST /api/v1/webhooks/wh_abc123/test \ -H "Authorization: Bearer your_api_key" \ -H "Content-Type: application/json" \ -d '{"event_type": "workflow.execution.completed"}'
Delivery History
GET /api/v1/webhooks/:id/executions
Query Parameters:
| Parameter | Type | Description |
|---|---|---|
page | integer | Page number |
per_page | integer | Items per page |
status | string | Filter: delivered, failed, pending |
Response:
json{ "data": [ { "id": "del_abc123", "event_id": "evt_xyz789", "event_type": "workflow.execution.completed", "status": "delivered", "response_code": 200, "response_time_ms": 145, "attempt": 1, "created_at": "2026-01-15T10:30:00Z" } ], "total": 42, "page": 1, "per_page": 20 }
Incoming Webhooks
Incoming webhooks let external services send data into Arcanflows. Each incoming webhook gets a unique public URL that can trigger workflows or store data.
List Incoming Webhooks
GET /api/v1/incoming-webhooks
Create Incoming Webhook
POST /api/v1/incoming-webhooks
Request Body:
| Field | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Display name |
slug | string | No | Custom URL slug (auto-generated if omitted) |
workflow_id | string | No | Workflow to trigger on receipt |
active | boolean | No | Enable immediately (default: true) |
bashcurl -X POST /api/v1/incoming-webhooks \ -H "Authorization: Bearer your_api_key" \ -H "Content-Type: application/json" \ -d '{ "name": "Stripe Payment Events", "slug": "stripe-payments", "workflow_id": "wf_abc123", "active": true }'
Response:
json{ "id": "iwh_abc123", "name": "Stripe Payment Events", "slug": "stripe-payments", "url": "https://api.arcanflows.io/webhooks/in/stripe-payments", "workflow_id": "wf_abc123", "active": true, "created_at": "2026-01-15T10:00:00Z" }
Get Incoming Webhook
GET /api/v1/incoming-webhooks/:id
List Received Events
GET /api/v1/incoming-webhooks/:id/events
Returns a log of all payloads received on this incoming webhook.
Receive Webhook (Public Endpoint)
POST /webhooks/in/:slug
This is the public URL that external services POST to. No authentication required. The payload is stored and optionally triggers the linked workflow.
bash# External service sends data to your incoming webhook curl -X POST https://api.arcanflows.io/webhooks/in/stripe-payments \ -H "Content-Type: application/json" \ -d '{"type": "payment_intent.succeeded", "data": {"amount": 2000}}'
Event Types
Arcanflows uses a structured event type system. Event types are organized by category and define the schema of event payloads.
List All Event Types
GET /api/v1/event-types
Response:
json{ "event_types": [ { "name": "agent.chat.completed", "category": "agent", "description": "Fired when an agent chat conversation ends", "schema": { "type": "object", "properties": { ... } } }, { "name": "workflow.execution.completed", "category": "workflow", "description": "Fired when a workflow execution finishes successfully" } ] }
Event Categories
GET /api/v1/event-types/categories
Returns grouped categories: agent, workflow, form, approval, data_table, system.
Get Event Type Details
GET /api/v1/event-types/:event_type
Returns full schema and documentation for a specific event type.
Available Events
Agent Events
| Event | Description |
|---|---|
agent.created | New agent created |
agent.updated | Agent settings changed |
agent.deleted | Agent deleted |
agent.published | Agent published |
agent.chat.started | Chat conversation started |
agent.chat.message | New message in conversation |
agent.chat.completed | Chat conversation ended |
Workflow Events
| Event | Description |
|---|---|
workflow.created | New workflow created |
workflow.updated | Workflow definition changed |
workflow.deleted | Workflow deleted |
workflow.published | Workflow published |
workflow.execution.started | Workflow execution began |
workflow.execution.completed | Workflow execution finished |
workflow.execution.failed | Workflow execution failed |
workflow.execution.node_completed | Individual node completed |
Form Events
| Event | Description |
|---|---|
form.created | New form created |
form.updated | Form configuration changed |
form.deleted | Form deleted |
form.published | Form published |
form.submission.created | New form submission |
form.submission.updated | Submission updated |
Approval Events
| Event | Description |
|---|---|
approval.requested | Approval request created |
approval.approved | Request approved |
approval.rejected | Request rejected |
approval.timeout | Request timed out |
Event Subscriptions
Event subscriptions connect event types to actions (webhook delivery, workflow trigger, notification, etc.).
List Subscriptions
GET /api/v1/event-subscriptions
Create Subscription
POST /api/v1/event-subscriptions
Request Body:
| Field | Type | Required | Description |
|---|---|---|---|
event_type | string | Yes | Event type to subscribe to (e.g., agent.chat.completed) |
action_type | string | Yes | Action: webhook, workflow, notification |
action_config | object | Yes | Action-specific configuration |
filters | object | No | Filter conditions for the event |
active | boolean | No | Enable immediately (default: true) |
bashcurl -X POST /api/v1/event-subscriptions \ -H "Authorization: Bearer your_api_key" \ -H "Content-Type: application/json" \ -d '{ "event_type": "form.submission.created", "action_type": "workflow", "action_config": { "workflow_id": "wf_abc123" }, "filters": { "form_id": "form_xyz789" } }'
Get Subscription
GET /api/v1/event-subscriptions/:id
Update Subscription
PUT /api/v1/event-subscriptions/:id
Delete Subscription
DELETE /api/v1/event-subscriptions/:id
Activate Workflow Subscription
POST /api/v1/workflows/:workflow_id/subscriptions/activate
Activates all event subscriptions linked to a workflow.
Deactivate Workflow Subscription
POST /api/v1/workflows/:workflow_id/subscriptions/deactivate
Deactivates all event subscriptions linked to a workflow.
Event Log
The event log provides an audit trail of all events emitted in your tenant.
List Events
GET /api/v1/event-log
Query Parameters:
| Parameter | Type | Description |
|---|---|---|
page | integer | Page number |
per_page | integer | Items per page |
event_type | string | Filter by event type |
from | string | Start date (ISO 8601) |
to | string | End date (ISO 8601) |
correlation_id | string | Filter by correlation ID |
Response:
json{ "data": [ { "id": "evt_abc123", "type": "workflow.execution.completed", "correlation_id": "corr_xyz789", "data": { "workflow_id": "wf_abc123", "execution_id": "exec_def456", "status": "completed" }, "created_at": "2026-01-15T10:30:00Z" } ], "total": 156, "page": 1, "per_page": 20 }
Get Event
GET /api/v1/event-log/:event_id
Trace Event Chain
GET /api/v1/event-log/trace/:correlation_id
Returns all events sharing the same correlation ID, allowing you to trace a chain of cause-and-effect events (e.g., form submission -> workflow execution -> notification sent).
Emit Test Event
POST /api/v1/events/test
Request Body:
json{ "event_type": "workflow.execution.completed", "data": { "workflow_id": "wf_test", "status": "completed" } }
Emits a test event that triggers all matching subscriptions. Useful for testing your event-driven workflows.
Webhook Security
Signature Verification
Every outgoing webhook includes HMAC-SHA256 signature headers:
X-Arcanflows-Signature: sha256=abc123...
X-Arcanflows-Timestamp: 1702469400
Verifying Signatures (Node.js)
javascriptconst crypto = require('crypto'); function verifyWebhookSignature(payload, signature, timestamp, secret) { // Reject if timestamp is older than 5 minutes (replay protection) const now = Math.floor(Date.now() / 1000); if (Math.abs(now - timestamp) > 300) { return false; } const signedPayload = `${timestamp}.${payload}`; const expected = crypto .createHmac('sha256', secret) .update(signedPayload) .digest('hex'); return crypto.timingSafeEqual( Buffer.from(signature), Buffer.from(`sha256=${expected}`) ); }
Verifying Signatures (Python)
pythonimport hmac, hashlib, time def verify_signature(payload: bytes, signature: str, timestamp: str, secret: str) -> bool: now = int(time.time()) if abs(now - int(timestamp)) > 300: return False signed_payload = f"{timestamp}.{payload.decode()}" expected = hmac.new(secret.encode(), signed_payload.encode(), hashlib.sha256).hexdigest() return hmac.compare_digest(signature, f"sha256={expected}")
Retry Policy
Failed webhook deliveries are retried with exponential backoff:
| Attempt | Delay | Cumulative |
|---|---|---|
| 1 | Immediate | 0 |
| 2 | 1 minute | 1 min |
| 3 | 5 minutes | 6 min |
| 4 | 30 minutes | 36 min |
| 5 | 2 hours | ~2.5 hrs |
| 6 | 8 hours | ~10.5 hrs |
| 7 | 24 hours | ~34.5 hrs |
After 7 failed attempts the delivery is marked as permanently failed. Retried requests include the header X-Arcanflows-Retry-Count.
Best Practices
- Respond quickly -- Return a 200 status immediately, then process the event asynchronously.
- Verify signatures -- Always validate the HMAC-SHA256 signature before processing.
- Handle duplicates -- Use the event
idfield for idempotency; the same event may be delivered more than once. - Use event subscriptions -- Prefer event subscriptions over webhooks when you want to trigger workflows automatically.
- Monitor delivery logs -- Check
/webhooks/:id/executionsregularly to catch failures early. - Use correlation IDs -- Trace related events using
/event-log/trace/:correlation_id.