Skip to content

Flow Scheduler API

The Flow Scheduler API (/fss/v1) lets scripts, CI pipelines and orchestrators run Tableau Prep flows, follow and cancel runs, and manage tasks, chains and schedules with an API client token.

Base URL and headers

Every call goes to the MetaMiner Server (MMS) listener, not to the Flow Scheduler Service (FSS) itself:

https://<mms-host>:<port>/fss/v1/...

The default MMS port is 49714. Use http:// only when SSL is not enabled on MMS. In a high-availability pair, call the load balancer address.

Header Value
Authorization Bearer <token>, the token of an API client (see Manage API Clients)
Content-Type application/json on every call with a body

Requests and responses are JSON. A request body larger than 64 KiB is refused with 413 before the token is checked. Run, task, chain, schedule, parameter and notification calls need the Flow Scheduler switched on and running; they fail until it is.

Who may call

Call Allowed API clients
GET /fss/v1/info Any API client
Runs, tasks, chains, parameters, notifications Any API client, for the environments and sites it is limited to
Change or run a schedule An admin client without site limits (403 FORBIDDEN otherwise); reading schedules is open to any client
Cancel a run An admin client: any run of its environments and sites. Any other client: a run it started, or a run of a task or chain it owns
Run a flow, task or chain as a non-admin client The client's bound Tableau user (tableauUsername) must be allowed to run every flow involved (403 RUN_FORBIDDEN otherwise)

The API never takes the caller's identity from the request. createdBy, updatedBy and triggeredBy are always the API client's name, and ownerUsername is ignored for a non-admin client. A Tableau permission change can take up to a minute to reach the run-permission check.

API client management and the audit are on Clients and Audit API.

Addressing

Item How you name it
Environment (env) The MetaMiner environment id, or its name (not case-sensitive). The environment must be enabled for the Flow Scheduler (see Allowed Environments). A body field on run calls; a query parameter (or body field) on task, chain and schedule calls.
Site (site) The Tableau site LUID. Required to run a flow and to create a task or chain.
Flow The Tableau flow LUID, as Tableau REST returns it.
Output steps The output step's numeric id, its name, or the output-step LUID that Tableau REST returns.
Runs, tasks, chains, schedules Flow Scheduler numeric ids, not Tableau LUIDs.

A missing env answers 400 BAD_REQUEST; an unknown one 404 ENV_NOT_FOUND. A client limited to sites must name its site (site=) when it lists tasks, chains or runs (400 SITE_REQUIRED). A call that names a task, chain or step by id is checked against the site that object is in (403 SITE_FORBIDDEN), and paths not tied to one site answer 403 SITE_SCOPE to such a client.

Service info

GET /fss/v1/info - any API client.

Returns apiVersion ("1"), authMode (TOKEN for API clients, NONE for Local only), the list of endpoints, and, when the Flow Scheduler answers, this node's role and the leader. It answers with the Flow Scheduler switched off too, so it is the simplest token check.

Status Meaning
200 Info returned
401 / 503 See Status Codes and Errors
curl -sS "https://<mms-host>:<port>/fss/v1/info" -H "Authorization: Bearer <token>"
Invoke-RestMethod -Uri "https://<mms-host>:<port>/fss/v1/info" `
  -Headers @{ Authorization = "Bearer <token>" }

Run a flow

POST /fss/v1/runflow - any API client allowed the environment and site.

Runs a Tableau Prep flow by LUID under the environment's service account, with one-off parameter values and outputs.

Field Required Meaning
env Yes Environment id or name
site Yes Tableau site LUID
flowLuid Yes Tableau flow LUID
flowName No Name recorded with the run
parameters No [{"name": "...", "value": "..."}] (or "id" instead of "name")
outputSteps No Outputs to run (id, name or LUID). Absent = every output.
runMode No full, incremental or default (the flow's own setting in Tableau). Any case.
wait No true = wait for the outcome
waitTimeoutSeconds No How long to wait: default 900, 1 to 3600

Without wait, the answer is 202 with {"status": "submitted", "runId", "envId", "flowLuid", "tableauJobId", "poll"}. The poll value is an older path that still works; GET /fss/v1/runs/{runId} returns the same run.

With wait: true, the answer carries the run summary (runId, status, tableauJobId, startedAt, completedAt, triggeredBy).

Status Meaning
202 Submitted (no wait)
200 wait: the run finished with success or coalesced
400 BAD_REQUEST: body not JSON, env, site or flowLuid missing, or an invalid value such as runMode
403 ENV_FORBIDDEN, SITE_FORBIDDEN, RUN_FORBIDDEN
404 ENV_NOT_FOUND
409 NOT_LEADER (standby node), NOT_LEADER_OR_ACTIVE (the Flow Scheduler refused the submit with a conflict)
502 wait: the run failed or was cancelled. Without wait: TABLEAU_UNAVAILABLE or SUBMIT_FAILED
504 wait: still running at the timeout; the run continues, poll it

When the Flow Scheduler refuses the submit (here and on runtask), MMS passes on its HTTP status and body; error holds the code named in these tables only when that body has no error text of its own.

curl -sS -X POST "https://<mms-host>:<port>/fss/v1/runflow" \
  -H "Authorization: Bearer <token>" -H "Content-Type: application/json" \
  -d '{"env": "<envId>", "site": "<site-luid>", "flowLuid": "<flow-luid>",
       "parameters": [{"name": "Region", "value": "East"}],
       "outputSteps": ["<output-name>"], "runMode": "incremental",
       "wait": true, "waitTimeoutSeconds": 600}'
$body = @{
  env = "<envId>"; site = "<site-luid>"; flowLuid = "<flow-luid>"
  parameters = @(@{ name = "Region"; value = "East" })
  outputSteps = @("<output-name>"); runMode = "incremental"
  wait = $true; waitTimeoutSeconds = 600
} | ConvertTo-Json -Depth 4
Invoke-RestMethod -Method Post -Uri "https://<mms-host>:<port>/fss/v1/runflow" `
  -Headers @{ Authorization = "Bearer <token>" } -ContentType "application/json" -Body $body

Run a task or chain

POST /fss/v1/runtask - any API client allowed the environment and the task's site.

Runs a configured task or chain now, under the environment's service account.

Field Required Meaning
env Yes Environment id or name
taskId or linkedTaskId Exactly one The task id, or the chain id
runMode No full, incremental or default; overrides the task for this run only
wait, waitTimeoutSeconds No As for runflow (default 900, 1 to 3600)

Without wait, the answer is 202 with {"status": "submitted", "envId", "taskId" or "linkedTaskId", "runId", "poll"}. If the run id is not known yet, runId and poll are left out; list the task's runs to find it. With wait: true, the answer is the run summary, as for runflow.

Status Meaning
202 Submitted
200 wait: success or coalesced
400 BAD_REQUEST: body not JSON, env missing, both or neither of taskId / linkedTaskId, invalid runMode
403 ENV_FORBIDDEN, SITE_FORBIDDEN, RUN_FORBIDDEN
404 ENV_NOT_FOUND, TASK_NOT_FOUND, LINKED_TASK_NOT_FOUND, FLOW_NOT_FOUND
409 NOT_LEADER (standby node), NOT_LEADER_OR_ACTIVE (the task is already running)
502 wait: failed or cancelled. Without wait: SUBMIT_FAILED
504 wait: still running at the timeout
curl -sS -X POST "https://<mms-host>:<port>/fss/v1/runtask" \
  -H "Authorization: Bearer <token>" -H "Content-Type: application/json" \
  -d '{"env": "<envId>", "taskId": <task-id>, "wait": true, "waitTimeoutSeconds": 1800}'
$body = @{ env = "<envId>"; taskId = <task-id>; wait = $true; waitTimeoutSeconds = 1800 } | ConvertTo-Json
Invoke-RestMethod -Method Post -Uri "https://<mms-host>:<port>/fss/v1/runtask" `
  -Headers @{ Authorization = "Bearer <token>" } -ContentType "application/json" -Body $body

Read a run

GET /fss/v1/runs/{runId} - any API client. Optional query parameter env.

A client sees only runs of its own environments and sites; any other run reads as not found.

Field Meaning
runId, status, runMode The run, its status value and run mode
startedAt, completedAt, triggeredBy Times and the API client or user that started it
tableauJobId, tableauFlowRunId Tableau's job and flow-run ids
outputs Per output: stepId, stepLuid, stepName, status, rowCount
parameters The values the run was submitted with: id, name, value
error {code, message, details} when the run failed or was cancelled, else null
steps For a chain: each step with stepOrder, flowId, flowName, runId, status (also skipped), error, outputs

tableauFlowRunId and outputs appear when MetaMiner can read them from the Tableau Server repository.

Status Meaning
200 Run returned
400 BAD_REQUEST: run id not a number
403 ENV_FORBIDDEN: the env named is not allowed for this client
404 FLOW_NOT_FOUND: no such run visible to this client
curl -sS "https://<mms-host>:<port>/fss/v1/runs/<run-id>" -H "Authorization: Bearer <token>"
Invoke-RestMethod -Uri "https://<mms-host>:<port>/fss/v1/runs/<run-id>" `
  -Headers @{ Authorization = "Bearer <token>" }

List runs

GET /fss/v1/runs?env=<envId> - any API client allowed the environment.

Query parameter Meaning
env Required. Environment id or name.
site Only runs of this site
taskId, linkedTaskId, flowId Only runs of this task, chain or flow
status Comma list of status values
triggeredBy Only runs started by this client or user
startedAfter, startedBefore ISO-8601 times, for example 2026-10-01T00:00:00Z
sort startedAt or -startedAt (newest first)
offset, limit Paging. limit default 50, 1 to 500 (outside that range: 400, not clamped)

The answer is {"runs": [...], "total", "offset", "limit"}. Each run has runId, status, taskId, linkedTaskId, flowId, flowName, tableauJobId, triggerType, triggeredBy, startedAt, completedAt. The list holds runs the Flow Scheduler started; runs started elsewhere in Tableau are not listed.

Status Meaning
200 List returned
400 BAD_REQUEST: env missing or not found, unknown status value, invalid filter or limit; SITE_REQUIRED for a site-limited client without site
403 ENV_FORBIDDEN, SITE_FORBIDDEN
curl -sS "https://<mms-host>:<port>/fss/v1/runs?env=<envId>&status=failed&startedAfter=2026-10-01T00:00:00Z&sort=-startedAt&limit=20" \
  -H "Authorization: Bearer <token>"
$uri = "https://<mms-host>:<port>/fss/v1/runs?env=<envId>&status=failed&startedAfter=2026-10-01T00:00:00Z&sort=-startedAt&limit=20"
(Invoke-RestMethod -Uri $uri -Headers @{ Authorization = "Bearer <token>" }).runs

Cancel a run

POST /fss/v1/runs/{runId}/cancel - see Who may call.

Optional body: {"env": "<envId>", "reason": "<text>"}. A chain stops and skips its remaining steps.

The answer is {"runId", "status": "cancelling" or "cancelled", "poll"}. A run in cancelling reads cancelled once Tableau has stopped it.

Status Meaning
200 Cancel accepted
400 BAD_REQUEST: run id not a number, body not JSON
403 ENV_FORBIDDEN, CANCEL_FORBIDDEN (not this client's run)
404 RUN_NOT_FOUND, ENV_NOT_FOUND
409 ALREADY_FINISHED, NOT_LEADER
502 CANCEL_FAILED
curl -sS -X POST "https://<mms-host>:<port>/fss/v1/runs/<run-id>/cancel" \
  -H "Authorization: Bearer <token>" -H "Content-Type: application/json" \
  -d '{"reason": "Upstream data late"}'
Invoke-RestMethod -Method Post -Uri "https://<mms-host>:<port>/fss/v1/runs/<run-id>/cancel" `
  -Headers @{ Authorization = "Bearer <token>" } -ContentType "application/json" `
  -Body '{"reason": "Upstream data late"}'

Run status values

The API reports these values. The statuses the web interface shows are on Run History.

Value Meaning
queued Accepted, not yet started in Tableau
running Running in Tableau, or waiting for Tableau or MMS
success Finished; every output succeeded
failed Failed, refused by Tableau, or an output failed (see error and outputs)
cancelled Cancelled, from the Flow Scheduler or from Tableau
coalesced Not started because the same flow was already running
server_down Held while Tableau Server is unreachable
skipped Chain steps only: not run because the chain stopped

Tasks, chains and schedules

These calls take env as a query parameter (or body field). Create calls for tasks and chains also need site.

Method and path What it does
GET /fss/v1/tasks List tasks
POST /fss/v1/tasks Create a task
PUT /fss/v1/tasks/{id} Change a task
DELETE /fss/v1/tasks/{id} Delete a task
POST /fss/v1/tasks/toggle/{id} Enable or disable: {"enabled": false, "reason": "..."}
GET /fss/v1/linkedtasks, GET /fss/v1/linkedtasks/{id} List chains, read one
POST /fss/v1/linkedtasks Create a chain
PUT /fss/v1/linkedtasks/{id}, DELETE /fss/v1/linkedtasks/{id} Change, delete a chain
POST /fss/v1/linkedtasks/toggle/{id} Enable or disable a chain
GET /fss/v1/schedules, GET /fss/v1/schedules/{id} List schedules, read one
POST /fss/v1/schedules Create a schedule (admin client without site limits)
PUT /fss/v1/schedules/{id}, DELETE /fss/v1/schedules/{id} Change, delete a schedule (admin client without site limits)
GET /fss/v1/schedules/{id}/next-runs?count=<n> Preview the next run times (default 5)
POST /fss/v1/schedules/enabled/{id} Suspend or resume one schedule: {"enabled": false}
POST /fss/v1/schedules/enabled Suspend or resume up to 500 schedules: {"ids": [...], "enabled": false}. All or nothing: an unknown id changes nothing (404).
POST /fss/v1/schedules/{id}/runnow Run every enabled task and chain on the schedule now; ?dryRun=true only lists them
GET, PUT /fss/v1/taskparameters?taskId=<id> Flow parameter values of a task
GET, PUT /fss/v1/stepparameters?stepId=<id> Flow parameter values of a chain step
GET, PUT /fss/v1/notifications/tasks/{id} E-mail notifications of a task
GET, PUT /fss/v1/notifications/linkedtasks/{id} E-mail notifications of a chain

Body fields

Object Fields
Task scheduleId (required), flowId (flow LUID), flowName, projectName, outputSteps, runMode, enabled (default true), ownerUsername (admin clients only)
Chain name, scheduleId, stopOnFailure, enabled, steps: [{"stepOrder", "flowId", "flowName", "runMode"}]
Schedule name, frequency (HOURLY, DAILY, WEEKLY, MONTHLY), startTime (HH:MM or HH:MM:SS), enabled; hourly: recurrenceMinutes (15, 30, 60, 120 or 240), optional endTime and daysOfWeek; weekly: daysOfWeek (MON to SUN); monthly: dayOfMonth (1 to 31, 0 = last day)

Schedules run in the environment's time zone; a timezone field is ignored. See Schedules.

Flow parameters

GET returns the stored values (params) and a flowParameterDigest of the flow's declared parameters. Send both back with PUT. If the flow's parameters changed since your GET, the save is refused with 409; read again and resend.

Responses

The Flow Scheduler answers these calls itself; its error bodies are {"error": "<text>"}. Refusals made before the call reaches it use the codes below.

Status Meaning
200 / 201 Done; the object is returned
400 BAD_REQUEST (missing env or site, body not a JSON object, invalid field), SITE_REQUIRED
403 ENV_FORBIDDEN, SITE_FORBIDDEN, SITE_SCOPE, FORBIDDEN (schedule change by a client that may not)
404 ENV_NOT_FOUND, NOT_FOUND (unknown resource or object)
409 NOT_LEADER (standby node); the Flow Scheduler's own conflicts
# Create a daily schedule, then a task on it
curl -sS -X POST "https://<mms-host>:<port>/fss/v1/schedules?env=<envId>" \
  -H "Authorization: Bearer <token>" -H "Content-Type: application/json" \
  -d '{"name": "nightly", "frequency": "DAILY", "startTime": "02:30"}'
curl -sS -X POST "https://<mms-host>:<port>/fss/v1/tasks?env=<envId>&site=<site-luid>" \
  -H "Authorization: Bearer <token>" -H "Content-Type: application/json" \
  -d '{"scheduleId": <schedule-id>, "flowId": "<flow-luid>", "flowName": "Sales prep"}'
$h = @{ Authorization = "Bearer <token>" }
$base = "https://<mms-host>:<port>/fss/v1"
$sched = Invoke-RestMethod -Method Post -Uri "$base/schedules?env=<envId>" -Headers $h `
  -ContentType "application/json" -Body '{"name": "nightly", "frequency": "DAILY", "startTime": "02:30"}'
$task = @{ scheduleId = $sched.id; flowId = "<flow-luid>"; flowName = "Sales prep" } | ConvertTo-Json
Invoke-RestMethod -Method Post -Uri "$base/tasks?env=<envId>&site=<site-luid>" -Headers $h `
  -ContentType "application/json" -Body $task

Writes in a high-availability pair

The Flow Scheduler leader node serves writes. Every /fss/v1 write that reaches the standby (runs, cancels, tasks, chains, schedules, parameters, notifications, API clients) answers 409 NOT_LEADER before anything is checked or recorded:

{ "error": "NOT_LEADER", "message": "writes are served by the Flow Scheduler leader node", "leader": "<leader-host>" }

Send it again through the load balancer or to the leader. leader is unknown when this node cannot read the Flow Scheduler role. See High Availability.