Build an Integration
Building an integration involves two key components: an Integration Manifest and a Handler Endpoint.
1. Create your integration manifest
The IntegrationManifest
is a JSON file that tells Pixelstack everything it needs to know about your integration. You will provide this manifest when adding your integration in your Pixelstack settings.
{ "name": "My Awesome Integration", "description": "A brief description of what this integration does.", "iconUrl": "https://example.com/icon.png", "handlerUrl": "https://api.example.com/pixelstack-handler", "supportedEvents": ["loadImages", "nodeCalled"], "settings": [ { "id": "apiKey", "name": "API Key", "description": "Your API Key for My Awesome Service.", "type": "string", "isSecret": true } ], "imageLoader": { "formInputs": [ { "id": "query", "name": "Search term", "type": "string", "required": true } ], "formSubmitLabel": "Search" }, "nodeTypes": [ { "id": "my-node", "name": "My Custom Node", "description": "This node does something awesome.", "inputs": [{ "id": "input-data", "name": "Input Data", "type": "string" }], "outputs": [{ "id": "output-data", "name": "Output Data", "type": "string" }] } ]}
Key Manifest Fields:
name
(string
): The display name of your integration.handlerUrl
(string
): The URL of your handler endpoint. Pixelstack will send POST requests here.supportedEvents
(IntegrationEvent[]
): Events your integration wants to listen to (loadImages
and/ornodeCalled
).settings
(IntegrationSetting[]
): Configuration settings users will provide, like API keys.imageLoader
(IntegrationImageLoader
): Defines the UI for your image loader.nodeTypes
(IntegrationNodeType[]
): An array of custom workflow nodes your integration provides.
2. Build a handler endpoint
Your handler is a web service that receives POST
requests from Pixelstack. The request body is a JSON payload containing event details. Your service needs to handle different event types and return the expected response.
To get type definitions for the integration events, you’ll need to install the @pixelstack/integration
package:
npm install @pixelstack/integration
pnpm add @pixelstack/integration
Here’s a basic handler using Hono, a popular web framework that can run on any JavaScript runtime:
import { Hono } from 'hono';import type { IntegrationEventData } from '@pixelstack/integration';
const app = new Hono();
app.post('/', async (c) => { const body = await c.req.json<IntegrationEventData>();
if (body.eventType === 'loadImages') { // Handle image loading. See below for details. }
if (body.eventType === 'nodeCalled') { // Handle a workflow node invocation. See below for details. }
return c.json({ success: true });});
export default app;
Building an image loader
To create an image loader:
- In your manifest, include
"loadImages"
insupportedEvents
. - Define the
imageLoader
object with theformInputs
your integration needs. - Implement the logic for the
loadImages
event in your handler.
When a user uses your image loader, your handler will receive a request with eventType: 'loadImages'
.
Example loadImages
request body:
{ "teamId": "team_123", "eventType": "loadImages", "settingValues": [{ "id": "apiKey", "value": "secret-user-api-key" }], "eventData": { "query": "landscapes" }}
Your handler should process this request, fetch images, and return an array of images.
Example loadImages
response body:
{ "images": [ { "imageUrl": "https://images.example.com/1.jpg", "thumbnailUrl": "https://images.example.com/1-thumb.jpg", "title": "A Beautiful Landscape", "subtitle": "By Jane Doe" } ]}
This response should conform to the IntegrationImageLoaderResponse
type.
Building workflow nodes
To add custom workflow nodes:
- In your manifest, include
"nodeCalled"
insupportedEvents
. - Define your custom nodes in the
nodeTypes
array. - Implement the logic for the
nodeCalled
event in your handler.
When a workflow containing your node is run, your handler will receive an event with eventType: 'nodeCalled'
.
Example nodeCalled
request body:
{ "teamId": "team_123", "eventType": "nodeCalled", "settingValues": [{ "id": "apiKey", "value": "secret-user-api-key" }], "eventData": { "nodeTypeId": "my-node", "inputValues": [{ "id": "input-data", "value": "Some data" }], "controlValues": [] }}
Your handler must perform the node’s logic and return the values for its outputs
.
Example nodeCalled
response body:
{ "outputs": [{ "id": "output-data", "value": "The result" }]}
We are excited to see what you will build! If you have any questions, please reach out to contact@pixelstack.io.