Skip to content

User Privacy API

The User Privacy API helps you comply with end-user data deletion requests mandated by global privacy laws such as GDPR and CCPA. The API lets you programmatically submit requests to delete all data for a set of known Amplitude IDs or User IDs.

Get more examples for this API

The Amplitude Developers Postman profile has a full library of example requests and responses for this API.

Check out the Amplitude Developers Profile to view the collection. You don't need a Postman account to browse.

If you already use Postman, you can fork and run this collection in Postman.

Authorization

This API uses basic authentication, using the API key and secret key for your project. Pass base64-encoded credentials in the request header like {{api-key}}:{{secret-key}}. api-key replaces username, and secret-key replaces the password.

Your authorization header should look something like this:

--header 'Authorization: Basic YWhhbWwsdG9uQGFwaWdlZS5jb206bClwYXNzdzByZAo'

See Find your Amplitude Project API Credentials for help locating your credentials.

Endpoints

Region Endpoint
Standard Server https://amplitude.com/api/2/deletions/users
EU Residency Server https://analytics.eu.amplitude.com/api/2/deletions/users

Considerations

Keep these considerations in mind when using the User Privacy API.

  • When you make a deletion request, Amplitude emails all account admins with the deletion details.
  • Amplitude deletes all events and user properties added up until the time that job runs for each Amplitude ID in a deletion job.
  • Running a deletion job for a user doesn't block new events for that user. Amplitude accepts new events from a deleted user.
  • If Amplitude receives events for a deleted user, then it counts the deleted user as a new user. Because deletion removes all user data from Amplitude servers, Amplitude doesn't recognize the new user as the deleted user.
  • To reduce resource impact and ensure high availability, Amplitude batches requests for deletions. Batch jobs are scheduled for 10-13 days after the date of the batch's first request. In line with GDPR article 12.3 and 17, Amplitude processes deletion requests without undue delay, within 30 days after receiving the request. The actual timeline for deletion depends on the complexity and number of requests Amplitude receives. If your data volume is large (>1BB/month), then Amplitude may need to reduce your frequency of deletion scheduling.
  • You can revoke requests in the batch until three (3) days before the day the job scheduled run date. During the three (3) day period, you can't edit the batch. Amplitude adds deletion requests made during this time to a new batch.
  • After the three (3) day period, the request's status changes to submitted. You can't stop the job at this point. The deletion process removes all data associated with the user from all Amplitude's systems, including associated recovery and back-up systems. After the job completes, its status changes to done.

User tracking

Using this API doesn't prevent future user tracking for the deleted users. To learn about how to stop tracking users in your application, see the setOptOut() method in documentation for the Amplitude SDK you're using.

Limits

The endpoint /api/2/deletions/users has a rate limit of 1 HTTP request per second. Each HTTP request can contain up to 100 amplitude_ids or user_ids. You can make up to 100 deletion requests per second if you batch 100 users in each request.

Delete users

POST /deletions/users

Add a user for deletion using a JSON body. Specify up to 100 users at a time. You can use mix of Amplitude IDs and User IDs.

JSON body parameter

The body parameter is required. It's the deletion request object listing the user_ids and amplitude_ids for the users to delete.

Name
Description
amplitude_ids Amplitude IDs for the users to delete.
user_ids User IDs for the users to delete.
requester The internal user who requested the deletion. This is useful for auditing.
ignore_invalid_id When true, the job ignores invalid user IDs. Invalid user IDs are users that don't exist in the project. Defaults to false
delete_from_org Delete user from the entire org instead of a single project. This feature is available in orgs with the Portfolio feature enabled. The users must exists in all projects. This option can be combined with ignore_invalid_id field to skip projects that are missing the given users. Values can be either True or False. Defaults to False.
include_mapped_user_ids When true, this parameter returns the valid user_id values that correspond to a supplied amplitude_id. This only changes the response object. To delete mapped users set with the User Mapping API, include each user_id of the mapped user in the user_ids array.

Example request

   curl --request POST 'https://amplitude.com/api/2/deletions/users'  \
   -u 'API_KEY:API_SECRET' \
   --header 'Content-Type: application/json' \
   --header 'Accept: application/json' \
   --data-raw '{
       "amplitude_ids": [123123, 543221],
       "user_ids": ["user_1"],
       "ignore_invalid_id": "True",
       "requester": "email@email.com"
   }'
POST /api/2/deletions/users HTTP/1.1
Host: amplitude.com
Authorization: Basic API_KEY:SECRET_KEY
Content-Type: application/json

{
    "amplitude_ids": [
        356896327775,
        356896327755

    ],
    "user_ids": [
        1000,
        2999
    ],
    "ignore_invalid_id": "true",
    "delete_from_org": "false",
    "requester": "employee@yourcompany.com"
}
var headers = {
  'Content-Type':'application/json',
  'Accept':'application/json'

};

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

  headers: headers,
  success: function(data) {
    console.log(JSON.stringify(data));
  }
})
const request = require('node-fetch');
const inputBody = '{
  "amplitude_ids": [
    "amp_id_1",
    "amp_id_2",
    "..."
  ],
  "user_ids": [
    "user_id_1",
    "user_id_2",
    "..."
  ],
  "requester": "employee@yourcompany.com"
}';
const headers = {
  'Content-Type':'application/json',
  'Accept':'application/json'

};

fetch('https://amplitude.com/api/2/deletions/users',
{
  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' => 'application/json'
}

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

p JSON.parse(result)
   import requests
   import json
   from requests.auth import HTTPBasicAuth

   url = "https://amplitude.com/api/2/deletions/users"

   payload = json.dumps({
     "amplitude_ids": [
       1231231
     ],
     "user_ids": [
       "user_1"
     ],
     "ignore_invalid_id": "true",
     "requester": "employee@yourcompany.com"
   })
   headers = {
     'Content-Type': 'application/json',
     'Accept': 'application/json'
   }
   auth = HTTPBasicAuth('API_KEY', 'API_SECRET')
   response = requests.request("POST", url, headers=headers, data=payload, auth=auth)

   print(response.text)
URL obj = new URL("https://amplitude.com/api/2/deletions/users");
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 (
  "fmt"
  "strings"
  "net/http"
  "io/ioutil"
)

func main() {

  url := "https://amplitude.com/api/2/deletions/users"
  method := "POST"

  payload := strings.NewReader(`{
    "amplitude_ids": [
        356896327775,
        356896327755

    ],
    "user_ids": [
        1000,
        2999
    ],
    "ignore_invalid_id": "true",
    "delete_from_org": "false",
    "requester": "employee@yourcompany.com"
}`)

  client := &http.Client {
  }
  req, err := http.NewRequest(method, url, payload)

  if err != nil {
    fmt.Println(err)
    return
  }
  req.Header.Add("Authorization", "Basic API_KEY:API_SECRET")
  req.Header.Add("Content-Type", "application/json")

  res, err := client.Do(req)
  if err != nil {
    fmt.Println(err)
    return
  }
  defer res.Body.Close()

  body, err := ioutil.ReadAll(res.Body)
  if err != nil {
    fmt.Println(err)
    return
  }
  fmt.Println(string(body))
}

Response

The response for a POST request contains these fields:

Name
Description
day The day the deletion job is scheduled to begin.
status The status of the deletion job.
amplitude_ids and user_ids List of the Amplitude IDs to delete.
app The project or app ID. Included when the deletion request is for multiple projects.

The amplitude_ids key contains these fields:

Name
Description
amplitude_id The Amplitude ID of the user to be deleted.
requester The person who requested the Amplitude ID to be deleted.
requested_on_day The day this deletion was requested.
user_id The corresponding User ID. Included when include_mapped_user_ids is true and the amplitude_id are matched to user_ids.

Get deletion jobs

/api/2/deletions/users?start_day=YYYY-MM-DD&end_day=YYYY-MM-DD

Retrieves a list of deletion jobs scheduled in a time range. The time range should include the date you made the request on plus 30 days. For example, you made a deletion request on August 1st, 2018. Your deletion request should have start_day = 2018-08-01 and end_day = 2018-08-31.

If the request returns no values, then no jobs are scheduled for that time range. Note: The largest permitted time range is six months.

Example request

# You can also use wget
curl -X GET https://amplitude.com/api/2/deletions/users?start_day=string&end_day=string \
  -H 'Accept: application/json' \
  -U API_KEY:API_SECRET
GET https://amplitude.com/api/2/deletions/users?start_day=string&end_day=string HTTP/1.1
Host: amplitude.com
Authorization: Basic API_KEY:API_SECRET
Accept: application/json
var headers = {
  'Accept':'application/json'

};

$.ajax({
  url: 'https://amplitude.com/api/2/deletions/users',
  method: 'get',
  data: '?start_day=string&end_day=string',
  headers: headers,
  success: function(data) {
    console.log(JSON.stringify(data));
  }
})
const request = require('node-fetch');

const headers = {
  'Accept':'application/json'

};

fetch('https://amplitude.com/api/2/deletions/users?start_day=string&end_day=string',
{
  method: 'GET',

  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});
require 'rest-client'
require 'json'

headers = {
  'Accept' => 'application/json'
}

result = RestClient.get 'https://amplitude.com/api/2/deletions/users',
  params: {
  'start_day' => 'string',
'end_day' => 'string'
}, headers: headers

p JSON.parse(result)
import requests
headers = {
  'Accept': 'application/json'
}

r = requests.get('https://amplitude.com/api/2/deletions/users', params={
  'start_day': 'string',  'end_day': 'string'
}, headers = headers)

print r.json()
URL obj = new URL("https://amplitude.com/api/2/deletions/users?start_day=string&end_day=string");
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("GET");
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{
        "Accept": []string{"application/json"},

    }

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

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

Query parameters

Name Description
start Required. First hour included in data series, formatted YYYYMMDD. For example, 20220201.
end Required. Last hour included in data series, formatted YYYYMMDD For example, 20220201.

Response

The success response for a GET request contains these fields:

Property
Description
day The day the deletion job is scheduled to begin.
status The deletion job's status.

Staging: The job hasn't started, and you can modify it. More deletion requests may get scheduled into this job and you can remove requests from this job.

Submitted: The job is submitted to run. You can't modify it.

Done: The job has finished running. You can't modify it.
amplitude_ids List of the Amplitude Ids of users to delete.
app Project or app ID. Appears if the deletion is applied to more than one project.
active_scrub_done_date The date that the scrub has completed, and the data is no longer accessible. After this point, the system waits 5 days for any backups to be automatically cleared. The status will change to 'done' only when the backups are removed.

The amplitude_ids key contains these fields:

Name
Description
amplitude_id The Amplitude ID of the user to be deleted.
requester The person who requested the Amplitude ID to be deleted.
requested_on_day The day this deletion was requested.
[
  {
    "day": "string",
    "amplitude_ids": [
      {
        "amplitude_id": 0,
        "requested_on_day": "string",
        "requester": "string"
      }
    ],
    "status": "string"
  }
]

Delete a User from a deletion job

Removes the specified Amplitude ID from a deletion job.

/api/2/deletions/users/AMPLITUDE_ID/YYYY-MM-DD

Example request

curl -X DELETE \
  'https://amplitude.com/api/2/deletions/users/AMPLITUDE_ID/JOB_START_DAY' \
    -H 'Content-Type: application/json' \
  -U API_KEY:API_SECRET
}'

Path variables

Name
Description
AMPLITUDE_ID Required. The amplitude_id to be removed from a deletion job.
JOB_START_DAY Required. Day the deletion is schedule for. YYYY-MM-DD

Response

A successful request returns a response with this schema:

Property
Description
amplitude_id The Amplitude ID of the user that was removed from the job
requester The person who requested the Amplitude ID to be deleted.
requested_on_day The day this deletion was requested.
 {
   "amplitude_id": 1234567,
   "requested_on_day": "string",
   "requester": "string"
 }

Status codes

Code Message
200 Success
400 Bad Request
401 Unauthorized

Was this page helpful?