Skip to main content
FlowFn
IntegrationsTemplatesPricingDocsBlogSign inStart free
All documentation

Fetch entries (flowfn.fetchData)

UpdatedJun 4, 2026Reading time4 min read

What is a fetch entry?

A fetch entry registers a single platform-tool action your playground JS can call by name to read data — list rows, get a record, search, etc. It's the read-side sibling of Action bindings: bindings are designed for writes (post a message, charge a card), fetch entries are designed for reads.

Each entry has a ref_key (a plain identifier you pick — not a secret), a platform + action (plus a connection for tools that need one), and an optional input template. The iframe then calls await flowfn.fetchData('<ref_key>', inputs) to run it.

Why a separate primitive?

  • No bearer credential. Unlike action bindings, fetch entries don't mint an invocation_code. The ref_key lives in your iframe source code; authentication is by allowlist membership + the playground's public access policy (published / password / embed gates).
  • Not tied to a DOM @key. Call flowfn.fetchData from anywhere in your JS — on page load, in event handlers, in helper functions. No need to bind it to a button.
  • Read-friendly defaults. No idempotency cache (reads are safe to retry); per-entry rate limit is higher than invoke (60 / window vs. 20). Outputs are returned in full unless you set an output capture filter.

Creating a fetch entry

  1. Open the bottom drawer's Fetch tab and click Add fetch.
  2. Pick a ref_key (snake_case identifier, e.g. list_artists). This is the name you'll use from JS — it's visible in iframe code, so treat it as public.
  3. Pick the Platform, Action, and team Connection. The connection's credentials run the action server-side; the iframe never sees them.
  4. For each input the action declares, pick a source: From @key (snapshot a registered @key at call time), Custom JS (a JS expression evaluated in the iframe), Static value (a literal baked in), or Skip (optional inputs only). The caller can always override by passing { name: value } as the second argument to flowfn.fetchData.
  5. Save. The entry appears in the list with a Copy snippet button so you can paste a ready-made flowfn.fetchData(...) call into your JS.

Input source examples

All static — no caller inputs needed:

// Editor: page_size = Static 50, sort = Static created_desc
const result = await flowfn.fetchData('list_artists');

Mixed sources — @key snapshot + caller override + Custom JS:

// Editor: q = From @key (@search_query), page_size = Static 50, ts = Custom JS (Date.now())
// Markup: <input data-key="search_query" />
const result = await flowfn.fetchData('list_artists');
// Server receives { q: '', page_size: 50, ts: 1716499200000 }

Caller override — pass anything explicitly to short-circuit @key / Custom JS resolution:

const result = await flowfn.fetchData('list_artists', { q: 'rock' });
// q comes from the override; ts still resolves from Custom JS.

The priority order at call time is: caller-supplied → Custom JS eval → @key snapshot → data-key DOM fallback → undefined (server rejects required inputs that resolve to undefined with invalid_inputs; extra fields not in declared_inputs are stripped).

Custom JS notes

Custom JS expressions are evaluated in your playground script's lexical scope (the same path js_value @keys use), so they can read top-level let/const bindings, the DOM, globals like location / navigator / Date, etc. The expression runs on every flowfn.fetchData call — there's no caching. Use it for dynamic values (timestamps, derived properties, computed query strings); use Static value for constants.

Calling fetchData from JS

flowfn.fetchData('list_artists', { q: 'pop' })
  .then((outputs) => render(outputs.items))
  .catch((err) => console.error(err.code, err.message));

The Promise resolves with the action's full outputs object (filtered through the entry's output_capture allowlist when one is set). On failure it rejects with an Error whose .code matches the server-side error code: entry_disabled, rate_limited, invalid_inputs, handler_error, invocation_timeout, ...

Disabling vs deleting

  • Disable via the toggle on the entry row to instantly stop responding to flowfn.fetchData('<ref_key>') calls without removing the entry. Useful for quick incident response.
  • Delete via the trash icon to remove the entry entirely. The ref_key becomes invalid and existing iframe code that calls it will start rejecting with "Fetch entry not found".

Security model

  • Allowlist, not credential. Anyone who can render the playground can call any enabled fetch entry on it. If you wouldn't expose the data to the same audience as the playground itself, don't register it.
  • Server-side everything. The platform, action, connection, and input template stay on the server. The iframe only knows the ref_key and the declared input names.
  • Inputs are validated against the entry's declared inputs server-side. Unknown fields are rejected.
  • Standard public access policy applies: the playground must be published; password / embed-allowed-domains gates still apply to fetch-data calls just like they do to the page itself.
  • Phase 1 limits: platform-tool actions only (AI models aren't supported as fetch entries yet); synchronous (~25 s budget); no file outputs; heavy-task tools (long-running ffmpeg / ML jobs) are refused at save time.

fetchData vs invoke at a glance

  • flowfn.invoke: write-side. Bound to a DOM @key, gated by a rotatable invocation_code, defaults to filtering outputs. Use for side-effecting actions (post, send, charge).
  • flowfn.fetchData: read-side. Standalone ref_key, allowlist-only, returns full outputs by default. Use for reads (list, get, search).

Spotted an issue or have feedback?

support@flowfn.com
Back to docs hub →