Provenance
Inbound Webhooks

Overview

Receive webhook events from external services and convert them into provenance interactions automatically.

Inbound Webhooks let you receive events from external services — Stripe, GitHub, Twilio, or any system that sends webhooks — and automatically convert them into provenance interactions. No custom integration code required.

How it works

External Service → Webhook URL → Source Validation → Mapping Match → Interaction Created
  1. An external service sends a webhook to your Provenance inbound URL
  2. The source validates the request (signature verification, schema validation)
  3. The mapping matches the payload against filter conditions and determines which resource type + action to use
  4. Field mappings extract data from the payload into the interaction metadata
  5. A provenance interaction is created automatically

Key concepts

Sources

A source represents an external service sending webhooks. Each source has:

  • A unique mnemonic (e.g. STRIPE, GITHUB)
  • An origin — interactions from this source are tagged with this origin
  • Signature verification — HMAC-SHA256, HMAC-SHA1, or plain comparison
  • Payload schema — optional AJV schema to validate incoming payloads at the source level
  • A webhook URL — unique per source, includes your tenant slug

Mappings

A mapping defines how a specific type of webhook payload becomes a provenance interaction. Each mapping belongs to a source and specifies:

  • Resource type and action — what kind of interaction to create
  • Filter conditions — match specific payloads (e.g. only checkout.session.completed events)
  • Schema validation — optional AJV schema for mapping-level validation, with support for targeting a nested sub-object via schemaRootPath
  • Field mappings — extract values from the payload into the interaction metadata
  • Resource ID path — which payload field to use as the resource ID
  • Metadata paths — map payload fields to interaction metadata like userId, sessionId, uowId
  • Priority — when multiple mappings match, the highest priority wins

Processing pipeline

When a webhook arrives:

  1. Source lookup — resolve the source from the URL (by ID or mnemonic)
  2. Signature verification — validate the request signature using the source's secret and algorithm
  3. Source schema validation — if the source has a payload schema, validate the raw payload
  4. Mapping selection — find all active mappings for this source, filter by conditions, pick the highest priority match
  5. Mapping schema validation — if the matched mapping has a payload schema, validate (optionally against a sub-object via schemaRootPath)
  6. Deduplication — if the mapping has an idempotency path, check for duplicate interactions
  7. Interaction creation — extract fields, build the interaction, and insert it

Webhook URLs

Each source gets two webhook URLs:

# By source ID
POST /api/inbound/:tenantSlug/:sourceId

# By mnemonic (human-readable)
POST /api/inbound/:tenantSlug/by-mnemonic/:mnemonic

Both are unauthenticated — security is handled by signature verification.

Sync mode (development)

For local testing, append ?sync=true to process the webhook synchronously instead of through the queue:

POST /api/inbound/:tenantSlug/:sourceId?sync=true

This is disabled in production (NODE_ENV=production).

API reference

MethodEndpointDescription
GET/api/inbound-sourcesList all sources
GET/api/inbound-sources/:idGet source by ID
POST/api/inbound-sourcesCreate source
PUT/api/inbound-sources/:idUpdate source
DELETE/api/inbound-sources/:idDelete source
GET/api/inbound-mappingsList all mappings
GET/api/inbound-mappings/:idGet mapping by ID
POST/api/inbound-mappingsCreate mapping
PUT/api/inbound-mappings/:idUpdate mapping
DELETE/api/inbound-mappings/:idDelete mapping
POST/api/inbound-mappings/:id/testTest mapping with sample payload
POST/api/inbound/:slug/:sourceIdReceive webhook (by source ID)
POST/api/inbound/:slug/by-mnemonic/:mnemonicReceive webhook (by mnemonic)