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
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) or application/pdf (for .pdf)
Content-Disposition: attachment; filename="your-document.docx" (or .pdf)
Code Examples
JavaScript (Fetch)
Python (Requests)
Node.js with fs
cURL
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 );
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 );
}
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...
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...
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 enabled tracked_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
404 Not Found
401 Unauthorized
500 Internal Server Error
{
"detail" : "File not found"
}
For best performance in production, use the direct download endpoint for
automated workflows and server-to-server communication.