Inbound Webhook Mappings
Connect external services like Clerk, Stripe, and Supabase to Molted Email without writing code.
Inbound webhook mappings let you receive webhooks from external services and automatically route data into Molted features -- sync contacts, subscribe to lists, or trigger journeys. No code required.
How it works
- Create an inbound webhook mapping in Molted
- Get a unique webhook URL (e.g.,
https://api.molted.email/v1/hooks/ink_abc123...) - Paste that URL into your provider's webhook settings
- Configure where the email lives in the payload, field mappings, and actions
When the provider sends a webhook, Molted extracts the email address, maps fields, and executes your configured actions.
Creating a webhook mapping
Via CLI
molted inbound-hooks create \
--name "Clerk Signups" \
--source clerk \
--email-path "data.email_addresses[0].email_address" \
--field-map "name=data.first_name" \
--field-map "clerkId=data.id" \
--action "sync_contact" \
--action "subscribe_to_list:lst_abc"Via API
POST /v1/agent/inbound-hooks
{
"name": "Clerk Signups",
"source": "clerk",
"emailPath": "data.email_addresses[0].email_address",
"fieldMappings": {
"name": "data.first_name",
"clerkId": "data.id"
},
"actions": [
{ "type": "sync_contact" },
{ "type": "subscribe_to_list", "listId": "lst_abc" }
]
}The response includes a urlToken field. Your webhook URL is:
https://api.molted.email/v1/hooks/{urlToken}Email path syntax
The emailPath field uses dot notation with array index support to extract the email address from any JSON payload structure:
| Provider | Email path |
|---|---|
| Clerk | data.email_addresses[0].email_address |
| Stripe | data.object.email |
| Supabase Auth | record.email |
| Custom | Any valid dot-notation path |
Field mappings
Map fields from the incoming payload to contact metadata:
{
"name": "data.first_name",
"company": "data.organization.name",
"plan": "data.metadata.plan"
}Mapped fields are stored as contact metadata and passed to list subscriber metadata.
Action types
Actions execute sequentially in the order configured.
| Action | Description | Parameter |
|---|---|---|
sync_contact | Upsert contact with mapped fields | None |
subscribe_to_list | Add contact to a list | listId (required) |
trigger_journey | Fire an event to start a journey | eventName (required) |
If an action fails, subsequent actions still execute. Failed actions are logged but don't block the webhook response.
Managing webhooks
# List all inbound webhook mappings
molted inbound-hooks list
# Get details for a specific webhook
molted inbound-hooks get <id>
# Update a webhook (e.g., disable it)
molted inbound-hooks update <id> --enabled false
# Delete a webhook
molted inbound-hooks delete <id>
# View recent delivery logs
molted inbound-hooks logs <id>Security model
This MVP does not perform provider-side signature verification (Svix, HMAC, etc.). The receiver endpoint is authenticated by the URL token alone -- anyone with the URL can trigger the configured actions. Treat tokens as secrets:
- Paste the URL directly into the provider dashboard; avoid logging or committing it
- If a URL leaks, delete and recreate the webhook mapping to rotate the token
- Per-token rate limit: 120 requests per 60 seconds. Excess deliveries receive
429
Signature verification is tracked as a post-MVP enhancement.
Delivery logs
Each webhook delivery is logged with:
- Timestamp and source IP
- Processing status (
processed,partial,failed,rejected) - Per-action execution results
- Error messages for failed actions
molted inbound-hooks logs <id> --limit 10Provider setup examples
Clerk
- Create the webhook mapping:
molted inbound-hooks create \ --name "Clerk user.created" \ --source clerk \ --email-path "data.email_addresses[0].email_address" \ --field-map "name=data.first_name" \ --action "sync_contact" \ --action "subscribe_to_list:<your-list-id>" - In the Clerk Dashboard, go to Webhooks and add a new endpoint
- Paste your Molted webhook URL
- Subscribe to the
user.createdevent
Stripe
- Create the webhook mapping:
molted inbound-hooks create \ --name "Stripe customer.created" \ --source stripe \ --email-path "data.object.email" \ --field-map "name=data.object.name" \ --field-map "stripeId=data.object.id" \ --action "sync_contact" - In the Stripe Dashboard, go to Developers > Webhooks
- Add your Molted webhook URL
- Select the
customer.createdevent