Outbound Integrations (iPaaS)
Ductor as the source — the iPaaS webhook adapter that pushes domain events to Zapier/n8n/custom consumers, and the n8n community node.
Most of this section is about Ductor reaching out to providers, or providers reaching in through triggers. Outbound integrations are the opposite direction of a different kind: Ductor as the event source for an external automation platform (iPaaS) like Zapier, n8n, or a custom endpoint. When a unit of Work is routed or a worker goes down, Ductor pushes that event to whatever the customer wired up on the other side.
Here the usual framing inverts: Zapier and n8n are downstream consumers of the clearing layer, not competitors to it. Ductor clears the work — prices it, routes it, executes it, settles it — and emits the lifecycle events those platforms react to. They automate what happens after a decision; Ductor is what made the decision.
Not the same as inbound provider webhooks
This is distinct from the Ductor-owned provider webhook subscriptions in Triggers & Polling, which receive events from providers. Here Ductor is the sender: it signs and delivers its own domain events to external consumers.
The iPaaS webhook adapter
The webhook adapter (modules/integrations/webhook/adapter.go) bridges Ductor's
internal event system to external webhook consumers. It subscribes to a fixed set
of domain events and maps them to stable iPaaS event types:
| iPaaS event | Mapped from domain event |
|---|---|
lead.routed | RoutableAssigned |
recipient.down | RecipientStateChanged (only when the new state is down / unhealthy / failed) |
budget.exhausted | RecipientCapacityChanged |
quality.alert | quality TierChanged and ProbationEnter |
sla.breach | SLA breach |
A Registration (id, URL, optional secret, and an events allowlist — empty or
* means all) receives a standardized WebhookPayload (id, event,
timestamp, tenant_id, data). An event whose type isn't mapped is dropped
before delivery, and recipient.down only fires on an actual failure transition.
Signing and retries
When a registration has a secret, each delivery is signed per the
Standard Webhooks spec — SignPayload computes
HMAC-SHA256 over {msg_id}.{timestamp}.{body}, encodes it as v1,<base64>, and
sets the X-Webhook-ID, X-Webhook-Timestamp, and X-Webhook-Signature headers.
Consumers verify with VerifySignature (constant-time compare). Delivery retries
with exponential backoff (MaxRetries, RetryBaseDelay), treating any non-2xx
response as a failure to retry.
The n8n community node
For n8n specifically, Ductor ships a community node package
(modules/integrations/n8n/) with three TypeScript entry points:
Ductor.node.ts— the action node (Ductor as a step in an n8n workflow).DuctorTrigger.node.ts— the trigger node (n8n workflows started by Ductor events).Ductor.credentials.ts— theductorApicredential used to authenticate.
Each operation's HTTP method and path come from an explicit route table
(routes.ts) derived from the google.api.http annotations on the proto
services, so every action maps to a REST endpoint that actually exists.
Action node
The action node lets an n8n builder manage Ductor routing objects and push leads without writing HTTP calls by hand. Four resources — Pool, Recipient, Rule, and Publisher — expose full CRUD. Lead is create-only, because a lead is routed, not stored as a collection.
| Resource | Operations | Routing notes |
|---|---|---|
| Pool | get, getAll, create, update, delete | update is a PATCH to /api/pools/{id}. |
| Recipient | get, getAll, create, update, delete | create and getAll are pool-scoped (/api/pools/{pool_id}/recipients); get / update / delete address a recipient by id (/api/recipients/{id}). |
| Rule | get, getAll, create, update, delete | Same shape as Recipient — pool-scoped create/list, id-scoped get/update/delete. |
| Publisher | get, getAll, create, update, delete | update is a PUT to /api/publishers/{id}. |
| Lead | create | Routes a lead through POST /api/route and returns the routing decision. |
Lead is create-only now
Earlier versions of the node listed get/getAll/update/delete on Lead and
targeted /api/v2/{resource}s paths that did not exist — every one of those
operations returned 404. The node now offers only Create on Lead, which
posts the routable to /api/route, and routes the remaining resources through
the verified route table above.
Trigger node and signature verification
The trigger node registers a webhook subscription through the API and then receives the iPaaS events listed above at the n8n webhook URL.
When you set a Webhook Secret on the trigger, the node verifies every
delivery before handing it to the workflow: it recomputes the HMAC-SHA256 over
{id}.{timestamp}.{body}, compares it in constant time against the
X-Webhook-Signature header (keyed by X-Webhook-ID and X-Webhook-Timestamp),
and rejects a mismatch with 401. The v1,<base64> format and inputs mirror
SignPayload in the webhook adapter exactly, so a forged or tampered payload
never reaches your workflow.
Set a webhook secret
Configuring a secret is strongly recommended. When it is left empty the trigger
passes deliveries through without verification — anyone who learns the
webhook URL could post events to it. Set a secret and only deliveries signed by
Ductor are accepted; everything else is rejected with 401.
Where to go next
- SDKs — programmatic integration when a webhook or n8n node isn't the right fit.
- Triggers & Polling — the inbound, Ductor-owned provider webhook side.
External MCP Providers
Import a remote MCP server's tools as governed Ductor connector actions, with metadata and executable imports kept separate and every call re-gated.
Action Assurance
The certified/community axis — what a certified claim carries, why expiry and revocation downgrade at read time, and how an agent surface can require certified before auto-executing.