The Amp Devcenter Test Developer Hub

Welcome to the Amp Devcenter Test developer hub. You'll find comprehensive guides and documentation to help you start working with Amp Devcenter Test as quickly as possible, as well as support if you get stuck. Let's jump right in!

Get Started    

Batch Event Upload API

The Batch Event Upload endpoint accepts JSON requests that contain an API key and a list of events.

The event JSON format follows our HTTP API format, and has the same requirements (such as each event must have an event type, etc). After a request is accepted successfully, the events in the batch should be queryable within 15 minutes most of the time. The JSON serialized payload must not exceed 20MB in size.

NOTE: In addition, 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 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.

Each API key is allowed to send up to 1000 events per second for any individual device / user Id. If you exceed that rate your upload will be rejected with a response code of 429. The response summary will indicate which device / user Ids have exceeded the limit, what their current events per second rate is, along with some other useful information. See below for more details.

429s in depth

Partition work by device_id if throughput is degraded
by throttling
                                .-----------.    .--------.
                             .->|Partition 1|--->|Worker 1|---.
.--------.                   |  '-----------'    '--------'   |  .---------.
|        |  .--------------. |  .-----------.    .--------.   '->|         |
|All data|->|hash device_id|--->|Partition 2|--->|Worker 2|----->|Amplitude|
|        |  '--------------' |  '-----------'    '--------'   .->|         |
'--------'                   |  .-----------.    .--------.   |  '---------'
                             '->|Partition 3|--->|Worker 3|---'
                                '-----------'    '--------'

We measure the rate of events for each deviceid and _each userid for a project, we refer to these rates as _events per device second (EPDS) & events per user second (EPUS) respectively. These are both averaged over a time window of (currently) 30 seconds. So for example an EPDS limit of 1000 would require that a device sends 30,000 events in a 30 second window for that device to be throttled i.e. receive HTTP status 429.

In addition to the per second limit, we also have a very rarely exceeded daily limit to prevent against spam and abuse. The limit will start counting after we’ve determined that a user/device is spamming us. We enforce a daily limit of 500,000 events uploaded per rolling 24 hours. The 24 hour rolling window applies in 1 hour interval. The daily limit applies for each deviceid and _each user_id for a project. Please note that this limit is independent of the EPDS/EPUS. Once a user/device has hit the 500,000 daily limit for a particular project any batches uploaded that contain that user/device will be rejected and we will return a 429 response with body indicating “exceeded_daily_quota_users” or “exceeded_daily_quota_devices” with list of deviceId/userId. The limit is rolling so once there are less than 500,000 events uploaded for a user/device in a given project in the last 24 hour period the batch can be retried. Please contact us for further support if you are encountering the daily limit.

When a request is throttled it means that some device or user in that request was throttled. Details about which can be found in the error response data. Logging the response will allow you to investigate which users or devices were the cause of throttling.

In general your application should not measure EPDS or EPUS itself. Send requests to Amplitude as fast as possible, then when a 429 error is received, sleep for a short period of time (e.g. 15 seconds) before trying to send that request again.

Because device_id and user_id are the attributes that determine throttling, partitioning work on one of these attributes will help isolate throttling to a specific partition of work. This way partitions which are not being throttled can still make progress while the throttled partitions are blocked by throttling.

Why use this endpoint instead of the HTTP API?

Feature comparison between /httpapi, /2/httpapi & /batch

FeatureHttp APIHttp API V2Batch
realtime?yesyesno
throttling @30 EPDS30 EPDS1,000 EPDS
request size1MB1MB20 MB
events/request2,0002,0002,000
error responsesvaguedetaileddetailed

Like the HTTP API, the Batch Event Upload endpoint can be used to send data directly from your server. Unlike the HTTP API, this endpoint is recommended for Customers that want to send large batches of data at a time, for example through scheduled jobs, rather than in a continuous realtime stream. Due to the higher rate of data that is permitted to this endpoint, data sent to this endpoint may be delayed based on load.

See Amplitude Help Center for more support articles and documentation.

Terms of service
Email: Support
License: MIT License

Post Batch

Code samples

# You can also use wget
curl -X POST https://api.amplitude.com/batch \
  -H 'Content-Type: application/json' \
  -H 'Accept: */*'
POST https//api.amplitude.com/batch HTTP/1.1
Host: api.amplitude.com
Content-Type: application/json
Accept: */*
var headers = {
  'Content-Type':'application/json',
  'Accept':'*/*'

};

$.ajax({
  url: 'https://api.amplitude.com/batch',
  method: 'post',

  headers: headers,
  success: function(data) {
    console.log(JSON.stringify(data));
  }
})
const request = require('node-fetch');
const inputBody = '{
  "api_key": "my_amplitude_api_key",
  "events": [
    {
      "user_id": "[email protected]",
      "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"
    }
  ]
}';
const headers = {
  'Content-Type':'application/json',
  'Accept':'*/*'

};

fetch('https://api.amplitude.com/batch',
{
  method: 'POST',
  body: inputBody,
  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});
require 'rest-client'
require 'json'

headers = {
  'Content-Type' => 'application/json',
  'Accept' => '*/*'
}

result = RestClient.post 'https://api.amplitude.com/batch',
  params: {
  }, headers: headers

p JSON.parse(result)
import requests
headers = {
  'Content-Type': 'application/json',
  'Accept': '*/*'
}

r = requests.post('https://api.amplitude.com/batch', params={

}, headers = headers)

print r.json()
URL obj = new URL("https://api.amplitude.com/batch");
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("POST");
int responseCode = con.getResponseCode();
BufferedReader in = new BufferedReader(
    new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
    response.append(inputLine);
}
in.close();
System.out.println(response.toString());
package main

import (
       "bytes"
       "net/http"
)

func main() {

    headers := map[string][]string{
        "Content-Type": []string{"application/json"},
        "Accept": []string{"*/*"},

    }

    data := bytes.NewBuffer([]byte{jsonReq})
    req, err := http.NewRequest("POST", "https://api.amplitude.com/batch", data)
    req.Header = headers

    client := &http.Client{}
    resp, err := client.Do(req)
    // ...
}

POST /batch
Bulk upload events

Bulk upload events to Amplitude via the batch event upload endpoint.

If you have used our HTTP API before, note that there are two minor but important differences in your POST request to /batch. 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.

Body parameter

{
  "api_key": "my_amplitude_api_key",
  "events": [
    {
      "user_id": "[email protected]",
      "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"
    }
  ]
}

Parameters

ParameterInTypeRequiredDescription
bodybodyUploadRequestBodytrueA JSON object containing your api_key and an array of events

Responses

StatusMeaningDescriptionSchema
200OKSuccessful batch event uploadSuccessSummary
400Bad RequestA 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
413Payload Too LargePayload size is too big (request size exceeds 20MB). You should split your events array payload in half and try again.PayloadTooLargeError
429Too Many RequestsToo many requests for a user / device. Amplitude will throttle requests for users and devices that exceed 1000 events per second (measured as an average over a recent time window) or 500,000 events per 24 hours rolling period (measured as a rolling window of 1-hour interval). If you encountered the "per seconds" throttling, 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. If you encountered the "daily limit" throttling, you should try again in the next hour and contact us for further support. Note: the daily limit (24-hours rolling limit) only applies if we've determined that your user/device is spammy.TooManyRequestsForDeviceError

This operation does not require authentication

UploadRequestBody

{
  "api_key": "my_amplitude_api_key",
  "events": [
    {
      "user_id": "[email protected]",
      "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"
    }
  ]
}

Properties

NameTypeRequiredRestrictionsDescription
api_keystringtruenoneAmplitude project API key
events[Event]truenoneArray of Events to upload
options[options]falsenoneObject

Event

{
  "user_id": "[email protected]",
  "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"
}
{
  "user_id": "[email protected]",
  "device_id": "C8F9E604-F01A-4BD9-95C6-8E5357DF265D",
  "event_type": "$identify",
  "time": 1396381378123,
  "user_properties": {
    "$set": {
      "age": 25,
      "gender": "female",
      "interests": [
      "chess",
      "football",
      "music"
    ]}
  },
  "event_id": 23,
  "session_id": 1396381378123,
  "insert_id": "5f0adeff-6668-4427-8d02-57d803a2b841"
}
{
  "user_id": "[email protected]",
  "device_id": "C8F9E604-F01A-4BD9-95C6-8E5357DF265D",
  "event_type": "$groupidentify",
  "time": 1396381378123,
  "groups": {
    "company_id": "1",
    "company_name": [
      "Amplitude",
      "DataMonster"
    ]
  },
  "group_properties": {
    "$set": {
      "start_date": "01/01/2017"
    }
  },
  "event_id": 23,
  "session_id": 1396381378123,
  "insert_id": "5f0adeff-6668-4427-8d02-57d803a2b841"
}

Properties

NameTypeRequiredRestrictionsDescription
user_idstringtruenoneA readable ID specified by you. Must have a minimum length of 5 characters. Required unless device_id is present.
device_idstringtruenoneA 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_typestringtruenoneA unique identifier for your event. Note: "$identify" and "$groupidentify" are predefined for identification and group identification. More information about the two operations can be found in the descriptions of "user_properties" and "group_properties".
timelongfalsenoneThe 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_propertiesobjectfalsenoneA 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. Object depth may not exceed 40 layers.
user_propertiesobjectfalsenoneA 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. In addition, user property operations ($set, $setOnce, $add, $append, $unset) are supported when "event_type" is "$identify". Object depth may not exceed 40 layers.
groupsobjectfalsenoneThis 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.
group_propertiesobjectfalsenoneThis feature is only available to Enterprise customers who have purchased the Accounts add-on. When "event_type" is "$groupidentify", the field is a dictionary of key-value pairs that represent properties tied to the groups listed in the "groups" field. The field is ignored for other event types. Group property operations ($set, $setOnce, $add, $append, $unset) are also supported.
app_versionstringfalsenoneThe current version of your application.
platformstringfalsenonePlatform of the device.
os_namestringfalsenoneThe name of the mobile operating system or browser that the user is using.
os_versionstringfalsenoneThe version of the mobile operating system or browser the user is using.
device_brandstringfalsenoneThe device brand that the user is using.
device_manufacturerstringfalsenoneThe device manufacturer that the user is using.
device_modelstringfalsenoneThe device model that the user is using.
carrierstringfalsenoneThe carrier that the user is using.
countrystringfalsenoneThe current country of the user.
regionstringfalsenoneThe current region of the user.
citystringfalsenoneThe current city of the user.
dmastringfalsenoneThe current Designated Market Area of the user.
languagestringfalsenoneThe language set by the user.
pricefloatfalsenoneThe price of the item purchased. Required for revenue data if the revenue field is not sent. You can use negative values to indicate refunds.
quantityintegerfalsenoneThe quantity of the item purchased. Defaults to 1 if not specified.
revenuefloatfalsenonerevneue = 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.
productIdstringfalsenoneAn identifier for the item purchased. You must send a price and quantity or revenue with this field.
revenueTypestringfalsenoneThe type of revenue for the item purchased. You must send a price and quantity or revenue with this field.
location_latfloatfalsenoneThe current Latitude of the user.
location_lngfloatfalsenoneThe current Longitude of the user.
ipstringfalsenoneThe IP address of the user. Use "$remote" to use the IP address on the upload request. 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.
idfastringfalsenone(iOS) Identifier for Advertiser.
idfvstringfalsenone(iOS) Identifier for Vendor.
adidstringfalsenone(Android) Google Play Services advertising ID
android_idstringfalsenone(Android) Android ID (not the advertising ID)
event_idintfalsenone(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_idlongfalsenone(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_idstringfalsenone(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

Properties

NameTypeRequiredRestrictionsDescription
min_id_lengthintegerfalsenoneMinimum permitted length for user_id & device_id fields
"options": {
  "min_id_length": 5,
}

SuccessSummary

{
  "code": 200,
  "events_ingested": 50,
  "payload_size_bytes": 50,
  "server_upload_time": 1396381378123
}

Properties

NameTypeRequiredRestrictionsDescription
codeintegerfalsenone200 success code
events_ingestedintegerfalsenoneThe number of events ingested from the upload request.
payload_size_bytesintegerfalsenoneThe size of the upload request payload in bytes.
server_upload_timelongfalsenoneThe time in milliseconds since epoch (Unix Timestamp) that our event servers accepted the upload request.

InvalidRequestError

{
  "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
    ]
  }
}

Properties

NameTypeRequiredRestrictionsDescription
codeintegerfalsenone400 error code
errorstringfalsenoneError 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_fieldstringfalsenoneIndicates which request-level required field is missing.
events_with_invalid_fieldsobjectfalsenoneA 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_fieldsobjectfalsenoneA map from field names to an array of indexes into the events array indicating which events are missing those required fields

PayloadTooLargeError

{
  "code": 413,
  "error": "Payload too large"
}

Properties

NameTypeRequiredRestrictionsDescription
codeintegerfalsenone413 error code
errorstringfalsenoneError description.

TooManyRequestsForDeviceError

{
  "code": 429,
  "error": "Too many requests for some devices and users",
  "eps_threshold": 1000,
  "throttled_devices": {
    "C8F9E604-F01A-4BD9-95C6-8E5357DF265D": 4000
  },
  "throttled_users": {
    "[email protected]": 4000
  },
  "exceeded_daily_quota_users": {
    "[email protected]": 500200
  },
  "exceeded_daily_quota_devices": {
    "A1A1A000-F01A-4BD9-95C6-8E5357DF265D": 500900
  },
  "throttled_events": [
    3,
    4,
    7
  ]
}

Properties

NameTypeRequiredRestrictionsDescription
codeintegerfalsenone429 error code
errorstringfalsenoneError description.
eps_thresholdintegerfalsenoneYour app's current events per second threshold. If you exceed this rate your requests will be throttled.
throttled_devicesobjectfalsenoneA map from device_id to its current events per second rate, for all devices that exceed the app's current threshold.
throttled_usersobjectfalsenoneA map from user_id to their current events per second rate, for all users that exceed the app's current threshold
throttled_events[integer]falsenoneArray of indexes in the events array indicating events whose user_id and/or device_id got throttled

Updated 3 months ago


Batch Event Upload API


Suggested Edits are limited on API Reference Pages

You can only suggest edits to Markdown body content, but not to the API spec.