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

# Create a workflow (not imported apps)

> <Info>This API is in beta. Endpoints, fields, and behavior may still change, so avoid depending on it in production.</Info>

Creates a workflow and starts it running.

The new workflow is active immediately, so a scheduled trigger begins firing on its schedule and an event trigger starts listening as soon as this returns. Create it, then call [Toggle workflow status (not imported apps)](/api-reference/toggle-workflow-status-not-imported-apps) if you want it paused instead.

A workflow's `name` is unique per app across everything that is not archived. Reusing a name is rejected.

This is only allowed from the app's main branch.

<Warning>The response includes fields beyond the ones documented here. Don't rely on undocumented response fields, as they can change at any time. Send only the fields documented here. Other request fields are not supported and their behavior can change.</Warning>



## OpenAPI

````yaml /developers/references/app-management/app-management-openapi.json post /api/apps/{app_id}/workflows
openapi: 3.1.0
info:
  title: Base44 App Management API
  version: 1.0.0
servers:
  - url: https://app.base44.com
security:
  - PersonalAccessTokenAuth: []
paths:
  /api/apps/{app_id}/workflows:
    post:
      summary: Create a workflow (not imported apps)
      description: >-
        <Info>This API is in beta. Endpoints, fields, and behavior may still
        change, so avoid depending on it in production.</Info>


        Creates a workflow and starts it running.


        The new workflow is active immediately, so a scheduled trigger begins
        firing on its schedule and an event trigger starts listening as soon as
        this returns. Create it, then call [Toggle workflow status (not imported
        apps)](/api-reference/toggle-workflow-status-not-imported-apps) if you
        want it paused instead.


        A workflow's `name` is unique per app across everything that is not
        archived. Reusing a name is rejected.


        This is only allowed from the app's main branch.


        <Warning>The response includes fields beyond the ones documented here.
        Don't rely on undocumented response fields, as they can change at any
        time. Send only the fields documented here. Other request fields are not
        supported and their behavior can change.</Warning>
      operationId: create_workflow_api_apps__app_id__workflows_post
      parameters:
        - name: app_id
          in: path
          required: true
          schema:
            type: string
            description: ID of the app whose workflows you want to work with.
            title: App Id
          description: ID of the app whose workflows you want to work with.
          example: 6820f3a4e7b91d003c45a1f2
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateWorkflowRequest'
      responses:
        '200':
          description: The created workflow.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/WorkflowResponse'
        '401':
          description: Missing or invalid credentials.
        '402':
          description: >-
            This workspace's plan does not include workflows. Upgrade to Builder
            or above.
        '403':
          description: >-
            You don't have access to this app, the app does not exist, or the
            app still runs the older automations engine instead of workflows. A
            missing app and an app you cannot reach are deliberately the same
            answer.
        '404':
          description: >-
            The trigger is a hook, and hooks are not available to you. The code
            is `hook_not_found`.
        '409':
          description: >-
            Another workflow on this app already uses this name, or the app is
            on a branch other than main. Imported apps return
            `dev_loop_managed`: workflows are not supported for this app type.
        '422':
          description: >-
            The definition or trigger is not valid. The body lists what is
            wrong.
        '429':
          description: >-
            Rate limit exceeded. The base limit is 20 requests per minute. See
            [Rate
            limits](/developers/references/apps-api/get-started/rate-limits) for
            the multiplier your plan gets.
      security:
        - PersonalAccessTokenAuth:
            - full_access
        - WorkspaceApiKeyAuth:
            - full_access
        - WorkspaceApiKeyBearerAuth:
            - full_access
components:
  schemas:
    CreateWorkflowRequest:
      properties:
        name:
          type: string
          title: Name
          description: >-
            Name for the workflow. Must be unique among the app's workflows that
            are not archived.
          example: Email me new signups
        description:
          anyOf:
            - type: string
            - type: 'null'
          title: Description
          description: What the workflow is for, in your own words.
          example: Sends an email whenever a User record is created.
        definition:
          additionalProperties: true
          type: object
          title: Definition
          description: >-
            The steps to run, as a CNCF Serverless Workflow v1.0 document. Check
            it with [Validate a workflow
            definition](/api-reference/validate-a-workflow-definition) first.
          example:
            do: []
            document:
              dsl: 1.0.0
              name: notify
              version: 1.0.0
        trigger:
          additionalProperties: true
          type: object
          title: Trigger
          description: >-
            What starts the workflow. The trigger goes inside `config`, whose
            `trigger_type` picks the kind and whose remaining fields configure
            it. Add a top-level `condition` to skip a dispatch unless a jq
            expression over the payload is truthy.
          example:
            config:
              cron_expression: 0 9 * * *
              timezone: UTC
              trigger_type: scheduled
        change_summary:
          anyOf:
            - type: string
            - type: 'null'
          title: Change Summary
          description: >-
            Note describing this version, kept in the workflow's version
            history.
          example: Initial version
      type: object
      required:
        - name
        - definition
        - trigger
      title: CreateWorkflowRequest
    WorkflowResponse:
      properties:
        run_accounting_available:
          type: boolean
          title: Run Accounting Available
          description: >-
            Whether definition-level run counters and last-run fields are
            available. False for hooks: numeric counters are placeholders (0),
            last-run fields are null; use run history instead.
          default: true
        social_post:
          anyOf:
            - $ref: '#/components/schemas/WorkflowSocialPost'
            - type: 'null'
          description: >-
            Current post content for a social publishing workflow, or `null`
            when no linked post is available.
        id:
          type: string
          title: Id
          description: ID of the workflow.
          example: 68b1c0d4e7b91d003c45a1f2
        app_id:
          type: string
          title: App Id
          description: ID of the app the workflow belongs to.
          example: 6820f3a4e7b91d003c45a1f2
        file_key:
          anyOf:
            - type: string
            - type: 'null'
          title: File Key
          description: >-
            Name of the workflow's file in the app's code. This is `null` on
            workflows saved before files were kept.
          example: email-me-new-signups
        name:
          type: string
          title: Name
          description: Name of the workflow.
          example: Email me new signups
        description:
          anyOf:
            - type: string
            - type: 'null'
          title: Description
          description: What the workflow is for.
          example: Sends an email whenever a User record is created.
        status:
          type: string
          title: Status
          description: >-
            Whether the workflow runs: `active`, `inactive`, or `archived`. See
            [Workflow
            status](/developers/references/apps-api/sections/workflows#workflow-status)
            for what each means and how it changes.
          example: active
        status_reason:
          anyOf:
            - type: string
            - type: 'null'
          title: Status Reason
          description: >-
            Why Base44 changed the workflow's status on its own, as one of
            `consecutive_failures`, `end_condition_reached`,
            `migration_activation_failed`, `workflows_not_available`,
            `app_blocked`, or `connector_disconnected`. This is `null` when you
            changed the status yourself. See [Workflow
            status](/developers/references/apps-api/sections/workflows#workflow-status)
            for what each code means.
          example: consecutive_failures
        current_version_id:
          anyOf:
            - type: string
            - type: 'null'
          title: Current Version Id
          description: >-
            Version the workflow runs today, as the SHA-256 hash of that
            definition. This is `null` until a definition is saved.
          example: 9f2c1a7b3e5d84f60c1b2a9e7d4f8c3b6a5e2d1f0c9b8a7e6d5c4b3a2f1e0d9c
        trigger:
          additionalProperties: true
          type: object
          title: Trigger
          description: >-
            What starts the workflow. The trigger sits under `config`, keyed by
            `trigger_type`.
          example:
            config:
              cron_expression: 0 9 * * *
              timezone: UTC
              trigger_type: scheduled
        app_type_context:
          anyOf:
            - additionalProperties: true
              type: object
            - type: 'null'
          title: App Type Context
          description: >-
            Caller-specific context captured when the workflow was created, such
            as the conversation that authored it. This API never sets it, so a
            workflow you create through it starts with `null`. Updating a
            workflow through this API doesn't clear an existing value either, so
            a workflow originally authored through the Base44 app editor or a
            superagent keeps its context here even after an API update.
          example:
            anchor_message_id: 68b1c0d4e7b91d003c45a1f2
            conversation_id: 0195f2a1-4c3e-7b21-9f0d-2a5c8e1b4d77
        last_run_at:
          anyOf:
            - type: string
              format: date-time
            - type: 'null'
          title: Last Run At
          description: >-
            When the workflow last started running, as an ISO 8601 UTC
            timestamp. This is `null` before its first run or for hooks; use run
            history for hooks.
          example: '2026-08-25T09:12:44Z'
        last_run_status:
          anyOf:
            - type: string
            - type: 'null'
          title: Last Run Status
          description: >-
            How the workflow's most recent run ended: `success`, `failed`, or
            `cancelled`. This is `null` before the first run or for hooks; use
            run history for hooks. See [Workflow
            status](/developers/references/apps-api/sections/workflows#workflow-status)
            for how this compares to a run's own `status`.
          example: success
        consecutive_failures:
          type: integer
          title: Consecutive Failures
          description: >-
            Runs that have failed in a row. Resets on the next success.
            Unavailable when `run_accounting_available` is false; the
            placeholder is 0.
          default: 0
          example: 0
        total_runs:
          type: integer
          title: Total Runs
          description: >-
            Runs the workflow has started, ever. Unavailable when
            `run_accounting_available` is false; the placeholder is 0.
          default: 0
          example: 48
        successful_runs:
          type: integer
          title: Successful Runs
          description: >-
            Runs that finished successfully, ever. Unavailable when
            `run_accounting_available` is false; the placeholder is 0.
          default: 0
          example: 44
        failed_runs:
          type: integer
          title: Failed Runs
          description: >-
            Runs that ended in an error, ever. Unavailable when
            `run_accounting_available` is false; the placeholder is 0.
          default: 0
          example: 3
        created_date:
          anyOf:
            - type: string
              format: date-time
            - type: 'null'
          title: Created Date
          description: When the workflow was created, as an ISO 8601 UTC timestamp.
          example: '2026-07-02T11:04:00Z'
        updated_date:
          anyOf:
            - type: string
              format: date-time
            - type: 'null'
          title: Updated Date
          description: When the workflow was last changed, as an ISO 8601 UTC timestamp.
          example: '2026-08-20T16:31:00Z'
        created_by:
          anyOf:
            - type: string
            - type: 'null'
          title: Created By
          description: Email of whoever created the workflow.
          example: you@example.com
        definition:
          anyOf:
            - additionalProperties: true
              type: object
            - type: 'null'
          title: Definition
          description: >-
            The steps the workflow runs, as a CNCF Serverless Workflow v1.0
            document. This is `null` when no version has been saved yet. Only
            this endpoint returns it. [List
            workflows](/api-reference/list-workflows) leaves it out.
          example:
            do: []
            document:
              dsl: 1.0.0
              name: notify
              version: 1.0.0
      type: object
      required:
        - id
        - app_id
        - name
        - status
      title: WorkflowResponse
    WorkflowSocialPost:
      properties:
        platform:
          type: string
          title: Platform
          description: Social network the post will be published to.
          example: linkedin
        title:
          type: string
          title: Title
          description: Title of the scheduled post.
          example: Meet our new app
        body:
          type: string
          title: Body
          description: Current text of the scheduled post, before its hashtags.
          example: Our new app is ready to try.
        hashtags:
          items:
            type: string
          type: array
          title: Hashtags
          description: Hashtags appended when publishing the post.
          example:
            - launch
      type: object
      required:
        - platform
        - title
        - body
        - hashtags
      title: WorkflowSocialPost
  securitySchemes:
    PersonalAccessTokenAuth:
      type: http
      scheme: bearer
      description: >-
        Personal access token, sent as `Authorization: Bearer <token>`. Each
        operation lists the permission it needs: `read_only` or `full_access`. A
        full-access token can call every operation. A read-only token can call
        only the operations that list `read_only`; anything else returns 403
        `read_only_credential_route_not_allowed`.
    WorkspaceApiKeyAuth:
      type: apiKey
      in: header
      name: api_key
      description: >-
        Workspace API key, sent as `api_key: <key>`. Each operation that accepts
        one lists what the key needs: a permission, `read_only` or
        `full_access`, like a personal access token, or a scope. A key without
        the scope gets 403 `workspace_api_key_scope_required`.
    WorkspaceApiKeyBearerAuth:
      type: http
      scheme: bearer
      description: >-
        Workspace API key, sent as `Authorization: Bearer <key>`. Accepted
        wherever `api_key` is, with the same permission.

````

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