Documents API
Documents are files ingested into Stagent for use as agent context, task outputs, or project references. Each document tracks its original file, extracted text, processing status, and version history. Documents can be linked to tasks, projects, or both.
Quick Start
Upload a document from the local filesystem, wait for processing, then download the file — a typical integration flow:
// 1. Upload a document from a local file path
const res = await fetch('/api/documents', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
file_path: '/Users/team/reports/q2-analysis.pdf',
projectId: 'proj-8f3a-4b2c',
direction: 'input',
metadata: { department: 'finance', quarter: 'Q2' },
}),
});
const doc: { documentId: string; status: string; processingStatus: string } = await res.json();
// → { documentId: "doc-7b2e-...", status: "uploaded", processingStatus: "queued" }
// 2. Poll until processing completes (text extraction, thumbnails)
let document: { status: string; extractedText: string };
do {
await new Promise((r) => setTimeout(r, 1000));
document = await fetch(`/api/documents/${doc.documentId}`).then((r) => r.json());
} while (document.status === 'processing');
console.log(document.status); // "ready"
console.log(document.extractedText); // "Q2 2026 Revenue Report..."
// 3. Download the original file
const fileUrl: string = `/api/documents/${doc.documentId}/file`;
window.open(fileUrl); // triggers browser download
// 4. Check version history (output documents only)
const versions: Array<{ id: string; version: number }> = await fetch(
`/api/documents/${doc.documentId}/versions`
).then((r) => r.json());
console.log(`${versions.length} version(s) available`); Base URL
/api/documents
Endpoints
List Documents
/api/documents Retrieve all documents with optional filtering by task, project, status, direction, or full-text search. Results include joined task, project, and workflow metadata.
Query Parameters
| Param | Type | Req | Description |
|---|---|---|---|
| taskId | string | — | Filter by task ID |
| projectId | string | — | Filter by project ID |
| status | enum | — | uploaded, processing, ready, or error |
| direction | enum | — | input or output |
| search | string | — | Full-text search across originalName and extractedText |
Response Body (Array)
| Field | Type | Req | Description |
|---|---|---|---|
| id | string (UUID) | * | Document identifier |
| taskId | string (UUID) | — | Linked task ID |
| projectId | string (UUID) | — | Linked project ID |
| filename | string | * | Stored filename (UUID-based) |
| originalName | string | * | Original filename at upload |
| mimeType | string | * | MIME type (e.g. text/markdown, application/pdf) |
| size | number | * | File size in bytes |
| storagePath | string | * | Absolute path to stored file |
| version | number | * | Document version number |
| direction | enum | * | input or output |
| category | string | — | Document category or metadata JSON |
| status | enum | * | uploaded, processing, ready, or error |
| extractedText | string | — | Full text extracted during processing |
| processedPath | string | — | Path to processed/thumbnail version |
| processingError | string | — | Error message if processing failed |
| createdAt | ISO 8601 | * | Creation timestamp |
| updatedAt | ISO 8601 | * | Last modification |
| taskTitle | string | — | Joined task title |
| projectName | string | — | Joined project name |
| workflowId | string | — | Joined workflow ID (via task) |
| workflowName | string | — | Joined workflow name |
| workflowRunNumber | number | — | Workflow run number from task |
Fetch all ready documents for a project — useful for building a document library or attaching context to tasks:
// Fetch ready documents for a project and group by direction
const response: Response = await fetch(
'/api/documents?projectId=proj-8f3a-4b2c&status=ready'
);
const docs: Array<{ direction: string }> = await response.json();
const inputs = docs.filter((d) => d.direction === 'input');
const outputs = docs.filter((d) => d.direction === 'output');
console.log(`${inputs.length} input docs, ${outputs.length} output docs`); Example response:
[
{
"id": "doc-7b2e-3f9a",
"originalName": "q2-analysis.pdf",
"mimeType": "application/pdf",
"size": 245780,
"version": 1,
"direction": "input",
"status": "ready",
"extractedText": "Q2 2026 Revenue Report...",
"projectId": "proj-8f3a-4b2c",
"projectName": "Marketing Analysis",
"createdAt": "2026-04-03T09:15:00.000Z",
"updatedAt": "2026-04-03T09:15:12.000Z"
}
] Create Document (from file path)
/api/documents Create a document by copying a file from the local filesystem into Stagent's managed storage. Triggers asynchronous text extraction and preprocessing. Paths are validated against security rules.
Request Body
| Field | Type | Req | Description |
|---|---|---|---|
| file_path | string | * | Absolute path to a local file |
| taskId | string (UUID) | — | Link to a task |
| projectId | string (UUID) | — | Link to a project |
| direction | enum | — | input or output (default: output) |
| metadata | Record<string, string> | — | Key-value metadata pairs |
Response Body
| Field | Type | Req | Description |
|---|---|---|---|
| documentId | string (UUID) | * | New document ID |
| status | string | * | Always "uploaded" |
| processingStatus | string | * | Always "queued" |
| originalName | string | * | Original filename |
| mimeType | string | * | Detected MIME type |
| size | number | * | File size in bytes |
Response 201 Created
Errors: 400 — Validation failure or file not found, 403 — Path traversal or restricted directory
Path Security: Files must reside under the user’s home directory or /tmp. System directories (/etc, /var, /proc, /sys, /dev, /root) and sensitive home directories (.ssh, .gnupg, .aws, .config, .env) are blocked.
Supported MIME Types: .md, .txt, .json, .csv, .html, .pdf, .png, .jpg, .jpeg, .gif, .webp, .docx, .xlsx
Ingest a PDF report as input context for a project — the file is copied into managed storage and text extraction begins automatically:
// Ingest a local file — processing starts automatically
const response: Response = await fetch('/api/documents', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
file_path: '/Users/team/reports/q2-analysis.pdf',
projectId: 'proj-8f3a-4b2c',
direction: 'input',
metadata: { department: 'finance', quarter: 'Q2' },
}),
});
const doc: { documentId: string; processingStatus: string } = await response.json();
console.log(doc.documentId); // "doc-7b2e-..."
console.log(doc.processingStatus); // "queued" Example response:
{
"documentId": "doc-7b2e-3f9a",
"status": "uploaded",
"processingStatus": "queued",
"originalName": "q2-analysis.pdf",
"mimeType": "application/pdf",
"size": 245780
}Errors: 400 — Zod validation failure or file not found
{
"error": "File not found at specified path"
} Get Document
/api/documents/{id} Retrieve a single document by ID with full metadata including joined task, project, and workflow details.
Response 200 — Document object (same schema as list item)
Fetch a document to check its processing status and read extracted text:
// Check processing status and read extracted text
const doc: { status: string; extractedText: string; processingError: string } =
await fetch('/api/documents/doc-7b2e-3f9a').then((r) => r.json());
if (doc.status === 'ready') {
console.log(`Extracted ${doc.extractedText.length} characters`);
} else if (doc.status === 'error') {
console.error(`Processing failed: ${doc.processingError}`);
} Example response:
{
"id": "doc-7b2e-3f9a",
"originalName": "q2-analysis.pdf",
"mimeType": "application/pdf",
"size": 245780,
"status": "ready",
"direction": "input",
"version": 1,
"extractedText": "Q2 2026 Revenue Report\n\nTotal revenue grew 18% quarter-over-quarter...",
"projectId": "proj-8f3a-4b2c",
"projectName": "Marketing Analysis",
"createdAt": "2026-04-03T09:15:00.000Z",
"updatedAt": "2026-04-03T09:15:12.000Z"
}Errors: 404 — { "error": "Document not found" }
Update Document
/api/documents/{id} Update document associations, category, metadata, or trigger reprocessing. Metadata is merged into the existing category JSON.
Request Body (all fields optional)
| Field | Type | Req | Description |
|---|---|---|---|
| taskId | string (UUID) | null | — | Reassign or unlink task |
| projectId | string (UUID) | null | — | Reassign or unlink project |
| category | string | — | Category label (max 100 chars) |
| metadata | Record<string, string> | — | Key-value pairs merged into category JSON |
| reprocess | boolean | — | Set true to re-run text extraction |
Response 200 — Updated document object
Reassign a document to a different project and trigger reprocessing after the source file changed:
// Tag the document and trigger reprocessing
await fetch('/api/documents/doc-7b2e-3f9a', {
method: 'PATCH',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
category: 'report',
metadata: { reviewed: 'true' },
reprocess: true,
}),
}); Errors: 400 — Validation failure, 404 — Not found
Delete Document
/api/documents/{id} Permanently delete a document and its stored file. If the document is linked to a task, cascade confirmation is required.
Query Parameters
| Param | Type | Req | Description |
|---|---|---|---|
| cascadeDelete | boolean | — | Set to true to confirm deletion of task-linked documents |
Response 204 No Content
Delete a document that is linked to a task — requires the cascade flag to confirm:
// Delete a task-linked document (requires cascade confirmation)
const res: Response = await fetch(
'/api/documents/doc-7b2e-3f9a?cascadeDelete=true',
{ method: 'DELETE' }
);
if (res.status === 409) {
console.log('Document is linked to a task — add ?cascadeDelete=true');
} Errors: 404 — Not found, 409 — Document linked to a task (add ?cascadeDelete=true to confirm)
Download Document File
/api/documents/{id}/file Download the raw file content with appropriate Content-Type and Content-Disposition headers. Supports inline display for images and PDFs, and thumbnail mode.
Query Parameters
| Param | Type | Req | Description |
|---|---|---|---|
| inline | 0 | 1 | — | Set to 1 for inline display (images and PDFs only) |
| thumb | 0 | 1 | — | Set to 1 to serve the processed/thumbnail version if available |
Response 200 — Raw file bytes with Content-Type and Content-Disposition headers
Download or display a document inline — useful for embedding PDFs or images in a preview panel:
// Embed a document preview in the UI
const previewUrl: string = '/api/documents/doc-7b2e-3f9a/file?inline=1';
const img: HTMLImageElement = document.createElement('img');
img.src = previewUrl;
// Or trigger a download
const link: HTMLAnchorElement = document.createElement('a');
link.href = '/api/documents/doc-7b2e-3f9a/file';
link.download = '';
link.click(); Errors: 404 — Document or file not found
List Document Versions
/api/documents/{id}/versions Retrieve version history for an output document. Finds all documents with the same originalName and projectId, ordered by version descending. Only output documents with a project binding have version history.
Response Body (Array)
| Field | Type | Req | Description |
|---|---|---|---|
| id | string (UUID) | * | Version document ID |
| version | number | * | Version number |
| size | number | * | File size in bytes |
| status | enum | * | Processing status |
| createdAt | ISO 8601 | * | When this version was created |
| workflowRunNumber | number | — | Workflow run that produced this version |
Track how an output document evolves across workflow runs — useful for auditing agent-generated reports:
// List all versions of an output document
const versions: Array<{ version: number; size: number; createdAt: string }> =
await fetch('/api/documents/doc-7b2e-3f9a/versions').then((r) => r.json());
versions.forEach((v) => {
console.log(`v${v.version} — ${(v.size / 1024).toFixed(1)} KB — ${v.createdAt}`);
}); Example response:
[
{
"id": "doc-7b2e-3f9a",
"version": 3,
"size": 312400,
"status": "ready",
"createdAt": "2026-04-03T14:20:00.000Z",
"workflowRunNumber": 5
},
{
"id": "doc-6a1d-2e8b",
"version": 2,
"size": 287600,
"status": "ready",
"createdAt": "2026-04-02T10:10:00.000Z",
"workflowRunNumber": 4
}
] Document Statuses
| Status | Description |
|---|---|
| uploaded | File stored, processing not yet started. |
| processing | Text extraction and preprocessing in progress. |
| ready | Processing complete, extracted text available. |
| error | Processing failed. See processingError for details. |
Document Directions
| Direction | Description |
|---|---|
| input | Reference material provided to agents. |
| output | Artifact produced by agent execution. |