name: my-webhook-api version: 1.0.0 description: > Inbound webhook endpoints for non-funnel sources — Stripe, GitHub, custom services. Funnel forms use the my-funnel-api proxy. triggers: [webhook, inbound, receiver, stripe events, github webhook, slack notification, delivery, payload, event ingest] checksum: sha256-pending
MyWebhookAPI
Per-org HTTP endpoints that accept inbound POSTs and durably store every delivery. A webhook on its own is a passive receiver — pair it with myworkflowapi to react to incoming events.
Capabilities
Scope: non-funnel inbound. Use this for Stripe → MyAPI, GitHub → MyAPI, custom services → MyAPI, anything where an external system POSTs to you. Funnel forms use the funnel proxy (see my-funnel-api: myapi funnel form ... --capture-to webhook:<id> if you need to bind a specific destination; otherwise the funnel's auto-provisioned webhook handles it). Don't hardcode api.mywebhookapi.com/webhook/in/<slug> URLs into funnel HTML.
Each endpoint has a unique inbound URL minted at create time. Anyone who knows the URL can POST to it; the body is stored verbatim along with headers and a timestamp. Deliveries are kept indefinitely (until you delete the endpoint).
The inbound URL accepts any JSON body — no enforced schema, no required fields. Whatever you POST is what gets stored. Two consequences:
- You decide the shape. Form submission, Stripe event, custom payload — all work. Be consistent within one webhook so downstream workflows can reference fields reliably.
- Workflows reference fields with
{{ payload.field }}templating. If your form POSTs{"email":"alice@x.com","message":"hi"}, a workflow step can do--to "{{ payload.email }}"to send a reply.
Treat the webhook slug as a secret — anyone with the URL can POST.
Commands
| Command | What it does |
|---|---|
myapi webhook create "<name>" [--description "..."] |
Create an endpoint, returns id + inbound URL |
myapi webhook list |
List all endpoints in your org |
myapi webhook delete <id> |
Delete an endpoint and all its deliveries |
myapi webhook delivery <delivery_id> |
Get the full payload + headers for one delivery |
Examples
# 1. Create a webhook
myapi webhook create "stripe-events" --description "Stripe payment events"
# → prints: Inbound URL: https://api.mywebhookapi.com/webhook/in/<slug>
# 2. POST to it from your service
curl -X POST https://api.mywebhookapi.com/webhook/in/<slug> \
-H "Content-Type: application/json" \
-d '{"event":"payment.succeeded"}'
# → responds with {"delivery_id":"<uuid>"} — capture this to inspect later
# 3. Inspect a delivery by id (there is no list-deliveries route)
myapi webhook delivery <delivery_id>
End-to-end recipe — contact form on your site
A contact form on yoursite.com that sends a thank-you email and a Slack ping when submitted:
WID=$(myapi webhook create "contact-form" --json | jq -r .id)
WURL=$(myapi webhook list --json | jq -r ".[] | select(.id==\"$WID\") | .url")
myapi workflow create "Contact form handler" \
--endpoint-id $WID \
--steps '[
{"type":"send_email","from":"hello@yoursite.com","to":"{{ payload.email }}","subject":"Thanks, {{ payload.name }}!","body":"We got your message."},
{"type":"slack","webhook_url":"https://hooks.slack.com/...","text":"New form submission from {{ payload.name }}"}
]'
# Drop this in your HTML — POSTs JSON to $WURL
echo "<form id='c'>
<input name='name' required>
<input name='email' type='email' required>
<textarea name='message' required></textarea>
<button>Send</button>
</form>
<script>
document.getElementById('c').onsubmit = async e => {
e.preventDefault();
await fetch('$WURL', {method:'POST', headers:{'Content-Type':'application/json'}, body: JSON.stringify(Object.fromEntries(new FormData(e.target)))});
alert('Thanks!');
};
</script>"
The form sends {name, email, message} → webhook stores it → workflow runs both steps → email + Slack ping.
Notes
- The inbound URL is public — anyone with it can POST. Treat the slug as a secret.
- Deliveries are kept indefinitely. Delete the endpoint to purge them.
- Failed workflow runs don't affect the delivery record — the inbound POST is always saved.
- Inbound responses:
200on success,4xxif the endpoint is missing or body isn't valid JSON.
Run myapi webhook --help for full flag reference.