Skip to content

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

  1. Your page calls FluidCloudPicker.open(...) (from picker.js). A centered popup opens on cloud.fluidvip.com/picker.
  2. 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.
  3. The user signs in to FluidCloud if needed (existing sessions are reused), browses their Spaces and folders, and confirms a selection.
  4. 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).

  1. Create a self-serve API key (see Authentication) if you don't have one.
  2. 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

OptionTypeDefaultMeaning
clientIdstringYour fcpk_ publishable id. Required for third-party sites.
multiplebooleantrueAllow selecting more than one file.
acceptstringallComma-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)functionCalled once with the selection.
onCancel()functionCalled 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.

FluidCloud API — part of the Fluidvip ecosystem.