External access

External access

External access lets people outside your team run a flow, either through a signed link you hand out or, for a public flow, without any link at all. This is useful for flows that collect input from customers, such as a feedback form or an onboarding step.

External access is in preview, and its API is subject to change.

Making a flow runnable externally

Mark a flow with @externalAccess to let people outside your team run it through a signed link:

flow ShareableFlow {
    inputs {
        name Text?
    }
    @externalAccess
    @permission(actions: [share], roles: [Admin])
}

A flow with @externalAccess is not openly runnable. An authorised user mints a signed link, and whoever holds the link can run the flow without signing in.

To make a flow runnable by anyone without a link, use @externalAccess(public: true):

flow PublicRunFlow {
    @externalAccess(public: true)
}

A public flow's run action requires no permission, so any caller, including an unauthenticated one, can start it.

The share permission

Minting, listing, and revoking signed links is gated by a share permission action. Only the roles you allow can hand out access:

flow ShareableFlow {
    inputs {
        name Text?
    }
    @externalAccess
    @permission(actions: [share], roles: [Admin])
}

Public and shareable are not mutually exclusive. A public flow can also mint shareable links, which is useful for baking per-record default inputs into a link, for example a per-order feedback link. Minting is still gated by the share permission even when the flow is public; being public only opens the run action.

flow PublicShareableFlow {
    inputs {
        name Text?
    }
    @externalAccess(public: true)
    @permission(actions: [share], roles: [Admin])
}

Single-use and reusable links

A single-use link counts as used only once a run completes. A visitor who abandons or fails a run can retry the same link until one run succeeds. Reusable links can be run any number of times.

External-facing copy

A flow's internal title and description are shown to authenticated Console users. To avoid exposing internal wording to anonymous visitors, set external copy in an externalAccess block in the flow's config:

import { ShareableFlow } from "@teamkeel/sdk";
 
export default ShareableFlow(
  {
    title: "Internal review flow",
    externalAccess: {
      title: "Leave your feedback",
      description: "Tell us about your order",
      introduction: "This takes about a minute.",
      branded: true,
    },
  },
  async (ctx) => {
    return ctx.complete({ title: "Thanks for your feedback" });
  },
);

For more on writing flows, see Writing flows and Permissions.