| name | posthog-webhooks-events |
| description | Implement PostHog webhook destinations, Action-triggered notifications,
and event querying via the Events API and HogQL.
Trigger: "posthog webhook", "posthog events API", "posthog actions",
"posthog notifications", "posthog event query", "posthog HogQL".
|
| allowed-tools | Read, Write, Edit, Bash(curl:*) |
| version | 1.12.0 |
| license | MIT |
| author | Jeremy Longshore <jeremy@intentsolutions.io> |
| tags | ["saas","posthog","webhooks"] |
| compatibility | Designed for Claude Code, also compatible with Codex and OpenClaw |
PostHog Webhooks & Events
Overview
PostHog sends webhooks via its CDP (Customer Data Platform) Destinations feature. You configure a Destination that fires when matching events are captured, sending an HTTP POST to your endpoint. This skill covers webhook destination setup, receiving and processing webhook payloads, querying events via the API, and using HogQL for custom event analysis.
Prerequisites
- PostHog project with personal API key (
phx_...)
- HTTPS endpoint to receive webhooks
- Events being captured in PostHog
Instructions
Step 1: Create a Webhook Destination via API
set -euo pipefail
curl -X POST "https://app.posthog.com/api/projects/$POSTHOG_PROJECT_ID/pipeline_destinations/" \
-H "Authorization: Bearer $POSTHOG_PERSONAL_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Signup Notifications",
"description": "Send webhook when user signs up",
"config": {
"url": "https://your-app.com/webhooks/posthog",
"method": "POST",
"headers": {
"X-Webhook-Secret": "your-webhook-secret"
},
"body": {
"event": "{event}",
"distinct_id": "{distinct_id}",
"person": "{person}",
"properties": "{properties}",
"timestamp": "{timestamp}"
}
},
"filters": {
"events": [
{"id": "user_signed_up", "type": "events"},
{"id": "subscription_started", "type": "events"}
]
}
}'
Step 2: Receive and Process Webhooks
import { NextResponse } from 'next/server';
import crypto from 'crypto';
const WEBHOOK_SECRET = process.env.POSTHOG_WEBHOOK_SECRET!;
function verifySignature(): {
expected = crypto.(, )
.(payload)
.();
crypto.(.(signature), .(expected));
}
{
: ;
: ;
: <, >;
: {
: <, >;
};
: ;
}
() {
body = request.();
signature = request..() || ;
( && signature !== ) {
.({ : }, { : });
}
: = .(body);
(payload.) {
:
(payload);
;
:
(payload);
;
:
(payload);
;
:
.();
}
.({ : });
}
() {
{ distinct_id, properties, person } = payload;
.();
(, {
: ,
: { : },
: .({
: [
{ : , : person.. },
{ : , : distinct_id },
],
}),
});
(process..!, {
: ,
: .({
: ,
}),
});
}
() {
.();
}
() {
.();
}