API specifications
Contents
PostHog's API specifications are (mostly) generated automatically from the OpenAPI spec. We have a tooling to generate the API specification markdown files from the OpenAPI spec.
Where we publish the API specifications
When ever you run the app locally, the API specification is available at /api/schema/, and you can view it using Swagger UI.
On the website, the API specification is available at /docs/api/. Some of these pages are hand-rolled, and some are generated from the OpenAPI spec.
| Page | Type |
|---|---|
| Overview | hand-rolled |
| Capture | hand-rolled |
| Flags | hand-rolled |
| Queries | hand-rolled |
| Actions | generated |
| Alerts | generated |
| Activity log | generated |
| Annotations | generated |
| Batch exports | generated |
| Cohorts | generated |
| Dashboards | generated |
| Dashboard templates | generated |
| Early access features | generated |
| Endpoints | generated |
| Environments | generated |
| Event definitions | generated |
| Events | generated |
| Experiments | generated |
| Feature flags | generated |
| Groups | generated |
| Groups types | generated |
| Hog functions | generated |
| Insights | generated |
| Invites | generated |
| Members | generated |
| Notebooks | generated |
| Organizations | generated |
| Persons | generated |
| Projects | generated |
| Property definitions | generated |
| Query | generated |
| Roles | generated |
| Session recordings | generated |
| Session recording playlists | generated |
| Sessions | generated |
| Subscriptions | generated |
| Surveys | generated |
| Users | generated |
| Web Analytics | generated |
How the website ingests the OpenAPI spec
The website ingests the OpenAPI specification during the Gatsby build process in two stages:
- During
sourceNodes: The OpenAPI spec is fetched and parsed usingOpenAPIParserandMenuBuilderfrom theredoclibrary. This creates a structured menu of API endpoints that's used for navigation. The menu groups endpoints and handles pagination for groups with more than 20 items. - During
onPostBuild: The build process fetches the OpenAPI spec fromhttps://app.posthog.com/api/schema/(or from thePOSTHOG_OPEN_API_SPEC_URLenvironment variable if set). The spec is then passed togenerateApiSpecMarkdown(), which:- Iterates through all paths and HTTP methods in the spec
- For each endpoint with an
operationId, creates a markdown file named after the operation ID - Recursively extracts all referenced component schemas for each endpoint
- Generates markdown files containing the endpoint's OpenAPI JSON in a code block
- Writes these files to
public/docs/open-api-spec/
The generated markdown files are then available at /docs/open-api-spec/{operationId}.md and are included in the documentation site's API reference section.
How to update the OpenAPI spec
Any of the automatically generated pages sources from the OpenAPI spec. To update the content of an automatically generated page, you need to update the OpenAPI spec by making changes to the PostHog/posthog repository.
Updating the page title and description
These updates happen in the
PostHog/posthog.comrepository.
Page title: Update the titleMap object in src/templates/ApiEndpoint.tsx. For example, to change the "Actions" page title, modify the actions entry in the map.
Page description: Create or update an overview.mdx file in the corresponding API folder. The file should be located at contents/docs/api/{name}/overview.mdx, where {name} matches the API endpoint name (e.g., events, feature-flags).
Example: contents/docs/api/events/overview.mdx contains the description that appears at the top of the Events API page.
Updating the endpoint title and description
These updates happen in the
PostHog/posthogrepository.
Endpoint title: The title is auto-generated from the operationId in the OpenAPI spec using the generateName() function in src/templates/ApiEndpoint.tsx. To customize it, update the operationId or description in the Django viewset in the PostHog repository. You basically need to update the path to update the title.
Endpoint description: Create an MDX file named after the endpoint's operationId in the appropriate API folder. The file should be located at contents/docs/api/{name}/{operationId}.mdx.
Example: contents/docs/api/feature-flags/feature_flags_list.mdx adds custom content that appears under the "List all feature flags" endpoint. The content from this file is rendered above the endpoint's description from the OpenAPI spec.
Updating the endpoint parameters and responses
The endpoint request body parameters, query parameters, path parameters, response body, response headers, API key scopes, etc. are all defined in the Django serializers and viewsets in the PostHog repository.
Generally, there are two types of "views" in Django and they require different annotations to generate accurate OpenAPI specs.
- Model-based CRUD views: These are views that are backed by Django models. These CRUD views are backed by models defined in the Django ORM. They map literally to Django model fields, and generally don't need any additional annotations for accurate request and response definitions.
- Function-based views: These are views that are backed by Python functions. These views are not backed by models, and generally annotated with
@actiondecorators. For these views, we need to manually annotate request and response definitions.
If an endpoint needs additional annotation, you can use the @validated_request decorator to annotate the view. This decorator will use the serializers passed in for both validation and annotation of the request bodies, query parameters, and response bodies, ensuring the OpenAPI spec stays accurate (or we know when they're not).
Basic usage
The @validated_request decorator wraps a view function and provides validation for request and response data:
Validating query parameters
Use query_serializer to validate query parameters:
Multiple response status codes
Declare multiple possible response status codes:
No response body
Declare status codes with no response body using None:
Validation modes
By default, @validated_request uses strict validation for requests (raises on invalid data) and non-strict for responses (logs warnings in DEBUG mode). You can control this:
Which endpoints have validated request and response definitions
The @validated_request decorator is new and many endpoints have not been annotated yet. The following endpoints have been annotated:
taskstask-runsfeature_flagsfeature_value
We plan on slowly annotating all endpoints with the @validated_request decorator through Q1 2026.
The special case for Capture
Ingestion is basically an entirely different service and not included in the OpenAPI spec. It also has special limitations like batching, rate limiting, etc that need to be documented separately. It doesn't fit the classic patterns for a RESTful API as well as other endpoints.
The ingestion team and docs team will need to work together to update the OpenAPI spec for the Capture endpoint.