# Flow node types

All node types share common fields (`id`, `type`, `label`, `description`, `position`). This page lists **runtime fields** per type.

## `start`

Entry point. Declares input contract and optional response type binding.

| Field | Required | Description |
|-------|----------|-------------|
| `responseTypeId` | no | GUID of a response type; when set, flow output is validated against it |
| `inputSchema` | no | Caller input contract for `/v1/evaluate` |

### `inputSchema`

```json
{
  "fields": [
    { "name": "userId", "type": "string", "required": true, "description": "CRM user id" },
    { "name": "amount", "type": "number", "required": true }
  ]
}
```

Field types: `string`, `number`, `integer`, `boolean`, `object`, `array`.

## `http`

Calls an operation from a registered OpenAPI source.

| Field | Required | Description |
|-------|----------|-------------|
| `apiSourceId` | yes | GUID of the API source in the tenant |
| `operationId` | yes | OpenAPI operation id |
| `inputs` | no | Map of parameter name → JSONata expression |

Example:

```json
{
  "id": "http_fetch_user",
  "type": "http",
  "apiSourceId": "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee",
  "operationId": "getUserById",
  "inputs": {
    "userId": "input.userId"
  }
}
```

HTTP responses are stored in run state under `nodes.{nodeId}`.

## `condition`

Branches on a JSONata boolean expression.

| Field | Required | Description |
|-------|----------|-------------|
| `expression` | yes | JSONata returning truthy/falsey |

Outgoing edges must use `"when": "true"` and `"when": "false"`.

## `transform`

Evaluates JSONata and stores the result on the node state (no branching).

| Field | Required | Description |
|-------|----------|-------------|
| `expression` | yes | JSONata expression |

## `wait_for_event`

Pauses the flow until an external resume call delivers an event.

| Field | Required | Description |
|-------|----------|-------------|
| `eventName` | yes | Event name matched on resume |
| `expression` | no | Optional guard expression |
| `timeoutSeconds` | no | Timeout |
| `uiAction` | no | UI hint while waiting (modal, redirect, etc.) |

Resume via `POST /v1/runs/{runId}/resume` with matching `event`.

## `decision`

Writes values into the flow's **response accumulator** and continues via an outgoing edge.

| Field | Required | Description |
|-------|----------|-------------|
| `responseValues` | yes* | Map of property name → literal or JSONata string |
| `result` | legacy | Legacy inline payload when no response type is bound |

### `responseValues`

Values may be:

- JSON literals: `"approved": true`
- JSONata strings (prefix `=`): `"reason": "=nodes.http_1.body.message"`

When `start.responseTypeId` is set, every key must exist on the response type.

Preferred pattern: `decision → end`.

## `end`

Terminal node. No outgoing edges required.

When a response type is bound, the accumulated response is validated and returned to the evaluate caller.

## Node id conventions

Use descriptive snake_case ids: `start_1`, `http_fetch_user`, `cond_amount_ok`, `decision_approve`.

Ids are referenced in JSONata as `nodes.{id}.field`.
