Files API
Files are content-addressed by SHA-256 hash. The same bytes always produce the same hash, so identical files are stored only once. Upload files before pushing a version that references them.
Workflow
- Compute the SHA-256 hash of your file locally
- Check if it exists with
HEAD - If not, upload it with
PUT - Reference it in records as
{"$file": "sha256:<hash>"} - Push your version โ the server verifies all referenced files exist
HEAD /api/collections/:owner/:slug/files/:hash
No auth required
Check if a file exists. Returns headers only, no body.
Parameters
:hash | SHA-256 hash, optionally prefixed with sha256: |
Response
200 | File exists. Content-Length and Content-Type headers set. |
404 | File not found. |
Example
curl -I https://underlay.org/api/collections/kf/archive/files/sha256:a1b2c3...
# HTTP/2 200
# Content-Length: 1048576
# Content-Type: application/pdf GET /api/collections/:owner/:slug/files/:hash
No auth required
Download a file. Returns the raw binary data with appropriate content type. Response is cacheable (immutable content).
Headers
Content-Type | MIME type of the file |
Cache-Control | public, max-age=31536000, immutable |
ETag | The file hash |
Example
curl -o paper.pdf \
https://underlay.org/api/collections/kf/archive/files/sha256:a1b2c3... PUT /api/collections/:owner/:slug/files/:hash
Auth: write scope
Upload a file. The server verifies the SHA-256 hash of the uploaded bytes matches the hash in the URL. If the file already exists, returns 200 without re-uploading.
Request
Send the file as the raw request body with the appropriate Content-Type header.
# Compute hash
HASH=$(shasum -a 256 paper.pdf | cut -d' ' -f1)
# Upload
curl -X PUT \
"https://underlay.org/api/collections/kf/archive/files/sha256:$HASH" \
-H "Authorization: Bearer $KEY" \
-H "Content-Type: application/pdf" \
--data-binary @paper.pdf Response 201
{
"hash": "a1b2c3d4e5f6...",
"size": 1048576
} Errors
200 | File already exists: {"hash": "...", "status": "exists"} |
400 | Hash mismatch โ the uploaded bytes don't match the hash in the URL. |
File references in records
To link a file to a record, use the $file convention:
{
"id": "pub-001",
"type": "Publication",
"data": {
"title": "An Example Paper",
"pdf": {"$file": "sha256:a1b2c3d4e5f6..."},
"thumbnail": {"$file": "sha256:f6e5d4c3b2a1..."}
}
} When pushing a version, the server scans all record data for $file references and verifies each referenced file exists. If any are missing, the push returns 422 with a list of needed hashes.