FlowDrop Orchestration Connector¶
Exposes FlowDrop workflows to external automation platforms as callable services via Drupal's Orchestration module.
Installation¶
flowdrop_orchestration_connector requires the Drupal Orchestration module as an additional dependency. This is a separate contrib module not bundled with FlowDrop.
# 1. Install the Orchestration module via Composer
composer require drupal/orchestration
# 2. Enable both modules
drush en orchestration flowdrop_orchestration_connector
# 3. Clear cache
drush cr
The drupal/orchestration package is available on Drupal.org. Verify it is compatible with your Drupal version before installing.
Warning
Running drush en flowdrop_orchestration_connector without first installing drupal/orchestration via Composer will fail with a module-not-found error. Always run composer require drupal/orchestration first.
No service account can be provisioned on orchestration 1.0.0
Orchestration's routes require a permission named use orchestration, but its permissions.yml defines use orchestration connect. The required permission is therefore declared by nothing, and only user 1 — who bypasses permission checks — can reach the API. Granting the permission the module does ship has no effect.
This affects all eight routes and is unfixed at 1.0.x HEAD. Until it is resolved upstream there is no way to authenticate an integration as anything other than user 1.
Overview¶
The flowdrop_orchestration_connector module makes FlowDrop workflows callable by external automation platforms such as Activepieces, n8n or Zapier. It adds an Orchestration Trigger node; any workflow containing one is published through the Orchestration services API, where an external platform can discover it, invoke it with a payload, and collect the result.
This module is an adapter. It translates between the Orchestration API and FlowDrop's trigger system and does nothing else — it holds no business logic, validates nothing, and dispatches no outbound HTTP. A narrow surface that always works is worth more here than a wide one that sometimes does. What it deliberately omits is listed under What this module does not do.
This module covers the inbound direction only: an external platform starting a FlowDrop run. For the opposite direction — a running workflow calling an external system and pausing until it answers — see the Call and Wait node in flowdrop_interrupt.
Every rule on this page is pinned in the specification registry under RT-OCX.
Dependencies¶
- flowdrop
- flowdrop_orchestration (orchestrator plugin system)
- flowdrop_pipeline (pipeline entities read by polling)
- flowdrop_workflow (workflow definitions)
- flowdrop_trigger (trigger system)
- flowdrop_runtime (workflow execution)
drupal:orchestration(Drupal Orchestration module)
Usage¶
For workflow authors¶
- Create a workflow.
- Add an Orchestration Trigger node as its entry point.
- Configure the expected payload schema and the orchestrator settings.
- The workflow is now discoverable by external platforms.
The payload arrives at the trigger node's data.payload output.
Service discovery¶
GET /orchestration/services
Authorization: Basic <credentials>
Returns every enabled workflow with an enabled orchestration trigger, along with its declared configuration schema.
Executing a workflow¶
POST /orchestration/service/execute
Authorization: Basic <credentials>
Content-Type: application/json
{
"id": "flowdrop::my_workflow__node_abc123",
"config": {
"payload": { "title": "…", "body": "…" }
}
}
The response is immediate, and its status is one of three values:
status |
Meaning |
|---|---|
completed |
Final. results holds the workflow output. |
interrupted |
The run paused — for a human decision, or an external call. results holds what completed so far; metadata.interrupt.interrupt.id identifies the interrupt. |
queued |
Accepted for asynchronous execution; nothing has run yet. |
For the latter two, keep execution_id and poll for the result.
execution_id is the correlation key
It is the pipeline entity id on every orchestrator, and it is the same identifier the poll response returns as pipeline_id. One field correlates a call to its eventual result, whichever engine ran it.
Polling for results¶
POST /orchestration/poll
Authorization: Basic <credentials>
Content-Type: application/json
{
"name": "flowdrop_pipelines",
"timestamp": 1234567890
}
[
{
"timestamp": 1234567890,
"data": {
"pipeline_id": "123",
"workflow_id": "my_workflow",
"trigger_config_id": "my_workflow__node_abc",
"status": "completed",
"started": 1234567880,
"completed": 1234567890,
"input_data": { },
"output_data": { },
"error_message": null
}
}
]
Three guarantees govern what a poll returns:
- Every terminal run is reported — completed, failed and cancelled — so a caller always reaches an end state rather than waiting forever on a run that quietly stopped. A run that is still executing or paused appears once it finishes.
- Only externally invoked runs are exposed. Scoping is on a positive
source: orchestrationmarker, never on the presence oftrigger_config_id— cron, entity and form triggers set that too, and scoping on it leaked unrelated internal runs, including their full output, to external callers. - One poll returns at most one page (50 runs). Poll again with the highest
timestamp/idyou received to collect the rest; a backlog drains over consecutive polls and nothing is skipped or repeated on the way.
The response is a page, not the whole backlog
The poll is incremental by design — you hand back the last cursor you saw — so the handlers never materialise more than a page of pipelines at a time, whatever the site's history. Two details make paging safe to rely on: a set of runs that finished in the same second is never split across a page boundary (a timestamp cursor could not express the split, so the tail would be lost), and a page that contains only internal runs is never answered as an empty result — the handler keeps reading until it has something for you or the backlog is genuinely empty. An empty response therefore means nothing new, always.
Configuration¶
Trigger conditions¶
Event-type-specific settings live under conditions.custom, which is the trigger system's declared extension point. Both keys are declarative metadata published to the calling platform — neither is enforced.
| Key | Purpose |
|---|---|
payload_schema |
JSON Schema describing the expected input, so the platform can render typed fields. |
required_fields |
Surfaced in discovery so the platform can mark fields required in its own form. |
Orchestrator settings¶
The shared trigger orchestrator settings apply: type, pipeline mode (new / reuse / singleton), retry policy and timeout.
The in-memory orchestrator is not usable here
flowdrop_runtime:synchronous persists no pipeline entity, so its runs could never be polled. A trigger configured this way is logged and run on synchronous_pipeline instead.
What this module does not do¶
| Not supported | Who handles it instead |
|---|---|
| Webhook / push delivery | The platform polls. Delivery semantics — timeouts, retry, dedup — are not an adapter's job, and polling reads persisted pipeline state, so it cannot stall a caller and survives changes to the execution engine. |
| Validating the payload | Nothing is enforced. payload_schema and required_fields are declarative; a payload violating them is passed through unmodified for the workflow to deal with. |
| Nested payload schemas | Only top-level properties become typed fields; deeper structure rides inside payload as an object. |
The in-memory flowdrop_runtime:synchronous orchestrator |
See above — a trigger configured this way falls back to synchronous_pipeline. |
Developer API¶
Services¶
| Service ID | Class | Description |
|---|---|---|
flowdrop_orchestration_connector.services_provider |
ServicesProvider |
Publishes FlowDrop workflows as callable orchestration services |
flowdrop_orchestration_connector.invoke_trigger_service |
InvokeTriggerService |
Bridges Orchestration API calls to FlowDrop pipeline/job execution |
flowdrop_orchestration_connector.poll_event_subscriber |
PollEventSubscriber |
Answers /orchestration/poll from persisted pipeline entities |
Architecture¶
External Platform (Activepieces, n8n, …)
│ POST /orchestration/service/execute
▼
Orchestration Module API
▼
ServicesProvider::execute()
▼
InvokeTriggerService::invoke()
│ builds the request via flowdrop_trigger's
│ OrchestrationRequestBuilder — the same shared
│ builder the cron, entity and form triggers use
▼
FlowDrop pipeline / job system
Results flow back the other way, on the platform's schedule:
External Platform
│ POST /orchestration/poll
▼
PollEventSubscriber → reads persisted pipeline entities
The connector subscribes to no runtime execution events. A run with no pipeline entity is invisible externally.
Troubleshooting¶
Workflows not appearing in the service list
- Ensure the workflow has an Orchestration Trigger node.
- Check that both the trigger and the workflow are enabled.
Authentication failures (403 for every non-admin user)
- Ensure
basic_authis enabled. - Otherwise this is almost certainly the upstream permission bug described under Installation. Confirm by repeating the request as user 1.
No results coming back
- Results are pulled, not pushed. Poll
/orchestration/poll; this module registers no webhooks. - Only runs backed by a pipeline entity are visible — the in-memory
synchronousorchestrator persists nothing. - Only terminal runs are returned. A paused run appears once it resolves or is cancelled.
References¶
- flowdrop_interrupt — the outbound direction: calling an external system and waiting for a callback
- flowdrop_trigger — trigger system that this module extends
- flowdrop_runtime — executes the triggered workflows
- flowdrop_orchestration — orchestrator plugin system
- Specification registry, RT-OCX — the pinned rules behind this page