> ## Documentation Index
> Fetch the complete documentation index at: https://docs.pdfnoodle.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Compress PDF

> Compress a PDF file to reduce its size. Choose between three compression levels depending on your quality requirements.

<Note>
  This tool requires a publicly accessible PDF URL. If your file is stored locally or in memory, you can upload it to our temporary bucket first using the [Get Signed Upload URL](/api-reference/tools/get-signed-upload-url) endpoint.
</Note>

POST [https://api.pdfnoodle.com/v1/tools/compress-pdf](https://api.pdfnoodle.com/v1/tools/compress-pdf)

## Request

<CodeGroup>
  ```bash cURL theme={null}
  curl --location 'https://api.pdfnoodle.com/v1/tools/compress-pdf' \
  --header 'Authorization: Bearer pdfnoodle_api_123456789' \
  --header 'Content-Type: application/json' \
  --data '{
      "url": "https://example.com/large-document.pdf",
      "compressLevel": "medium",
      "finalFilename": "compressed-document.pdf",
      "expiration": 3600
  }'
  ```

  ```javascript JavaScript theme={null}
  const response = await fetch(
    "https://api.pdfnoodle.com/v1/tools/compress-pdf",
    {
      method: "POST",
      headers: {
        Authorization: "Bearer pdfnoodle_api_123456789",
        "Content-Type": "application/json",
      },
      body: JSON.stringify({
        url: "https://example.com/large-document.pdf",
        compressLevel: "medium",
        finalFilename: "compressed-document.pdf",
        expiration: 3600,
      }),
    }
  );

  const result = await response.json();
  ```

  ```python Python theme={null}
  import requests

  response = requests.post(
      'https://api.pdfnoodle.com/v1/tools/compress-pdf',
      headers={
          'Authorization': 'Bearer pdfnoodle_api_123456789',
          'Content-Type': 'application/json'
      },
      json={
          'url': 'https://example.com/large-document.pdf',
          'compressLevel': 'medium',
          'finalFilename': 'compressed-document.pdf',
          'expiration': 3600
      }
  )

  result = response.json()
  ```
</CodeGroup>

## Response

<CodeGroup>
  ```json Success (200 OK) theme={null}
  {
    "status": "SUCCESS",
    "url": "https://s3.amazonaws.com/...",
    "fileName": "compressed-document.pdf",
    "urlValidUntil": "2025-01-01T02:00:00.000Z",
    "metadata": {
      "originalSize": "2.5 MB",
      "compressedSize": "1.2 MB",
      "reduction": "52%"
    }
  }
  ```

  ```json Validation Error (400 Bad Request) theme={null}
  {
    "message": "compressLevel is Invalid enum value. Expected 'low' | 'medium' | 'high', received 'ultra'"
  }
  ```
</CodeGroup>

The response includes a `metadata` object with compression details so you can see exactly how much the file size was reduced.

The compressed file is stored persistently and can be re-downloaded at any time from the [dashboard logs](https://app.pdfnoodle.com/logs).

## Compression Levels

| Level    | Quality                            | Best for                            |
| -------- | ---------------------------------- | ----------------------------------- |
| `low`    | Highest quality, least compression | Print-ready documents               |
| `medium` | Balanced quality and size          | General use, email attachments      |
| `high`   | Most compression, lower quality    | Web viewing, maximum size reduction |

<Info>
  The `medium` compression level is the default and works well for most use cases. Use `low` when you need to preserve maximum quality (e.g., print materials) and `high` when file size is the priority.
</Info>

## Operation Tracking

Each compress operation creates a record in your dashboard logs, allowing you to:

* View all past compress operations with their status and metadata
* Re-download compressed files at any time via the logs table
* Track usage across your team

<Note>
  **Business and Scale plans**: Compress operations are unlimited and do not count toward your PDF generation quota.

  **Starter plans**: Compress operations count toward your total volume quota.
</Note>

## Async Mode

By default, the request waits for the compression to complete before returning a response. If you set `async: true`, the endpoint returns immediately with a `requestId` and `statusUrl` that you can use to poll for the result.

```json Async Response (200 OK) theme={null}
{
  "requestId": "pdfnoodle_request_123456789",
  "statusUrl": "https://api.pdfnoodle.com/v1/tools/status/pdfnoodle_request_123456789",
  "message": "The tool is being executed asynchronously. Check the status using the status URL."
}
```

Use the [Get Tool Status](/api-reference/tools/get-tool-status) endpoint to check the result.

### Request Timeout (>30 seconds)

<Warning>
  Even without `async: true`, if the operation takes more than 30 seconds it will automatically be processed in the background.
</Warning>

If the compression takes longer than 30 seconds, you'll receive a `202 Accepted` response with a `requestId` and `statusUrl` to poll for the result:

```json Timeout (202 Accepted) theme={null}
{
  "requestId": "pdfnoodle_request_123456789",
  "statusUrl": "https://api.pdfnoodle.com/v1/tools/status/pdfnoodle_request_123456789",
  "message": "Couldn't complete the operation within 30 seconds, it is being processed asynchronously. Check the status using the status URL."
}
```

## Parameters

<ParamField body="url" type="string" required>
  A valid, publicly accessible URL pointing to the PDF file you want to
  compress.
</ParamField>

<ParamField body="compressLevel" type="string" default="medium">
  The compression intensity. Must be one of: `"low"`, `"medium"`, or `"high"`.
  Default: `"medium"`.
</ParamField>

<ParamField body="finalFilename" type="string">
  The desired filename for the compressed PDF. Must end with `.pdf`. If not
  provided, the original filename from the URL will be used, or a random name
  will be generated.
</ParamField>

<ParamField body="expiration" type="number" default="3600">
  Number of seconds that the generated signed URL will take to expire. Must be
  between 60 (1 minute) and 604800 (7 days). Default: 3600 (1 hour).
</ParamField>

<ParamField body="async" type="boolean" default="false">
  If `true`, the request returns immediately with a `requestId` and `statusUrl`
  instead of waiting for the operation to complete. You can then poll the
  [Get Tool Status](/api-reference/tools/get-tool-status) endpoint to check
  when the result is ready.
</ParamField>
