# List versions of a flow

GET

/v1/flows/{flowId}/versions

```sh
curl --request GET \
  --url 'https://example.com/v1/flows/example/versions?limit=25&includeTombstoned=false' \
  --header 'Authorization: Bearer <token>'
```

Cursor-paginated. Sort order is binding-defined (for example semver asc). Defaults to active versions only. Pass `?includeTombstoned=true` to include unregistered versions too, each with `unregisteredAt`: a retired flow (every version unregistered) answers too, with its versions to reinstate.

## Authorizations

- **[bearerAuth](https://docs.kindgi.com/v0.1.10/reference/api.md#bearerauth)**

## Parameters

### Path Parameters

**flowId**

required

string

FlowId — dotted namespace (`acme.ingest-invoice`).

### Query Parameters

**limit**

integer

default: 25 >= 1 <= 100

1..100. Default 25.

**cursor**

string

Where the previous page ended: its `nextCursor`, as it came. A runtime that seals cursors takes one only for the same list, filters and caller, within a day; otherwise `400 bad-input`, and the list starts again without it. Absent → first page.

**includeTombstoned**

boolean

When `true`, the response includes soft-tombstoned versions in addition to active ones. Tombstoned rows carry an `unregisteredAt` ISO timestamp; active rows omit the field. Default: `false` (active-only).

## Responses

### 200

Page of flow versions.

application/json

object

**data**

required

Array\<object>

object

**id**

required

FlowId — dotted namespace (e.g. `ingest.contract-pdf`).

string

**version**

required

Semver.

string

**projectId**

The flow’s project: every version of a flow is in the one project. Absent when the runtime doesn’t record it: a pack `kindgi dev` serves from disk, or a runtime before Kindgi 0.1.6.

string format: uuid

**name**

string

**description**

string

**nodes**

required

Array\<object>

object

**id**

required

string

**kind**

required

string

Allowed values: tool agent loop fanout subgraph

**ref**

Handler reference for leaf nodes.

string

**config**

object

**_key_**

additional properties

any

**_key_**

additional properties

any

**edges**

required

Array\<object>

object

**id**

required

string

**from**

required

Source node id or `$start` sentinel.

string

**to**

required

Destination node id or `$end` sentinel.

string

**when**

Optional predicate expression evaluated at edge dispatch time (see `@kindgi/flow`).

object

**_key_**

additional properties

any

**policy**

Optional per-edge runtime policy (retry, timeoutMs, …).

object

**_key_**

additional properties

any

**maxParallelism**

integer

\>= 1

**metadata**

object

**_key_**

additional properties

any

**pins**

The exact tool and agent versions a flow version runs: its lockfile. Set by the runtime when the version is published, never in the publish body: each tool the flow runs, and each agent it runs at no named version, resolves once to its latest version then, which every run of that flow version uses. Absent on a version published before pins existed (it binds the latest versions per run).

object

**tools**

required

Tool id → exact version.

object

**_key_**

additional properties

string

**agents**

required

Agent id → exact version, for agent nodes that name no version.

object

**_key_**

additional properties

string

**pinsDigest**

Set by the runtime with `pins`: `sha256:<hex>` of the pins’ canonical JSON (sorted keys, no whitespace).

string

/^sha256:\[0-9a-f]{64}$/

**derivedFrom**

Set by the runtime on an agent or flow version a deploy registered in place of the definition’s version, which was registered already with other pins or content (versions never change). Never in the publish body.

object

**version**

required

The version the definition names.

string

**reason**

required

`pins-changed`: a block it uses has a new version; `unpinned`: the definition’s version was published before pins existed; `version-taken`: the definition’s version holds another definition; `edited`: derived from `version` with some data-block pins swapped (`POST /v1/agents/{agentId}/versions`).

string

Allowed values: pins-changed unpinned version-taken edited

**label**

For `edited`: a short label for the version.

string

**by**

For `edited`: who derived it (`user:<id>`).

string

**proposalId**

For `edited`: the improvement proposal it was derived for. Such a version serves no scope until a promotion makes it live.

string

**unregisteredAt**

Present only on an unregistered version (`GET …/versions/{version}` reads those too). Unregister stops a version being chosen, not the pins that hold it: a new run naming it is refused, while a resumed run and a published version that pins it still run it.

string format: date-time

**nextCursor**

Opaque cursor for the next page. Absent when `hasMore: false`.

string

**hasMore**

required

boolean

##### Example

```json
{
  "data": [
    {
      "nodes": [
        {
          "kind": "tool"
        }
      ],
      "derivedFrom": {
        "reason": "pins-changed"
      }
    }
  ]
}
```

### 400

`bad-input`: a `cursor` this list didn’t issue.

application/json

object

**error**

required

object

**code**

required

Stable machine-readable discriminant. Values match domain error codes (see `docs/API-ROUTE-CONVENTIONS.md` §4.3).

string

**message**

required

string

**details**

Optional, kind-specific.

object

**_key_**

additional properties

any

**requestId**

required

Server-assigned request id; also echoed via `X-Request-Id` header.

string

##### Examplegenerated

```json
{
  "error": {
    "code": "example",
    "message": "example",
    "details": {},
    "requestId": "example"
  }
}
```

### 401

Missing / malformed / expired / revoked bearer token.

application/json

object

**error**

required

object

**code**

required

Stable machine-readable discriminant. Values match domain error codes (see `docs/API-ROUTE-CONVENTIONS.md` §4.3).

string

**message**

required

string

**details**

Optional, kind-specific.

object

**_key_**

additional properties

any

**requestId**

required

Server-assigned request id; also echoed via `X-Request-Id` header.

string

##### Examplegenerated

```json
{
  "error": {
    "code": "example",
    "message": "example",
    "details": {},
    "requestId": "example"
  }
}
```

### 404

No flow was ever registered with that id under this tenant.

application/json

object

**error**

required

object

**code**

required

Stable machine-readable discriminant. Values match domain error codes (see `docs/API-ROUTE-CONVENTIONS.md` §4.3).

string

**message**

required

string

**details**

Optional, kind-specific.

object

**_key_**

additional properties

any

**requestId**

required

Server-assigned request id; also echoed via `X-Request-Id` header.

string

##### Examplegenerated

```json
{
  "error": {
    "code": "example",
    "message": "example",
    "details": {},
    "requestId": "example"
  }
}
```

## See also

- [`GET /v1/flows/{flowId}`: Fetch the latest version of a flow](https://docs.kindgi.com/v0.1.10/reference/api/operations/flowsget.md)
- [`GET /v1/flows/{flowId}/versions/{version}`: Fetch a specific flow version](https://docs.kindgi.com/v0.1.10/reference/api/operations/flowsgetversion.md)
- [`POST /v1/flows/{flowId}/versions/{version}/unregister`: Unregister a specific flow version](https://docs.kindgi.com/v0.1.10/reference/api/operations/flowsunregister.md)
- [`POST /v1/flows/{flowId}/versions/{version}/reinstate`: Reinstate a specific tombstoned flow version](https://docs.kindgi.com/v0.1.10/reference/api/operations/flowsreinstateversion.md)
- [Error code `bad-input`](https://docs.kindgi.com/v0.1.10/reference/errors.md#bad-input)
- [Every error code](https://docs.kindgi.com/v0.1.10/reference/errors.md)
