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

# Download Document (Direct)

> Download your document directly without a presigned URL step

## Download Document Directly

Get the document file directly as a binary response, eliminating the two-step presigned URL process. This endpoint is ideal for programmatic downloads and reduces latency. Supports both Word (.docx) and PDF (.pdf) formats.

### Path Parameters

<ParamField path="doc_id" type="string" required>
  The unique identifier of the document to download (UUID)
</ParamField>

### Response

Returns the document file directly with appropriate headers:

* `Content-Type`: `application/vnd.openxmlformats-officedocument.wordprocessingml.document` (for .docx) or `application/pdf` (for .pdf)
* `Content-Disposition`: `attachment; filename="your-document.docx"` (or .pdf)

### Code Examples

<CodeGroup>
  ```javascript JavaScript (Fetch) theme={null}
  const docId = "a1b2c3d4-e5f6-7890-abcd-ef1234567890";

  const response = await fetch(
    `https://api.agentoffice.dev/v1/documents/${docId}/download`,
    {
      headers: {
        Authorization: "Bearer YOUR_API_KEY",
      },
    }
  );

  // Get filename from Content-Disposition header
  const contentDisposition = response.headers.get("Content-Disposition");
  let filename = "document.docx";
  if (contentDisposition) {
    const match = contentDisposition.match(/filename="?(.+?)"?$/);
    if (match) filename = match[1];
  }

  // Convert to blob and trigger download
  const blob = await response.blob();
  const url = window.URL.createObjectURL(blob);
  const a = document.createElement("a");
  a.href = url;
  a.download = filename;
  a.click();
  window.URL.revokeObjectURL(url);
  ```

  ```python Python (Requests) theme={null}
  import requests

  doc_id = 'a1b2c3d4-e5f6-7890-abcd-ef1234567890'
  url = f'https://api.agentoffice.dev/v1/documents/{doc_id}/download'

  headers = {
      'Authorization': 'Bearer YOUR_API_KEY'
  }

  response = requests.get(url, headers=headers)

  # Get filename from Content-Disposition header
  content_disposition = response.headers.get('Content-Disposition', '')
  filename = 'document.docx'
  if 'filename=' in content_disposition:
      filename = content_disposition.split('filename=')[1].strip('"')

  # Save to disk
  with open(filename, 'wb') as f:
      f.write(response.content)

  print(f"Downloaded: {filename}")
  ```

  ```javascript Node.js with fs theme={null}
  import fs from "fs";

  const docId = "a1b2c3d4-e5f6-7890-abcd-ef1234567890";

  const response = await fetch(
    `https://api.agentoffice.dev/v1/documents/${docId}/download`,
    {
      headers: {
        Authorization: "Bearer YOUR_API_KEY",
      },
    }
  );

  // Get filename from Content-Disposition header
  const contentDisposition = response.headers.get("Content-Disposition");
  let filename = "document.docx";
  if (contentDisposition) {
    const match = contentDisposition.match(/filename="?(.+?)"?$/);
    if (match) filename = match[1];
  }

  // Save the file
  const buffer = await response.arrayBuffer();
  fs.writeFileSync(filename, Buffer.from(buffer));
  console.log(`Downloaded: ${filename}`);
  ```

  ```bash cURL theme={null}
  curl -X GET 'https://api.agentoffice.dev/v1/documents/a1b2c3d4-e5f6-7890-abcd-ef1234567890/download' \
    -H 'Authorization: Bearer YOUR_API_KEY' \
    --output document.docx
  ```
</CodeGroup>

## Benefits over Presigned URL Method

<CardGroup cols={2}>
  <Card title="Reduced Latency" icon="bolt">
    One request instead of two - no intermediate S3 URL step
  </Card>

  <Card title="Simpler Code" icon="code">
    Fewer lines of code, cleaner implementation
  </Card>

  <Card title="Better for APIs" icon="server">
    Perfect for server-to-server communication
  </Card>

  <Card title="Same Features" icon="check">
    Supports tracked changes and all document features
  </Card>
</CardGroup>

## Complete Workflow Example

Here's a complete example showing upload, edit, and direct download:

<CodeGroup>
  ```javascript JavaScript theme={null}
  import { v4 as uuidv4 } from "uuid";

  const API_KEY = "YOUR_API_KEY";
  const BASE_URL = "https://api.agentoffice.dev";

  async function processDocument(file) {
    // 1. Upload document
    const formData = new FormData();
    formData.append("file", file);

    const uploadResponse = await fetch(`${BASE_URL}/v1/documents/`, {
      method: "POST",
      headers: { Authorization: `Bearer ${API_KEY}` },
      body: formData,
    });

    const { docId } = await uploadResponse.json();
    console.log("Uploaded document:", docId);

    // 2. Apply edit
    const editResponse = await fetch(`${BASE_URL}/v1/documents/${docId}/edits`, {
      method: "POST",
      headers: {
        Authorization: `Bearer ${API_KEY}`,
        "Content-Type": "application/json",
      },
      body: JSON.stringify({
        editUid: uuidv4(),
        editInstructions: "Update all dates to 2024",
      }),
    });

    const editResult = await editResponse.json();
    console.log("Edit applied:", editResult.editApplied);

    // 3. Download edited document directly
    const downloadResponse = await fetch(
      `${BASE_URL}/v1/documents/${docId}/download`,
      {
        headers: { Authorization: `Bearer ${API_KEY}` },
      }
    );

    // Get filename from header
    const contentDisposition = downloadResponse.headers.get(
      "Content-Disposition"
    );
    let filename = "document.docx";
    if (contentDisposition) {
      const match = contentDisposition.match(/filename="?(.+?)"?$/);
      if (match) filename = match[1];
    }

    // Download the file
    const blob = await downloadResponse.blob();

    // Trigger browser download
    const url = window.URL.createObjectURL(blob);
    const a = document.createElement("a");
    a.href = url;
    a.download = filename;
    a.click();
    window.URL.revokeObjectURL(url);

    console.log("Downloaded:", filename);
  }
  ```

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

  API_KEY = 'YOUR_API_KEY'
  BASE_URL = 'https://api.agentoffice.dev'

  def process_document(file_path):
      headers = {'Authorization': f'Bearer {API_KEY}'}

      # 1. Upload document
      with open(file_path, 'rb') as f:
          files = {'file': f}
          upload_response = requests.post(
              f'{BASE_URL}/v1/documents/',
              headers=headers,
              files=files
          )

      doc_id = upload_response.json()['docId']
      print(f'Uploaded document: {doc_id}')

      # 2. Apply edit
      edit_payload = {
          'editUid': str(uuid.uuid4()),
          'editInstructions': 'Update all dates to 2024'
      }

      edit_response = requests.post(
          f'{BASE_URL}/v1/documents/{doc_id}/edits',
          headers={**headers, 'Content-Type': 'application/json'},
          json=edit_payload
      )

      edit_result = edit_response.json()
      print(f"Edit applied: {edit_result['editApplied']}")

      # 3. Download edited document directly
      download_response = requests.get(
          f'{BASE_URL}/v1/documents/{doc_id}/download',
          headers=headers
      )

      # Get filename from Content-Disposition header
      content_disposition = download_response.headers.get('Content-Disposition', '')
      filename = 'document.docx'
      if 'filename=' in content_disposition:
          filename = content_disposition.split('filename=')[1].strip('"')

      # Save file
      with open(f'edited_{filename}', 'wb') as f:
          f.write(download_response.content)

      print(f'Downloaded: edited_{filename}')

  # Usage
  process_document('document.docx')
  ```
</CodeGroup>

## Comparison: Direct vs Presigned URL

| Feature                | Direct Download (`/download`)         | Presigned URL (`GET /{doc_id}`)                 |
| ---------------------- | ------------------------------------- | ----------------------------------------------- |
| **Number of Requests** | 1 request                             | 2 requests (get URL, then download)             |
| **Latency**            | Lower - single round trip             | Higher - two round trips                        |
| **Use Case**           | Programmatic/API usage                | Client-side downloads, sharing links            |
| **URL Expiration**     | N/A - direct download                 | Configurable (1 second - 24 hours)              |
| **Security**           | API key required for each download    | Anyone with URL can download (until expiration) |
| **Tracked Changes**    | ✅ Supported                           | ✅ Supported                                     |
| **Best For**           | Server-to-server, automated workflows | Temporary sharing, client downloads             |

## When to Use Each Method

<AccordionGroup>
  <Accordion title="Use Direct Download When...">
    * Building server-to-server integrations
    * Automating document processing workflows
    * You need the lowest possible latency
    * You want tighter security control (API key per request)
    * Processing documents in CI/CD pipelines
  </Accordion>

  <Accordion title="Use Presigned URL When...">
    * Sharing documents with users without API access
    * You need temporary, expiring download links
    * Building client-side applications with limited backend
    * You want to offload download traffic from your API
    * Implementing time-limited document sharing
  </Accordion>
</AccordionGroup>

## Tracked Changes Support

Both download methods support tracked changes. If you enabled `tracked_changes` when uploading the document, the downloaded file will show all edits with Word's track changes feature.

```javascript Example with tracked changes theme={null}
// Upload with tracked changes enabled
const formData = new FormData();
formData.append("file", file);
formData.append("tracked_changes", "true");
formData.append("author_name", "Your Name");

const { docId } = await (
  await fetch(`${BASE_URL}/v1/documents/`, {
    method: "POST",
    headers: { Authorization: `Bearer ${API_KEY}` },
    body: formData,
  })
).json();

// ... make edits ...

// Download shows tracked changes
const response = await fetch(`${BASE_URL}/v1/documents/${docId}/download`, {
  headers: { Authorization: `Bearer ${API_KEY}` },
});
```

## Error Responses

<ResponseExample>
  ```json 404 Not Found theme={null}
  {
    "detail": "File not found"
  }
  ```

  ```json 401 Unauthorized theme={null}
  {
    "detail": "Invalid or missing API key"
  }
  ```

  ```json 500 Internal Server Error theme={null}
  {
    "detail": "Failed to process direct download"
  }
  ```
</ResponseExample>

<Tip>
  For best performance in production, use the direct download endpoint for
  automated workflows and server-to-server communication.
</Tip>
