The HTTP API is one of the ways you can start sending data to Amplitude. This is part of Getting Started with using Amplitude. Use our HTTP API to send server-side event data; limit is 10 events per device/user per second.
There are 3 other ways to get data into Amplitude: using the Amplitude SDKs, integrating with Segment, or integrating with mParticle.
Important Note:
This article has been moved to our new Developer Center. For the latest info, please see HTTP API v2
- This endpoint replaces the deprecated HTTP API v1
Table of Contents
- Upload Limit
- All Zero Device IDs: Limited Ad Tracking Enabled
- HTTP API v2 Improvements
- Request Format
- Response Format
- Foot Notes
- Optional Keys
- Common Questions
Upload Limit
Limit your upload to 100 batches/sec and 1000 events/sec. You can batch events into an upload but we recommend not sending more than 10 events per batch. Thus, we expect at most 100 batches to be sent per second, and so the 1000 events/sec limit still applies as we do not recommend sending more than 10 events per batch. Note: This applies to customers on our Starter Plan only.
For paying customers, please reach out to us if you need to send more than 1000 events/sec. There is no hard limit on the Amplitude Enterprise plan. However, please note that we will throttle requests for individual devices that exceed 10 events/second as stated in the below HTTP status codes section.
For request size, please limit your requests to no more than 2000 events per request and under 1 MB. If you exceed these size limits, you will receive a 413 error.
Recommendation: For high volume customers concerned with scale, please partition your work based on device_id (or user_id if you don't have a device_id). This ensures that throttling on a particular device_id (or user_id) doesn't impact all senders in your system. If you are proxying events to Amplitude, please ensure that throttling is forwarded to your clients to create backpressure instead of letting spammy clients slow down a partition of work in your system.
All Zero Device IDs: Limited Ad Tracking Enabled
As of iOS 10, if the user enables Limit Ad Tracking, Apple will replace the Identifier for Advertiser (IDFA) with all zeros. Amplitude will drop a Device ID of all zeros from the event and return an error on the request (since Device IDs are required for all events). Thus, if you are passing the IDFA as the Device ID, then we recommend running a check on the IDFA value and passing a different Device ID value like the Identifier for Vendor (IDFV) instead.
Windows Operating System
If you are using a Windows operating system, then you may have to replace all single quotes with double quotes and escape all double quotes as well.
String Character Limit
There is a character limit of 1024 characters for all string values (user_id, event or user property values, etc.).
Setting Date Values
Amplitude compares dates as strings, so it is recommended to use the ISO 8601 format (YYYY-MM-DDTHH:mm:ss), which will allow you to perform date comparisons in the platform, (e.g. '2016-01-31' > '2016-01-01'). This will also work for datetime values (e.g. '2017-08-07T10:09:08' > '2017-08-07T01:07:00').
Setting Time Values
The time
parameter in each event must be sent as millisecond since epoch. Any other format (such as ISO format) will result in a 400 Bad Request response. Previously in the deprecated HTTP API, we have simply ignore the time
field if it has invalid type or invalid format and use the current server time instead. However, in HTTP API V2, the validation for time
is now enforced and will result in the request being rejected if the field has invalid type or invalid format.
Event Deduplication
It is highly recommended that you send an insert_id
for each event to prevent duplicate events from being received by Amplitude. We will ignore subsequent events sent with the same insert_id within the past 7 days. You can read more about this field below.
Device IDs and User IDs minimum length
Device IDs and User IDs must be strings with a length of 5 characters or more. This is to prevent potential instrumentation issues. If an event contains a device ID or user ID that is too short, the ID value will be removed from the event. This may cause the upload to be rejected with a 400 error if that event does not have a user ID or device ID value. The default minimum length of 5 characters can be overriden by passing min_id_length
override option with the request (more on this field below).
HTTP API V2 improvements over deprecated HTTP API
This HTTP API V2 endpoint is an improvement and a replacement of the deprecated HTTP API
The main improvements are:
- The HTTP API V2 request and response format is the same with the Batch Event Upload API. Since sending requests and parsing responses are done identically, all that is required to switch between the HTTP API V2 and the Batch API is to change the endpoint URL. The benefit of this is if you are being throttled on the HTTP API V2 then you can easily change to the batch endpoint by simply changing the endpoint URL.
- The HTTP API V2 uses JSON response and provides better error reporting around 400s & throttling compared to the deprecated HTTP API. For example, 400 bad request will provide more details on which event index and event field is invalid, 429 throttling will provide more details on current eps (events per second) and which device is being throttle, etc. (More details on possible error responses below)
- Better validations to reject incorrectly instrumented events
- Validation on
Content-type
header (must be set toapplication/json
) - Validation on proper JSON request body
- Validation on
event_type
name (cannot be event names that are reserved for Amplitude use) - Validation on
device_id
length (must be 5 or more characters unless overrided withmin_id_length
) - Validation on
user_id
length (must be 5 or more characters unless overrided withmin_id_length
) - Validation on
time
field in event payload (must be number of milliseconds since the start of epoch time)
- Validation on
Request Format
Send a POST request to https://api2.amplitude.com/2/httpapi
The post body must be a JSON payload with JSON encoding only. The JSON payload should contain an API key and a list of events.
If you have used our deprecated HTTP API before, note that there are two minor but important differences in your POST request to HTTP API V2 (endpoint /2/httpapi). First, your Content-type must be application/json
. Second, your key for the events
payload is events
plural, NOT event
singular. Take a look at the code sample to the right for more details.
Parameter | In | Type | Required | Description |
---|---|---|---|---|
body | body | UploadRequestBody | true | A JSON object containing your api_key and an array of events |
UploadRequestBody
Name | Type | Required | Restrictions | Description |
---|---|---|---|---|
api_key | string | true | none | Amplitude project API key |
events | [Event] | true | none | Array of Events to upload |
options | [options] | false | none | Object |
In the request example below the parameters are highlighted purple, and the values in red are what you need to replace with the parameters you are specifically interested in.
curl -H 'Content-Type: application/json' -d '{"api_key":"API_Key","events":[{"user_id":"12345", "event_type":"watch_tutorial", "user_properties":{"Cohort":"Test A"}, "country":"United States", "ip":"127.0.0.1", "time":1396381378123}]}' https://api2.amplitude.com/2/httpapi
Keys for the Event Argument
The following keys can be sent within the JSON event object. Note that one of user_id
or device_id
is required, as well as the event_type
.
Note: '[Amplitude] Country', '[Amplitude] City', '[Amplitude] Region', and '[Amplitude] DMA' are user properties pulled using GeoIP. For any HTTP API events, if GeoIP information is unavailable, then we pull the information from the 'location_lat' and 'location_lng' keys if those keys are populated. If these location properties are manually set, then Amplitude will not modify that property.
Important:
- This should not be used if
device_brand
,device_manufacturer
, anddevice_model
are used.
Name | Type | Required | Restrictions | Description |
---|---|---|---|---|
user_id | string | true | none | A readable ID specified by you. Must have a minimum length of 5 characters. Required unless device_id is present. |
device_id | string | true | none | A device-specific identifier, such as the Identifier for Vendor on iOS. Required unless user_id is present. If a device_id is not sent with the event, it will be set to a hashed version of the user_id. |
event_type | string | true | none | A unique identifier for your event. If you would like to make an Identify call, please set "event_type" to $identify . |
time | long | false | none | The timestamp of the event in milliseconds since epoch. If time is not sent with the event, it will be set to the request upload time. |
event_properties | object | false | none | A dictionary of key-value pairs that represent additional data to be sent along with the event. You can store property values in an array. Date values are transformed into string values. |
user_properties | object | false | none | A dictionary of key-value pairs that represent additional data tied to the user. You can store property values in an array. Date values are transformed into string values. |
groups | object | false | none | This feature is only available to Enterprise customers who have purchased the Accounts add-on. This field adds a dictionary of key-value pairs that represent groups of users to the event as an event-level group. You can only track up to 5 groups. |
app_version | string | false | none | The current version of your application. |
platform | string | false | none | Platform of the device. |
os_name | string | false | none | The name of the mobile operating system or browser that the user is using. |
os_version | string | false | none | The version of the mobile operating system or browser the user is using. |
device_brand | string | false | none | The device brand that the user is using. |
device_manufacturer | string | false | none | The device manufacturer that the user is using. |
device_model | string | false | none | The device model that the user is using. |
carrier | string | false | none | The carrier that the user is using. |
country | string | false | none | The current country of the user. |
region | string | false | none | The current region of the user. |
city | string | false | none | The current city of the user. |
dma | string | false | none | The current Designated Market Area of the user. |
language | string | false | none | The language set by the user. |
price | float | false | none | The price of the item purchased. Required for revenue data if the revenue field is not sent. You can use negative values to indicate refunds. |
quantity | integer | false | none | The quantity of the item purchased. Defaults to 1 if not specified. |
revenue | float | false | none | revneue = price * quantity. If you send all 3 fields of price, quantity, and revenue, then (price * quantity) will be used as the revenue value. You can use negative values to indicate refunds. |
productId | string | false | none | An identifier for the item purchased. You must send a price and quantity or revenue with this field. |
revenueType | string | false | none | The type of revenue for the item purchased. You must send a price and quantity or revenue with this field. |
location_lat | float | false | none | The current Latitude of the user. |
location_lng | float | false | none | The current Longitude of the user. |
ip | string | false | none | The IP address of the user. Use "$remote" to use your server's IP address. We will use the IP address to reverse lookup a user's location (city, country, region, and DMA). Amplitude has the ability to drop the location and IP address from events once it reaches our servers. You can submit a request to our platform specialist team here to configure this for you. |
idfa | string | false | none | (iOS) Identifier for Advertiser. |
idfv | string | false | none | (iOS) Identifier for Vendor. |
adid | string | false | none | (Android) Google Play Services advertising ID |
android_id | string | false | none | (Android) Android ID (not the advertising ID) |
event_id | int | false | none | (Optional) An incrementing counter to distinguish events with the same user_id and timestamp from each other. We recommend you send an event_id, increasing over time, especially if you expect events to occur simultanenously. |
session_id | long | false | none | (Optional) The start time of the session in milliseconds since epoch (Unix Timestamp), necessary if you want to associate events with a particular system. A session_id of -1 is the same as no session_id specified. |
insert_id | string | false | none | (Optional) A unique identifier for the event. We will deduplicate subsequent events sent with an insert_id we have already seen before within the past 7 days. We recommend generation a UUID or using some combination of device_id, user_id, event_type, event_id, and time. |
Options
Name | Type | Required | Restrictions | Description |
---|---|---|---|---|
min_id_length | integer | false | none | Minimum permitted length for user_id & device_id fields |
Example:
{
"api_key": "my_amplitude_api_key",
"events": [
{
"user_id": "datamonster@gmail.com",
"device_id": "C8F9E604-F01A-4BD9-95C6-8E5357DF265D",
"event_type": "watch_tutorial",
"time": 1396381378123,
"event_properties": {
"load_time": 0.8371,
"source": "notification",
"dates": [
"monday",
"tuesday"
]
},
"user_properties": {
"age": 25,
"gender": "female",
"interests": [
"chess",
"football",
"music"
]
},
"groups": {
"company_id": "1",
"company_name": [
"Amplitude",
"DataMonster"
]
},
"app_version": "2.1.3",
"platform": "iOS",
"os_name": "Android",
"os_version": "4.2.2",
"device_brand": "Verizon",
"device_manufacturer": "Apple",
"device_model": "iPhone 9,1",
"carrier": "Verizon",
"country": "United States",
"region": "California",
"city": "San Francisco",
"dma": "San Francisco-Oakland-San Jose, CA",
"language": "English",
"price": 4.99,
"quantity": 3,
"revenue": -1.99,
"productId": "Google Pay Store Product Id",
"revenueType": "Refund",
"location_lat": 37.77,
"location_lng": -122.39,
"ip": "127.0.0.1",
"idfa": "AEBE52E7-03EE-455A-B3C4-E57283966239",
"idfv": "BCCE52E7-03EE-321A-B3D4-E57123966239",
"adid": "AEBE52E7-03EE-455A-B3C4-E57283966239",
"android_id": "BCCE52E7-03EE-321A-B3D4-E57123966239",
"event_id": 23,
"session_id": 1396381378123,
"insert_id": "5f0adeff-6668-4427-8d02-57d803a2b841"
}
]
}
Response Format
It's important that you implement retry logic and send an insert_id (used for deduplication of the same event) in your events, in the unlikely event that our API endpoint becomes unavailable and we are unable to ingest events. If you do not receive a 200 status code (which means your event was successfully received by Amplitude), then you should retry your request. Here are the HTTP status codes you may receive:
Status | Meaning | Description | Schema |
---|---|---|---|
200 | OK | Successful real time event upload | SuccessSummary |
400 | Bad Request | A 400 indicates invalid upload request. Possible reasons for invalid request: The request body is not valid JSON. The error will say "Invalid JSON request body".The request body is missing at least one of: required api_key and events array of at least one event. The error will say "Request missing required field". The missing_field will indicate which is missing.At least one of the events in the request is missing a required field. The error will say "Request missing required field". The events_missing_required_fields will be a map from field names to an array of indexes indicating the events missing those required fields.At least one of the events in the request has an invalid value for one of the fields (for example setting a string for the time field). The error will say "Invalid field values on some events". The events_with_invalid_fields will be a map from field names to an array of indexes indicating the events with invalid values for those fields. |
InvalidRequestError |
413 | Payload Too Large | Payload size is too big (request size exceeds 1MB). You should split your events array payload into multiple requests and try again. | PayloadTooLargeError |
429 | Too Many Requests | Too many requests for a user / device. Amplitude will throttle requests for users and devices that exceed 10 events per second (measured as an average over a recent time window). You should pause sending events for that user / device for a period of 30 seconds before retrying and continue retrying until you no longer receive a 429 response. | TooManyRequestsForDeviceError |
500, 502 504 | Server Error | We encountered an error while handling the request. A request with this response may or may not have been accepted by Amplitude, upon retrying the request, the events may or may not be duplicated. To resolve this risk, we recommend sending an insert_id in your requests. | |
503 | Service Unavailable | If we do not commit your request to our system as a result of an internal failure, then we will return HTTP status code 503. A request with this response can be retried without any risk of duplicating an event. |
SuccessSummary
Name | Type | Description |
---|---|---|
code | integer | 200 success code |
events_ingested | integer | The number of events ingested from the upload request. |
payload_size_bytes | integer | The size of the upload request payload in bytes. |
server_upload_time | long | The time in milliseconds since epoch (Unix Timestamp) that our event servers accepted the upload request. |
Example:
{
"code": 200,
"events_ingested": 50,
"payload_size_bytes": 50,
"server_upload_time": 1396381378123
}
InvalidRequestError
Name | Type | Description |
---|---|---|
code | integer | 400 error code |
error | string | Error description. Possible values are Invalid request path , Missing request body , Invalid JSON request body , Request missing required field , Invalid event JSON , Invalid API key , Invalid field values on some events |
missing_field | string | Indicates which request-level required field is missing. |
events_with_invalid_fields | object | A map from field names to an array of indexes into the events array indicating which events have invalid values for those fields |
events_with_missing_fields | object | A map from field names to an array of indexes into the events array indicating which events are missing those required fields |
Example:
{
"code": 400,
"error": "Request missing required field",
"missing_field": "api_key",
"events_with_invalid_fields": {
"time": [
3,
4,
7
]
},
"events_with_missing_fields": {
"event_type": [
3,
4,
7
]
}
}
PayloadTooLargeError
Name | Type | Description |
---|---|---|
code | integer | 413 error code |
error | string | Error description. |
Example:
{
"code": 413,
"error": "Payload too large"
}
TooManyRequestsForDeviceError
Name | Type | Description |
---|---|---|
code | integer | 429 error code |
error | string | Error description. |
eps_threshold | integer | Your app's current events per second threshold. If you exceed this rate your requests will be throttled. |
throttled_devices | object | A map from device_id to its current events per second rate, for all devices that exceed the app's current threshold. |
throttled_users | object | A map from user_id to their current events per second rate, for all users that exceed the app's current threshold |
throttled_events | [integer] | Array of indexes in the oevents array indicating events whose user_id and/or device_id got throttled |
Example:
{
"code": 429,
"error": "Too many requests for some devices and users",
"eps_threshold": 10,
"throttled_devices": {
"C8F9E604-F01A-4BD9-95C6-8E5357DF265D": 11
},
"throttled_users": {
"datamonster@amplitude.com": 12
},
"throttled_events": [
3,
4,
7
]
}
Footnotes
1) These user properties and all other user properties persist in following events if not explicitly changed at the time of subsequent events (as of 06/24/2016). Please refer to footnotes 2 and 3 to assure that you update these properties appropriately.
2) These fields (platform, os_name, os_version, device_brand, device_manufacturer, device_model, and carrier) must all be updated together. Setting only some of these fields will automatically reset all of the other property values to null if they are not also explicitly set for the same event. All property values will otherwise persist to a subsequent event if the values are not changed to a different string or if all values are passed as null. Amplitude will attempt to use device_brand, device_manufacturer, and device_model to map the corresponding device type.
3) These fields (country, region, city, DMA) must all be updated together. Setting any of these fields will automatically reset all of the other property values to null if they are not also explicitly set for the same event. All property values will otherwise persist to a subsequent event if the values are not changed to a different string or if all values are passed as null.
4) To implement property values as arrays, restructure the key-value pairs as follows: "property_name": [value1, value2, value3]. Note: For all event/user properties that Amplitude automatically tracks, you cannot store their values as an array. For example, you cannot store the values of '[Amplitude] Country' as an array.
5) If this field is populated with a non-zero value, then the event is assumed to be a revenue event.
Optional Keys
The following optional keys are interpreted in a special way on our backend.
Optional Amplitude Specific Key | Description |
---|---|
event_id int |
An incrementing counter to distinguish events with the same user_id and timestamp from each other. Note: We recommend you send an event_id, increasing over time, especially if you suspect any events to occur simultaneously. An event_id is not required to send a session_id though. 1 |
session_id long |
The start time of the session in milliseconds since epoch (Unix Timestamp), necessary if you want to associate events with a particular session (a session_id of -1 implies that you not sending a session_id, and so no session metrics will be tracked). Here is more information. 1396381378123 |
insert_id string |
A unique identifier for the event being inserted; we will deduplicate subsequent events sent with an insert_id we have already seen before within the past 7 days. Some combination of device_id, user_id, session_id, event_type, and event_id or time, would likely serve as a sufficient insert_id value. "f47ac10b-58cc-4372-a567-0e02b2c3d479" |
Common Issues with HTTP API V2 Implementations
There are some considerations related to using the HTTP API rather than using our client libraries. Some of these relate to product analytics, and some are primarily technical.
Product Analytics Considerations
It is important to make sure that everything you want to log is represented in your server API. For example, in a funnel, you may only send a single call to the server at the end, but you might want to track the user as they progress through the steps.
Also, there is context that might not be tracked on the server. An example is the location where an action was performed (if there is more than one way to perform an action), which might not be passed to the server.
To make sure that everything required is available server-side, you can start by writing out the flows you want to track, and making sure that all of the events and event properties are represented by API calls.
Technical Considerations
There are some things that the client SDKs take care of that you have to handle by yourself if you do the tracking server-side. The main things are session ids, insert ids and retry/connection logic.
Amplitude's data collection endpoints have extremely high uptime, but there are very occasionally small outages, or you could hit the rate limits if you're sending a lot of data from your server. As a result, it's important that your retry logic is correct if you want to make sure that everything is logged correctly.
Our client libraries store up to 1000 events and will retry if the events aren't sent successfully
Make sure to familiarize yourself with our HTTP response codes, and that your server handles them correctly.
Also make sure you are familiar with our insert_id, which allow us to deduplicate events if you happen to send duplicate events.
Finally, the session_id has to be in a specific format (ms since the epoch) for us to track them properly. Both session_id and insert_id are covered in the above section.