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

# Create a workflow

> Make a workflow from plain words, and Orgo drafts the steps, or from its lines. It starts off.

Makes a new workflow. Send `describe` (plain words: Orgo drafts the steps) or `lines` (the steps themselves), one of the two. The workflow’s `id` is its name in lowercase words joined by `-`, so **Morning report** is `morning-report`.

A new workflow is off. Fix what `to_fix` says, check it with [Validate](https://docs.orgo.ai/api-reference/workflows/validate.md), then turn it on with [Update a workflow](https://docs.orgo.ai/api-reference/workflows/update.md) and `{ "on": true }`.

## Headers

**Idempotency-Key** `string`

8 to 255 printable characters. A retry with the same key and body within a day answers with the workflow the first request made, and makes nothing new. The same key with another body answers `409` with `code: "idempotency_key_reused"`.

## Request body

**name** `string`

A few words, at most 40 characters. Left out, the name the lines or the draft give the start, else the first words of `describe`.

**describe** `string`

What it does, in plain words, at most 2,000 characters: what starts it and each step. Orgo’s drafting model writes the lines. Needs a key with AI write as well as Workflows write. Send this or `lines`.

**lines** `string`

The workflow, one JSON object per line, the start first. The format is at [orgo.ai/workflows.md](https://www.orgo.ai/workflows.md). Send this or `describe`.

**time\_zone** `string`

An IANA zone its times are read in, like `America/New_York`. You can also set it later with [Update a workflow](https://docs.orgo.ai/api-reference/workflows/update.md).

## Response

`201`, with the version in the `ETag` header.

**id** `string`

The workflow’s id.

**name** `string | null`

Its name.

**on** `boolean`

`false`: a new workflow is off.

**version** `integer`

Send it as `If-Match` on a later write.

**lines** `string`

The workflow as kept, one JSON object per step.

**settings** `object`

What it asks for once, name to value. Empty for a new workflow.

**to\_fix** `string[]`

What still has to be done before it can run, in plain words, like `Fill in channel`.

**problems** `object[]`

The same, each with the `step` it is on and `say`. A setting to fill in is on the start.

**dropped** `string[]`

Present when something you sent was left out or rewritten, naming each.

## Example

```bash cURL theme={null}
curl -X POST https://www.orgo.ai/api/workflows \
  -H "Authorization: Bearer $ORGO_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{"name":"Morning report","describe":"Every weekday at 9 AM, write a short report on yesterday’s new customers and post it in #sales on Slack."}'
```

```python Python theme={null}
import os, uuid, requests

r = requests.post(
    "https://www.orgo.ai/api/workflows",
    headers={
        "Authorization": f"Bearer {os.environ['ORGO_API_KEY']}",
        "Idempotency-Key": str(uuid.uuid4()),
    },
    json={"name": "Morning report", "lines": open("morning-report.jsonl").read()},
)
workflow = r.json()
print(workflow["id"], workflow["to_fix"])
```

```javascript JavaScript theme={null}
import { readFileSync } from "node:fs";

const r = await fetch("https://www.orgo.ai/api/workflows", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.ORGO_API_KEY}`,
    "Content-Type": "application/json",
    "Idempotency-Key": crypto.randomUUID(),
  },
  body: JSON.stringify({ name: "Morning report", lines: readFileSync("morning-report.jsonl", "utf8") }),
});
const workflow = await r.json();
```

### Response

```json theme={null}
{
  "id": "morning-report",
  "name": "Morning report",
  "on": false,
  "version": 1,
  "lines": "{\"id\":\"a\",\"kind\":\"start\",\"title\":\"9:00 AM\",\"sub\":\"Weekdays\",\"name\":\"Morning report\"}\n{\"id\":\"b\",\"after\":[\"a\"],\"kind\":\"agent\",\"agent\":\"hermes\",\"title\":\"Write the report\",\"task\":\"Write a short report on yesterday’s new customers.\"}\n{\"id\":\"c\",\"after\":[\"b\"],\"kind\":\"app\",\"app\":\"slack\",\"title\":\"Post\",\"where\":\"{channel}\",\"message\":\"{report}\"}",
  "settings": {},
  "to_fix": ["Fill in channel"],
  "problems": [{ "step": "a", "say": "Fill in channel" }]
}
```

## Errors

Every error is `{ "error", "code" }`, often with `say` (a few words) and `next` (the call that fixes it).

| Status | Code | When |
| - | - | - |
| `400` | `invalid_body` | Neither `describe` nor `lines`, or both; a name with no letters or digits; `describe` past 2,000 characters; or an `Idempotency-Key` that is not 8 to 255 printable characters. |
| `401` | | No key, or a key Orgo doesn’t know. |
| `403` | `key_permission` | A restricted key without Workflows write, or `describe` from a key without AI write. |
| `404` | (no body) | Workflows aren’t open to your account. |
| `409` | `already_exists` | A workflow with that id exists. The body carries its `id`; change it with [Replace a workflow’s steps](https://docs.orgo.ai/api-reference/workflows/replace.md), or pick another name. |
| `409` | `reserved_name` | The name would take one of Orgo’s own ids, like `live` or `draft`. |
| `409` | `too_many_workflows` | You have 200 workflows, the most an account can have. |
| `409` | `idempotency_key_reused` | That key was used with another body. |
| `409` | `idempotency_busy` | A request with that key is still going. Retry after `retry_after` seconds. |
| `413` | `body_too_large` | The body is over 128 KB. |
| `422` | `invalid_lines` | Lines that could not be read, named in `dropped`. Nothing was made. |
| `422` | `draft_unusable` | The description could not be drafted as a workflow. Say it another way, naming the start and each step. |
| `429` | `rate_limited` | Too many writes or drafts. Carries `Retry-After`. |
| `502` | `draft_failed` | The drafting model didn’t answer. Nothing was made. Retry. |
| `503` | `draft_unconfigured` | Drafting isn’t set up here. Send `lines`. |
| `503` | | Orgo couldn’t verify the key because of a server-side fault. Retry. |


## OpenAPI

````yaml POST /workflows
openapi: 3.1.0
info:
  title: Orgo API
  description: >-
    Launch cloud computers that AI agents can control and interact with. Create
    workspaces, provision computers, and control them programmatically.
  version: 2.0.0
  contact:
    name: Orgo Support
    email: contact@orgo.ai
    url: https://orgo.ai
servers:
  - url: https://www.orgo.ai/api
    description: Production
security:
  - bearerAuth: []
tags:
  - name: Support
    description: >-
      Orgo’s support agent, for programs: ask how to do something in Orgo and
      get an answer with full URLs and copyable commands.
  - name: Account
    description: >-
      Account capacity: how many computers an account may run, and adding or
      giving back more.
  - name: Agent accounts
    description: >-
      Accounts an AI agent makes for itself, and the claim link a person uses to
      take one over.
  - name: Clients
    description: >-
      Run Orgo for your clients from your own app: a workspace and scoped key
      each, billed to you or to them.
  - name: Workspaces
    description: Organize computers into named workspaces
  - name: Computers
    description: Provision and manage virtual computers
  - name: Computer Lifecycle
    description: Start, stop, and restart computers
  - name: Computer Actions
    description: Control mouse, keyboard, and execute commands
  - name: Screens
    description: >-
      More than one desktop on a single computer. Each screen is its own X
      server with its own cursor and window manager, so an agent working on one
      cannot disturb another.
  - name: Files
    description: Upload and download files
  - name: Templates
    description: Author, build, and launch reproducible computers from templates
  - name: Chat
    description: Run an agent on a computer through OpenAI-compatible chat completions.
  - name: Workflows
    description: >-
      Routines that run the same way every time: a start, then steps. Make them
      from plain words or lines, check them, run them and follow their runs (in
      preview).
paths:
  /workflows:
    post:
      tags:
        - Workflows
      summary: Make a workflow from plain words or from its lines
      description: >-
        Body: describe (plain words: Orgo drafts the steps) or lines (one JSON
        object per step, the start first; the format is at
        https://www.orgo.ai/workflows.md), and name. Its id is its name in
        lowercase words joined by - (Morning report: morning-report); with no
        name, the name its lines or the draft give it, else the first words of
        describe. A new workflow is off: check it (POST
        /api/workflows/{id}/validate), then turn it on with PATCH { "on": true
        }. describe takes a key with AI write too (403 key_permission). Send an
        Idempotency-Key (8 to 255 printable characters) so a retry answers with
        the workflow the first request made; the same key with another body is
        409 idempotency_key_reused.
      parameters:
        - name: Idempotency-Key
          in: header
          required: false
          schema:
            type: string
            minLength: 8
            maxLength: 255
          description: >-
            A retry with the same key and body answers as the first request did,
            for a day.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateWorkflow'
            examples:
              describe:
                summary: From plain words
                value:
                  name: Morning report
                  describe: >-
                    Every weekday at 9 AM, read yesterday’s new Stripe customers
                    and post a summary in #sales on Slack.
              lines:
                summary: From its lines
                value:
                  name: Morning report
                  lines: >-
                    {"id":"a","kind":"start","title":"9:00
                    AM","sub":"Weekdays","name":"Morning report"}

                    {"id":"b","after":["a"],"kind":"agent","agent":"hermes","title":"Write
                    the report","task":"Write a short report on yesterday’s new
                    customers."}

                    {"id":"c","after":["b"],"kind":"app","app":"slack","title":"Post","where":"{channel}","message":"{report}"}
      responses:
        '201':
          description: The workflow, made.
          headers:
            ETag:
              description: The version, quoted.
              schema:
                type: string
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Workflow'
              example:
                id: morning-report
                name: Morning report
                'on': false
                version: 3
                lines: >-
                  {"id":"a","kind":"start","title":"9:00
                  AM","sub":"Weekdays","name":"Morning report"}

                  {"id":"b","after":["a"],"kind":"agent","agent":"hermes","title":"Write
                  the report","task":"Write a short report on yesterday’s new
                  customers."}

                  {"id":"c","after":["b"],"kind":"app","app":"slack","title":"Post","where":"{channel}","message":"{report}"}
                settings: {}
                to_fix:
                  - Fill in channel
                problems:
                  - step: a
                    say: Fill in channel
        '400':
          description: >-
            Neither describe nor lines, or both, or a name with no letters or
            digits (invalid_body); an Idempotency-Key that is not 8 to 255
            printable characters.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/WorkflowError'
        '401':
          description: Unauthenticated (with WWW-Authenticate and docs).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/WorkflowError'
        '403':
          description: >-
            A key without Workflows access at this level (key_permission); a key
            that may not act on the workflow’s computer (key_permission: Control
            write and AI write, or computer_key_held).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/WorkflowError'
        '404':
          description: Workflows are not open to this account (a bare 404, no body).
        '409':
          description: >-
            One by that id already exists (already_exists, with id), a name kept
            for the API’s own paths (reserved_name, like live or draft), or an
            Idempotency-Key already used with another body
            (idempotency_key_reused) or still going (idempotency_busy).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/WorkflowError'
        '413':
          description: >-
            The body is too large (body_too_large): at most 64 KB, 128 KB for a
            PUT, 32 KB for an answer.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/WorkflowError'
        '422':
          description: >-
            Lines that could not be read (invalid_lines, with dropped), or a
            description that could not be drafted (draft_unusable). Nothing was
            made.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/WorkflowError'
        '429':
          $ref: '#/components/responses/RateLimited'
        '502':
          description: The drafting model did not answer (draft_failed). Nothing was made.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/WorkflowError'
        '503':
          description: >-
            Drafting is not set up here (draft_unconfigured): send lines. Also
            when Orgo could not verify the credential because of a server-side
            fault (with Retry-After: 5).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/WorkflowError'
components:
  schemas:
    CreateWorkflow:
      type: object
      description: describe or lines, one of the two.
      properties:
        name:
          type: string
          maxLength: 40
        describe:
          type: string
          maxLength: 2000
          description: What it does, in plain words. Orgo drafts the steps.
        lines:
          type: string
          description: >-
            The steps themselves, one JSON object per line
            (https://www.orgo.ai/workflows.md).
        time_zone:
          type: string
          description: An IANA zone its times are read in, like America/New_York.
    Workflow:
      type: object
      required:
        - id
        - name
        - 'on'
        - version
        - lines
        - settings
        - to_fix
        - problems
      properties:
        id:
          type: string
          pattern: ^[a-z0-9-]{1,60}$
        name:
          type:
            - string
            - 'null'
        'on':
          type: boolean
          description: Whether its start runs it. It is on only while it can run.
        version:
          type: integer
          description: Send it as If-Match on a write.
        lines:
          type: string
          description: >-
            The workflow, one JSON object per step, the start first
            (https://www.orgo.ai/workflows.md).
        settings:
          type: object
          additionalProperties:
            type: string
          description: What it asks for once, name to value.
        to_fix:
          type: array
          items:
            type: string
          description: >-
            What still has to be done before it can run, in the person’s words.
            Empty: ready.
        problems:
          type: array
          items:
            type: object
            properties:
              step:
                type: string
                description: 'The step it is on (empty: the whole workflow).'
              say:
                type: string
        turned_off:
          type: boolean
          description: This write left it unable to run, so it was turned off.
        dropped:
          type: array
          items:
            type: string
          description: What of the lines sent was left out or rewritten.
    WorkflowError:
      type: object
      required:
        - error
        - code
      properties:
        error:
          type: string
        code:
          type: string
        say:
          type: string
          description: The same, short, for a person.
        next:
          type: string
          description: The call that fixes it.
        to_fix:
          type: array
          items:
            type: string
        problems:
          type: array
          items:
            type: object
        version:
          type:
            - integer
            - 'null'
          description: 'version_conflict: the newest version.'
        lines:
          type:
            - string
            - 'null'
          description: 'version_conflict: the newest lines, to merge into.'
    RateLimited:
      type: object
      required:
        - error
        - code
        - limit
        - retry_after
      properties:
        error:
          type: string
          description: Which limit, in plain words, and when to try again.
        code:
          type: string
          const: rate_limited
        limit:
          type: string
          enum:
            - computer_create_per_minute
            - computer_create_per_hour
            - computer_create_per_day
            - computer_lifecycle_per_minute
            - computer_lifecycle_per_computer_per_minute
            - computer_control_per_minute
            - computer_control_per_computer_per_minute
            - chat_runs_per_minute
            - chat_runs_concurrent
            - workspace_create_per_hour
            - api_other_per_minute
        retry_after:
          type: integer
          minimum: 1
          description: Seconds to wait.
      example:
        error: >-
          Too many API requests this minute (120 a minute on your plan). Try
          again in 12 seconds.
        code: rate_limited
        limit: api_other_per_minute
        retry_after: 12
  responses:
    RateLimited:
      description: >-
        Over one of the account's plan rate limits (`rate_limited`): `limit`
        names it, and `retry_after` and `Retry-After` say how many seconds to
        wait. Limits are per account, the workspace owner's when the request
        acts on a computer or a workspace, and set by its plan. See [Account
        limits and rate limits](/guides/account-limits#plan-rate-limits).
      headers:
        Retry-After:
          $ref: '#/components/headers/RetryAfter'
        RateLimit-Limit:
          $ref: '#/components/headers/RateLimitLimit'
        RateLimit-Remaining:
          $ref: '#/components/headers/RateLimitRemaining'
        RateLimit-Reset:
          $ref: '#/components/headers/RateLimitReset'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/RateLimited'
  headers:
    RetryAfter:
      description: Seconds to wait before asking again.
      schema:
        type: integer
        minimum: 1
    RateLimitLimit:
      description: The tightest limit this request counts against.
      schema:
        type: integer
    RateLimitRemaining:
      description: How many are left of it in this window.
      schema:
        type: integer
    RateLimitReset:
      description: Seconds until its window starts again.
      schema:
        type: integer
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      description: API key authentication. Get your key at orgo.ai/workspaces

````

This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.