Capture and batch API endpoints

Last updated:

|Edit this page

The capture and batch endpoints are the main way to send events to PostHog. Beyond user behavior, they are also used to identify users, update person or group properties, migrate from other platforms, and more. Our SDKs handle the different event types for you, but with the API, you need to send the right type of event (listed below) to trigger the functionality you want.

Both are POST-only public endpoints that use your project API key and do not return any sensitive data from your PostHog instance.

Note: Make sure to send API requests to the correct domain. These are https://us.i.posthog.com for US Cloud, https://eu.i.posthog.com for EU Cloud, and your self-hosted domain for self-hosted instances. Confirm yours by checking your URL from your PostHog instance.

Here are examples of the types of events you can send:

Single event

Every event request must contain an api_key, distinct_id, and event field with the name. Both the properties and timestamp fields are optional.

curl -v -L --header "Content-Type: application/json" -d '{
"api_key": "<ph_project_api_key>",
"event": "event name",
"distinct_id": "user distinct id",
"properties": {
"account_type": "pro"
},
"timestamp": "[optional timestamp in ISO 8601 format]"
}' <ph_client_api_host>/capture/

Batch events

You can capture multiple events in one request with the /batch API route. There is no limit on the number of events you can send in a batch, but the entire request body must be less than 20MB by default.

This example shows how the required distinct_id value can also be passed in properties.

curl -v -L --header "Content-Type: application/json" -d '{
"api_key": "<ph_project_api_key>",
"historical_migration": false,
"batch": [
{
"event": "batched_event_name_1",
"properties": {
"distinct_id": "user distinct id",
"account_type": "pro"
},
"timestamp": "[optional timestamp in ISO 8601 format]"
},
{
"event": "batched_event_name_2",
"properties": {
"distinct_id": "user distinct id",
"account_type": "pro"
}
}
]
}' <ph_client_api_host>/batch/

The historical_migration field is optional. For realtime events, it can be left out or set to false.

Historical migrations

When running migrations, the historical_migration field must be set to true. This ensures that events are processed in order without triggering our spike detection systems.

curl -v -L --header "Content-Type: application/json" -d '{
"api_key": "<ph_project_api_key>",
"historical_migration": true,
"batch": [
{
"event": "batched_event_name",
"properties": {
"distinct_id": "user_id"
},
"timestamp": "2024-04-03T12:00:00Z"
},
{
"event": "batched_event_name",
"properties": {
"distinct_id": "user_id"
},
"timestamp": "2024-04-03T12:00:00Z"
}
]
}' <ph_client_api_host>/batch/

Alias

This assigns another distinct ID to the same user. Read more in our identify docs.

In this example, 123 is merged into 456 and 456 becomes the main distinct_id for events associated with 123.

curl -v -L --header "Content-Type: application/json" -d '{
"api_key": "<ph_project_api_key>",
"event": "$create_alias",
"distinct_id": "123",
"properties": {
"alias": "456"
}
}' <ph_client_api_host>/capture/

Group identify

Updates a group's information or creates one if it does not exist. Read more in our group analytics docs.

curl -v -L --header "Content-Type: application/json" -d '{
"api_key": "<ph_project_api_key>",
"event": "$groupidentify",
"distinct_id": "groups_setup_id",
"properties": {
"$group_type": "<group_type>",
"$group_key": "<company_name>",
"$group_set": {
"name": "<company_name>",
"subscription": "premium"
"date_joined": "[optional timestamp in ISO 8601 format]"
}
}
}' <ph_client_api_host>/capture/

Groups

Captures event with a group. In this case, company is a group type. You can set it to the value you want such as organization, project, or channel. Read more in our group analytics docs.

Note: This event will not create a new group if a new key being used. To create a group, see the group identify event.

curl -v -L --header "Content-Type: application/json" -d '{
"api_key": "<ph_project_api_key>",
"event": "event name",
"distinct_id": "user distinct id",
"properties": {
"$groups": {"company": "<company_name>"}
}
}' <ph_client_api_host>/capture/

Identify

Updates person properties. Read more in our identify docs.

Note: The $identify event works differently from the identify() method in the JavaScript SDK. This event updates the person properties, while the JavaScript identify() method connects an anonymous user and a distinct ID.

curl -v -L --header "Content-Type: application/json" -d '{
"api_key": "<ph_project_api_key>",
"event": "$identify",
"distinct_id": "user distinct id",
"properties": {
"$set": {
"is_cool": "true"
}
},
"timestamp": "2020-08-16T09:03:11.913767"
}' <ph_client_api_host>/capture/

Pageview

Default PostHog events and properties have the $ prefix. The most common and popular of these is the $pageview event.

curl -v -L --header "Content-Type: application/json" -d '{
"api_key": "<ph_project_api_key>",
"event": "$pageview",
"distinct_id": "user distinct id",
"properties": {
"$current_url": "https://posthog.com/docs/api/capture"
}
}' <ph_client_api_host>/capture/

Screen view

The equivalent of a pageview for mobile apps.

curl -v -L --header "Content-Type: application/json" -d '{
"api_key": "<ph_project_api_key>",
"event": "$screen",
"distinct_id": "user distinct id",
"properties": {
"$screen_name": "TheScreen"
}
}' <ph_client_api_host>/capture/

Survey

Although there is a lot of functionality you miss out on if you only use the API, you can capture survey related events. These include survey sent, survey shown, and survey dismissed, each of which requires $survey_id as a property. Read our docs on implementing custom surveys for more information.

curl -v -L --header "Content-Type: application/json" -d '{
"api_key": "<ph_project_api_key>",
"event": "survey sent",
"distinct_id": "user distinct id",
"properties": {
"$survey_id": "survey_id",
"$survey_response": "Awesome!"
}
}' <ph_client_api_host>/capture/

Invalid events

We perform basic validation on the payload and project API key (api_key), returning a failure response if an error is encountered.

PostHog does not return an error to the client when the following happens:

  • An event does not have a name
  • An event does not have the distinct_id field set
  • The distinct_id field of an event has an empty value

These three cases above cause the event to not be ingested, but you still receive a 200: OK response from PostHog.

This approach enables us to process events asynchronously if necessary, ensuring reliability and low latency for our event ingestion endpoints.

Questions?

Was this page useful?

Next article

Decide feature flags API endpoint

The decide endpoint is used to evaluate a feature flag for a given user. This means it is the main endpoint not only for feature flags, but also experimentation, early access features, and survey targeting. It is a POST-only public endpoint that uses your project API key and does not return any sensitive data from your PostHog instance. Note: Make sure to send API requests to the correct domain. These are https://us.i.posthog.com for US Cloud, https://eu.i.posthog.com for EU Cloud, and…

Read next article