Studio

Integration Studio

Connect third-party APIs, manage webhooks, build event pipelines, and transform data between systems.

Overview

Integration Studio provides the glue layer between FlowOS and the rest of your toolchain. It exposes connectors (configured API connections), a webhook manager for outbound and inbound events, an event bus for platform-wide pub/sub, a REST API builder to expose custom endpoints, a data transformer, and a circuit-breaker dashboard for connection health monitoring.

Connectors

A connector is a configured connection to a third-party service. Once a connector is added and authenticated, it can be used in workflow action nodes, App Studio data sources, and the REST API builder.

GET
/api/flows/connectors

List all configured connectors

POST
/api/flows/connectors

Add a new connector

GET
/api/flows/connectors/:id

Get connector details (secrets masked)

PATCH
/api/flows/connectors/:id

Update connector config or credentials

DELETE
/api/flows/connectors/:id

Remove a connector

POST
/api/flows/connectors/:id/test

Health-check the connector (updates its healthCheck status)

GET
/api/flows/connectors/:id/runtime-schema

List the connector's configured endpoints (name, method, path, schemas)

Create a connector

bash
POST /api/flows/connectors
{
  "connectorName": "Jira Production",
  "connectorType": "rest_api",
  "provider": "Atlassian Jira",
  "configuration": {
    "baseUrl": "https://acme.atlassian.net/rest/api/3",
    "authType": "basic",
    "authConfig": {
      "username": "bot@acme.com",
      "password": "{{secrets.JIRA_API_TOKEN}}"
    }
  },
  "endpoints": [
    { "name": "Create issue", "method": "POST", "path": "/issue" }
  ]
}

// Response
{
  "success": true,
  "data": {
    "_id": "con_01HZ...",
    "connectorName": "Jira Production",
    "connectorType": "rest_api",
    "provider": "Atlassian Jira",
    "configuration": { "baseUrl": "...", "authType": "basic", "authConfig": { "username": "bot@acme.com", "password": "***" } },
    "isActive": true,
    "healthCheck": { "enabled": false, "status": "unknown" }
  }
}

Built-in connector presets

GET /api/flows/connectors/presets returns ready-made starting configs (base URL, auth type, OAuth endpoints, sample endpoints) for common providers:

FieldTypeRequiredDefaultDescription
slackpresetoptionalSlack — post messages, upload files (bearer token)
jirapresetoptionalAtlassian Jira — create/transition issues (basic auth)
teamspresetoptionalMicrosoft Teams — send channel messages (OAuth2)
servicenowpresetoptionalServiceNow — create incidents, update CMDB CIs (basic auth)
githubpresetoptionalGitHub — create issues and issue comments (bearer token)
openaipresetoptionalOpenAI — create responses and embeddings (bearer token)
postgrespresetoptionalPostgreSQL — execute query, bulk upsert (basic auth)
twiliopresetoptionalTwilio — send SMS, create calls (basic auth)
whatsapp-twiliopresetoptionalWhatsApp via Twilio — send messages/media (basic auth)
pagerdutypresetoptionalPagerDuty — create incidents, list services/on-calls (bearer token)
datadogpresetoptionalDatadog — query metrics, create events, list monitors (api_key)
salesforcepresetoptionalSalesforce — create/update/query records (OAuth2)
azure-devopspresetoptionalAzure DevOps — work items and builds (OAuth2)
zendeskpresetoptionalZendesk — tickets and users (api_key)
generic-restpresetoptionalBlank REST scaffold for bespoke internal or partner systems

Test one connector endpoint directly

bash
POST /api/flows/connectors/:id/test-endpoint
{
  "endpointName": "Create issue",
  "body": {
    "fields": { "project": { "key": "OPS" }, "summary": "Server disk at 95%", "issuetype": { "name": "Bug" } }
  }
}

// Executes one real request through the connector's configured auth/baseUrl —
// the same call a workflow's Connector Action node would make.

Webhooks

Outbound webhooks let FlowOS push event payloads to URLs you control when platform events occur. Inbound webhooks generate URLs that external systems can POST to, triggering workflows.

GET
/api/webhooks

List webhooks (filter by ?direction=inbound|outbound)

POST
/api/webhooks

Create a webhook

GET
/api/webhooks/:id

Get webhook details

PATCH
/api/webhooks/:id

Update webhook name, url, direction, secret, or active state

DELETE
/api/webhooks/:id

Delete a webhook

GET
/api/webhooks/:id/logs

List delivery/receipt log entries for a webhook

Create an outbound webhook

bash
POST /api/webhooks
{
  "name": "Incident alerts to Slack bridge",
  "direction": "outbound",
  "url": "https://hooks.example.com/flowos-incidents",
  "secret": "wh_sec_..."          // used to sign outbound deliveries (X-FlowOS-Signature header)
}

Verifying webhook signatures

typescript
import crypto from 'crypto'

function verifyFlowOSWebhook(
  payload: string,      // raw request body as string
  signature: string,    // X-FlowOS-Signature header value
  secret: string
): boolean {
  const expected = crypto
    .createHmac('sha256', secret)
    .update(payload)
    .digest('hex')
  return crypto.timingSafeEqual(
    Buffer.from(signature),
    Buffer.from('sha256=' + expected)
  )
}

// Express handler
app.post('/webhook', express.raw({ type: 'application/json' }), (req, res) => {
  const sig = req.headers['x-flowos-signature'] as string
  if (!verifyFlowOSWebhook(req.body.toString(), sig, process.env.WH_SECRET!)) {
    return res.status(401).send('Invalid signature')
  }
  const event = JSON.parse(req.body.toString())
  // process event...
  res.status(200).send('OK')
})

Event Bus

The FlowOS event bus is a platform-wide pub/sub system. Producers publish events to named topics; consumers subscribe and process them asynchronously. Topics persist events for up to 7 days.

GET
/api/events/types

List registered event types

POST
/api/events/types

Register a new event type

POST
/api/events/emit

Emit (publish) an event

GET
/api/events/log

Query the event log (filter by eventName, source, dispatchStatus)

bash
// Publish an event
POST /api/events/emit
{
  "eventName": "infrastructure.disk.threshold_exceeded",
  "payload": {
    "host": "prod-web-01",
    "mount": "/dev/sda1",
    "usagePercent": 95,
    "freeGb": 12
  }
}

// Response
{ "eventId": "evt_01HZ...", "eventName": "infrastructure.disk.threshold_exceeded", "emittedAt": "2026-06-01T10:00:00Z" }

Circuit Breaker

Every connector is protected by an automatic circuit breaker. After a configurable number of consecutive failures, the connector transitions to open state and requests are rejected immediately without waiting for a timeout. After a cooldown, the circuit moves to half-open to probe recovery.

bash
GET /api/v1/connectors/:id/circuit-breaker

// Response
{
  "data": {
    "connectorId": "con_01HZ...",
    "state": "closed",        // "closed" (normal) | "open" (tripped) | "half-open"
    "failureCount": 0,
    "failureThreshold": 5,
    "successCount": 142,
    "lastFailureAt": null,
    "nextRetryAt": null
  }
}
bash
// Manually reset a tripped circuit
POST /api/v1/connectors/:id/circuit-breaker/reset

Data Transformer

The transformer converts data between shapes using JSONata expressions. Use it in workflow Transform nodes or call it directly via API to test expressions.

bash
POST /api/v1/transformer/evaluate
{
  "expression": "{ 'summary': title, 'assignee': assignedTo.email, 'tags': labels.name[] }",
  "input": {
    "title": "API latency spike",
    "assignedTo": { "name": "Alice", "email": "alice@acme.com" },
    "labels": [{ "name": "infra" }, { "name": "p1" }]
  }
}

// Response
{
  "data": {
    "output": {
      "summary": "API latency spike",
      "assignee": "alice@acme.com",
      "tags": ["infra", "p1"]
    },
    "durationMs": 2
  }
}
FlowOS uses JSONata for data transformation — a powerful expression language for JSON. See the JSONata documentation at jsonata.org for the full syntax reference.