Files & Assets
fetch directly for file transfers, and the SDK's DirectusFile collection for metadata queries.Upload a File
Send a POST request with multipart/form-data to the assets endpoint. The response returns the file IDs only.
// Upload with fetch — the SDK has no upload method
const form = new FormData();
form.append('file', fileInput.files[0]);
const uploadResponse = await fetch('https://example.monospace.io/api/blog/assets', {
method: 'POST',
headers: {
Authorization: 'Bearer YOUR_API_KEY',
},
body: form,
});
const { data } = await uploadResponse.json();
const fileId = data[0].id;
// Then query metadata via SDK
const fileMeta = await client.DirectusFile.readOne({
key: fileId,
fields: ['id', 'fileName', 'fileSize', 'mediaType', 'title', 'description'],
});
curl -X POST https://example.monospace.io/api/blog/assets \
-H "Authorization: Bearer YOUR_API_KEY" \
-F "file=@photo.jpg"
const form = new FormData();
form.append('file', fileInput.files[0]);
const response = await fetch('https://example.monospace.io/api/blog/assets', {
method: 'POST',
headers: {
Authorization: 'Bearer YOUR_API_KEY',
},
body: form,
});
const { data } = await response.json();
// data: [{ "id": "a1b2c3d4-..." }]
fileName, fileSize, and mediaType, query the DirectusFile collection in a separate request. This limitation will likely be lifted in a future version.DIRECTUS_MAX_FILE_PAYLOAD_SIZE). Requests exceeding this limit receive 413 Payload Too Large.Upload Multiple Files
Include multiple file fields in a single request. Each field with a filename is treated as a separate file upload.
curl -X POST https://example.monospace.io/api/blog/assets \
-H "Authorization: Bearer YOUR_API_KEY" \
-F "file1=@photo.jpg" \
-F "file2=@document.pdf" \
-F "file3=@report.csv"
const form = new FormData();
form.append('photo', photoFile);
form.append('document', documentFile);
form.append('report', reportFile);
const response = await fetch('https://example.monospace.io/api/blog/assets', {
method: 'POST',
headers: {
Authorization: 'Bearer YOUR_API_KEY',
},
body: form,
});
const { data } = await response.json();
// data: [{ "id": "..." }, { "id": "..." }, { "id": "..." }]
Download a File
Retrieve a file by its ID. Files are served inline by default — images display in the browser, PDFs open in the viewer.
curl https://example.monospace.io/api/blog/assets/a1b2c3d4-5678-90ab-cdef-1234567890ab \
-H "Authorization: Bearer YOUR_API_KEY" \
-o photo.jpg
const response = await fetch(
'https://example.monospace.io/api/blog/assets/a1b2c3d4-5678-90ab-cdef-1234567890ab',
{
headers: {
Authorization: 'Bearer YOUR_API_KEY',
},
},
);
const blob = await response.blob();
You can include any filename after the file ID in the URL. This is useful for SEO — search engines and link previews will use the filename from the URL:
GET /api/blog/assets/a1b2c3d4-5678-90ab-cdef-1234567890ab/photo.jpg
DIRECTUS_REDIRECT_ASSET_READ is enabled and the storage connector supports presigned URLs, the server returns a 307 Temporary Redirect to a presigned URL (60-second expiry). Otherwise, the file is streamed directly.Force a File Download
By default, files are served inline (Content-Disposition: inline). Add ?download=true to force the browser to download the file as an attachment.
curl "https://example.monospace.io/api/blog/assets/a1b2c3d4-5678-90ab-cdef-1234567890ab?download=true" \
-H "Authorization: Bearer YOUR_API_KEY" \
-o photo.jpg
const response = await fetch(
'https://example.monospace.io/api/blog/assets/a1b2c3d4-5678-90ab-cdef-1234567890ab?download=true',
{
headers: {
Authorization: 'Bearer YOUR_API_KEY',
},
},
);
const blob = await response.blob();
Read File Metadata
File metadata lives in the DirectusFile collection. System files and project files have separate endpoints.
Project Files
Project files are accessed through the standard items API at /api/{project}/items/DirectusFile. They include additional metadata fields beyond the base set.
const file = await client.DirectusFile.readOne({
key: 'a1b2c3d4-5678-90ab-cdef-1234567890ab',
fields: ['id', 'fileName', 'fileSize', 'mediaType', 'title', 'description', 'tags'],
});
curl "https://example.monospace.io/api/blog/items/DirectusFile/a1b2c3d4-5678-90ab-cdef-1234567890ab?fields=id,fileName,fileSize,mediaType,title,description,tags" \
-H "Authorization: Bearer YOUR_API_KEY"
const response = await fetch(
'https://example.monospace.io/api/blog/items/DirectusFile/a1b2c3d4-5678-90ab-cdef-1234567890ab?fields=id,fileName,fileSize,mediaType,title,description,tags',
{
headers: {
Authorization: 'Bearer YOUR_API_KEY',
},
},
);
const { data } = await response.json();
System Files
System files (org logos, project logos, user avatars) have a dedicated endpoint at /api/system/files. These require authentication and only expose the base metadata fields.
curl https://example.monospace.io/api/system/files/a1b2c3d4-5678-90ab-cdef-1234567890ab \
-H "Authorization: Bearer YOUR_API_KEY"
const response = await fetch(
'https://example.monospace.io/api/system/files/a1b2c3d4-5678-90ab-cdef-1234567890ab',
{
headers: {
Authorization: 'Bearer YOUR_API_KEY',
},
},
);
const { data } = await response.json();
// data.id, data.fileName, data.fileSize, data.mediaType
List Files
Project Files
List project file metadata using the standard items API. Supports filtering, sorting, and pagination.
const files = await client.DirectusFile.readMany({
fields: ['id', 'fileName', 'fileSize', 'mediaType', 'title'],
});
curl "https://example.monospace.io/api/blog/items/DirectusFile?fields=id,fileName,fileSize,mediaType,title" \
-H "Authorization: Bearer YOUR_API_KEY"
const params = new URLSearchParams({
fields: 'id,fileName,fileSize,mediaType,title',
});
const response = await fetch(
`https://example.monospace.io/api/blog/items/DirectusFile?${params}`,
{
headers: {
Authorization: 'Bearer YOUR_API_KEY',
},
},
);
const { data } = await response.json();
System Files
curl "https://example.monospace.io/api/system/files?fields=id,fileName,fileSize,mediaType" \
-H "Authorization: Bearer YOUR_API_KEY"
const response = await fetch(
'https://example.monospace.io/api/system/files?fields=id,fileName,fileSize,mediaType',
{
headers: {
Authorization: 'Bearer YOUR_API_KEY',
},
},
);
const { data } = await response.json();
Delete a File
Delete a file and its metadata. Returns 204 No Content on success. This removes both the database record and the file from storage.
curl -X DELETE https://example.monospace.io/api/blog/assets/a1b2c3d4-5678-90ab-cdef-1234567890ab \
-H "Authorization: Bearer YOUR_API_KEY"
await fetch(
'https://example.monospace.io/api/blog/assets/a1b2c3d4-5678-90ab-cdef-1234567890ab',
{
method: 'DELETE',
headers: {
Authorization: 'Bearer YOUR_API_KEY',
},
},
);
// 204 No Content
File Metadata Fields
Project DirectusFile
| Field | Type | Nullable | Description |
|---|---|---|---|
id | uuid | No | Primary key |
fileName | string | No | Original file name |
fileSize | bigint | No | Size in bytes |
mediaType | string | No | MIME type (auto-detected from extension if not provided) |
title | string | Yes | User-editable title |
description | string | Yes | User-editable description |
tags | json | Yes | User-editable tags |
System DirectusFile
| Field | Type | Nullable | Description |
|---|---|---|---|
id | uuid | No | Primary key |
fileName | string | No | Original file name |
fileSize | bigint | No | Size in bytes |
mediaType | string | No | MIME type |
Associate a File with an Item
Store the file's UUID in a relation field on your collection. Upload the file first, then reference its ID when creating or updating an item.
// 1. Upload with fetch
const form = new FormData();
form.append('file', fileInput.files[0]);
const uploadResponse = await fetch('https://example.monospace.io/api/blog/assets', {
method: 'POST',
headers: {
Authorization: 'Bearer YOUR_API_KEY',
},
body: form,
});
const { data: uploaded } = await uploadResponse.json();
const fileId = uploaded[0].id;
// 2. Create the article via SDK, connecting the file
const article = await client.Articles.createOne({
data: {
title: 'My Article',
cover_image: {
_connect: { key: { id: fileId } },
},
},
fields: ['id', 'title', { cover_image: ['id', 'fileName'] }],
});
# 1. Upload the file
curl -X POST https://example.monospace.io/api/blog/assets \
-H "Authorization: Bearer YOUR_API_KEY" \
-F "file=@photo.jpg"
# Response: { "data": [{ "id": "a1b2c3d4-..." }] }
# 2. Create an article connecting the uploaded file
curl -X POST https://example.monospace.io/api/blog/items/articles \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '[{
"title": "My Article",
"cover_image": {
"_connect": { "key": { "id": "a1b2c3d4-5678-90ab-cdef-1234567890ab" } }
}
}]'
// 1. Upload the file
const form = new FormData();
form.append('file', fileInput.files[0]);
const uploadResponse = await fetch('https://example.monospace.io/api/blog/assets', {
method: 'POST',
headers: {
Authorization: 'Bearer YOUR_API_KEY',
},
body: form,
});
const { data: uploaded } = await uploadResponse.json();
const fileId = uploaded[0].id;
// 2. Create an article connecting the uploaded file
const articleResponse = await fetch('https://example.monospace.io/api/blog/items/articles', {
method: 'POST',
headers: {
Authorization: 'Bearer YOUR_API_KEY',
'Content-Type': 'application/json',
},
body: JSON.stringify([{
title: 'My Article',
cover_image: {
_connect: { key: { id: fileId } },
},
}]),
});
const { data: article } = await articleResponse.json();
DirectusFile collection. Use _connect to link an uploaded file — see Relational Data for all relational operations.Endpoint Summary
| Operation | Endpoint | Method | Response |
|---|---|---|---|
| Upload (project) | /api/{project}/assets | POST | { data: [{ id }] } |
| Upload (system) | /api/system/assets | POST | { data: [{ id }] } |
| Download | /api/{project}/assets/{file_id} | GET | File stream |
| Download (named) | /api/{project}/assets/{file_id}/{file_name} | GET | File stream |
| Delete (project) | /api/{project}/assets/{file_id} | DELETE | 204 |
| Delete (system) | /api/system/assets/{file_id} | DELETE | 204 |
| File metadata (system) | /api/system/files/{file_id} | GET | { data: {...} } |
| List files (system) | /api/system/files | GET | { data: [...] } |
| File metadata (project) | /api/{project}/items/DirectusFile/{id} | GET | { data: {...} } |
| List files (project) | /api/{project}/items/DirectusFile | GET | { data: [...] } |
See Also
- Reading Data — query items and file metadata
- Writing Data — create and update items with file references
- Authentication — get API keys for authenticated requests