> ## Documentation Index
> Fetch the complete documentation index at: https://docs.devset.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Engine API: Execute and Monitor Workflow Runs

> Submit workflows for async execution, simulate runs without a broker, list active and completed runs, stream events, and stop runs gracefully.

The Engine API is the core execution layer of Devset. You use it to submit compiled workflow definitions for asynchronous execution, simulate workflows locally without touching any broker, inspect the state of active or historical runs, and retrieve every event emitted during a run. All endpoints are relative to `http://localhost:8082`.

***

## POST /engine/execute

Submit a workflow for asynchronous execution. Devset compiles your workflow DSL, queues it internally, and returns a `runId` immediately. Use that ID with the other `/engine/runs` endpoints to track progress.

<ParamField body="(workflow DSL)" type="object" required>
  A compiled workflow definition in Devset's workflow DSL JSON format. See the [Workflow DSL reference](/reference/workflow-dsl) for the full schema.
</ParamField>

**Request example**

```json theme={null}
{
  "id": "order-flow",
  "messageType": "kafka",
  "topic": "orders.events",
  "producerName": "local-kafka",
  "pipeline": [
    {
      "name": "order-created",
      "set": { "id": { "$fn": "uuid()" }, "amount": 42, "status": "PENDING" }
    }
  ]
}
```

**Response — 202 Accepted**

```json theme={null}
{
  "runId": "a3f1c2d4-89ab-4e12-b456-426614174000",
  "status": "PENDING",
  "executions": 1
}
```

<ResponseField name="runId" type="string">
  UUID that uniquely identifies this execution. Pass it to `/engine/runs/{runId}` to poll status or retrieve events.
</ResponseField>

<ResponseField name="status" type="string">
  Initial lifecycle status of the run. Typically `PENDING` immediately after submission.
</ResponseField>

<ResponseField name="executions" type="integer">
  The number of executions requested for this run.
</ResponseField>

***

## POST /engine/simulate

Simulate a workflow without dispatching any messages to a broker. Devset executes the workflow in-process and returns all events synchronously in a single response. Use this to validate payloads and stage logic before running against a live broker.

<ParamField body="(workflow DSL)" type="object" required>
  A workflow definition in Devset's workflow DSL JSON format — the same shape accepted by `POST /engine/execute`.
</ParamField>

**Request example**

```json theme={null}
{
  "id": "order-flow",
  "messageType": "kafka",
  "topic": "orders.events",
  "producerName": "local-kafka",
  "pipeline": [
    {
      "name": "order-created",
      "set": { "id": "order-123", "amount": 42, "status": "PENDING" }
    }
  ]
}
```

**Response — 200 OK**

```json theme={null}
{
  "runId": "SIMULATION",
  "status": "COMPLETED",
  "executionCount": 1,
  "executions": [
    {
      "executionIndex": 1,
      "eventCount": 1,
      "events": [
        {
          "stageName": "order-created",
          "header": {},
          "payload": { "id": "order-123", "amount": 42, "status": "PENDING" }
        }
      ]
    }
  ]
}
```

<ResponseField name="runId" type="string">
  Always `"SIMULATION"` for simulated runs.
</ResponseField>

<ResponseField name="status" type="string">
  Always `"COMPLETED"` for a finished simulation.
</ResponseField>

<ResponseField name="executionCount" type="integer">
  Total number of execution groups in the response.
</ResponseField>

<ResponseField name="executions" type="array">
  Ordered list of execution groups, each containing the events produced during that iteration.

  <Expandable title="Execution group fields">
    <ResponseField name="executionIndex" type="integer">
      One-based index of this execution iteration.
    </ResponseField>

    <ResponseField name="eventCount" type="integer">
      Number of events produced in this execution.
    </ResponseField>

    <ResponseField name="events" type="array">
      Events produced during this execution iteration.

      <Expandable title="Event fields">
        <ResponseField name="stageName" type="string">
          The name of the workflow stage that emitted this event.
        </ResponseField>

        <ResponseField name="header" type="object">
          Message headers that would have been attached to the broker message.
        </ResponseField>

        <ResponseField name="payload" type="object">
          The fully-resolved message payload for this stage.
        </ResponseField>
      </Expandable>
    </ResponseField>
  </Expandable>
</ResponseField>

<Tip>
  Use simulate before every deploy to a live environment. It catches payload construction errors and missing field references without producing any noise in your broker.
</Tip>

***

## GET /engine/runs

List all active and completed runs. The response groups runs into two buckets: `active` for runs that are still in progress and `completed` for runs that have reached a terminal state.

**Response — 200 OK**

```json theme={null}
{
  "active": [
    {
      "runId": "a3f1c2d4-89ab-4e12-b456-426614174000",
      "status": "RUNNING",
      "active": true,
      "requestedExecutions": 10,
      "submittedExecutions": 4,
      "completedExecutions": 3,
      "failedExecutions": 0,
      "errorMessage": null
    }
  ],
  "completed": [
    {
      "runId": "b7e2d1a5-12cd-4f89-c567-537725285111",
      "status": "COMPLETED",
      "active": false,
      "requestedExecutions": 5,
      "submittedExecutions": 5,
      "completedExecutions": 5,
      "failedExecutions": 0,
      "errorMessage": null
    }
  ]
}
```

<ResponseField name="active" type="array">
  Runs that are in a non-terminal state (`PENDING`, `RUNNING`, or `STOPPING`).
</ResponseField>

<ResponseField name="completed" type="array">
  Runs that have reached a terminal state (`COMPLETED`, `FAILED`, or `STOPPED`).

  <Expandable title="Run status fields">
    <ResponseField name="runId" type="string">
      UUID that uniquely identifies the run.
    </ResponseField>

    <ResponseField name="status" type="string">
      Current lifecycle status. One of `PENDING`, `RUNNING`, `COMPLETED`, `FAILED`, `STOPPING`, or `STOPPED`.
    </ResponseField>

    <ResponseField name="active" type="boolean">
      `true` if the run is in a non-terminal state.
    </ResponseField>

    <ResponseField name="requestedExecutions" type="integer">
      Total number of executions requested when the run was submitted.
    </ResponseField>

    <ResponseField name="submittedExecutions" type="integer">
      Number of executions that have been dispatched so far.
    </ResponseField>

    <ResponseField name="completedExecutions" type="integer">
      Number of executions that have finished successfully.
    </ResponseField>

    <ResponseField name="failedExecutions" type="integer">
      Number of executions that encountered an error.
    </ResponseField>

    <ResponseField name="errorMessage" type="string | null">
      Error detail if the run reached `FAILED` status, or `null` otherwise.
    </ResponseField>
  </Expandable>
</ResponseField>

***

## GET /engine/runs/{runId}

Retrieve the status of a single run by its ID. The response has the same shape as one element in the `active` or `completed` arrays returned by `GET /engine/runs`.

**Path parameters**

<ParamField path="runId" type="string" required>
  The UUID of the run to look up.
</ParamField>

**Response — 200 OK**

```json theme={null}
{
  "runId": "a3f1c2d4-89ab-4e12-b456-426614174000",
  "status": "RUNNING",
  "active": true,
  "requestedExecutions": 10,
  "submittedExecutions": 4,
  "completedExecutions": 3,
  "failedExecutions": 0,
  "errorMessage": null
}
```

***

## GET /engine/runs/{runId}/events

Fetch all events emitted during a run, grouped by execution index. Each execution group corresponds to one iteration of the workflow.

**Path parameters**

<ParamField path="runId" type="string" required>
  The UUID of the run whose events you want to retrieve.
</ParamField>

**Response — 200 OK**

```json theme={null}
{
  "runId": "a3f1c2d4-89ab-4e12-b456-426614174000",
  "status": "COMPLETED",
  "executionCount": 2,
  "executions": [
    {
      "executionIndex": 1,
      "eventCount": 1,
      "events": [
        {
          "stageName": "order-created",
          "header": {},
          "payload": { "id": "order-123", "amount": 42 }
        }
      ]
    },
    {
      "executionIndex": 2,
      "eventCount": 1,
      "events": [
        {
          "stageName": "order-created",
          "header": {},
          "payload": { "id": "order-456", "amount": 75 }
        }
      ]
    }
  ]
}
```

<ResponseField name="runId" type="string">
  The UUID of the run.
</ResponseField>

<ResponseField name="status" type="string">
  The current status of the run at the time of the request.
</ResponseField>

<ResponseField name="executionCount" type="integer">
  Total number of execution groups in the response.
</ResponseField>

<ResponseField name="executions" type="array">
  Ordered list of execution groups.

  <Expandable title="Execution group fields">
    <ResponseField name="executionIndex" type="integer">
      One-based iteration index for this group of events.
    </ResponseField>

    <ResponseField name="eventCount" type="integer">
      Number of events in this execution group.
    </ResponseField>

    <ResponseField name="events" type="array">
      All events emitted during this execution iteration.

      <Expandable title="Event fields">
        <ResponseField name="stageName" type="string">
          The workflow stage that produced this event.
        </ResponseField>

        <ResponseField name="header" type="object">
          Headers attached to the broker message.
        </ResponseField>

        <ResponseField name="payload" type="object">
          The resolved message payload.
        </ResponseField>
      </Expandable>
    </ResponseField>
  </Expandable>
</ResponseField>

<Note>
  Events are available while the run is in progress. You can poll this endpoint during a `RUNNING` run to observe events as they are produced.
</Note>

***

## POST /engine/runs/{runId}/stop

Request a graceful stop for an active run. Devset transitions the run to `STOPPING` and allows any in-flight stage to complete before halting. The run status moves to `STOPPED` once it winds down. The response contains the updated run status at the time the stop was acknowledged.

**Path parameters**

<ParamField path="runId" type="string" required>
  The UUID of the run to stop.
</ParamField>

No request body is required.

**Response — 202 Accepted**

```json theme={null}
{
  "runId": "a3f1c2d4-89ab-4e12-b456-426614174000",
  "status": "STOPPING",
  "active": true,
  "requestedExecutions": 10,
  "submittedExecutions": 6,
  "completedExecutions": 5,
  "failedExecutions": 0,
  "errorMessage": null
}
```

Poll `GET /engine/runs/{runId}` to confirm the run reaches `STOPPED` status.

<Warning>
  Sending a stop request to a run that is already `COMPLETED`, `FAILED`, or `STOPPED` is a no-op. The run status will not change, and you will still receive a 202 response.
</Warning>
