Corteksa
GuidesAutomation

Frontend Integration

Automation — Frontend Integration

For web (React/Next.js) and mobile developers building the workflow builder. After this page you can list, compose, save, and activate a workflow without asking a backend engineer.

Every endpoint authenticates with the admin login JWT (not an API key):

Authorization: Bearer <jwt>

Required permission

Workflow endpoints are gated by the admin permission system (see Authorization):

To…You need the route
List / read / preview / stats / templatesworkflow.read
Create a workflow / use a templateworkflow.create
Update, activate/pause, retry, approve/rejectworkflow.update
Deleteworkflow.delete

The /workflow/meta/* metadata endpoints require only a valid admin login (no workflow.* route) so the builder can populate pickers before the user has any create rights.

The flow

1. Metadata     GET /workflow/meta/triggers, /actions, /operators
2. Object model GET /workflow/meta/objects/:objectSlug/fields   → build field pickers
3. Variables    GET /workflow/meta/variables/:triggerType       → {{token}} palette
4. Save draft   POST /workflow                                   → is_active:false
5. Validate     POST /workflow/meta/validate-session-link        → can it activate?
6. Activate     PUT  /workflow/:slug/toggle
7. Monitor      GET  /workflow/:slug/executions  ·  WS /workflow/events

How a config is shaped (slug-first)

A workflow is trigger_type + trigger_config, an optional filter_config, action_type + action_config, and an optional steps[] array. All references are slugsobject_slug, session_slug, field_slug, status_field_slug — never numeric ids. Example create body:

{
  "name": "Welcome new leads on WhatsApp",
  "trigger_type": "record_created",
  "trigger_config": { "object_slug": "leads" },
  "filter_config": {
    "condition_groups": [
      { "conditions": [
        { "field_slug": "source", "operator": "equals", "value": "website" }
      ] }
    ]
  },
  "action_type": "send_message",
  "action_config": {
    "session_slug": "sales-wa",
    "phone_field_slug": "phone",
    "message_template": "Hi {{name}} 👋 thanks for reaching out!",
    "link_to_record": true
  }
}

filter_config is OR between condition_groups, AND within each group's conditions. Operators per field type come from GET /workflow/meta/operators.

Activate = validate first

A new workflow is created paused. PUT /workflow/:slug/toggle flips is_active. Activation runs a gate: a message-triggered workflow that reads or writes a CRM record needs its messaging session linked to an object, otherwise it returns 400 with code: "SESSION_NOT_LINKED_TO_OBJECT" and unlinkedSessionSlugs[]. Call POST /workflow/meta/validate-session-link with the in-progress draft to show that banner before the user hits Activate (same gate, no persistence). Deactivating is always allowed.

Media attachments

For a send_message action in mode: "media", upload files first via POST /workflow/attachments/upload (multipart, field files). It returns { url, storage_key, media_type, ... } — stash url on action_config.attachments[].

Execution progress (WebSocket)

Connect Socket.IO to the /workflow/events namespace, passing the JWT in the handshake. You join your admin:{id} and tenant:{db} rooms and receive live run events:

import { io } from 'socket.io-client';
const socket = io(`${WS_HOST}/workflow/events`, {
  auth: { token: jwt },
  query: { tenantDb },   // or send x-tenant-database header
});
socket.on('connected', () => {});
socket.on('workflow:execution.completed', (e) => bump(e.workflowId));
socket.on('workflow:execution.failed', (e) => showError(e));
socket.on('workflow:execution.skipped', (e) => {});
socket.on('workflow:stats.updated', (e) => refreshStats(e.workflowId));

Full event list: Events.

UI concerns

  • Actions are async — an execution is queued, not run inline. Show run status from GET /workflow/:slug/executions (or the WS event), not the save response.
  • Dry-runPOST /workflow/:slug/test runs the config against sample data with no side effects; GET /workflow/:slug/preview renders a human summary and GET /workflow/:slug/impact estimates how often it would have fired.
  • Errors — see Troubleshooting for 400 / 403 causes.

Next

On this page