> ## 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.

# Update PDF Metadata

> Update the embedded metadata of a PDF file, such as title, author, subject, keywords, and more. The original PDF content is preserved.

<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/update-pdf-metadata](https://api.pdfnoodle.com/v1/tools/update-pdf-metadata)

## Request

<CodeGroup>
  ```bash cURL theme={null}
  curl --location 'https://api.pdfnoodle.com/v1/tools/update-pdf-metadata' \
  --header 'Authorization: Bearer pdfnoodle_api_123456789' \
  --header 'Content-Type: application/json' \
  --data '{
      "url": "https://example.com/document.pdf",
      "metadata": {
          "title": "Annual Report 2025",
          "author": "Acme Corp",
          "subject": "Financial Summary",
          "keywords": ["finance", "annual", "report"],
          "creator": "Acme Document System"
      },
      "finalFilename": "annual-report-2025.pdf",
      "expiration": 3600
  }'
  ```

  ```javascript JavaScript theme={null}
  const response = await fetch(
    "https://api.pdfnoodle.com/v1/tools/update-pdf-metadata",
    {
      method: "POST",
      headers: {
        Authorization: "Bearer pdfnoodle_api_123456789",
        "Content-Type": "application/json",
      },
      body: JSON.stringify({
        url: "https://example.com/document.pdf",
        metadata: {
          title: "Annual Report 2025",
          author: "Acme Corp",
          subject: "Financial Summary",
          keywords: ["finance", "annual", "report"],
          creator: "Acme Document System",
        },
        finalFilename: "annual-report-2025.pdf",
        expiration: 3600,
      }),
    }
  );

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

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

  response = requests.post(
      'https://api.pdfnoodle.com/v1/tools/update-pdf-metadata',
      headers={
          'Authorization': 'Bearer pdfnoodle_api_123456789',
          'Content-Type': 'application/json'
      },
      json={
          'url': 'https://example.com/document.pdf',
          'metadata': {
              'title': 'Annual Report 2025',
              'author': 'Acme Corp',
              'subject': 'Financial Summary',
              'keywords': ['finance', 'annual', 'report'],
              'creator': 'Acme Document System'
          },
          'finalFilename': 'annual-report-2025.pdf',
          'expiration': 3600
      }
  )

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

## Response

<CodeGroup>
  ```json Success (200 OK) theme={null}
  {
    "status": "SUCCESS",
    "url": "https://s3.amazonaws.com/...",
    "fileName": "annual-report-2025.pdf",
    "urlValidUntil": "2025-01-01T02:00:00.000Z"
  }
  ```

  ```json Validation Error (400 Bad Request) theme={null}
  {
    "message": "url is must be a valid URL"
  }
  ```
</CodeGroup>

The response contains a `url` pointing to the updated PDF file. While the URL in the response expires after the time specified in `expiration` (default: 1 hour), the file itself is stored persistently and can be downloaded at any time from the [dashboard logs](https://app.pdfnoodle.com/logs). The original PDF content is unchanged - only the metadata fields you specified are updated.

<Info>
  On macOS, you can verify the updated metadata by right-clicking the downloaded PDF and selecting **Get Info** in Finder. On Windows, right-click the file and select **Properties > Details**.
</Info>

## Operation Tracking

Each metadata update creates a record in your dashboard logs, allowing you to:

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

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

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

## Async Mode

By default, the request waits for the metadata update 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 operation 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 whose metadata you
  want to update.
</ParamField>

<ParamField body="metadata" type="object" required>
  An object containing the metadata fields to update. At least one field should
  be provided. See available fields below.
</ParamField>

<ParamField body="metadata.title" type="string">
  A human-readable title for the document.
</ParamField>

<ParamField body="metadata.author" type="string">
  The individual or organization that created the document.
</ParamField>

<ParamField body="metadata.subject" type="string">
  A brief description of the document's topic.
</ParamField>

<ParamField body="metadata.keywords" type="string[]">
  A list of keywords describing the content.
</ParamField>

<ParamField body="metadata.creator" type="string">
  The original software or system that created the content.
</ParamField>

<ParamField body="metadata.copyright" type="string">
  Copyright information for the document.
</ParamField>

<ParamField body="metadata.createDate" type="string">
  The creation date of the document (ISO date string).
</ParamField>

<ParamField body="metadata.modDate" type="string">
  The last modification date of the document (ISO date string).
</ParamField>

<ParamField body="metadata.pdfVersion" type="number">
  The PDF specification version (e.g., `1.7`).
</ParamField>

<ParamField body="metadata.producer" type="string">
  The software that produced the PDF.
</ParamField>

<ParamField body="metadata.marked" type="boolean">
  Whether the PDF is marked (tagged) for accessibility.
</ParamField>

<ParamField body="metadata.trapped" type="string">
  Trapping status. Common values: `"Unknown"`, `"True"`, `"False"`.
</ParamField>

<ParamField body="finalFilename" type="string">
  The desired filename for the updated 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>
