Media & uploads
Media & uploads
The Media API manages the image, file, and video assets behind your content — uploading new files, replacing bytes on an existing asset, tagging and organizing a library, and minting time-limited URLs for protected assets. Images and files share one set of endpoints; video is a separate, larger surface because uploads and delivery both go through a dedicated streaming pipeline.
Concepts
| Term | Meaning |
|---|---|
| Asset | An image or file record — the entry you list, tag, and delete. |
| Video | A separate resource type for streamable video, identified by its own ID and by a distinct video-provider ID. |
| Visibility | public (served directly) or protected (requires a signed URL, or a namespace binding, to resolve). |
| Signed URL | A time-limited URL that grants access to a protected asset or video without exposing it publicly. |
| Namespace binding | The list of app namespaces allowed to mint signed URLs for a protected asset. Only meaningful for protected visibility. |
List and fetch assets
curl -sf "https://api.falcata.io/api/v1/media/assets?limit=20" \
-H "Authorization: Bearer $FURNACE_TOKEN" | jq '.data[] | {id, filename, url}'
Fetch a single asset with GET /media/assets/{id}, or up to 100 at once:
curl -sf -X POST "https://api.falcata.io/api/v1/media/assets/by-ids" \
-H "Authorization: Bearer $FURNACE_TOKEN" \
-H "Content-Type: application/json" \
-d '{"ids":["id1","id2","id3"]}' | jq '.data[] | {id, filename, url}'
Upload an image or file
Uploads are base64-encoded JSON, which caps practical payload size around 10 MB after encoding overhead. For anything larger, request a pre-signed upload URL instead of inlining the bytes.
IMAGE_B64=$(base64 -i photo.jpg)
curl -sf -X POST "https://api.falcata.io/api/v1/media/upload/image" \
-H "Authorization: Bearer $FURNACE_TOKEN" \
-H "Content-Type: application/json" \
-d "{\"filename\":\"photo.jpg\",\"data\":\"$IMAGE_B64\",\"tags\":[\"hero\"]}" | jq '.data.id'
The CLI handles the base64 encoding for you; the raw REST call needs it done by hand.
Files that aren't images use POST /media/upload/file with the same base64-in-JSON shape.
Replace, tag, and organize
Replacing an image keeps its asset ID and editorial metadata — use it to swap bytes without breaking links that point at the ID.
curl -sf -X POST "https://api.falcata.io/api/v1/media/assets/$ASSET_ID/replace" \
-H "Authorization: Bearer $FURNACE_TOKEN" \
-H "Content-Type: application/json" \
-d "{\"mimeType\":\"image/jpeg\",\"originalName\":\"photo-v2.jpg\",\"size\":12345,\"imageData\":\"$IMAGE_B64\"}" | jq '.data.assetId'
Poll GET /media/assets/{id} until processingStatus is ready before linking to the new bytes. Tag or delete assets in bulk with one call per action:
curl -sf -X POST "https://api.falcata.io/api/v1/media/assets/batch-tags" \
-H "Authorization: Bearer $FURNACE_TOKEN" \
-H "Content-Type: application/json" \
-d '{"action":"add","ids":["id1","id2"],"tags":["featured"]}' | jq '.data.updated'
action is "add" or "remove" — one call handles one direction, not both at once. POST /media/assets/batch-delete follows the same {ids: [...]} shape and deletes permanently; there's no undo.
Resolve or sign a URL
A public asset's CDN URL resolves directly. A protected asset needs a signed URL, minted per request.
# Public asset — fast CDN URL lookup
curl -sf "https://api.falcata.io/api/v1/media/assets/$ASSET_ID/resolve?transformClass=thumb" \
-H "Authorization: Bearer $FURNACE_TOKEN" | jq '.data'
# Protected asset — time-limited signed URL
curl -sf -X POST "https://api.falcata.io/api/v1/media/assets/$ASSET_ID/url" \
-H "Authorization: Bearer $FURNACE_TOKEN" \
-H "Content-Type: application/json" -d '{}' | jq '.data.url'
To let another app mint signed URLs for a protected asset, bind it to that namespace (admin token required):
curl -sf -X POST "https://api.falcata.io/api/v1/media/assets/$ASSET_ID/namespaces" \
-H "Authorization: Bearer $FURNACE_TOKEN" \
-H "Content-Type: application/json" \
-d '{"allowedNamespaces":["marozzo"]}' | jq '.data'
allowedNamespaces is required on every call — pass an array to grant, [] to lock the asset to admin-only minting, or null to clear the binding entirely.
Upload a video
Video upload is two steps: create the record to get a resumable upload endpoint, transfer the bytes, then finalize.
curl -sf -X POST "https://api.falcata.io/api/v1/media/videos/upload" \
-H "Authorization: Bearer $FURNACE_TOKEN" \
-H "Content-Type: application/json" \
-d '{"title":"Lesson 1","tags":["tutorial"]}' | jq '.data | {id, tusUploadUrl}'
# ... transfer bytes to tusUploadUrl (TUS resumable-upload protocol), then:
curl -sf -X POST "https://api.falcata.io/api/v1/media/videos/$VIDEO_ID/finalize" \
-H "Authorization: Bearer $FURNACE_TOKEN"
Get a signed playback URL using the video's provider ID, not its media asset ID:
curl -sf -X POST "https://api.falcata.io/api/v1/media/videos/$BUNNY_VIDEO_ID/signed-url" \
-H "Authorization: Bearer $FURNACE_TOKEN" \
-H "Content-Type: application/json" -d '{}' | jq '.data.url'
Everything else — stats, tag listings, CDN configuration, and full field-by-field responses — is in the full reference.