Skip to main content
This guide walks you through creating a custom Prismatic connector using Spectral. By the end, you will have a component with one action, a connection, and a passing local test.
1

Install Spectral

Add @prismatic-io/spectral to your project as a dependency.
npm install @prismatic-io/spectral
Spectral requires TypeScript. If you have not configured TypeScript yet, see the installation guide for tsconfig requirements.
2

Create a component with one action

Create an index.ts file at the root of your component package. Use the component and action functions exported from Spectral to define your connector.
index.ts
import { component, action, input } from "@prismatic-io/spectral";

// Define an action that fetches a record by ID
const getRecord = action({
  display: {
    label: "Get Record",
    description: "Fetch a single record from the API by its ID.",
  },
  inputs: {
    recordId: input({
      label: "Record ID",
      type: "string",
      required: true,
      comments: "The unique identifier of the record to fetch.",
      example: "rec_01HV2K",
    }),
  },
  perform: async (context, params) => {
    const { recordId } = params;
    // Replace with a real API call
    const data = { id: recordId, name: "Example Record" };
    return { data };
  },
});

// Assemble the component
export default component({
  key: "my-connector",
  public: false,
  display: {
    label: "My Connector",
    description: "A custom connector built with Spectral.",
    iconPath: "icon.png",
  },
  actions: { getRecord },
});
The component function accepts a ComponentDefinition object. The key field must be unique within your Prismatic organization. Setting public: false limits the component to your organization.
3

Define an input

Inputs are defined using the input helper. Each input maps directly to a field shown in the integration builder UI.
inputs.ts
import { input } from "@prismatic-io/spectral";

// A reusable string input for an API endpoint
export const apiEndpoint = input({
  label: "API Endpoint",
  type: "string",
  required: true,
  default: "https://api.example.com/v1",
  comments: "The base URL of the API to connect to.",
  example: "https://api.example.com/v1",
});

// A password input — displayed as masked in the UI
export const apiToken = input({
  label: "API Token",
  type: "password",
  required: true,
  comments: "Your API authentication token.",
});
Common type values include "string", "password", "boolean", "text" (multiline), "code", and "connection".
4

Define a basic connection

Connections hold authentication credentials. Use the connection function to define one and then attach it to your component.
connection.ts
import { connection, input } from "@prismatic-io/spectral";

export const myApiConnection = connection({
  key: "myApiConnection",
  display: {
    label: "My API Connection",
    description: "Authenticates requests to the My API service.",
  },
  inputs: {
    endpoint: input({
      label: "API Endpoint",
      type: "string",
      required: true,
      default: "https://api.example.com/v1",
      comments: "Base URL of the API.",
    }),
    apiKey: input({
      label: "API Key",
      type: "password",
      required: true,
      comments: "Your secret API key.",
    }),
  },
});
Register the connection on your component by adding it to the connections array:
index.ts
import { component, action, input } from "@prismatic-io/spectral";
import { myApiConnection } from "./connection";

const getRecord = action({
  display: {
    label: "Get Record",
    description: "Fetch a single record from the API by its ID.",
  },
  inputs: {
    connection: input({
      label: "Connection",
      type: "connection",
      required: true,
    }),
    recordId: input({
      label: "Record ID",
      type: "string",
      required: true,
      example: "rec_01HV2K",
    }),
  },
  perform: async (context, params) => {
    const { connection, recordId } = params;
    const { endpoint, apiKey } = connection.fields as {
      endpoint: string;
      apiKey: string;
    };
    // Use endpoint and apiKey to make an authenticated request
    const data = { id: recordId, endpoint };
    return { data };
  },
});

export default component({
  key: "my-connector",
  public: false,
  display: {
    label: "My Connector",
    description: "A custom connector built with Spectral.",
    iconPath: "icon.png",
  },
  actions: { getRecord },
  connections: [myApiConnection],
});
For OAuth 2.0 connections, use oauth2Connection with oauth2Type: OAuth2Type.AuthorizationCode or oauth2Type: OAuth2Type.ClientCredentials.
5

Test the action locally

Spectral ships a testing module with an invoke helper that runs your action’s perform function locally without deploying to Prismatic.Create a test file alongside your component source:
index.test.ts
import { testing } from "@prismatic-io/spectral";
import { describe, it, expect } from "vitest";
import myComponent from "./index";
import { myApiConnection } from "./connection";

const { invoke, createConnection } = testing;

describe("getRecord action", () => {
  it("returns a record for the given ID", async () => {
    // Build a test connection value from the connection definition
    const testConnection = createConnection(myApiConnection, {
      endpoint: "https://api.example.com/v1",
      apiKey: "test-key-123",
    });

    // Invoke the action directly, bypassing the Prismatic runtime
    const { result } = await invoke(myComponent.actions.getRecord, {
      connection: testConnection,
      recordId: "rec_01HV2K",
    });

    expect(result.data).toMatchObject({ id: "rec_01HV2K" });
  });
});
Run your tests with your preferred test runner:
npx vitest run
testing.invoke accepts the action definition directly, an object of input parameters, and an optional partial ActionContext. It returns { result, loggerMock } so you can also assert on log output.
6

Publish your component

Once your tests pass, compile your TypeScript and publish the component to Prismatic using the Prismatic CLI (prism).
# Compile TypeScript
npx tsc

# Publish via the Prismatic CLI
prism components:publish
After publishing, the component appears in your organization’s component library and can be used in the integration builder.
Run component-manifest (included in @prismatic-io/spectral) to generate a type-safe manifest file before publishing. This enables type checking when referencing your component from code-native integrations.

Next steps

Custom connectors

Learn about actions, triggers, data sources, and connections in depth.

Connections

Add OAuth 2.0 and on-prem connection support to your component.

Testing

Unit test actions, triggers, and data sources with the Spectral testing module.

Code-native integrations

Build full integrations in TypeScript using flows and config wizards.