Log icon
ForEach icon
Request icon

Bulk Approve Paused Executions from an Approver Console

Kestra flow that takes a multiselect of paused execution ids and an Approve or Reject decision, then resumes each execution through the Kestra API with a signoff value.

Categories
Business

Give approvers one screen instead of one email per request. This Kestra blueprint is the backend of an approver console: a reviewer picks any number of paused executions from a multiselect, chooses Approve or Reject, and the flow resumes each approved execution through the Kestra executions API, passing a signoff value into the paused task's onResume inputs. It is designed to sit behind a Kestra App (an Enterprise Edition and Kestra Cloud feature) that lists pending approvals as a form, turning dozens of individual human-in-the-loop gates into a single batch decision.

How it works

  1. The executionIdsToBeApproved input (MULTISELECT with allowCustomValue: true) carries the ids of paused executions. In the companion App this list is populated dynamically from the executions API; the static values here are placeholders to replace.
  2. The action input (SELECT) captures the decision, Approve or Reject.
  3. The logDecision task (io.kestra.plugin.core.log.Log) records who decided what, making every batch approval auditable as an execution.
  4. The for_each task (io.kestra.plugin.core.flow.ForEach) iterates the selected ids with concurrencyLimit: 1 so resumes happen in order. Its runIf only fires when the action is Approve and at least one execution was selected, so a Reject decision is simply logged without resuming anything.
  5. The nested approve task (io.kestra.plugin.core.http.Request) POSTs multipart/form-data to /api/v1/{tenant}/executions/{id}/resume with a bearer token, submitting signoff: true as the onResume input of the paused io.kestra.plugin.core.flow.Pause task in each target flow.

What you get

  • Batch approval of any number of paused executions in a single action.
  • A durable audit record: each decision is itself an execution with logs and inputs.
  • Ordered, throttled resumes so downstream systems are not hit all at once.
  • A reusable pattern for driving the Kestra API from inside a flow.

Who it's for

  • Managers and change approvers who face queues of human-in-the-loop requests.
  • Platform teams building approval consoles on top of Kestra Apps.
  • Anyone standardizing how paused executions get resumed instead of ad hoc UI clicks.

Why orchestrate this with Kestra

Approvals scattered across emails and UI clicks leave no consolidated record and scale linearly with request volume. By making the approval itself a flow, every batch decision gets inputs, logs, timestamps, and an identity attached. The ForEach plus Request combination works against any Kestra tenant, and because the decision is just an execution, you can trigger notifications, SLA timers, or escalation flows from it like any other event. Pair it with a Kestra App form and approvers never need to open individual executions at all.

Prerequisites

  • Target flows that pause with io.kestra.plugin.core.flow.Pause and accept a signoff value in onResume.
  • A Kestra API token with permission to resume executions in the target tenant.
  • Set the kestraUrl and tenant variables for your instance.
  • A Kestra App bound to this flow for the console experience (EE or Kestra Cloud).

Secrets

  • KESTRA_API_TOKEN: bearer token used by the Request task to call the executions resume API.

Quick start

  1. Add KESTRA_API_TOKEN to your Kestra namespace and set the kestraUrl and tenant variables.
  2. Deploy the flow, then start a flow containing a Pause task with a signoff boolean in onResume.
  3. Execute this flow, paste the paused execution id into the multiselect, and choose Approve.
  4. Confirm the target execution resumed with signoff: true.
  5. Build an App on top of this flow so the multiselect is populated automatically.

How to extend

  • Handle rejection actively by calling the kill or set-labels API endpoints in an else branch.
  • Populate the multiselect dynamically with an expression that queries the executions API for paused runs.
  • Notify requesters of the outcome with io.kestra.plugin.notifications.slack.SlackIncomingWebhook.
  • Add a reason input and forward it in formData so approvals carry a justification.
  • Restrict who can run the flow with namespace-level RBAC in the Enterprise Edition.

Links

Share this Blueprint
See How

New to Kestra?

Use blueprints to kickstart your first workflows.