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

# Run App

> Start an asynchronous app execution. Returns immediately with an execution ID
and pre-created output placeholders.

**Providing inputs:**
- Use the `inputs` object with parameter **names** as keys (from the Get App response)
- For `options` parameters, send the **option label** (e.g. `"Caucasian"`, not an internal value)
- For `url` parameters, send a publicly accessible URL
- For `text` parameters, send a string value
- Omit optional parameters to use their defaults

**After starting:**
You can poll `GET /v1/runs/{runId}` every 3-5 seconds, use a **webhook**
to receive results automatically, stream via `GET /v1/runs/{runId}/stream`,
or combine approaches -- they all work side by side.

**Webhook (optional, recommended for agents):**
Pass `?webhook=https://your-server.com/callback` as a query parameter. When the execution
completes, we POST the results to your URL -- same structure as the polling response, signed
with ED25519 for verification. The polling endpoint still works regardless, so you can use
it as a fallback or for safety checks. See the Webhook Verification endpoint for details.


Start an execution of a specific app. You choose the app and provide exact inputs. For automatic app selection, use `POST /v1/content/create` instead.

Key each field in `inputs` by the parameter's `key` (stable snake\_case identifier) or `name` from `GET /v1/apps/{appId}`. Prefer `key` when present — it never changes, while `name` is a display label and matches case-sensitively.

## Getting results

| Method                                    | Best for                                                  |
| ----------------------------------------- | --------------------------------------------------------- |
| **Wait** — `GET /v1/runs/{id}/wait`       | Agents. Blocks until done, no polling loop.               |
| **Webhook** — pass `?webhook=<url>`       | Production. Results POST to your URL on completion.       |
| **SSE** — `GET /v1/runs/{id}/stream`      | Real-time UIs. Server-Sent Events with per-node progress. |
| **Poll** — `GET /v1/runs/{id}` every 3-5s | Fallback when none of the above fit.                      |


## OpenAPI

````yaml POST /v1/apps/{appId}/runs
openapi: 3.1.0
info:
  title: Lamina Apps API
  version: 1.0.0
  description: >
    Professional creative content production for AI agents. Create brand-aligned
    images, videos, and designs from natural-language briefs using 30+
    specialized AI pipelines.


    Unlike raw model APIs (DALL-E, Flux, Kling), Lamina automatically applies
    brand guidelines, selects the optimal multi-model pipeline, scores output
    quality, and delivers permanent CDN-hosted URLs with composability metadata
    for chaining.


    ## Authentication

    All endpoints require an API key passed via one of these headers:

    - `x-api-key: lma_your_key` (recommended)

    - `Authorization: Bearer lma_your_key`


    API keys are workspace-scoped. Create them in **Settings -> API Keys**.


    ## Quick Start (One-Call Path)

    `POST /v1/create` with `{ "brief": "product photo of sneakers", "sync": true
    }` — returns completed output inline with CDN URL.


    ## Quick Start (Advanced)

    1. `GET /v1/apps` -- browse 30+ specialized creative apps

    2. `GET /v1/apps/{appId}` -- inspect input parameters

    3. `POST /v1/apps/{appId}/runs?webhook=<url>` -- run with your inputs

    4. Receive results via webhook, poll `GET /v1/runs/{runId}`, or stream via
    `GET /v1/runs/{runId}/stream`


    ## Rate Limits

    All `/v1/*` endpoints are currently limited to 100 requests per minute per
    IP.

    On `429`, read the `RateLimit-*` and `Retry-After` headers before retrying.


    ## How Inputs Work

    When running an app, provide inputs as a JSON object keyed by parameter
    **name** (from the app details response).


    - **text** parameters: send a string value (e.g. a prompt or description)

    - **options** parameters: send the **label** of the option (e.g.
    `"Caucasian"`), not an internal value

    - **url** parameters: send a publicly accessible URL to an image or video


    Every parameter is returned with `required: true`. Parameters with a
    `default` can safely be omitted -- the app will use the default value.


    ## Endpoint Groups

    | Group | Purpose |

    |-------|---------|

    | **Apps** | Discover and inspect available content creation apps |

    | **Runs** | Run workflows, track progress, and retrieve results |

    | **Assets** | Browse generated images, videos, and text from past
    executions |

    | **Intelligence** | Brand context, performance prediction, recommendations,
    and trends |

    | **Publishing** | Publish content to connected social channels |

    | **Content** | One-call agent operations: create, score, brief, batch |

    | **Account** | Credit balance and rate limit visibility |

    | **Templates** | Content creation templates and strategies |

    | **Webhooks** | Webhook signature verification |
servers:
  - url: https://app.uselamina.ai
    description: Production
security:
  - apiKey: []
tags:
  - name: Create
    description: Create content from briefs, run specific apps, and use templates
  - name: Discover
    description: Find and inspect available apps and their input schemas
  - name: Track
    description: Monitor execution progress, retrieve results, and browse generated assets
  - name: Intelligence
    description: >-
      Brand context, performance prediction, content recommendations, and trend
      signals
  - name: Distribute
    description: Publish content to social channels and transfer assets to CDN
  - name: Score
    description: Evaluate content quality, brand alignment, and engagement potential
  - name: Account
    description: Credit balance, rate limits, and health checks
  - name: Webhooks
    description: Webhook signature verification for secure callback handling
paths:
  /v1/apps/{appId}/runs:
    post:
      tags:
        - Create
      summary: Run App
      description: >
        Start an asynchronous app execution. Returns immediately with an
        execution ID

        and pre-created output placeholders.


        **Providing inputs:**

        - Use the `inputs` object with parameter **names** as keys (from the Get
        App response)

        - For `options` parameters, send the **option label** (e.g.
        `"Caucasian"`, not an internal value)

        - For `url` parameters, send a publicly accessible URL

        - For `text` parameters, send a string value

        - Omit optional parameters to use their defaults


        **After starting:**

        You can poll `GET /v1/runs/{runId}` every 3-5 seconds, use a **webhook**

        to receive results automatically, stream via `GET
        /v1/runs/{runId}/stream`,

        or combine approaches -- they all work side by side.


        **Webhook (optional, recommended for agents):**

        Pass `?webhook=https://your-server.com/callback` as a query parameter.
        When the execution

        completes, we POST the results to your URL -- same structure as the
        polling response, signed

        with ED25519 for verification. The polling endpoint still works
        regardless, so you can use

        it as a fallback or for safety checks. See the Webhook Verification
        endpoint for details.
      operationId: executeApp
      parameters:
        - $ref: '#/components/parameters/appId'
        - name: webhook
          in: query
          required: false
          schema:
            type: string
            format: uri
          description: >
            URL to receive execution results when complete. We POST the same
            payload

            as the polling endpoint, signed with ED25519. Must be https or http.
          example: https://your-server.com/lamina-callback
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                inputs:
                  type: object
                  description: >
                    Parameter values keyed by parameter **name** (from the Get
                    App response).

                    Keys are case-sensitive and must match exactly.
                  additionalProperties: true
                  example:
                    Upload: https://example.com/my-photo.jpg
                    Style: Disney / Pixar
                    Aspect Ratio: '1:1'
              required:
                - inputs
            example:
              inputs:
                Upload: https://example.com/my-photo.jpg
                Style: Disney / Pixar
                Aspect Ratio: '1:1'
      responses:
        '202':
          description: >-
            Run started. Poll `GET /v1/runs/{runId}` or stream via SSE for
            results.
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: '#/components/schemas/ExecutionStarted'
              example:
                data:
                  runId: fc32ae7d-6840-4be3-8fb1-539a60e33fc3
                  workflowId: 80d4d454-8844-489f-b903-2ad65a414482
                  workflowName: test sync
                  status: queued
                  webhookUrl: https://your-server.com/lamina-callback
                  outputs:
                    - id: aiDesignerNode-1773051929782-5yzqjkwpm
                      label: AI Designer
                      type: pending
                      value: null
                      status: pending
                      error: null
                    - id: aiDesignerNode-1773132653203-v9hn959pe
                      label: AI Designer
                      type: pending
                      value: null
                      status: pending
                      error: null
        '400':
          description: |
            Invalid inputs. The `details` array lists each validation error,
            including which parameter failed and the valid options.
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                  details:
                    type: array
                    items:
                      type: string
              example:
                error: Invalid inputs
                details:
                  - >-
                    "Model Gender": invalid option "Other". Must be one of:
                    Male, Female
                  - >-
                    "Location": invalid option "Space". Must be one of: Studio,
                    Urban, Park, Indoors, Beach
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
        '429':
          $ref: '#/components/responses/TooManyRequests'
components:
  parameters:
    appId:
      name: appId
      in: path
      required: true
      schema:
        type: string
        format: uuid
      description: The app ID (UUID) from the List Apps response
  schemas:
    ExecutionStarted:
      type: object
      description: Returned when execution starts. All output values are null initially.
      required:
        - runId
        - workflowId
        - status
      properties:
        runId:
          type: string
          format: uuid
          description: >-
            Use this to poll `GET /v1/runs/{runId}` or stream via SSE for
            results.
        workflowId:
          type: string
          format: uuid
          description: The app that was executed
        workflowName:
          type: string
          description: App name
        status:
          type: string
          enum:
            - queued
          description: Always `queued` initially.
        webhookUrl:
          type: string
          nullable: true
          description: >-
            The webhook URL that will receive results (if provided in the
            request).
        outputs:
          type: array
          description: >-
            Pre-created output placeholders. Values are null until processing
            completes.
          items:
            $ref: '#/components/schemas/Output'
    Output:
      type: object
      description: A single output from a processing node.
      required:
        - id
        - label
        - type
        - status
      properties:
        id:
          type: string
          description: Node identifier (matches workflow node `id`)
        label:
          type: string
          description: Human-readable name
        type:
          type: string
          description: |
            `pending` -- not yet produced (still processing)
            `image` -- `value` is a URL to a generated image
            `video` -- `value` is a URL to a generated video
            `text` -- `value` is generated text content
        value:
          description: The output content. Null while `status` is `pending`.
          nullable: true
        status:
          type: string
          enum:
            - pending
            - completed
            - error
          description: |
            `pending` -- still processing
            `completed` -- result ready in `value`
            `error` -- failed, check `error` field
        error:
          type: string
          nullable: true
          description: Error message if this output failed. Null on success.
  responses:
    Unauthorized:
      description: Missing or invalid API key
      content:
        application/json:
          schema:
            type: object
            properties:
              error:
                type: string
          example:
            error: Invalid API key
    NotFound:
      description: Resource not found
      content:
        application/json:
          schema:
            type: object
            properties:
              error:
                type: string
          example:
            error: App not found
    TooManyRequests:
      description: >-
        Rate limit exceeded. All `/v1/*` endpoints are currently limited to 100
        requests per minute per IP.
      headers:
        RateLimit-Policy:
          description: Active rate limit policy.
          schema:
            type: string
            example: 100;w=60
        RateLimit-Limit:
          description: Max requests allowed in the current window.
          schema:
            type: integer
            example: 100
        RateLimit-Remaining:
          description: Requests remaining in the current window.
          schema:
            type: integer
            example: 0
        RateLimit-Reset:
          description: Seconds until the current window resets.
          schema:
            type: integer
            example: 60
        Retry-After:
          description: Seconds to wait before retrying.
          schema:
            type: integer
            example: 60
      content:
        text/plain:
          schema:
            type: string
          example: Too many requests from this IP, please try again in a minute
  securitySchemes:
    apiKey:
      type: apiKey
      in: header
      name: x-api-key
      description: 'Workspace API key. Prefix: `lma_`. Example: `lma_abc123...`'

````