Skip to main content
Your action can have a fetchers property that is an array of fetcher references. Fetchers allow you to populate dropdown options dynamically by fetching data from external APIs.

Define the fetcher in your action

First, export a fetcher constant and reference it in your action: In the action file (actions/createChatCompletion.ts):
import { createAction } from "@typebot.io/forge";
import { auth } from "../auth";

// Export the fetcher constant
export const modelsFetcher = {
  id: "fetchModels",
} as const;

export const createChatCompletion = createAction({
  name: "Create chat completion",
  auth,
  options: option.object({
    model: option.string.layout({
      fetcher: modelsFetcher.id, // Reference the fetcher by its id
      label: "Model",
      placeholder: "Select a model",
    }),
    // ... other options
  }),
  fetchers: [modelsFetcher], // Register the fetcher
  // ...
});

Implement the fetcher handler

The fetcher implementation logic should be defined in your handlers file using createFetcherHandler: In the handlers file (handlers.ts):
import { createActionHandler, createFetcherHandler } from "@typebot.io/forge";
import { parseUnknownError } from "@typebot.io/lib/parseUnknownError";
import ky from "ky";
import { createChatCompletion, modelsFetcher } from "./actions/createChatCompletion";

export default [
  createActionHandler(createChatCompletion, {
    server: async ({ credentials, options, variables, logs }) => {
      // Action implementation
    },
  }),
  createFetcherHandler(
    createChatCompletion, // Pass the action as first parameter
    modelsFetcher.id, // Pass the fetcher id
    async ({ credentials, options }) => {
      if (!credentials?.apiKey)
        return {
          data: [],
        };

      try {
        const response = await ky
          .get("https://api.example.com/models", {
            headers: {
              authorization: `Bearer ${credentials.apiKey}`,
            },
          })
          .json<{ data: { id: string; name: string }[] }>();

        return {
          data: response.data.map((model) => ({
            value: model.id,
            label: model.name,
          })),
        };
      } catch (err) {
        return {
          error: await parseUnknownError({ err }),
        };
      }
    }
  ),
];

Fetcher response format

The fetcher function must return an object with either a data or error property:
  • Success: { data: (string | { label: string; value: string })[] }
  • Error: { error: string | { description: string; details?: string; context?: string } }
The data array can contain either:
  • Simple strings: ["model-1", "model-2", "model-3"]
  • Objects with label and value: [{ label: "GPT-4", value: "gpt-4" }, { label: "GPT-3.5", value: "gpt-3.5-turbo" }]

Available parameters

The fetcher handler receives the following parameters:
  • credentials: The authenticated credentials for the action
  • options: The current values of all action options (useful when you have dependencies between options)
By passing the action as the first parameter to createFetcherHandler, TypeScript will automatically infer the correct types for credentials and options.