PostHog
by @byungkyu
PostHog API integration with managed authentication. Product analytics, feature flags, session recordings, experiments, and more. Use this skill when users w...
clawhub install posthog-apiπ About This Skill
name: posthog description: | PostHog API integration with managed authentication. Product analytics, feature flags, session recordings, experiments, and more. Use this skill when users want to query analytics events, manage feature flags, analyze user behavior, view session recordings, or run A/B experiments. For other third party apps, use the api-gateway skill (https://clawhub.ai/byungkyu/api-gateway). compatibility: Requires network access and valid Maton API key metadata: author: maton version: "1.0" clawdbot: emoji: π¦ homepage: "https://maton.ai" requires: env: - MATON_API_KEY
PostHog
Access the PostHog API with managed authentication. Query product analytics events with HogQL, manage feature flags, analyze user behavior, view session recordings, and run A/B experiments.
Quick Start
# List projects
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/posthog/api/projects/')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
Base URL
https://api.maton.ai/posthog/{native-api-path}
Maton proxies requests to {subdomain}.posthog.com and automatically injects your credentials.
Authentication
All requests require the Maton API key in the Authorization header:
Authorization: Bearer $MATON_API_KEY
Environment Variable: Set your API key as MATON_API_KEY:
export MATON_API_KEY="YOUR_API_KEY"
Getting Your API Key
1. Sign in or create an account at maton.ai 2. Go to maton.ai/settings 3. Copy your API key
Connection Management
Manage your PostHog OAuth connections at https://api.maton.ai.
List Connections
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/connections?app=posthog&status=ACTIVE')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
Create Connection
python <<'EOF'
import urllib.request, os, json
data = json.dumps({'app': 'posthog'}).encode()
req = urllib.request.Request('https://api.maton.ai/connections', data=data, method='POST')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
req.add_header('Content-Type', 'application/json')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
Get Connection
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/connections/{connection_id}')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
Response:
{
"connection": {
"connection_id": "{connection_id}",
"status": "ACTIVE",
"creation_time": "2026-02-23T09:37:57.686121Z",
"last_updated_time": "2026-02-23T09:39:11.851118Z",
"url": "https://connect.maton.ai/?session_token=...",
"app": "posthog",
"metadata": {}
}
}
Open the returned url in a browser to complete OAuth authorization.
Delete Connection
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/connections/{connection_id}', method='DELETE')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
Specifying Connection
If you have multiple PostHog connections, specify which one to use with the Maton-Connection header:
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/posthog/api/projects/')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
req.add_header('Maton-Connection', '{connection_id}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
If you have multiple connections, always include this header to ensure requests go to the intended account.
Security & Permissions
API Reference
Organizations
#### Get Current Organization
GET /posthog/api/organizations/@current/
Projects
#### List Projects
GET /posthog/api/projects/
Response:
{
"count": 1,
"next": null,
"previous": null,
"results": [
{
"id": 136209,
"uuid": "019583c6-377c-0000-e55c-8696cbc33595",
"organization": "019583c6-3635-0000-5798-c18f20963b3b",
"api_token": "phc_XXX",
"name": "Default project",
"timezone": "UTC"
}
]
}
#### Get Current Project
GET /posthog/api/projects/@current/
Users
#### Get Current User
GET /posthog/api/users/@me/
Query (HogQL)
The query endpoint is the recommended way to retrieve events and run analytics queries.
#### Run HogQL Query
POST /posthog/api/projects/{project_id}/query/
Content-Type: application/json{
"query": {
"kind": "HogQLQuery",
"query": "SELECT event, count() FROM events GROUP BY event ORDER BY count() DESC LIMIT 10"
}
}
Response:
{
"columns": ["event", "count()"],
"results": [
["$pageview", 140504],
["$autocapture", 108691],
["$identify", 5455]
],
"types": [
["event", "String"],
["count()", "UInt64"]
]
}
Persons
#### List Persons
GET /posthog/api/projects/{project_id}/persons/?limit=10
Response:
{
"results": [
{
"id": "5d79eecb-93e6-5c8b-90f9-8510ba4040b8",
"uuid": "5d79eecb-93e6-5c8b-90f9-8510ba4040b8",
"name": "user@example.com",
"is_identified": true,
"distinct_ids": ["user-uuid", "anon-uuid"],
"properties": {
"email": "user@example.com",
"name": "John Doe"
}
}
],
"next": "https://us.posthog.com/api/projects/{project_id}/persons/?limit=10&offset=10"
}
#### Get Person
GET /posthog/api/projects/{project_id}/persons/{person_uuid}/
Dashboards
#### List Dashboards
GET /posthog/api/projects/{project_id}/dashboards/
#### Get Dashboard
GET /posthog/api/projects/{project_id}/dashboards/{dashboard_id}/
#### Create Dashboard
POST /posthog/api/projects/{project_id}/dashboards/
Content-Type: application/json{
"name": "My Dashboard",
"description": "Analytics overview"
}
#### Update Dashboard
PATCH /posthog/api/projects/{project_id}/dashboards/{dashboard_id}/
Content-Type: application/json{
"name": "Updated Dashboard Name"
}
Insights
#### List Insights
GET /posthog/api/projects/{project_id}/insights/?limit=10
#### Get Insight
GET /posthog/api/projects/{project_id}/insights/{insight_id}/
#### Create Insight
POST /posthog/api/projects/{project_id}/insights/
Content-Type: application/json{
"name": "Daily Active Users",
"query": {
"kind": "InsightVizNode",
"source": {
"kind": "TrendsQuery",
"series": [{"kind": "EventsNode", "event": "$pageview", "math": "dau"}],
"interval": "day",
"dateRange": {"date_from": "-30d"}
}
}
}
Feature Flags
#### List Feature Flags
GET /posthog/api/projects/{project_id}/feature_flags/
#### Get Feature Flag
GET /posthog/api/projects/{project_id}/feature_flags/{flag_id}/
#### Create Feature Flag
POST /posthog/api/projects/{project_id}/feature_flags/
Content-Type: application/json{
"key": "my-feature-flag",
"name": "My Feature Flag",
"active": true,
"filters": {
"groups": [{"rollout_percentage": 100}]
}
}
#### Update Feature Flag
PATCH /posthog/api/projects/{project_id}/feature_flags/{flag_id}/
Content-Type: application/json{
"active": false
}
#### Delete Feature Flag
Use soft delete by setting deleted: true:
PATCH /posthog/api/projects/{project_id}/feature_flags/{flag_id}/
Content-Type: application/json{
"deleted": true
}
Cohorts
#### List Cohorts
GET /posthog/api/projects/{project_id}/cohorts/
#### Get Cohort
GET /posthog/api/projects/{project_id}/cohorts/{cohort_id}/
#### Create Cohort
POST /posthog/api/projects/{project_id}/cohorts/
Content-Type: application/json{
"name": "Active Users",
"groups": [
{
"properties": [
{"key": "$pageview", "type": "event", "value": "performed_event"}
]
}
]
}
Actions
#### List Actions
GET /posthog/api/projects/{project_id}/actions/
#### Create Action
POST /posthog/api/projects/{project_id}/actions/
Content-Type: application/json{
"name": "Signed Up",
"steps": [{"event": "$identify"}]
}
Session Recordings
#### List Session Recordings
GET /posthog/api/projects/{project_id}/session_recordings/?limit=10
Response:
{
"results": [
{
"id": "019c8795-79e3-7a05-ac56-597b102f1960",
"distinct_id": "user-uuid",
"recording_duration": 1807,
"start_time": "2026-02-22T23:00:46.389000Z",
"end_time": "2026-02-22T23:30:53.297000Z",
"click_count": 0,
"keypress_count": 0,
"start_url": "https://example.com/register"
}
],
"has_next": false
}
#### Get Session Recording
GET /posthog/api/projects/{project_id}/session_recordings/{recording_id}/
Annotations
#### List Annotations
GET /posthog/api/projects/{project_id}/annotations/
#### Create Annotation
POST /posthog/api/projects/{project_id}/annotations/
Content-Type: application/json{
"content": "New feature launched",
"date_marker": "2026-02-23T00:00:00Z",
"scope": "project"
}
Surveys
#### List Surveys
GET /posthog/api/projects/{project_id}/surveys/
#### Create Survey
POST /posthog/api/projects/{project_id}/surveys/
Content-Type: application/json{
"name": "NPS Survey",
"type": "popover",
"questions": [
{
"type": "rating",
"question": "How likely are you to recommend us?"
}
]
}
Experiments
#### List Experiments
GET /posthog/api/projects/{project_id}/experiments/
#### Create Experiment
POST /posthog/api/projects/{project_id}/experiments/
Content-Type: application/json{
"name": "Button Color Test",
"feature_flag_key": "button-color-test"
}
Event Definitions
#### List Event Definitions
GET /posthog/api/projects/{project_id}/event_definitions/?limit=10
Property Definitions
#### List Property Definitions
GET /posthog/api/projects/{project_id}/property_definitions/?limit=10
Pagination
PostHog uses offset-based pagination:
GET /posthog/api/projects/{project_id}/persons/?limit=10&offset=20
Response includes pagination info:
{
"count": 100,
"next": "https://us.posthog.com/api/projects/{project_id}/persons/?limit=10&offset=30",
"previous": "https://us.posthog.com/api/projects/{project_id}/persons/?limit=10&offset=10",
"results": [...]
}
For session recordings, use has_next boolean:
{
"results": [...],
"has_next": true
}
Code Examples
JavaScript
const response = await fetch(
'https://api.maton.ai/posthog/api/projects/',
{
headers: {
'Authorization': Bearer ${process.env.MATON_API_KEY}
}
}
);
const data = await response.json();
Python
import os
import requestsresponse = requests.get(
'https://api.maton.ai/posthog/api/projects/',
headers={'Authorization': f'Bearer {os.environ["MATON_API_KEY"]}'}
)
data = response.json()
Python - HogQL Query
import os
import requestsresponse = requests.post(
'https://api.maton.ai/posthog/api/projects/@current/query/',
headers={
'Authorization': f'Bearer {os.environ["MATON_API_KEY"]}',
'Content-Type': 'application/json'
},
json={
'query': {
'kind': 'HogQLQuery',
'query': 'SELECT event, count() FROM events GROUP BY event LIMIT 10'
}
}
)
data = response.json()
Notes
@current as a shortcut for the current project ID (e.g., /api/projects/@current/dashboards/)136209)PATCH with {"deleted": true} instead of HTTP DELETEjq or other commands, environment variables like $MATON_API_KEY may not expand correctly in some shell environments. Use Python examples instead.Error Handling
| Status | Meaning | |--------|---------| | 400 | Missing PostHog connection | | 401 | Invalid or missing Maton API key | | 429 | Rate limited | | 4xx/5xx | Passthrough error from PostHog API |
Rate Limits
Resources
π‘ Examples
# List projects
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/posthog/api/projects/')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
π Tips & Best Practices
@current as a shortcut for the current project ID (e.g., /api/projects/@current/dashboards/)136209)PATCH with {"deleted": true} instead of HTTP DELETEjq or other commands, environment variables like $MATON_API_KEY may not expand correctly in some shell environments. Use Python examples instead.