JustFlows

Elsa Workflows · Developers

Build on Elsa Workflows

Start Elsa workflows from your own plugin, react when they start, or script the Elsa admin with a staff session. The Elsa credentials never leave the plugin.

What you can build

Plugins that start workflows

Call triggerElsaEvent, dispatchElsaWorkflow, or executeElsaWorkflow for the current site. The credentials stay inside Elsa Workflows.

Reactions to starts

Listen for justflows.elsa-workflows.* hooks in a plugin, or subscribe a webhook to the same events.

Staff tools

Script the Elsa admin with a staff session: list workflows and executions, start a workflow, or set comment workflows.

Workflows in Studio

Start an Elsa workflow with an Event activity named after a Justflows event, such as justflows.forms.submitted.

Base URL

text
https://your-site.example/api/elsa-workflows

The older /ext/justflows.elsa-workflows address also works. Paths in this reference are relative to the base URL.

Who can call a route

Every route needs a staff session: the jf_session cookie, plus the capability listed on the route. Writes send the CSRF token as x-csrf-token. Each route also checks that the session belongs to the current site and that Elsa is turned on for that website. Routes that change the shared connection or a workspace server only answer on the installation’s main site.

Elsa Workflows has no API keys and no AI agent tools of its own. Other plugins use the SDK instead of these routes.

A staff script in the admin's browser session
const ELSA = "https://your-site.example/api/elsa-workflows";
const csrf = document.cookie.match(/(?:^|; )jf_csrf=([^;]+)/)?.[1];

// Faulted runs on this site's tenant.
const { items } = await (await fetch(`${ELSA}/instances?status=faulted`, { credentials: "include" })).json();

// Start a published workflow again with the same correlation id.
await fetch(`${ELSA}/workflows/${items[0].definitionId}/start`, {
  method: "POST",
  credentials: "include",
  headers: { "Content-Type": "application/json", "x-csrf-token": csrf },
  body: JSON.stringify({ confirm: true, correlationId: items[0].correlationId, input: {} }),
});

Errors

Failures use one envelope with a stable code and a fixed message. Messages never include a response from Elsa, a URL, or a credential.

json
{ "error": { "code": "unconfigured", "message": "No Elsa connection is saved on this site." } }
CodeStatusMeaning
unauthorized401No session.
forbidden403The session lacks the capability, belongs to another site, or the route is for the main site only.
feature_disabled403Elsa is turned off for this website.
invalid400The input is not valid, such as an id, a page number, or workflow input over 16 KB.
ssrf400The address is not allowed: not HTTPS on port 443, or a private or metadata host.
unconfigured409This site has no Elsa connection.
quota429The site reached its monthly workflow start limit.
unsupported404The Elsa server does not offer that operation.
rate-limit503Elsa asked the connector to slow down.
auth, forbidden, tenant, timeout, tls, network, http, invalid502Elsa refused the call, could not be reached, or answered with something the connector does not understand.

Rate limits

RoutesLimit
Reads60 a minute
Starting a workflow20 a minute
Saving or removing a connection, workspace server, or comment workflow20 a minute
Testing a connection, and refreshing the overview10 a minute

What reaches Elsa

Calls go to the Elsa 3 API under /elsa/api with the site’s tenant in X-Tenant-Id. Start requests send { versionOptions: "Published", input, correlationId }. Responses are allow-listed: workflow input, output, variables, and state are dropped before anything reaches the browser.