# HTTP API


This guide provides a complete reference for the RudderStack HTTP API.

## Overview

RudderStack offers an easy-to-use [HTTP API](https://documenter.getpostman.com/view/16242548/TzeWFT6D) that you can use to send your events programmatically. The API is fully Segment-compatible and is helpful in cases where you cannot use the SDKs.

RudderStack recommends using the [RudderStack SDKs]({{< ref "sources/event-streams/sdks/_index.md" >}}) for tracking and routing user events from your sources. The SDKs offer automatic tagging of user context, event batching, and a retry functionality during delivery failure.

To use the HTTP API, configure an [HTTP source]({{< ref "sources/event-streams/http.md" >}}) in the dashboard, then send `POST` requests to your [data plane URL]({{< ref "dashboard-guides/_index.md#connections" >}}) via the `v1/<event_type>` endpoints.

{{< tip >}}
If the client cannot send `POST` requests (for example, HTML/CSS-only UIs), use the [Pixel API]({{< ref "api/pixel-api.md" >}}) with the same HTTP source write key instead.
{{< /tip >}}

## Prerequisites

- The RudderStack HTTP server must be accessible from your HTTP client
- [Set up a source]({{< ref "dashboard-guides/sources.md#add-a-source" >}}) and connect it to a [destination]({{< ref "dashboard-guides/destinations.md#add-a-destination" >}}) in your RudderStack dashboard
- Note your [source write key]({{< ref "dashboard-guides/sources.md#overview" >}}) to authenticate API requests

{{< image src="images/dashboard-guides/sources/source-information.webp" alt="Source information" >}}

- Download (Right click > **Save Link As**) and import the Postman collection in this [URL](https://www.getpostman.com/collections/480307c55ad2b9dd4e27). Then, edit the variables `source_write_key` and `data_plane_url`with your write key and [data plane URL]({{< ref "dashboard-guides/_index.md#connections" >}})

## Authorization

RudderStack uses Basic Authentication for authenticating all HTTP requests.

If you're using Postman, authenticate the API by including an empty string (`""`) as the username and your [source write key](#prerequisites) as the password in the **Authorization** tab.

{{< info >}}
To send events via the RudderStack HTTP API, set the **Content-Type** header to `application/json`.
{{< /info >}}

## Base URL

Use the {{< glossary_tooltip "data-plane-url" >}} as the base URL for your API requests.

## Identify

The  [`identify`]({{< ref "event-spec/standard-events/identify.md" >}}) call lets you associate a visiting user to their actions and record any associated traits.

{{% api-method method="post" host="{DATA_PLANE_URL}" path="/v1/identify" %}}

#### Sample payload


```json title="identify.json"
{
  "userId": "identified user id",
  "anonymousId":"anon-id-new",
  "context": {
    "traits": {
       "trait1": "new-val"  
    },
    "ip": "14.5.67.21",
    "library": {
        "name": "http"
    }
  },
  "timestamp": "2020-02-02T00:23:09.544Z"
}
```

#### Usage

{{< tabs tabTotal="2" >}}
{{% tab tabName="CURL" %}}
```bash
curl -u <source_write_key>: -X POST <data_plane_url>/v1/identify \
-d @identify.json \
--header "Content-Type: application/json" 
```
{{% /tab %}}
{{% tab tabName="HTTPie" %}}
```bash
http -a <source_write_key>: <DATA_PLANE_URL>/v1/identify < identify.json
```
{{% /tab %}}
{{< /tabs >}}

#### Accepted fields

{{< query-paramsList >}}
  {{< query-params keyname="anonymousId" valuename="Sets the user ID for cases where there is no unique identifier for the user. Either `userId` or `anonymousId` is required." keytype="optional" datatype="string" >}}
  {{< query-params keyname="userId" valuename="Unique identifier for a particular user in your database." keytype="required, if `anonymousId` is not present" datatype="string" >}}
  {{< query-params keyname="context" valuename="Dictionary of information that provides context about a message. However, it is not directly related to the API call." keytype="optional" datatype="object" >}}
  {{< query-params keyname="integrations" valuename="A dictionary containing the destinations to be either enabled or disabled." keytype="optional" datatype="object" >}}
  {{< query-params keyname="timestamp" valuename="The timestamp of the message's arrival. If you are passing the timestamp in the event, make sure it conforms to the ISO 8601 date format `yyyy-MM-ddTHH:mm:ss.SSSZ`. For example: `2022-02-01T19:14:18.381Z`" keytype="optional" datatype="datetime" >}}
  {{< query-params keyname="traits" valuename="Dictionary of the traits associated with the user, such as `name`or `email`" keytype="optional" datatype="object" >}}
{{< /query-paramsList >}}

## Track

The [`track`]({{< ref "event-spec/standard-events/track.md" >}}) call lets you track user actions along with any properties associated with them.

{{% api-method method="post" host="{DATA_PLANE_URL}" path="/v1/track" %}}

#### Sample payload


```json
{
  "userId": "identified user id",
  "anonymousId":"anon-id-new",
  "event": "Product Purchased new",
  "properties": {
    "name": "Shirt",
    "revenue": 4.99
  },
  "traits": {
    "email": "alex@example.com"
  },
  "context": {
    "ip": "14.5.67.21",
    "library": {
        "name": "http"
    }
  },
  "timestamp": "2020-02-02T00:23:09.544Z"
}
```

#### Usage

{{< tabs tabTotal="2" >}}
{{% tab tabName="CURL" %}}
```bash
curl -u <source_write_key>: -X POST <data_plane_url>/v1/track \
-d @track.json \
--header "Content-Type: application/json" 
```
{{% /tab %}}
{{% tab tabName="HTTPie" %}}
```bash
http -a <source_write_key>: <DATA_PLANE_URL>/v1/track < track.json
```
{{% /tab %}}
{{< /tabs >}}

#### Accepted fields

{{< query-paramsList >}}
  {{< query-params keyname="anonymousId" valuename="Sets the user ID for cases where there is no unique identifier for the user. Either `userId` or `anonymousId` is required." keytype="optional" datatype="string" >}}
  {{< query-params keyname="userId" valuename="Unique identifier for a particular user in your database." keytype="required, if `anonymousId` is not present" datatype="string" >}}
  {{< query-params keyname="context" valuename="Dictionary of information that provides context about a message. However, it is not directly related to the API call." keytype="optional" datatype="object" >}}
  {{< query-params keyname="event" valuename="Name of the event being performed by the user." keytype="required" datatype="string" >}}
  {{< query-params keyname="properties" valuename="Dictionary of the properties associated with a particular event." keytype="optional" datatype="object" >}}
  {{< query-params keyname="traits" valuename="Explicitly specified user traits. Note that:<br /><br /><ul><li>The client-side SDKs automatically add this object persisted from the `identify` event.</li><li>Any traits specified in the `track` event will override the existing traits persisted from the `identify` event.</li><li>The override will be applicable only for the particular `track` event where the `traits` object is specified explicitly. For future events, the user traits persisted from the `identify` event are used. </li></ul>" keytype="optional" datatype="object" >}}
  {{< query-params keyname="integrations" valuename="A dictionary containing the destinations to be either enabled or disabled." keytype="optional" datatype="object" >}}
  {{< query-params keyname="timestamp" valuename="The timestamp of the message's arrival. If you are passing the timestamp in the event, make sure it conforms to the ISO 8601 date format `yyyy-MM-ddTHH:mm:ss.SSSZ`. For example: `2022-02-01T19:14:18.381Z`" keytype="optional" datatype="datetime" >}}
{{< /query-paramsList >}}

## Page

The [`page`]({{< ref "event-spec/standard-events/page.md" >}}) call lets you record your website's page views with any additional relevant information about the viewed page.

{{% api-method method="post" host="{DATA_PLANE_URL}" path="/v1/page" %}}

#### Sample payload


```json
{
  "userId": "identified user id",
  "anonymousId":"anon-id-new",
  "name": "Page View",
  "properties": {
    "title": "Home",
    "path": "/"
  },
  "context": {
    "ip": "14.5.67.21",
    "library": {
        "name": "http"
    }
  },
  "timestamp": "2020-02-02T00:23:09.544Z"
}
```

#### Usage

{{< tabs tabTotal="2" >}}
{{% tab tabName="CURL" %}}
```bash
curl -u <source_write_key>: -X POST <data_plane_url>/v1/page \
-d @page.json \
--header "Content-Type: application/json" 
```
{{% /tab %}}
{{% tab tabName="HTTPie" %}}
```bash
http -a <your_write_key>: <DATA_PLANE_URL>/v1/page < page.json
```
{{% /tab %}}
{{< /tabs >}}

#### Accepted fields

{{< query-paramsList >}}
  {{< query-params keyname="anonymousId" valuename="Sets the user ID for cases where there is no unique identifier for the user. Either `userId` or `anonymousId` is required." keytype="optional" datatype="string" >}}
  {{< query-params keyname="userId" valuename="Unique identifier for a particular user in your database." keytype="required, if `anonymousId` is not present" datatype="string" >}}
  {{< query-params keyname="context" valuename="Dictionary of information that provides context about a message. However, it is not directly related to the API call." keytype="optional" datatype="object" >}}
  {{< query-params keyname="integrations" valuename="A dictionary containing the destinations to be either enabled or disabled." keytype="optional" datatype="object" >}}
  {{< query-params keyname="name" valuename="Name of the page being viewed." keytype="required" datatype="string" >}}
  {{< query-params keyname="properties" valuename="Dictionary of the properties associated with a particular event." keytype="optional" datatype="object" >}}
  {{< query-params keyname="timestamp" valuename="The timestamp of the message's arrival. If you are passing the timestamp in the event, make sure it conforms to the ISO 8601 date format `yyyy-MM-ddTHH:mm:ss.SSSZ`. For example: `2022-02-01T19:14:18.381Z`" keytype="optional" datatype="datetime" >}}
{{< /query-paramsList >}}

## Screen

The [`screen`]({{< ref "event-spec/standard-events/screen.md" >}}) call is the mobile equivalent of the `page` call. It lets you record whenever your user views their mobile screen with any additional relevant information about the screen.

{{% api-method method="post" host="{DATA_PLANE_URL}" path="/v1/screen" %}}

#### Sample payload

```json
{
  "userId": "identified user id",
  "anonymousId":"anon-id-new",
  "name": "Screen View",
  "properties": {
    "prop1": "5"
  },
  "context": {
    "ip": "14.5.67.21",
    "library": {
        "name": "http"
    }
  },
  "timestamp": "2020-02-02T00:23:09.544Z"
}
```

#### Usage

{{< tabs tabTotal="2" >}}
{{% tab tabName="CURL" %}}
```bash
curl -u <source_write_key>: -X POST <data_plane_url>/v1/screen \
-d @screen.json \
--header "Content-Type: application/json" 
```
{{% /tab %}}
{{% tab tabName="HTTPie" %}}
```bash
http -a <source_write_key>: <DATA_PLANE_URL>/v1/screen < screen.json
```
{{% /tab %}}
{{< /tabs >}}

#### Accepted fields

{{< query-paramsList >}}
  {{< query-params keyname="anonymousId" valuename="Sets the user ID for cases where there is no unique identifier for the user. Either `userId` or `anonymousId` is required." keytype="optional" datatype="string" >}}
  {{< query-params keyname="userId" valuename="Unique identifier for a particular user in your database." keytype="required, if `anonymousId` is not present" datatype="string" >}}
  {{< query-params keyname="context" valuename="Dictionary of information that provides context about a message. However, it is not directly related to the API call." keytype="optional" datatype="object" >}}
  {{< query-params keyname="integrations" valuename="A dictionary containing the destinations to be either enabled or disabled." keytype="optional" datatype="object" >}}
  {{< query-params keyname="name" valuename="Name of the screen being viewed." keytype="required" datatype="string" >}}
  {{< query-params keyname="properties" valuename="Dictionary of the properties associated with the page being viewed, such as `url` and `referrer`." keytype="optional" datatype="object" >}}
  {{< query-params keyname="timestamp" valuename="The timestamp of the message's arrival. If you are passing the timestamp in the event, make sure it conforms to the ISO 8601 date format `yyyy-MM-ddTHH:mm:ss.SSSZ`. For example: `2022-02-01T19:14:18.381Z`" keytype="optional" datatype="datetime" >}}
{{< /query-paramsList >}}

## Group

The [`group`]({{< ref "event-spec/standard-events/group.md" >}}) call lets you link an identified user with a group such as a company, organization, or an account. It also lets you record any custom traits associated with that group, like the name of the company, the number of employees, etc.

{{% api-method method="post" host="{DATA_PLANE_URL}" path="/v1/group" %}}

#### Sample payload


```json
{
  "userId": "user123",
  "groupId": "group1",
  "traits": {
    "name": "Company",
    "industry": "Industry",
    "employees": 123
  },
  "context": {
    "traits": {
       "trait1": "new-val"  
    },
    "ip": "14.5.67.21",
    "library": {
        "name": "http"
    }
  },
  "timestamp": "2020-01-21T00:21:34.208Z"
}
```

#### Usage

{{< tabs tabTotal="2" >}}
{{% tab tabName="CURL" %}}
```bash
curl -u <source_write_key>: -X POST <data_plane_url>/v1/group \
-d @group.json \
--header "Content-Type: application/json" 
```
{{% /tab %}}
{{% tab tabName="HTTPie" %}}
```bash
http -a <source_write_key>: <DATA_PLANE_URL>/v1/group < group.json
```
{{% /tab %}}
{{< /tabs >}}

#### Accepted fields

{{< query-paramsList >}}
  {{< query-params keyname="anonymousId" valuename="Sets the user ID for cases where there is no unique identifier for the user. Either `userId` or `anonymousId` is required." keytype="optional" datatype="string" >}}
  {{< query-params keyname="userId" valuename="Unique identifier for a particular user in your database." keytype="required, if `anonymousId` is not present" datatype="string" >}}
  {{< query-params keyname="context" valuename="Dictionary of information that provides context about a message. However, it is not directly related to the API call." keytype="optional" datatype="object" >}}
  {{< query-params keyname="integrations" valuename="A dictionary containing the destinations to be either enabled or disabled." keytype="optional" datatype="object" >}}
  {{< query-params keyname="groupId" valuename="Unique identifier of the group, as present in your database." keytype="required" datatype="string" >}}
  {{< query-params keyname="traits" valuename="Dictionary of the traits associated with the group, such as `name`or `email`" keytype="optional" datatype="object" >}}
  {{< query-params keyname="timestamp" valuename="The timestamp of the message's arrival. If you are passing the timestamp in the event, make sure it conforms to the ISO 8601 date format `yyyy-MM-ddTHH:mm:ss.SSSZ`. For example: `2022-02-01T19:14:18.381Z`" keytype="optional" datatype="datetime" >}}
{{< /query-paramsList >}}

## Alias

The [`alias`]({{< ref "event-spec/standard-events/alias.md" >}}) call lets you merge different identities of a known user.

{{< info >}}
`alias` is an advanced method that lets you change the tracked user's ID explicitly. This method is useful when managing identities for some of the downstream destinations.
{{< /info >}}

{{% api-method method="post" host="{DATA_PLANE_URL}" path="/v1/alias" %}}

#### Sample payload


```json
{
  "userId": "user123",
  "previousId": "previd1",
  "context": {
    "traits": {
       "trait1": "new-val"  
    },
    "ip": "14.5.67.21",
    "library": {
        "name": "http"
    }
  },
  "timestamp": "2020-01-21T00:21:34.208Z"
}
```

#### Usage

{{< tabs tabTotal="2" >}}
{{% tab tabName="CURL" %}}

```bash
curl -u <source_write_key>: -X POST <data_plane_url>/v1/alias \
-d @alias.json \
--header "Content-Type: application/json" 
```
{{% /tab %}}
{{% tab tabName="HTTPie" %}}
```bash
http -a <source_write_key>: <DATA_PLANE_URL>/v1/alias < alias.json
```
{{% /tab %}}
{{< /tabs >}}

#### Accepted fields

{{< query-paramsList >}}
  {{< query-params keyname="userId" valuename="Unique identifier for a particular user in your database." keytype="required, if `anonymousId` is not present" datatype="string" >}}
  {{< query-params keyname="context" valuename="Dictionary of information that provides context about a message. However, it is not directly related to the API call." keytype="optional" datatype="object" >}}
  {{< query-params keyname="integrations" valuename="A dictionary containing the destinations to be either enabled or disabled." keytype="optional" datatype="object" >}}
  {{< query-params keyname="previousId" valuename="The previous unique identifier of the user." keytype="required" datatype="string" >}}
  {{< query-params keyname="traits" valuename="Dictionary of the traits associated with the group, such as `name`or `email`" keytype="optional" datatype="object" >}}
  {{< query-params keyname="timestamp" valuename="The timestamp of the message's arrival. If you are passing the timestamp in the event, make sure it conforms to the ISO 8601 date format `yyyy-MM-ddTHH:mm:ss.SSSZ`. For example: `2022-02-01T19:14:18.381Z`" keytype="optional" datatype="datetime" >}}
{{< /query-paramsList >}}

## Batch

The `batch` call allows you to send a series of `identify`, `track`, `page`, `group` and `screen` requests in a single batch. This call helps you minimize the number of outbound requests, thus enabling better performance.

{{< info >}}
RudderStack sets a maximum limit of `4 MB` per batch request and `32 KB` per call.
{{< /info >}}

{{% api-method method="post" host="{DATA_PLANE_URL}" path="/v1/batch" %}}

#### Sample payload


```json
{
    "batch": [{
            "userId": "identified user id",
            "anonymousId": "anon-id-new",
            "type": "identify",
            "context": {
                "traits": {
                    "trait1": "new-val"
                },
                "ip": "14.5.67.21",
                "library": {
                    "name": "http"
                }
            },
            "timestamp": "2020-02-02T00:23:09.544Z"
        },
        {
            "userId": "identified user id",
            "anonymousId": "anon-id-new",
            "event": "Product Purchased new",
            "type": "track",
            "properties": {
                "name": "Shirt",
                "revenue": 4.99
            },
            "context": {
                "ip": "14.5.67.21",
                "library": {
                    "name": "http"
                }
            },
            "timestamp": "2020-02-02T00:23:09.544Z"
        },
        {
            "userId": "identified user id",
            "anonymousId": "anon-id-new",
            "name": "Page View",
            "type": "page",
            "properties": {
                "title": "Home",
                "path": "/"
            },
            "context": {
                "ip": "14.5.67.21",
                "library": {
                    "name": "http"
                }
            },
            "timestamp": "2020-02-02T00:23:09.544Z"
        },
        {
            "userId": "identified user id",
            "anonymousId": "anon-id-new",
            "name": "Screen View",
            "type": "screen",
            "properties": {
                "prop1": "5"
            },
            "context": {
                "ip": "14.5.67.21",
                "library": {
                    "name": "http"
                }
            },
            "timestamp": "2020-02-02T00:23:09.544Z"
        },
        {
            "userId": "user123",
            "type": "group",
            "groupId": "group1",
            "traits": {
                "name": "Company",
                "industry": "Industry",
                "employees": 123
            },
            "context": {
                "traits": {
                    "trait1": "new-val"
                },
                "ip": "14.5.67.21",
                "library": {
                    "name": "http"
                }
            },
            "timestamp": "2020-01-21T00:21:34.208Z"
        },
        {
            "userId": "user123",
            "previousId": "previd1",
            "type":"alias",
            "context": {
                "traits": {
                    "trait1": "new-val"
                },
                "ip": "14.5.67.21",
                "library": {
                    "name": "http"
                }
            },
            "timestamp": "2020-01-21T00:21:34.208Z"
        }

    ]
}
```
#### Usage

{{< tabs tabTotal="2" >}}
{{% tab tabName="CURL" %}}
```bash
curl -u <source_write_key>: -X POST <data_plane_url>/v1/batch \
-d @batch.json \
--header "Content-Type: application/json" 
```
{{% /tab %}}
{{% tab tabName="HTTPie" %}}
```bash
http -a <source_write_key>: <DATA_PLANE_URL>/v1/batch < batch.json
```
{{% /tab %}}
{{< /tabs >}}

#### Accepted fields

{{< query-paramsList >}}
  {{< query-params keyname="batch" valuename="An array of `identify`, `track`, `page`, `group` and `screen` calls. Each call must have a `type` property and a valid method name." keytype="required" datatype="array" >}}
{{< /query-paramsList >}}

## HTTP responses

| Status code | <div style="width:350px">Description</div> | 
| :-----| :-----| 
| `200` | Successful API request | 
| `400` | Bad request — possible reasons include: <br /><br /><ul><li>Invalid request method</li><li>Invalid request body</li><li>Invalid source/destination ID</li><li>Empty batch payload</li><li>Event exceeds the [maximum allowed request size](#maximum-allowed-request-size)</li><li>Event exceeds the [maximum allowed JSON nesting depth](#maximum-allowed-json-nesting-depth)</li></ul> |
| `401` | Missing or invalid authorization header <br /><br />{{< info >}}Make sure that the source write key and the basic authentication header is valid.{{< /info >}} |
| `404` | Source or destination is disabled |
| `413` | Request body is too large |
| `429` | Too many requests |
| `500` | Internal server error |

## Maximum allowed request size

RudderStack allows messages with a maximum size of `32 KB` per call. The [`batch`](#batch) endpoint accepts a maximum call size of `4 MB` per batch, and `32 KB` per call. RudderStack responds with a `400 Bad Request` error if these limits are exceeded.

## Maximum allowed JSON nesting depth

RudderStack accepts event JSON payloads with a maximum nesting depth of 200 levels. Events that exceed this limit are rejected during ingestion with error feedback returned to the sender.

The following example highlights how JSON nesting depth is calculated. Both objects and arrays count toward the nesting depth:

```json
{
  "a": [
    {
      "b": {
        "c": "This JSON has a nesting depth of 4"
      }
    }
  ]
}
```

In this example, the array `a` is at depth 1, the object inside the array is at depth 2, the object `b` is at depth 3, and the field `c` is at depth 4.

## Event ordering 

To maintain event ordering while using the HTTP API, make sure to include [`sentAt`]({{< ref "event-spec/standard-events/common-fields.md#common-fields" >}}) and `anonymousId` as a header in every request.

{{< image src="images/api/http-event-ordering.webp" alt="Event ordering" >}}

## Historical imports

RudderStack lets you import any historical data by simply adding the `timestamp` argument to any of your API calls. However, this can be done only for the destinations that accept historical time-stamped data, like Amplitude, Mixpanel, etc. 

{{< info >}}
If you are tracking current events, leave out the `timestamp` field. RudderStack will automatically add the timestamps to the event requests.
{{< /info >}}

