> ## Documentation Index
> Fetch the complete documentation index at: https://x-preview-mintlify-cdd4f466.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Integration guide

> Integrate the X API v2 Batch Compliance endpoints: create a job, upload your ID file to the tokenized upload URL, poll job status, and download results.

The Batch Compliance endpoints let you upload large datasets of Post IDs or user IDs and find out what action is needed to keep your datasets in sync with user intent and the current state of content on X. This guide covers how the upload and download flow works and the constraints to plan for.

<Warning>
  Resumable uploads are no longer supported. Setting `resumable` in the body of `POST /2/compliance/jobs` returns a 400 error: `Resumable uploads are not supported; create the job without resumable`. Create the job without the `resumable` field and upload your file in a single `PUT` request.

  Upload and download URLs are now served from `api.x.com` with a signed `token` query parameter. Earlier versions of these endpoints returned Google Cloud Storage signed URLs (`storage.googleapis.com`) and used `X-Goog-*` headers; that guidance no longer applies.
</Warning>

## How the upload flow works

When you create a job with [`POST /2/compliance/jobs`](/x-api/compliance/create-compliance-job), the response includes two pre-authorized URLs:

* `upload_url` — a `PUT` endpoint of the form `https://api.x.com/2/compliance/jobs/{id}/upload?token=...`. Upload your newline-delimited ID file here. See [Upload Compliance Job Submission](/x-api/compliance/upload-compliance-job-submission).
* `download_url` — a `GET` endpoint of the form `https://api.x.com/2/compliance/jobs/{id}/download?token=...`. Download results here once the job status is `complete`. See [Download Compliance Job Results](/x-api/compliance/download-compliance-job-results).

The `token` query parameter is an opaque signed token scoped to the job. Use each URL exactly as returned; do not modify or strip the token.

Both URLs expire. The job object reports the expiry times in the `upload_expires_at` and `download_expires_at` fields. If a URL expires before you use it, create a new job.

## Step one: create a job

Specify whether you are uploading Post IDs or user IDs with the `type` parameter (`tweets` or `users`). Replace `$APP_ACCESS_TOKEN` with your App only Access Token.

```bash theme={null}
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",
    "name": "my-compliance-job"
  }'
```

The response contains the job `id`, `upload_url`, `download_url`, and their expiry times:

```json theme={null}
{
  "data": {
    "id": "1234567890",
    "type": "tweets",
    "name": "my-compliance-job",
    "status": "created",
    "upload_url": "https://api.x.com/2/compliance/jobs/1234567890/upload?token=OPAQUE_SIGNED_TOKEN",
    "upload_expires_at": "2026-08-28T14:15:00.000Z",
    "download_url": "https://api.x.com/2/compliance/jobs/1234567890/download?token=OPAQUE_SIGNED_TOKEN",
    "download_expires_at": "2026-09-04T14:00:00.000Z",
    "created_at": "2026-08-28T14:00:00.000Z"
  }
}
```

## Step two: upload your ID file

Prepare a plain text file with one Post ID or user ID per line, then `PUT` it to the `upload_url` from the create response:

```bash theme={null}
curl --request PUT "$UPLOAD_URL" \
  --header 'Content-Type: application/octet-stream' \
  --data-binary @ids.txt
```

Upload the complete file in a single request before `upload_expires_at`.

## Step three: poll job status

Poll [`GET /2/compliance/jobs/{id}`](/x-api/compliance/get-compliance-job-by-id) until the status is `complete`:

```bash theme={null}
curl "https://api.x.com/2/compliance/jobs/1234567890" \
  --header 'Authorization: Bearer $APP_ACCESS_TOKEN'
```

## Step four: download results

Once the job status is `complete`, `GET` the `download_url` before `download_expires_at`:

```bash theme={null}
curl "$DOWNLOAD_URL" -o results.jsonl
```

Results are newline-delimited JSON with one object per ID that has a compliance event. IDs without compliance events are omitted and remain valid.

## Constraints

* One unfinished job per type at a time. Cancel an in-progress job with [`DELETE /2/compliance/jobs/{id}`](/x-api/compliance/cancel-compliance-job) before creating another job of the same type.
* The ID file must be plain text with exactly one numeric ID per line, and every ID must match the job `type`.
* The job creation, status, and list endpoints are rate limited to 150 requests per 15 minutes per App. See [Rate limits](/x-api/fundamentals/rate-limits).

## Next steps

<CardGroup cols={2}>
  <Card title="Quickstart" icon="https://mintcdn.com/x-preview-mintlify-cdd4f466/wmn-ppXSF48Y--Zf/icons/xds/icon-rocket.svg?fit=max&auto=format&n=wmn-ppXSF48Y--Zf&q=85&s=278c60f9f1ed75667fa94a2401b47bc2" href="/x-api/compliance/batch-compliance/quickstart" width="24" height="24" data-path="icons/xds/icon-rocket.svg">
    Create your first compliance job
  </Card>

  <Card title="API Reference" icon="https://mintcdn.com/x-preview-mintlify-cdd4f466/H5DHaVidtY4xMr3_/icons/xds/icon-code.svg?fit=max&auto=format&n=H5DHaVidtY4xMr3_&q=85&s=b197559fb66a72395f8039d79101c056" href="/x-api/compliance/create-compliance-job" width="24" height="24" data-path="icons/xds/icon-code.svg">
    Full endpoint documentation
  </Card>
</CardGroup>
