🎁 Get the FREE AI Skills Starter Guide β€” Subscribe β†’
BytesAgainBytesAgain
πŸ¦€ ClawHub

PostHog

by @byungkyu

PostHog API integration with managed authentication. Product analytics, feature flags, session recordings, experiments, and more. Use this skill when users w...

TERMINAL
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

  • Access is scoped to events, persons, feature flags, insights, and dashboards within the connected PostHog account.
  • All write operations require explicit user approval. Before executing any create, update, or delete call, confirm the target resource and intended effect with the user.
  • 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 requests

    response = 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 requests

    response = 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

  • Use @current as a shortcut for the current project ID (e.g., /api/projects/@current/dashboards/)
  • Project IDs are integers (e.g., 136209)
  • Person UUIDs are in standard UUID format
  • The Events endpoint is deprecated; use the Query endpoint with HogQL instead
  • Session recordings include activity metrics like click_count, keypress_count
  • PostHog uses soft delete: use PATCH with {"deleted": true} instead of HTTP DELETE
  • IMPORTANT: When piping curl output to jq 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

  • Analytics endpoints (insights, persons, recordings): 240/minute, 1200/hour
  • HogQL query endpoint: 120/hour
  • CRUD endpoints: 480/minute, 4800/hour
  • Resources

  • PostHog API Overview
  • HogQL Documentation
  • Feature Flags
  • Session Replay
  • Experiments
  • Maton Community
  • Maton Support
  • πŸ’‘ 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

  • Use @current as a shortcut for the current project ID (e.g., /api/projects/@current/dashboards/)
  • Project IDs are integers (e.g., 136209)
  • Person UUIDs are in standard UUID format
  • The Events endpoint is deprecated; use the Query endpoint with HogQL instead
  • Session recordings include activity metrics like click_count, keypress_count
  • PostHog uses soft delete: use PATCH with {"deleted": true} instead of HTTP DELETE
  • IMPORTANT: When piping curl output to jq or other commands, environment variables like $MATON_API_KEY may not expand correctly in some shell environments. Use Python examples instead.