Download Document (Direct)
curl --request GET \
--url https://api.agentoffice.dev/v1/documents/{doc_id}/download \
--header 'Authorization: Bearer <token>'import requests
url = "https://api.agentoffice.dev/v1/documents/{doc_id}/download"
headers = {"Authorization": "Bearer <token>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
fetch('https://api.agentoffice.dev/v1/documents/{doc_id}/download', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.agentoffice.dev/v1/documents/{doc_id}/download",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api.agentoffice.dev/v1/documents/{doc_id}/download"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("Authorization", "Bearer <token>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://api.agentoffice.dev/v1/documents/{doc_id}/download")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.agentoffice.dev/v1/documents/{doc_id}/download")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["Authorization"] = 'Bearer <token>'
response = http.request(request)
puts response.read_body{
"detail": "File not found"
}
{
"detail": "Invalid or missing API key"
}
{
"detail": "Failed to process direct download"
}
API Reference
Download Document (Direct)
Download your document directly without a presigned URL step
GET
/
v1
/
documents
/
{doc_id}
/
download
Download Document (Direct)
curl --request GET \
--url https://api.agentoffice.dev/v1/documents/{doc_id}/download \
--header 'Authorization: Bearer <token>'import requests
url = "https://api.agentoffice.dev/v1/documents/{doc_id}/download"
headers = {"Authorization": "Bearer <token>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
fetch('https://api.agentoffice.dev/v1/documents/{doc_id}/download', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.agentoffice.dev/v1/documents/{doc_id}/download",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api.agentoffice.dev/v1/documents/{doc_id}/download"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("Authorization", "Bearer <token>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://api.agentoffice.dev/v1/documents/{doc_id}/download")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.agentoffice.dev/v1/documents/{doc_id}/download")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["Authorization"] = 'Bearer <token>'
response = http.request(request)
puts response.read_body{
"detail": "File not found"
}
{
"detail": "Invalid or missing API key"
}
{
"detail": "Failed to process direct download"
}
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
string
required
The unique identifier of the document to download (UUID)
Response
Returns the document file directly with appropriate headers:Content-Type:application/vnd.openxmlformats-officedocument.wordprocessingml.document(for .docx) orapplication/pdf(for .pdf)Content-Disposition:attachment; filename="your-document.docx"(or .pdf)
Code Examples
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);
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}")
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}`);
curl -X GET 'https://api.agentoffice.dev/v1/documents/a1b2c3d4-e5f6-7890-abcd-ef1234567890/download' \
-H 'Authorization: Bearer YOUR_API_KEY' \
--output document.docx
Benefits over Presigned URL Method
Reduced Latency
One request instead of two - no intermediate S3 URL step
Simpler Code
Fewer lines of code, cleaner implementation
Better for APIs
Perfect for server-to-server communication
Same Features
Supports tracked changes and all document features
Complete Workflow Example
Here’s a complete example showing upload, edit, and direct download: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);
}
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')
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
Use Direct Download When...
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
Use Presigned URL When...
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
Tracked Changes Support
Both download methods support tracked changes. If you enabledtracked_changes when uploading the document, the downloaded file will show all edits with Word’s track changes feature.
Example with tracked changes
// 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
{
"detail": "File not found"
}
{
"detail": "Invalid or missing API key"
}
{
"detail": "Failed to process direct download"
}
For best performance in production, use the direct download endpoint for
automated workflows and server-to-server communication.

