---
title: "Create a flow"
method: POST
path: "/v1/flows"
tags: ["flows"]
---

# Create a flow

`POST /v1/flows`

## Request

- Base URL: `https://api.flowral.app`
- URL: `https://api.flowral.app/v1/flows`
- Auth: one of:
  - HTTP bearer
  - OAuth 2 (client credentials, token URL `https://api.flowral.app/v1/oauth/token`, scopes: `flows:write`)

Creates a flow and, optionally, its whole task graph in one call. A task's `after` references other tasks **by index in this request**, so the dependency chain arrives with the flow rather than in follow-up calls. Cycles are refused outright.

## Request body

- object
  - `name` string, required
  - `description` string
  - `dueDate` string: ISO 8601. Used by the schedule and report endpoints to answer "is this on track".
  - `tasks` object[]: Tasks to create, in order. Each: `{ name, description?, estimateHours?, assigneeId?, after?: [index] }`, where `after` holds indexes into this same array.

## Response `201`

CREATED

- Flow: A flow with its full task graph and derived state.
  - `id` string, required
  - `name` string, required
  - `description` string, nullable
  - `archived` boolean, required
  - `public` boolean: Whether this flow is published — readable by anyone with its link, with no account. Assignees, comments and files are never included in the public view.
  - `publicUrl` string, nullable: The published link, or null when the flow is private.
  - `dueDate` string, date-time: The date the flow is meant to land, if one is set.
  - `taskCount` integer
  - `doneCount` integer
  - `readyCount` integer: Tasks that can be started right now.
  - `createdAt` string, date-time
  - `updatedAt` string, date-time
  - `tasks` Task[], required
    - `id` string, required
    - `flowId` string, required
    - `parentId` string, nullable, required: Set when this is a sub-task — the objective it belongs to. Null for an objective itself.
    - `name` string, required
    - `description` string, nullable
    - `status` 'blocked' | 'ready' | 'in_progress' | 'done', required: Derived from the graph on read, never stored. Work moves ready → in_progress → done; nothing jumps straight to done.
    - `dependsOn` string[], required: Task ids that must be done first.
    - `blockedBy` string[]: Of those, the ones not yet done. Empty when status is not "blocked".
    - `assigneeId` string, nullable
    - `estimateHours` number, nullable
    - `criticalPath` boolean: True when this task is on the chain that decides the flow's finish date.
    - `subtasks` SubTask[]
      - `id` string, required
      - `name` string, required
      - `done` boolean, required
      - `assigneeId` string, nullable: Workspace member id.
      - `estimateHours` number, nullable
    - `requiredDeliverables` object[]: Files that have to be handed in before the task can complete.
      - `id` string
      - `name` string
      - `satisfied` boolean

## Other responses

- `400`: VALIDATION_FAILED · CIRCULAR_DEPENDENCY
- `401`: UNAUTHORIZED
- `403`: FORBIDDEN · PLAN_REQUIRED · SUBSCRIPTION_PAST_DUE
- `429`: RATE_LIMITED

---

[API](https://skmtc.dev/flowral/apis/flowral-api.md) · [All operations](https://skmtc.dev/flowral/apis/flowral-api/llms.txt) · [OpenAPI document](https://skmtc.dev/flowral/apis/flowral-api/revisions/6cd2337b682c?raw)
