---
title: "Generate or edit an app from a text instruction"
method: POST
path: "/workflows/generate"
tags: ["Apps"]
---

# Generate or edit an app from a text instruction

`POST /workflows/generate`

## Request

- Base URL: `https://app.uselamina.ai/v1`
- URL: `https://app.uselamina.ai/v1/workflows/generate`
- Auth: one of:
  - API key in header `x-api-key`
  - HTTP bearer

Analyze a plain-language instruction with the configured workflow planner, assemble a validated workflow graph from the node catalog, and auto-publish it as a private, immediately-runnable app. Returns the app schema; run it via POST /apps/{appId}/runs. Pass baseAppId to EDIT an existing generated app in place instead of building a new one.

## Request body

- object
  - `instruction` string, required: What the app should create — or, with baseAppId, the change to apply (e.g. "add a 9:16 crop output").
  - `baseAppId` string: Edit mode. The appId of a generated app to modify in place (same appId, run history preserved). The planner starts from its current graph and applies the instruction as a targeted edit. Requires creator or workspace owner/admin. Omit to build a new app.
  - `ops` object[]: Edit mode cheap path: explicit edit operations applied deterministically (no planner LLM call, no credit charge). Requires baseAppId; instruction becomes optional. Each item is one of setNodeData / addNode / removeNode / addEdge / removeEdge / addParameter / removeParameter / setParameter.
  - `name` string: Optional preferred app name.
  - `visibility` 'private' | 'shared' | 'public'
  - `provider` 'claude' | 'openai': Planner LLM provider override. Defaults to WFGEN_PROVIDER, then OpenAI.
  - `brandProfileId` string: Bake a specific brand profile's voice, visual anchors, and guardrails into the generated app so it produces on-brand output. Omit to use the workspace's active brand.
  - `run` boolean: One-shot: after generating the app, immediately start a run using `inputs`. Returns a `run` object with the runId — poll GET /runs/{runId}.
  - `inputs` object: Input values keyed by the generated app's parameter `key` (media as URLs, options as labels). Used only when `run` is true.
  - `test` boolean: Sandbox mode (or send header `X-Lamina-Test: true`): validate the request and return a stub app — no planner LLM call, nothing persisted, no credits charged.

## Response `200`

App generated and published

- object
  - `data` object, required
    - `appId` string, uuid, required
    - `name` string, required
    - `description` string, nullable
    - `visibility` 'private' | 'shared' | 'public'
    - `runUrl` string, required
    - `parameters` object[]
    - `outputs` object[]
    - `tier` 'deterministic' | 'fast_edit' | 'recipe' | 'planner': Which path produced this: `deterministic` (explicit ops, no LLM, free) or `planner` (LLM generation).
    - `creditsSpent` number: Credits this generation charged (0 for the deterministic ops path).
    - `editability` object, nullable: Deterministic measure of how tweakable the generated app is — param clarity, grouping, node granularity, output-steerability (planner tier only). A low `score` plus its `notes` is a cue to offer the user a refinement.
      - `score` number: 0–1; higher = more editable.
      - `subscores` object
      - `notes` string[]
    - `run` object, nullable: Present only when `run` was requested.
      - `started` boolean, required
      - `runId` string, uuid
      - `status` string
      - `errors` object[]

## Other responses

- `401`: Missing or invalid API key
- `500`: Internal server error

---

[API](https://skmtc.dev/uselamina/apis/lamina-v1-api.md) · [All operations](https://skmtc.dev/uselamina/apis/lamina-v1-api/llms.txt) · [OpenAPI document](https://skmtc.dev/uselamina/apis/lamina-v1-api/revisions/73b598526531?raw)
