Batch compliance
Introduction
X is committed to our community of developers who build with the X API. As part of this commitment, we aim to make our API open and fair to developers, safe for people on X, and beneficial for the X platform as a whole. It is crucial that any developer who stores X content offline, ensures the data reflects user intent and the current state of content on X. For example,when someone on X deletes a Post or their account, protects their Posts, or scrubs the geo information from their Posts, it is critical for both X and our developers to honor that person’s expectations and intent. The batch compliance endpoints provide developers an easy tool to help maintain X data in compliance with the X Developer Agreement and Policy.
These batch compliance endpoints allow you to upload large datasets of Post or user IDs to retrieve their compliance status in order to determine what data requires action in order to bring your datasets into compliance. Please note, use of the batch compliance endpoints is restricted to aforementioned use cases, and any other purpose is prohibited and may result in enforcement action.
Typically, there are 4 steps involved in working with this endpoint:
-
Create a compliance job You can specify the job type (with the value tweets or users to indicate whether the dataset you want to upload has Post IDs or user IDs. You can have one concurrent job per job type at any time.
-
Upload your dataset to the upload_url Next, you upload your dataset as a plain text file to the provided upload_url, with each line of the file containing a single Post ID or user ID. The upload_url expires after 15 minutes.
-
(Optional) Check the job status You can check the status of your compliance job to see whether it is created, in_progress, failed or complete.
-
Download the results When your job is complete, you can download the results using the download_url. The download_url expires after one week (from when the job was created).
This result will contain a set of JSON objects (one object per line). Each object will contain a Post ID, the Post’s creation date (useful to locate Posts organized by date), required action, the reason for the compliance action, and the date the user was suspended.
You will receive the following compliance event types in your results:
- deleted - indicates that the Post or User account was deleted
- deactivated - indicates that the Post or User account has been deactivated
- scrub_geo - indicates that the geo information associated with the Post or User was removed
- protected - indicates the account that made the Post became private
- suspended - indicates the account that made the Post was suspended
Account setup
To access these endpoints, you will need:
- An approved developer account.
- To authenticate using the keys and tokens from a developer App that is located within a Project.
Learn more about getting access to the X API v2 endpoints in our getting started guide.
Getting started with the batch compliance endpoints
Working with the batch compliance endpoints generally involves 5 steps:
- Creating a compliance job
- Preparing the list of Post IDs or user IDs
- Uploading the list of Post IDs or user IDs
- Checking the status of the compliance job
- Downloading the results
In this section, we will learn how to go through each of these steps using the command line. If you would like to see sample code in different programming languages, please visit our X API v2 sample code GitHub repository.
Prerequisites
To complete this guide, you will need to have a set of keys and tokens to authenticate your request. You can generate these keys and tokens by following these steps:
- Sign up for a developer account and receive approval.
- Create a Project and an associated developer App in the developer portal.
- Navigate to your App’s “Keys and tokens” page to generate the required credentials. Make sure to save all credentials in a secure location.
Step one: Create a compliance job
First, you will have to create a compliance job and specify whether you will be uploading Post IDs or user IDs (using the type parameter). Optionally, you can also give your job a name (using the name parameter).
To authorize this request, you will need to use App only. To do so, make sure to replace the $APP_ACCESS_TOKEN below with your App Access Token that you can generate in your X App on the developer portal.
curl --request POST 'https://api.x.com/2/compliance/jobs' \ --header 'Authorization: Bearer $APP_ACCESS_TOKEN' \ --header 'Content-Type: application/json' \ --data-raw '{"type": "tweets"}'
If your API call is successful, you will get a response similar to the following:
Take note of the value from the upload_url, download_url, and id fields; you will need those in the following steps.
Step two: Prepare a list of Post IDs or user IDs
Create a text file with Post IDs or user IDs, where each line contains a Post ID or user ID. The contents of the text file can look something like this:
1417856744319971329
1415457498803232770
1415348607813832708
1413515358766452738
…
…
Note: The file above can either contain Post IDs or User IDs and can not be a mix of both.
You can upload your file directly to this URL via a PUT request. Note that the URL is already signed with an authentication token, which means you will not authenticate by passing your App Access Token again. Make sure to pass a Content-Type header to signal you are uploading a text file and replace the $FILE_LOCATION below with the path to your file.
A status code 200 will indicate that the upload was successful.
Step three (optional): Check your job status
Large uploads may take some time to process. You can request a status update from the content compliance job endpoint by specifying the job ID you received in the first step.
Again, make sure to replace the ID with your job ID from the first step.
curl --request GET 'https://api.x.com/2/compliance/jobs/$ID' \ --header 'Authorization: Bearer $APP_ACCESS_TOKEN'
Code copied to clipboard
The response will include information about the job.
A complete status means the results are ready for you to download. Note: The other values of statuses can be created, complete, in_progress, failed and expired
Step four: Download the results
As you receive a job completion status, you can download the compliance results from the URL indicated in the download_url field (also generated in the first step). This URL is already signed with an authentication token, which means you will not need authenticate by passing your App Access Token again.
The result will contain a set of JSON objects (one object per line). Each object will contain a Post or user ID, the Post or user’s creation date (useful to locate Posts organized by date), required action, the reason for the compliance action, and its date:
Your code can parse each JSON line to locate the Post or user ID and delete the Posts and users with those IDs from your dataset to stay in compliance. If there is no corresponding JSON object for an ID you uploaded, you can assume that ID is in compliance.
Note: Not all compliance events will include the redacted_atfield.
Working with resumable uploads
When using the Batch compliance endpoints, developers can batch upload large amounts of X data and understand what action is needed to ensure that their datasets reflect user intent and the current state of the content on X. Uploading large amounts of data to a remote server is a relatively straightforward operation when systems and connectivity are stable and reliable. However, this may not always be the case. Some environments may impose a connection timeout, effectively cutting the connection between your app and the upload server after a set amount of time; you may also encounter connection issues, for example when trying to upload a large file from your laptop over a wi-fi connection. In these circumstances, it’s desirable to upload smaller portions of that file at a time, rather than having one single continuous connection.
X’s batch compliance endpoints rely on Google Cloud Storage to process large files. This type of storage is optimized for various applications; Cloud Storage supports a technique to manage large files called resumable uploads.
If the upload goes wrong at any point, Google Cloud Storage is able to resume the operation from where it was left off.
Creating a resumable job
Step one:
First, you will have to create a compliance job and specify whether you will be uploading Post IDs or user IDs (using the type parameter). Additionally, add resumable to the body and set it to true. Make sure to replace the $APP_ACCESS_TOKEN below with your App only Access Token below.
If your API call is successful, you will get a response similar to the following:
Take note of the value from the upload_url, you will need it in the following steps.
Step two:
Next, you will need to initiate the resumable upload. In order to do so, make a POST call to the upload_url from the previous step and make sure to include the following headers:
Content-Type: text/plain
Content-Length: 0
x-goog-resumable: start
If this call is successful, you will get a 201 response code. Then, in the response header, copy the value for the location header which will look something like this:
You can then upload your Post or User IDs to this location by following step two onwards, from the quick start guide.
Because of their technical complexity, resumable uploads are best used in conjunction with code. This guide will use Node.js with the needle request library.
Install the dependencies
Before proceeding, you should have a Node.js environment installed; you can obtain Node.js from its website. Once installed, Node.js will contain a utility called npm; make sure both Node and npm are installed by calling the following command, and ensure it doesn’t result in an error.
$ npm -v 6.4.1
A version number similar to this signifies your environment is ready (note that your version number may differ). We will use npm to install the upload library. Run this command:
$ npm install -g needle
You’re all set; there is no additional configuration required.
Request a resumable destination
When creating a new job, set the resumable parameter to true so you can get a destination that supports a resumable upload. In the response payload, you will receive an upload_url value.
Prepare the code to upload a file
By default, the library will create a new upload destination by accepting an upload location (called bucket) and the name of the file you wish to upload. Because the batch compliance endpoints create their own destination, we will need to tell the library we already have a location ready to accept our upload.
We will need to pass this value to the upload library, along with the name of the file containing the data to upload. Create a file, and name it twitter-upload.js. Add the following code:
Save the file wherever it makes the most sense. Next, in your command line, invoke the script and pass two parameters:
- The first will be the location of the file (with the Post or User IDs) that you wish to upload.
- The second will be the upload URL we received from the compliance endpoint response.
Ensure the URL is surrounded in double-quotes, and do the same for your file name if it contains spaces or other characters:
You will see output similar to this:
Starting upload to: https://storage.googleapis.com/twttr-tweet-compliance/<redacted> Upload not completed, resuming Initiating upload
You can pause the upload at any time by pressing Ctrl + C or closing your command line. You will be able to resume the upload from where you left off when you invoke the same command at a later stage. Once the file has been completely uploaded, you will see the following message:
Upload complete
At this point, you will be able to use the compliance status endpoint to check on the status of your compliance job, and you will be able to download the compliance result when complete.
API reference index
For the complete API reference, select an endpoint from the list:
Creates a new compliance job | POST /2/compliance/jobs |
Returns status and download information about a specified compliance job | GET /2/compliance/jobs/:job_id |
Returns a list of recent compliance jobs | GET /2/compliance/jobs |
GET /2/compliance/jobs/:id
Get a single compliance job with the specified ID.
Endpoint URL
https://api.x.com/2/compliance/jobs/:id
Authentication and rate limits
Authentication methods supported by this endpoint | OAuth 2.0 App-only |
Rate limit | App rate limit (Application-only): 150 requests per 15-minute window shared among all users of your app |
Path parameters
Name | Type | Description |
---|---|---|
id Required | number | The unique identifier for the compliance job you want to retrieve. |
Example code with offical SDKs
Example responses
Response fields
Name | Type | Description |
---|---|---|
id | string | The unique identifier for this job. |
created_at | date (ISO 8601) | The date and time when the job was created. |
type | enum (tweets , users ) | The type of the job, whether tweets or users. |
name | string | The user defined job name. Only returned if specified when the job was created. |
upload_url | string | A URL representing the location where to upload IDs consumed by your app. This URL is already signed with an authentication key, so you will not need to pass any additional credentials or headers to authenticate the request. |
upload_expires_at | date (ISO 8601) | The date and time until which the upload URL will be available (usually 15 minutes from the request time). |
download_url | string | The predefined location where to download the results from the compliance job. This URL is already signed with an authentication key, so you will not need to pass any additional credential or header to authenticate the request. |
download_expires_at | date (ISO 8601) | The date and time until which the download URL will be available (usually 7 days from the request time). |
error | string | Only returned when jobs.status is failed . Specifies the reason why the job did not complete successfully. |
GET /2/compliance/jobs
Returns a list of recent compliance jobs.
Endpoint URL
https://api.x.com/2/compliance/jobs
Authentication and rate limits
Authentication methods supported by this endpoint | OAuth 2.0 App-only |
Rate limit | App rate limit (Application-only): 150 requests per 15-minute window shared among all users of your app |
Query parameters
Name | Type | Description |
---|---|---|
type Required | enum (tweets , users ) | Allows to filter by job type - either by tweets or user ID. Only one filter (tweets or users) can be specified per request. |
status Optional | enum (created , in_progress , failed , complete ) | Allows to filter by job status. Only one filter can be specified per request. Default: all |
Example code with offical SDKs
Example responses
Response fields
Name | Type | Description |
---|---|---|
id | string | The unique identifier for this job. |
created_at | date (ISO 8601) | The date and time when the job was created. |
type | enum (tweets , users ) | The type of the job, whether tweets or users. |
name | string | The user defined job name. Only returned if specified when the job was created. |
upload_url | string | A URL representing the location where to upload IDs consumed by your app. This URL is already signed with an authentication key, so you will not need to pass any additional credentials or headers to authenticate the request. |
upload_expires_at | date (ISO 8601) | The date and time until which the upload URL will be available (usually 15 minutes from the request time). |
download_url | string | The predefined location where to download the results from the compliance job. This URL is already signed with an authentication key, so you will not need to pass any additional credential or header to authenticate the request. |
download_expires_at | date (ISO 8601) | The date and time until which the download URL will be available (usually 7 days from the request time). |
status | enum (in_progress , failed , complete ) | Current status of this job. |
error | string | Only returned when jobs.status is failed . Specifies the reason why the job did not complete successfully. |
POST /2/compliance/jobs
”Creates a new compliance job for Tweet IDs or user IDs.
A compliance job will contain an ID and a destination URL. The destination URL represents the location that contains the list of IDs consumed by your App.
You can run one batch job at a time.”
Endpoint URL
https://api.x.com/2/compliance/jobs
Authentication and rate limits
Authentication methods supported by this endpoint | OAuth 2.0 App-only |
Rate limit | App rate limit (Application-only): 150 requests per 15-minute window shared among all users of your app |
JSON body parameters
Name | Type | Description |
---|---|---|
type Required | enum (tweets , users ) | Specify whether you will be uploading tweet or user IDs. You can either specify tweets or users. |
name Optional | string | A name for this job, useful to identify multiple jobs using a label you define. |
resumable Optional | boolean | Specifies whether to enable the upload URL with support for resumable uploads. If true, this endpoint will return a pre-signed URL with resumable uploads enabled. |
Example code with offical SDKs
Example responses
Response fields
Name | Type | Description |
---|---|---|
id | string | The unique identifier for this job. |
created_at | date (ISO 8601) | The date and time when the job was created. |
type | enum (tweets , users ) | The type of the job, whether tweets or users. |
name | string | The user defined job name. Only returned if specified when the job was created. |
upload_url | string | A URL representing the location where to upload Tweet IDs consumed by your App. This URL is already signed with an authentication key, so you will not need to pass any additional credentials or headers to authenticate the request. |
upload_expires_at | date (ISO 8601) | The date and time until which the upload URL will be available (usually 15 minutes from the request time). |
download_url | string | The predefined location where to download the results from the compliance job. This URL is already signed with an authentication key, so you will not need to pass any additional credentials or headers to authenticate the request. |
download_expires_at | date (ISO 8601) | The date and time until which the download URL will be available (usually seven days from the request time). |