Appearance
Embeddable picker
Let your users pick files from their own FluidCloud drive without leaving your app — the same pattern as the Google Drive Picker. You add one script tag, the user browses and selects in a FluidCloud window, and your page receives short-lived download URLs for exactly the files they chose.
The picker is a user-facing, browser-only flow: your secret fck_ API key is never involved in the page. Everything the host page needs is a publishable client id (fcpk_…), which identifies your app and is safe to ship in page source.
How it works
- Your page calls
FluidCloudPicker.open(...)(frompicker.js). A centered popup opens oncloud.fluidvip.com/picker. - FluidCloud checks that your page's origin is registered for your client id. Unregistered origins get a neutral "can't use the picker" screen and your page receives nothing.
- The user signs in to FluidCloud if needed (existing sessions are reused), browses their Spaces and folders, and confirms a selection.
- FluidCloud mints a short-lived URL (~30 minutes) for each selected file and posts them to your page via
postMessage— targeted at your exact origin, never*.
The URLs are served from FluidCloud's file CDN and require no credentials, so your frontend can render them directly or your backend can fetch and import the bytes. After ~30 minutes they expire; nothing persistent is created and no share-link quota is consumed.
Selection is user-scoped
The picker only ever exposes files the signed-in user can already access (their tenant, their folder grants, scanned-clean files). It grants your app a copy of their choice — it is not an API onto their drive.
1. Register your site
The picker is part of the FluidCloud API feature (Elite plan).
- Create a self-serve API key (see Authentication) if you don't have one.
- Register the exact origins your pages run on:
bash
curl -X PUT https://api-cloud.fluidvip.com/api/v1/me/api-keys/KEY_ID/picker \
-H "Authorization: Bearer USER_JWT" \
-H "Content-Type: application/json" \
-d '{"origins": ["https://app.example.com", "http://localhost:3000"]}'The response includes your publishable picker_client_id:
json
{
"id": "…",
"name": "My app",
"picker_public_id": "fcpk_k3…",
"picker_origins": ["https://app.example.com", "http://localhost:3000"]
}Rules: origins must be bare https:// origins (scheme + host, no path); plain http:// is allowed only for localhost / 127.0.0.1; up to 10 per key. Setting {"origins": []} disables embedding while keeping the client id stable.
2. Open the picker
html
<script src="https://cloud.fluidvip.com/picker.js"></script>
<script>
function importFromFluidCloud() {
FluidCloudPicker.open({
clientId: "fcpk_…", // your publishable client id
multiple: true, // default true; false = single pick
accept: "image/*,video/*", // optional MIME filter
disposition: "inline", // or "attachment" (download headers)
onPicked: function (items) {
// items: [{ id, name, mime, size, url, expires_at }]
// Each url is valid for ~30 minutes.
items.forEach(function (f) { console.log(f.name, f.url); });
},
onCancel: function () {},
});
}
</script>
<button onclick="importFromFluidCloud()">Import from FluidCloud</button>Options
| Option | Type | Default | Meaning |
|---|---|---|---|
clientId | string | — | Your fcpk_ publishable id. Required for third-party sites. |
multiple | boolean | true | Allow selecting more than one file. |
accept | string | all | Comma-separated MIME filter, e.g. image/*,application/pdf. |
disposition | "inline" | "attachment" | "inline" | Whether the minted URLs serve inline (fetch/render) or as downloads. |
mode | "popup" | "iframe" | "popup" | Third-party sites must use the popup; inline iframing is reserved for Fluid's own platforms. |
onPicked(items) | function | — | Called once with the selection. |
onCancel() | function | — | Called when the user dismisses the picker. |
open() returns { close() } so you can dismiss the picker programmatically.
Picked items
json
{
"id": "8b6f…",
"name": "spring-shoot-014.jpg",
"mime": "image/jpeg",
"size": 4181923,
"url": "https://cloud-files.fluidvip.com/s/…",
"expires_at": 1751892000
}expires_at is UNIX seconds. If you need the bytes past expiry, download them to your side while the URL is live — re-opening the picker is the only way to get a fresh URL, by design.
Importing server-side
The URLs are plain HTTPS — hand them to your backend and fetch:
python
import httpx
for item in picked_items: # forwarded from your frontend
data = httpx.get(item["url"]).content
store(item["name"], data)Errors & edge cases
- "This site can't use the picker" — the page origin isn't registered for the client id (or the key was revoked / the plan lapsed). Register the origin in step 1.
- Popup blocked — call
open()from a direct user gesture (a click handler), never from async code. - Files still scanning — freshly uploaded files can't be picked until the malware scan marks them clean (they render disabled in the grid).
Endpoint details
The REST endpoints behind the widget (GET /picker/context, POST /picker/grants, PUT /me/api-keys/{id}/picker) are documented in the Picker API reference — useful if you're building a custom picker UI instead of using picker.js.
Security model
- The publishable
fcpk_id authorizes nothing by itself — embedding also requires an origin match, enforced server-side both before the picker renders and again when URLs are minted. - Selection messages are
postMessage-targeted at your exact origin. - Minted URLs are HMAC-signed, tenant-bound, expire in ~30 minutes, and cover only the files the user explicitly confirmed.