Upload Document
Upload a file to your workspace for automatic ingestion. The file is stored in S3 and queued for asynchronous processing (parsing, chunking, embedding, and indexing).
POST /api/v1/documents
Authentication
Requires an API key with the write permission.
| Header | Value |
|---|---|
X-API-Key | ink_live_abc123... |
Content-Type | multipart/form-data |
Request
Send a multipart/form-data request with the following fields:
Form Fields
| Field | Type | Required | Description |
|---|---|---|---|
file | binary | Yes | The document file to upload. Maximum size: 50 MB. |
metadata | string (JSON) | No | A JSON-encoded string of key-value metadata pairs to attach to the document. |
Supported File Types
| File Type | MIME Type |
|---|---|
| Plain text | text/plain |
| Markdown | text/markdown |
| CSV | text/csv |
application/pdf | |
| JSON | application/json |
| Word (.docx) | application/vnd.openxmlformats-officedocument.wordprocessingml.document |
| Excel (.xlsx) | application/vnd.openxmlformats-officedocument.spreadsheetml.sheet |
Code Examples
- cURL
- Python
- JavaScript
curl -X POST https://api.inherent.systems/api/v1/documents \
-H "X-API-Key: $INHERENT_API_KEY" \
-F "file=@./my-document.pdf"
With metadata:
curl -X POST https://api.inherent.systems/api/v1/documents \
-H "X-API-Key: $INHERENT_API_KEY" \
-F "file=@./my-document.pdf" \
-F 'metadata={"title": "Q4 Report", "department": "engineering"}'
import requests
import json
with open("my-document.pdf", "rb") as f:
response = requests.post(
"https://api.inherent.systems/api/v1/documents",
headers={"X-API-Key": "ink_live_abc123..."},
files={"file": ("my-document.pdf", f, "application/pdf")},
data={"metadata": json.dumps({"title": "Q4 Report", "department": "engineering"})},
)
doc = response.json()
print(f"Document {doc['document_id']} uploaded, status: {doc['status']}")
const fs = require("fs");
const FormData = require("form-data");
const form = new FormData();
form.append("file", fs.createReadStream("./my-document.pdf"));
form.append(
"metadata",
JSON.stringify({ title: "Q4 Report", department: "engineering" })
);
const response = await fetch("https://api.inherent.systems/api/v1/documents", {
method: "POST",
headers: {
"X-API-Key": "ink_live_abc123...",
},
body: form,
});
const doc = await response.json();
console.log(`Document ${doc.document_id} uploaded, status: ${doc.status}`);
Response
Status: 201 Created
{
"document_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"name": "my-document.pdf",
"workspace_id": "ws_abc123",
"storage_url": "s3://inherent-documents/ws_abc123/a1b2c3d4/my-document.pdf",
"mime_type": "application/pdf",
"size_bytes": 245760,
"status": "pending",
"message": "Document uploaded successfully. Processing will begin shortly."
}
Response Fields
| Field | Type | Description |
|---|---|---|
document_id | string | Unique document identifier (UUID) |
name | string | Original filename as uploaded |
workspace_id | string | ID of the workspace the document belongs to |
storage_url | string | Internal S3 storage location |
mime_type | string | Detected MIME type of the uploaded file |
size_bytes | integer | File size in bytes |
status | string | Always "pending" -- processing is asynchronous |
message | string | Human-readable confirmation message |
Asynchronous Processing
Documents are processed asynchronously after upload. The response returns immediately with status: "pending". Use the List Documents or Get Document endpoint to check when processing completes (status changes to "completed").
Errors
| Status | Error Type | Description |
|---|---|---|
400 | bad-request | Unsupported file type, empty file, or missing file field |
401 | unauthorized | Missing or invalid API key |
403 | forbidden | API key does not have write permission |
413 | payload-too-large | File exceeds the 50 MB size limit |
422 | validation-error | Invalid metadata JSON or other validation failure |
429 | rate-limit-exceeded | Rate limit exceeded |
Example Error Responses
Unsupported file type:
{
"type": "https://api.inherent.systems/errors/bad-request",
"title": "Bad Request",
"status": 400,
"detail": "Unsupported file type: application/x-executable. Allowed types: text/plain, text/markdown, text/csv, application/pdf, application/json, application/vnd.openxmlformats-officedocument.wordprocessingml.document, application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
"instance": "/api/v1/documents",
"trace_id": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
"timestamp": "2026-04-03T12:34:56.789Z"
}
File too large:
{
"type": "https://api.inherent.systems/errors/payload-too-large",
"title": "Payload Too Large",
"status": 413,
"detail": "File size 67108864 bytes exceeds the maximum allowed size of 52428800 bytes (50 MB).",
"instance": "/api/v1/documents",
"trace_id": "c3d4e5f6-7890-abcd-ef12-345678901234",
"timestamp": "2026-04-03T12:35:10.123Z"
}