Enable datasource-root webhook so vendors can POST to the platform receiver. Inbound auth is always webhookInbound. events[] then chooses the path: vendor change names refresh through CIP get; names that match a capability key run that governed operation.
Prerequisites
- Connected System
authentications[]slot withusage: webhookInbound(see Authentication methods catalog and Configure authentication) - Change-signal events (vendor names that are not capability keys): capability
get, CIPoperations.get,idPath, plus rootresourceType/primaryKey - Capability events (
create,update,delete, or a custom camelCase key on this entity): that capability must exist;getandidPathare not required for this mode
Where it lives
| Layer | Location |
|---|---|
| Webhook band | <datasourceKey>.json → root webhook |
| Inbound auth | <systemKey>-system.json → authentications[] usage: webhookInbound |
| UI | Business Entity Sync tab — webhook summary / receiver URLs (when available) |
Manifest keys are on the Business Entity root (not under sync).
Builder MCP
| Manifest section | Datasource root webhook |
| Auth slot | System authentications[] — help topics for authentication |
| Repair hooks | aifabrix repair <systemKey> --auth-webhook |
How to set
- Add or repair webhook inbound auth (required for both modes):
aifabrix repair <systemKey> --auth-webhook
aifabrix validate <systemKey>
- Choose dispatch with
events[]— do not mix both kinds on one entity.
events[] entry |
Runtime |
|---|---|
Capability key on this entity (create, update, delete, or custom camelCase) |
Run that CIP operation. fieldMappings reshape the vendor body. |
| Any other name (typical dotted vendor events) | Create a sync intent, then CIP get using idPath. |
- Author
webhook(JSONPaths only — no HTTP header names on this object).
Change-signal example:
{
"webhook": {
"enabled": true,
"endpointMode": "datasource",
"events": ["record.updated", "record.created"],
"deleteEvents": ["record.deleted"],
"idPath": "$.objectId",
"eventTypePath": "$.subscriptionType",
"vendorDeliveryIdPath": "$.deliveryId"
}
}
Capability-inbound example (endpointMode: datasource gives one URL per entity):
{
"webhook": {
"enabled": true,
"endpointMode": "datasource",
"events": ["create"]
}
}
- Wire secrets for the
webhookInboundslot inenv.template(kv://…) — never commit values. Keep outboundusage: apiseparate (bot token vs signing secret). - Validate and upload, then register the generated POST URL with the vendor.
Defaults and examples
| Field | Role |
|---|---|
enabled |
Default false — set true to accept POSTs |
endpointMode |
system | datasource | event — scopes the generated path |
events |
Names that either match a capability key or trigger sync intents (min 1 when enabling) |
deleteEvents |
Optional subset of change-signal events → local soft-delete / inactive only |
idPath |
JSONPath to vendor object id — required for change-signal refresh, not for capability events |
eventTypePath |
JSONPath to event type when mode is not event and multiple events |
vendorDeliveryIdPath |
JSONPath to delivery id for idempotent dedupe |
Generated POST paths
endpointMode |
Path pattern |
|---|---|
system |
/webhooks/{systemKey} |
datasource |
/webhooks/{systemKey}/{datasourceKey} |
event |
/webhooks/{systemKey}/{datasourceKey}/{eventKey} |
Headers vs JSONPaths (schema 2.9.2+)
| Concern | Where it lives |
|---|---|
| Event type / delivery id in JSON body | webhook.eventTypePath, webhook.vendorDeliveryIdPath |
| HTTP header names for inbound auth / routing | Connected System webhookInbound credential config only — not on webhook |
Do not put eventTypeHeader or vendorDeliveryIdHeader on the datasource webhook object — those fields were removed from the schema. Use credential-slot config for headers.
Validate
aifabrix validate <systemKey>
aifabrix test-integration <systemKey>
Confirm webhookInbound when webhook.enabled: true. For change-signal events, prove CIP get (datasource test-e2e) before live vendor traffic. For capability events, prove the named operation (structure / integration tests) — do not add a fake get to pass certification.
Common mistakes
| Mistake | Fix |
|---|---|
| Mixing dotted vendor events and capability keys on one entity | Use two Business Entities, or one event kind per entity |
| Mapping change-signal body fields into storage | Configure CIP get + fieldMappings |
| Capability inbound without fieldMappings | Map the vendor body on that operation |
HTTP header names on webhook |
Move to webhookInbound credential slot |
Requiring get / idPath for capability-only events[] |
Those fields are for change-signal refresh only |
Confusing webhook with syncBridge |
Webhook = inbound POST; syncBridge = enterprise propagation |
| User OAuth for inbound workers | Use service-capable credentials for webhookInbound |
Signing secret on the api slot |
Split api (outbound) vs webhookInbound (inbound) |
Limits
Webhook coverage depends on the vendor and deployment. Capability-named events[] run that CIP operation on the same generated POST URL; other names stay change-signal plus CIP get. Confirm capability dispatch is live before registering Request URLs. Cross-datasource propagation after a change signal: Configure sync bridge.
Concept framing: Enterprise webhooks. Auth slots: Configure authentication.