Falaah Falaah AI

Workflows API

List workflow definitions, start a workflow run, read its status and current step, move it on with an event, and cancel it with the Muin Workflows API.

A workflow definition is a process you set up in Muin, such as an invoice approval. Each time it runs, Muin creates a workflow instance that tracks where that run is. The Workflows API lets your system start instances, read their status, move them on, and cancel them.

When you’d use this

  • Start an approval in Muin when a record is created in your own system.
  • Show the status of a Muin approval in another tool.
  • Move a run on, for example to approved, from your own app.
  • Cancel a run that is no longer needed.

Before you start

  • All paths are on https://muin-api.falaah.ai/api/v1/workflows.
  • Send your key as Authorization: Bearer $MUIN_API_KEY. A Read key can only make GET requests. Starting, moving and cancelling a run need Write.
  • A key acts as the person who created it. That person needs access to Workflows, and the workflow’s module must be turned on for your organization.

Keys, scopes, rate limits and general errors: Authentication.


List workflow definitions

GET /api/v1/workflows/definitions

Parameter Type Required Description
category string No Only definitions in this category
document_type string No Only definitions that support this document type
limit integer No 1 to 100. Default 100
offset integer No Rows to skip. Default 0
curl "https://muin-api.falaah.ai/api/v1/workflows/definitions?limit=20" \
  -H "Authorization: Bearer $MUIN_API_KEY"
{
  "workflows": [
    {
      "id": "3b6f2a10-8c4d-4f0e-9a51-7d2c1e9b4a20",
      "name": "Invoice approval",
      "slug": "invoice-approval",
      "description": "Route an invoice to a manager for approval",
      "category": "finance",
      "module_code": "finance",
      "version": "1.0",
      "is_active": true,
      "is_template": false,
      "tier": "automation",
      "dsl": { "...": "the workflow document" },
      "created_at": "2026-09-01T16:00:00Z",
      "updated_at": "2026-09-20T18:30:00Z"
    }
  ],
  "total": 1
}

Use id as workflow_definition_id when you start a run. dsl is the full workflow document, including the events each step accepts.


Get a workflow definition

GET /api/v1/workflows/definitions/{definition_id}

Parameter Type Required Description
definition_id string (path) Yes The definition’s id or its slug
curl https://muin-api.falaah.ai/api/v1/workflows/definitions/invoice-approval \
  -H "Authorization: Bearer $MUIN_API_KEY"

The response is one definition, with the same fields as an item in the list above, plus latest_version (id, version, status, published_at) when the definition has a version.


Start a workflow instance

POST /api/v1/workflows/instances

Field Type Required Description
workflow_definition_id UUID Yes The definition to run
document_id UUID No A Muin document this run is about
initial_data object No Starting data for the run. Default {}
curl -X POST https://muin-api.falaah.ai/api/v1/workflows/instances \
  -H "Authorization: Bearer $MUIN_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "workflow_definition_id": "3b6f2a10-8c4d-4f0e-9a51-7d2c1e9b4a20",
    "initial_data": { "invoice_number": "INV-1042", "amount": 1250.00 }
  }'

Returns 201 with the new instance. The run starts from its first step right away.

{
  "id": "9e4d7c21-5a3b-4f86-b0e2-1c8a6f3d2e57",
  "tenant_id": "0a1b2c3d-4e5f-4a6b-8c7d-9e0f1a2b3c4d",
  "workflow_definition_id": "3b6f2a10-8c4d-4f0e-9a51-7d2c1e9b4a20",
  "document_id": null,
  "started_by_id": "5f6e7d8c-9b0a-4c1d-8e2f-3a4b5c6d7e8f",
  "current_state": "manager_review",
  "previous_state": "submitted",
  "status": "waiting_human",
  "status_message": null,
  "initial_context": { "invoice_number": "INV-1042", "amount": 1250.0 },
  "started_at": "2026-10-09T17:05:12Z",
  "completed_at": null,
  "due_at": null,
  "error_message": null,
  "retry_count": 0,
  "priority": "medium",
  "workflow_definition_version_id": "c2d3e4f5-a6b7-4c8d-9e0f-1a2b3c4d5e6f",
  "created_at": "2026-10-09T17:05:12Z",
  "updated_at": "2026-10-09T17:05:13Z"
}

Responses also carry state_data, transition_history, checkpoint_data, checkpoint_at, the escalation fields (escalation_level, escalated_to_id, escalated_at), error_details and workflow_definition.


List workflow instances

GET /api/v1/workflows/instances

Parameter Type Required Description
workflow_definition_id UUID No Only runs of this definition
document_id UUID No Only runs about this document
status string No Only runs with this status (see Instance statuses)
module string No Only runs of definitions in this module, for example compliance
limit integer No 1 to 100. Default 50
offset integer No Rows to skip. Default 0
curl "https://muin-api.falaah.ai/api/v1/workflows/instances?status=waiting_human&limit=50&offset=0" \
  -H "Authorization: Bearer $MUIN_API_KEY"
{
  "workflows": [
    {
      "id": "9e4d7c21-5a3b-4f86-b0e2-1c8a6f3d2e57",
      "workflow_definition_id": "3b6f2a10-8c4d-4f0e-9a51-7d2c1e9b4a20",
      "current_state": "manager_review",
      "status": "waiting_human",
      "started_at": "2026-10-09T17:05:12Z",
      "waiting_on": {
        "task_id": "7a8b9c0d-1e2f-4a3b-9c4d-5e6f7a8b9c0d",
        "task_title": "Approve invoice INV-1042",
        "assignee_id": "1f2e3d4c-5b6a-4978-8695-a4b3c2d1e0f9",
        "assignee_name": "Sarah Ahmed",
        "since": "2026-10-09T17:05:13Z",
        "due_at": null,
        "candidate_assignee_ids": []
      }
    }
  ],
  "total": 1,
  "limit": 50,
  "offset": 0
}

Each item has the same fields as the start response. waiting_on names the task and person a waiting run is held on. To page, raise offset by limit until you have read total rows.


Get a workflow instance

GET /api/v1/workflows/instances/{instance_id}

Parameter Type Required Description
instance_id UUID (path) Yes The instance id
curl https://muin-api.falaah.ai/api/v1/workflows/instances/9e4d7c21-5a3b-4f86-b0e2-1c8a6f3d2e57 \
  -H "Authorization: Bearer $MUIN_API_KEY"
{
  "id": "9e4d7c21-5a3b-4f86-b0e2-1c8a6f3d2e57",
  "current_state": "manager_review",
  "previous_state": "submitted",
  "status": "waiting_human",
  "transition_history": [ { "...": "one entry per step change" } ],
  "document": null,
  "human_tasks": [
    {
      "id": "7a8b9c0d-1e2f-4a3b-9c4d-5e6f7a8b9c0d",
      "title": "Approve invoice INV-1042",
      "status": "pending",
      "priority": "medium",
      "assigned_to_id": "1f2e3d4c-5b6a-4978-8695-a4b3c2d1e0f9",
      "assigned_to_name": "Sarah Ahmed",
      "created_at": "2026-10-09T17:05:13+00:00",
      "due_at": null,
      "candidate_assignee_ids": []
    }
  ]
}

The detail response has every field of the start response, plus:

Field Description
current_state The step the run is on now
previous_state The step it came from
status Overall status (see below)
document id, filename and document_type of the linked document, or null
human_tasks Tasks this run created for people

Instance statuses

Status Meaning
active Running
waiting Waiting before it can continue
waiting_human Waiting on a person’s task
paused Paused, by the pause call below or because something it depends on was turned off
completed Finished
failed Stopped on an error. error_message says why
cancelled Cancelled
timeout Ran out of time

Move an instance on (approve, reject, other events)

POST /api/v1/workflows/instances/{instance_id}/transition

There is no separate approve or reject call. You send the event the current step accepts, such as approved or rejected. The events are defined in the workflow’s dsl.

Field Type Required Description
instance_id UUID (path) Yes The instance id
event string Yes The event to fire
data object No Data passed with the event. Default {}
curl -X POST https://muin-api.falaah.ai/api/v1/workflows/instances/9e4d7c21-5a3b-4f86-b0e2-1c8a6f3d2e57/transition \
  -H "Authorization: Bearer $MUIN_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "event": "approved", "data": { "note": "Within budget" } }'

Returns the instance after the move, with the same fields as the start response.

When the run is waiting on a person’s task, only that person, or an owner or admin, can move it on. So the key must belong to that person, or to an owner or admin. An owner or admin who moves it on for someone else must say why in data.override_reason. The reason is kept on the run’s history.


Cancel an instance

POST /api/v1/workflows/instances/{instance_id}/cancel

Parameter Type Required Description
instance_id UUID (path) Yes The instance id
curl -X POST https://muin-api.falaah.ai/api/v1/workflows/instances/9e4d7c21-5a3b-4f86-b0e2-1c8a6f3d2e57/cancel \
  -H "Authorization: Bearer $MUIN_API_KEY"

Returns the instance with "status": "cancelled". A run that is already completed or cancelled cannot be cancelled.

Other instance actions

These take no body (retry takes an optional one) and return the instance.

Action Request Allowed when the status is
Pause POST /api/v1/workflows/instances/{instance_id}/pause active, waiting or waiting_human
Resume POST /api/v1/workflows/instances/{instance_id}/resume paused
Retry POST /api/v1/workflows/instances/{instance_id}/retry failed (restarts from its last checkpoint) or cancelled (restarts from the first step). Send {"from_task": "<step>"} to restart a failed run from that step

Workflow events and webhooks

Workflow runs are not in the list of events that deliver to webhooks today. To follow a run, read it with GET /api/v1/workflows/instances/{instance_id}. A workflow can also post to your server itself with a webhook step. How Muin signs those posts: Webhooks.


When it goes wrong

Status When What to do
400 An owner or admin moved on a step waiting for someone else without data.override_reason. Add override_reason to data.
403 The key is Read-only on a POST, its creator lacks access to Workflows, the workflow’s module is not on for your organization, or the definition is turned off. On a transition: the step is waiting for someone else. Use a Write key from someone with access, turn the definition on, or let the assigned person decide the task.
404 No definition or instance with that ID in your organization. Check the ID. Definitions also accept the slug.
409 Retry with from_task on a run that is not failed. Retry only failed runs from a step.
422 The body is invalid, the run could not start, the event is not accepted at the current step, or the status does not allow the action (for example, cancelling a completed run). Read current_state and status, then send an event or action that fits.
500 The workflow hit an error while moving on. The run is marked failed. Read error_message on the instance, fix the cause, then retry.

Next step

  • Authentication: create the API key these calls need.
  • Webhooks: receive Muin events on your server and verify signatures.