Private files with signed transfers
Store private documents and serve them through authenticated flows, with short-lived signed tickets for direct upload and download.
- Signed upload and download tickets
- Range requests supported
- Keys never leave your server
Direct transfer, signed
Request a ticket, then PUT the file straight to the returned URL. Bytes do not detour through your application server.
Upload tickets are single-use
An upload ticket is spent once. Download tickets stay valid until they expire, which makes them safe to hand to a media player.
Your API key stays server-side
The download URL carries its own signature. Nothing about your API key is appended to a link you give a browser.
Range requests work
Download URLs honour Range, so video scrubbing and resumable downloads behave the way clients expect.
Scopes, not blanket access
blob.read permits reads, blob.write permits uploads and deletion. The key must belong to the project that owns the file.
Confirm closes the loop
After the upload completes, a confirm call records the object. An abandoned upload does not silently become a phantom row.
Expiry is part of the contract
Every ticket endpoint returns an expiry. Use it. A client that caches a download URL for a day and retries forever will produce support tickets, not resilience.
const ticket = await fetch(`${base}/api/storage/upload-ticket`, {
method: 'POST',
headers: { Authorization: `Bearer ${process.env.VELTIC_API_KEY}` },
body: JSON.stringify({ projectId, key: 'invoices/2026-09.pdf' })
}).then(response => response.json());
await fetch(ticket.uploadUrl, {
method: 'PUT',
headers: { 'x-veltic-upload-token': ticket.token },
body: file
});Build the whole backend in one project
One plan, one dashboard, one command line interface. PostgreSQL, applications, functions, storage and realtime.