
{% callout type="info" heading="User Privacy API v2 is available" %}
Amplitude has released User Privacy API v2, hosted at `privacy.amplitude.com`. For new integrations, we recommend [User Privacy API v2](/docs/apis/analytics/user-privacy-v2). This page documents the v1 API (`/api/2/deletions/users` on `amplitude.com`).
{% /callout %}

## Regions

The base URL depends on your project's data residency. In all examples on this page, use the default base URL unless your project uses Amplitude's EU data center—in that case use the EU base URL in this table.

Requests go to `https://amplitude.com` (default) or `https://analytics.eu.amplitude.com` (EU). The `https://analytics.amplitude.com` hostname is the Analytics web app (browser UI); use the hosts in this table for REST requests, not `analytics.amplitude.com`.

| Data residency | Base URL                             |
| -------------- | ------------------------------------ |
| Default        | `https://amplitude.com`              |
| EU             | `https://analytics.eu.amplitude.com` |

## Considerations

Note the following when using the User Privacy API:

- You can delete data for an end user across a single project or across your entire organization. By default, deletion requests create jobs for the project that the request's API key identifies. To delete a user across your entire organization, set the `delete_from_org` parameter to `true`. When `delete_from_org` is `true`, the API creates one deletion job per project that contains data for the requested users, and treats `ignore_invalid_ids` as `true` regardless of the input.
- When you make a deletion request, Amplitude [emails all account admins](https://help.amplitude.com/hc/en-us/articles/360031965572-Manage-user-privacy-notifications-in-Amplitude) with the deletion details.
- Amplitude deletes all events and user properties added up until the time the 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, Amplitude 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.
- Amplitude schedules batch jobs for deletions to reduce resource impact and ensure high availability. The batch's first request date is the reference point for scheduling. In line with GDPR articles 12.3 and 17, Amplitude processes deletion requests within 30 days after receiving the request. The actual timeline depends on the complexity and number of requests. If your data volume is large (>1BB/month), Amplitude may reduce your frequency of deletion scheduling.
- You can revoke requests in the batch until three (3) days before the job's scheduled run date. During the three (3) day period, you can't edit the batch. Amplitude adds deletion requests made during this period to a new batch.
- After the three (3) day period, the request's status changes to `submitted`, and you can't stop the job. The deletion process removes all data associated with the user from all of Amplitude's systems, including associated recovery and back-up systems. After the job completes, its status changes to `done`.
- To check the progress of your deletion requests, use the GET API to inspect the job status for each project, using each project's API key.
- This User Privacy API only deletes data from the Amplitude platform. To delete data from the Statsig platform, use the [Statsig User Data Deletion Requests API](https://docs.statsig.com/compliance/user_data_deletion_requests).

{% callout type="warning" heading="User tracking" %}
Using this API doesn't prevent future user tracking for the deleted users. To stop tracking users in your application, refer to the `setOptOut()` method in the documentation for the Amplitude SDK you're using.

If you use warehouse Change Data Capture (CDC) sources or other data warehouse ingestion methods, and you delete a user's data in Amplitude while that data still exists in your data warehouse, Amplitude may reingest it during the next sync. To ensure complete deletion, delete the user's data from your data warehouse or other ingestion sources.
{% /callout %}

## 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`. There is also a limit of 8 requests running in parallel for a given project.

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 a mix of Amplitude IDs and User IDs.

{% accordion title="Example: Delete a user in one project" %}

{% code-group %}
```bash cURL
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"],
    "requester": "employee@yourcompany.com"
}'
```

```http HTTP
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
],
"requester": "employee@yourcompany.com"
}
```

```js JavaScript
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));
  },
});
```

```js Node
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);
});
```

```ruby Ruby
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)
```

```python Python
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"
  ],
  "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)
```

```java Java
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());
```

```go Go
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
    ],
    "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))
}
```
{% /code-group %}
{% /accordion %}

{% accordion title="Example: Delete users from all projects" %}
{% code-group %}
```bash cURL
curl --location --request POST 'https://amplitude.com/api/2/deletions/users' \
-u 'API_KEY:SECRET_KEY' \
--header 'Content-Type: application/json' \
--data-raw '{
    "amplitude_ids": [
        356896327775,
        356896327755

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

```bash HTTP
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
    ],
    "delete_from_org": "true",
    "ignore_invalid_ids": "true",
    "requester": "employee@yourcompany.com"
}
```

```js JavaScript
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));
  },
});
```

```js Node
const request = require('node-fetch');
const inputBody = '{
  "amplitude_ids": [
    "amp_id_1",
    "amp_id_2",
    "..."
  ],
  "user_ids": [
    "user_id_1",
    "user_id_2",
    "..."
  ],
  "delete_from_org": true,
  "ignore_invalid_ids": true,
  "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);
});
```

```ruby Ruby
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)
```

```python Python
import requests
import json

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

payload = json.dumps({
  "amplitude_ids": [
    356896327775,
    356896327755
  ],
  "user_ids": [
    1000,
    2999
  ],
  "delete_from_org": True,
  "ignore_invalid_ids": True,
  "requester": "employee@yourcompany.com"
})
headers = {
  'Authorization': 'Basic API_KEY:API_SECRET',
  'Content-Type': 'application/json'
}

response = requests.request("POST", url, headers=headers, data=payload)

print(response.text)
```

```java Java
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());
```

```go Go
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
    ],
    "delete_from_org": true,
    "ignore_invalid_ids": true,
    "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))
}
```
{% /code-group %}
{% /accordion %}

### 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`       | Boolean. Defaults to `false`. When `false`, if any users in the request aren't found in the project, the API returns a 400 error and doesn't mark any users for deletion. When `true`, the API returns a 200 success that includes a list of `invalid_ids` and adds any users found in the project to the job. `invalid_ids` represent requested users with no data in the project. If `delete_from_org` is `true`, the API sets this field to `true` and ignores the input. |
| `delete_from_org`         | Boolean. Defaults to `false`. When `false`, the request deletes the requested users only from the project that the API key identifies. When `true`, the API deletes the requested users across your entire organization by inserting them into a job for each project that contains their data. When `true`, the API sets `ignore_invalid_ids` to `true` and ignores the input.                                                                                              |
| `include_mapped_user_ids` | When `true`, returns the valid `user_id` values that correspond to a supplied `amplitude_id`. This parameter only changes the response object. To delete mapped users set with the [User Mapping API](/docs/apis/analytics/user-mapping/), include each mapped user's `user_id` in the `user_ids` array.                                                                                                                                                                     |

### 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.                             |
| `invalid_ids`                  | When `ignore_invalid_ids` is `true`, contains a list of users that were requested but not found in the 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, if you made a deletion request on August 1st, 2018, your query should have `start_day = 2018-08-01` and `end_day = 2018-08-31`.

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

{% code-group %}
```bash cURL
# 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
```

```bash HTTP
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
```

```js JavaScript
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));
  },
});
```

```js Node
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);
  });
```

```ruby Ruby
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)
```

```python Python
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()
```

```java Java
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());
```

```go Go
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)
    // ...
}
```
{% /code-group %}

### Query parameters

| Name        | Description                                                                                    |
| ----------- | ---------------------------------------------------------------------------------------------- |
| `start_day` | Required. First hour included in data series, formatted `YYYY-MM-DD`. For example, `2022-02-01`. |
| `end_day`   | Required. Last hour included in data series, formatted `YYYY-MM-DD`. For example, `2022-02-01`.   |

### Response

The success response for a `GET` request contains these fields:

- **`day`**
  - **Description**: The day the deletion job is scheduled to begin.
- **`status`**
  - **Description**:
    - 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`**
  - **Description**: List of the Amplitude Ids of users to delete.
- **`app`**
  - **Description**: Project or app ID. Appears if the deletion is applied to more than one project.
- **`active_scrub_done_date`**
  - **Description**: The date the scrub completed and the data is no longer accessible. After this date, Amplitude waits 5 days for any backups to clear automatically. The status changes to `done` only after 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.                     |

```json
[
  {
    "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`

```bash
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.                       |

```json
{
  "amplitude_id": 1234567,
  "requested_on_day": "string",
  "requester": "string"
}
```

## Status codes

| Code | Message      |
| ---- | ------------ |
| 200  | Success      |
| 400  | Bad Request  |
| 401  | Unauthorized |
