How to build a custom data connector plugin for your API

Integrating data from your custom API with Builder.io makes fetching and binding data from that API so much easier.

The most straightforward way to integrate any API resources is using a @builder.io/data-plugin-tools, and here are some steps to build your own custom data connector plugin:

  1. clone Builder repository and then navigate to the plugin example folder here:
git clone https://github.com/BuilderIO/builder.git
# start from a preconfigured plugin code by copying its content to another folder
cp -r plugins/contentful plugins/[my-backend]
npm install @builder.io/data-plugin-tools
  1. Delete content of src/plugin.tsx, so we replace it with the new configuration, then start by
import { registerDataPlugin } from '@builder.io/data-plugin-tools';

registerDataPlugin(
  {
    name: 'Foobar',
    id: '@builder.io/plugin-foobar',
    settings: [
      // list of information needed to connect store, optional
      {
        name: 'apiKey',
        friendlyName: 'Lorem Ipsum',
        type: 'string',
        required: true,
        helperText:
          'Get your API key from https://example.com/account/settings',
      }
    ],
    ctaText: `Connect FooBar`,
  },
  /**
   * settings here will be an observable map of the settings you configured above in settings,
   *  ( in this example settings.get('storeId') will give us the storeId entered by user)
   */
  // Observable map of the settings configured above
  async settings => {
    const apiKey = settings.get('apiKey')?.trim();
    return {
      async getResourceTypes() {
        return [
          {
          name: 'Resource 1',
          id: `resource-1`,
          canPickEntries: true,
          // inputs are the query parameter definitions for your public API
          inputs: () => {
            return [
              {
                name: 'include',
                friendlyName: 'Retrieve linked assets level',
                advanced: true,
                defaultValue: 2,
                type: 'number',
              },
              {
                name: 'limit',
                defaultValue: 10,
                min: 0,
                max: 100,
                type: 'number',
              },

              {
                name: 'order',
                friendlyName: 'Order By'
                type: 'string',
                enum: ['a', 'b']
              },
            ];
          },
          toUrl: (options: any) => {
            // by entry
            if (options.entry) {
              return `https://public.example.com/spaces/${apiKey}/resource/${options.entry}`
            }
            // by query
            const params = qs.stringify(options,
              { allowDots: true, skipNulls: true }
            );
            return  `https://public.example.com/spaces/${apiKey}/search?${params}`
            );
          },
          }
        ]
      },
      async getEntriesByResourceType(typeId: string, options) {
        const results = await fetch(`https://public.example.com/spaces/${apiKey}?${qs.stringify(options)}`)
      },
    };
  }
);

Now that you added your custom data connector, we can check to see if it’s working correctly by running locally

npm install
npm run start

Start a server at http://localhost:1268

Go to the Builder plugin settings and add your local plugin https://localhost:1268/plugin.system.js?pluginId=@foobar/plugin-builder`

Now you should see new data connector options in the data tab in the editor.

Once you’re done testing your new integration, submit a pull request to Builder with the new code, we’ll help review it, and publish it to npm. Or, if you’d like it to be a private plugin, talk to us, and we can support private plugins as part of an enterprise plan.

See more:

Contentful plugin source code for a more concrete example.

Extensibility docs for more ways on how Builder can be extended.