Skip to main content

Browser & mobile uploads

Uploading directly from a client (a browser tab or a phone) is convenient but exposes whatever key the client holds. FilesHub gives you two safe paths: a restricted key locked to your origin/app, or a backend proxy that never ships a key to the client. Choose based on how sensitive uploads are.

Browser uploads

A browser sends the file as multipart/form-data. Let the browser set the Content-Type (so the multipart boundary is correct) and only set X-API-Key.

const form = new FormData();
form.append('file', fileInput.files[0]);
form.append('visibility', 'public');

await fetch('https://fileshub.zaions.com/api/v1/objects', {
method: 'POST',
headers: { 'X-API-Key': PUBLIC_RESTRICTED_KEY }, // see below
body: form,
});

Make the browser key restricted

A key embedded in client JavaScript is readable by anyone. Mark it restricted in Nova and add your site's domain to its allowed-origins list. FilesHub then checks the request's Origin/Referer, so the key is useless from any other site. Use a restricted, write-only-where-needed key for low-risk public uploads (avatars, attachments). Full setup — including *.example.com wildcards — is in API key restrictions.

Or proxy through your backend

For anything sensitive, don't put a key in the browser at all. The browser uploads to your server (same-origin), and your server forwards the bytes to FilesHub with a server-side key:

Browser --(multipart)--> Your API --(X-API-Key)--> FilesHub --(201 url)--> Your API --> Browser

This keeps the key secret and lets you validate, resize, or virus-scan before storing.

Mobile uploads (Capacitor, React Native, native)

Mobile clients send the same multipart POST. If the key is app-restricted, include your package/bundle id in X-App-Id — and, when the Android origin pins signing certificates, the cert fingerprint in X-Android-Cert:

X-API-Key: fh_live_xxx
X-App-Id: com.example.myapp
X-Android-Cert: AB:CD:... # Android only, when certificate pinning is on

See API key restrictions for computing the fingerprint (keytool / a Kotlin snippet) and the iOS bundle-id path.

Capacitor / fetch from a WebView
const form = new FormData();
form.append('file', blob, 'photo.jpg');
form.append('visibility', 'public');

await fetch('https://fileshub.zaions.com/api/v1/objects', {
method: 'POST',
headers: { 'X-API-Key': key, 'X-App-Id': 'com.example.myapp' },
body: form,
});

Capacitor's WebView and most native HTTP stacks already send a platform user-agent; you usually only need to add X-App-Id.

Which path should I use?

SituationRecommended path
Public avatars/attachments, low riskRestricted browser/app key scoped to your domain/bundle id.
Anything private or business-criticalBackend proxy — key never leaves your server.
Need to validate/transform before storingBackend proxy.

When in doubt, proxy. It costs one extra hop and removes the entire class of leaked-client-key problems. See Authentication for how restrictions are enforced and File visibility for public vs private.