The Files API allows you to upload files as part of record operations and download files with optional thumbnail generation.
Upload files
Files are uploaded as part of record create/update operations using multipart/form-data.
Create record with file
POST /api/collections/{collection}/records
Use multipart/form-data to upload files with record data.
curl -X POST http://127.0.0.1:8090/api/collections/posts/records \
-H "Authorization: Bearer YOUR_TOKEN" \
-F "title=My Post" \
-F "content=Post content" \
-F "image=@/path/to/image.jpg"
Update record files
PATCH /api/collections/{collection}/records/{id}
Replace files:
curl -X PATCH http://127.0.0.1:8090/api/collections/posts/records/RECORD_ID \
-H "Authorization: Bearer YOUR_TOKEN" \
-F "image=@/path/to/new-image.jpg"
Append files (using + modifier):
curl -X PATCH http://127.0.0.1:8090/api/collections/posts/records/RECORD_ID \
-H "Authorization: Bearer YOUR_TOKEN" \
-F "images+=@/path/to/another-image.jpg"
Prepend files (using + prefix):
curl -X PATCH http://127.0.0.1:8090/api/collections/posts/records/RECORD_ID \
-H "Authorization: Bearer YOUR_TOKEN" \
-F "+images=@/path/to/first-image.jpg"
Remove specific files (using - modifier):
curl -X PATCH http://127.0.0.1:8090/api/collections/posts/records/RECORD_ID \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_TOKEN" \
-d '{
"images-": ["existing_filename.jpg", "another_file.png"]
}'
Download files
Download files from file field records.
GET /api/files/{collection}/{recordId}/{filename}
The collection name or ID
The record ID containing the file
The name of the file to download
Thumbnail size (e.g., 100x100, 300x200). Only works for images.
File token for accessing protected files (see Generate file token)
Authentication: Required for protected files (when field has protected: true)
Response
Returns the file with appropriate Content-Type header.
curl http://127.0.0.1:8090/api/files/posts/RECORD_ID/image.jpg \
--output image.jpg
Generate file token
Generate a token to access protected files.
Authentication: Required (must be authenticated)
Response
File access token (valid for the authenticated user’s session)
curl -X POST http://127.0.0.1:8090/api/files/token \
-H "Authorization: Bearer YOUR_AUTH_TOKEN"
Thumbnail generation
PocketBase automatically generates thumbnails for image files on-demand.
Thumbnails are generated for:
- PNG (
.png)
- JPEG (
.jpg, .jpeg)
- GIF (
.gif)
- WebP (
.webp)
Default sizes
The default thumbnail size is 100x100, but you can configure custom sizes in the collection’s file field settings.
Thumbnail sizes
Specify thumbnail dimensions using {width}x{height} format:
# Square thumbnail
curl http://127.0.0.1:8090/api/files/posts/RECORD_ID/photo.jpg?thumb=100x100
# Rectangle thumbnail
curl http://127.0.0.1:8090/api/files/posts/RECORD_ID/photo.jpg?thumb=300x200
# Custom size (if configured in field settings)
curl http://127.0.0.1:8090/api/files/posts/RECORD_ID/photo.jpg?thumb=500x500
Thumbnails are generated on first request and cached. The original file is served if thumbnail generation fails.
Custom thumbnail sizes
Define custom thumbnail sizes in your collection’s file field configuration:
{
"name": "image",
"type": "file",
"options": {
"maxSelect": 1,
"maxSize": 5242880,
"thumbs": ["100x100", "300x200", "800x600"]
}
}
Protected files
Mark file fields as protected to require authentication for access.
Field configuration
{
"name": "document",
"type": "file",
"options": {
"protected": true
}
}
Accessing protected files
Protected files require either:
- File token (recommended for client-side access)
- Direct auth (collection’s
viewRule is checked)
// 1. Generate file token
const tokenResponse = await fetch('http://127.0.0.1:8090/api/files/token', {
method: 'POST',
headers: { 'Authorization': 'Bearer ' + authToken }
});
const { token } = await tokenResponse.json();
// 2. Use token to access file
const fileUrl = `http://127.0.0.1:8090/api/files/documents/${recordId}/file.pdf?token=${token}`;
File field options
When defining file fields in collections, you can configure:
File URLs
File URLs follow this pattern:
http://127.0.0.1:8090/api/files/{collection}/{recordId}/{filename}
You can construct file URLs from record data:
const record = {
id: 'RECORD_ID',
collectionName: 'posts',
image: 'filename.jpg'
};
const fileUrl = `http://127.0.0.1:8090/api/files/${record.collectionName}/${record.id}/${record.image}`;
View collection files
For view collections, files are served from the original collection record:
GET /api/files/{viewCollection}/{viewRecordId}/{filename}
PocketBase automatically resolves the file to the original collection’s record.
Best practices
- Use appropriate MIME type restrictions for security
- Set reasonable
maxSize limits
- Use protected files for sensitive documents
- Generate thumbnails only for sizes you need
- Consider CDN caching for public files
File naming
PocketBase automatically handles file naming:
- Generates unique filenames to prevent collisions
- Preserves file extensions
- Sanitizes filenames for safe storage
Storage
Files are stored in:
pb_data/storage/{collectionId}/{recordId}/
Thumbnails are stored in:
pb_data/storage/{collectionId}/{recordId}/thumbs_{filename}/
Common errors
| Code | Description |
|---|
| 400 | Invalid file type or size exceeds limit |
| 403 | Insufficient permissions for protected file |
| 404 | File, record, or collection not found |
| 500 | File system error |