Package-name note: These approved examples use
cliodot-flosync. Other supplied SDK material usescliodotor@cliodot/flosync; confirm the current package before copying an import.
This guide explains how to build connectors in all supported ways: JSON, ConnectorBuilder (SDK chaining), custom execute (local), and Postman conversion. Each method includes building, registering/pushing, and using the connector.
Prerequisites#
- FlowSync API access with
connectors.writepermission - API credentials:
apiKeyandapiSecret(from user registration) - JWT token obtained via
POST /api-core/cliodot/user/login-with-api-key
Overview#
| Method | Build | Register/Push | Use |
|---|---|---|---|
| JSON | JSON file | Push to server (cURL/SDK) | Workflows, client.connectors.execute() |
| ConnectorBuilder | SDK chaining | Push to server | Workflows, client.connectors.execute() |
| Custom Execute | Define with execute function |
flosync.registerConnector() (local only) |
Workflows (local runs) |
| Postman | Convert collection | Push to server | Workflows, client.connectors.execute() |
API Base Path#
https://your-api-domain.com/api-core/cliodot/connectors
Method 1: JSON Definition#
Create a JSON file matching the connector schema. Required: name, type, auth. For REST: base_url, endpoints.
Build (connectors/my-api.json):
{
"_id": "my-api",
"name": "My API",
"slug": "my-api",
"description": "Custom API connector",
"type": "REST",
"base_url": "https://api.example.com/v1",
"auth": {
"type": "bearer",
"token": "",
"header_name": "Authorization",
"prefix": "Bearer "
},
"endpoints": [
{
"name": "Get Item",
"method": "GET",
"path": "/items/{{ pathParams.id }}",
"pathParams": { "id": "string" }
},
{
"name": "Create Item",
"method": "POST",
"path": "/items",
"headers": { "Content-Type": "application/json" },
"body_schema": { "name": "string", "value": "number" }
}
],
"meta": {
"category": "Custom",
"logo": "https://via.placeholder.com/64",
"status": "active",
"visibility_settings": { "visibility": "private", "public_access": "none" },
"last_updated": "2025-01-27T00:00:00Z"
}
}
Push (cURL):
curl -X POST https://your-api-domain.com/api-core/cliodot/connectors \
-H "Authorization: Bearer YOUR_JWT" \
-H "Content-Type: application/json" \
-d @connectors/my-api.json
Register (SDK):
const { FlosyncClient } = require('cliodot-flosync');
const connectorDef = require('./connectors/my-api.json');
const client = new FlosyncClient({ baseUrl, apiKey, apiSecret });
await client.authenticate();
await client.connectors.push(connectorDef);
await client.connectors.install('my-api', { auth: { token: process.env.MY_API_TOKEN } });
Use (workflow):
s.connector('my-api', 'Get Item', { pathParams: { id: '123' } });
s.connector('my-api', 'Create Item', { body: { name: 'Widget', value: 99 } });
Use (direct execute):
const result = await client.connectors.execute('my-api', 'Get Item', { pathParams: { id: '123' } });
Method 2: ConnectorBuilder (SDK Chaining)#
Use the SDK connector() builder to define REST connectors programmatically.
Build:
const { connector } = require('cliodot-flosync');
const myConnector = connector('my-api', 'My API')
.description('Custom API connector')
.baseUrl('https://api.example.com/v1')
.bearer('')
.get('Get Item', '/items/{{ pathParams.id }}', {
pathParams: { id: 'string' },
response_mapping: { id: 'id', name: 'name' }
})
.post('Create Item', '/items', {
headers: { 'Content-Type': 'application/json' },
body_schema: { name: 'string', value: 'number' }
})
.meta({
category: 'Custom',
logo: 'https://via.placeholder.com/64',
status: 'active',
visibility_settings: { visibility: 'private', public_access: 'none' }
})
.build();
Push and register:
const { FlosyncClient, connector } = require('cliodot-flosync');
const client = new FlosyncClient({ baseUrl, apiKey, apiSecret });
await client.authenticate();
const myConnector = connector('my-api', 'My API')
.baseUrl('https://api.example.com/v1')
.bearer('')
.get('Get Item', '/items/{{ pathParams.id }}', { pathParams: { id: 'string' } })
.post('Create Item', '/items', { body_schema: { name: 'string', value: 'number' } })
.meta({ category: 'Custom', logo: '...', status: 'active', visibility_settings: { visibility: 'private', public_access: 'none' } })
.build();
await client.connectors.push(myConnector);
await client.connectors.install('my-api', { auth: { token: process.env.MY_API_TOKEN } });
Use (workflow):
s.connector('my-api', 'Get Item', { pathParams: { id: '123' } });
s.connector('my-api', 'Create Item', { body: { name: 'Widget', value: 99 } });
ConnectorBuilder methods:
| Method | Description |
|---|---|
baseUrl(url) |
Base API URL |
bearer(token) |
Bearer token auth |
apiKey(key, keyName?) |
API key auth |
botToken(token, prefix?) |
Bot token (e.g. Discord Bot prefix) |
customFlow(flow) |
Custom auth with token exchange flow (JWT bearer, etc.) |
authConfig(auth) |
Custom auth object |
get(name, path, opts?) |
GET endpoint |
post(name, path, opts?) |
POST endpoint |
put(name, path, opts?) |
PUT endpoint |
patch(name, path, opts?) |
PATCH endpoint |
delete(name, path, opts?) |
DELETE endpoint |
endpoint(name, method, path, opts?) |
Generic endpoint |
meta(m) |
Metadata (category, logo, status, visibility_settings). Adds last_updated automatically. |
build() |
Returns connector object |
Endpoint options: params, pathParams, body_schema, headers, response_mapping, description, timeout_ms, sample_responses.
Method 3: Custom Execute (Local Only)#
For full control over logic, define a connector with an execute function. These run locally only (not pushed to the server). Use flosync.registerConnector() to register them.
Build (define connector with execute):
const { flosync, variable: v } = require('cliodot-flosync');
const myCustomConnector = {
_id: 'my.custom',
type: 'system',
name: 'My Custom Logic',
meta: { category: 'custom' },
auth: { type: 'none' },
actions: [
{ id: 'validate', name: 'Validate' },
{ id: 'transform', name: 'Transform' },
],
execute: async (action, options, context) => {
const body = options.body || options;
if (action === 'validate') {
const valid = body.email && body.email.includes('@');
return { valid, email: body.email };
}
if (action === 'transform') {
return {
...body,
normalized: body.name?.trim().toLowerCase(),
timestamp: new Date().toISOString(),
};
}
throw new Error('Unknown action: ' + action);
},
};
Register:
flosync.registerConnector('my.custom', myCustomConnector);
Or with config (for connector-specific settings):
flosync.configure({
connectors: {
'my.custom': { /* optional config */ },
},
});
flosync.registerConnector('my.custom', myCustomConnector);
Use (workflow):
s.connector('my.custom', 'validate', { body: { email: v.body('email') } });
s.connector('my.custom', 'transform', { body: v.stepResult('save') });
Use (direct run):
const result = await flosync.runConnector('my.custom', 'validate', {
body: { email: 'user@example.com' },
});
Execute signature:
execute(
action: string,
options: { body?: any; params?: any; pathParams?: any; headers?: any },
context: { trigger?: any; stepResults?: any; vars?: any; headers?: any; connectorConfig?: any; env?: any }
): Promise<unknown>
Return format: Return any object. The engine uses it as the step result. For { raw, mapped }, the engine uses mapped ?? raw.
Method 4: Postman Conversion#
Convert an existing Postman collection to a connector:
curl -X POST https://your-api-domain.com/api-core/cliodot/connectors/convert/postman \
-H "Authorization: Bearer YOUR_JWT" \
-F "collection=@/path/to/collection.postman_collection.json"
Returns a connector object. Push it via POST /connectors or client.connectors.push(). See /docs/connectors/build#method-4-postman-conversion for details.