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

# Publish the Draft of a Workflow

> Checks the draft and, when nothing stops it, makes it the next version and the one new visitors get. Versions never
change once published. A visitor already partway through keeps the version they started on (for up to 30 days).
The check reads what each composition can do right now (a table the visitor adds to, a goal the widget reports,
the websites it may be embedded on), so a workflow never goes live pointing at something that has gone.
It is refused with 422 (`BUSINESS_OPERATION_INVALID`) when the draft has errors; the `issues` in the error's
`details` name the blocks to fix: an unconnected trigger, a condition without rules, a composition that is not
published, a field or action that is gone, a composition whose allowed websites exclude the site the workflow
starts on. Nothing is published when the draft has no changes since the live version.
The `revision` is the one the editor read, and a publish of a draft that has moved on is refused with 409.
For personal workspace, use 'personal' as workspaceId.
For organization workspace, use the organization UUID as workspaceId. Any active member can publish.




## OpenAPI

````yaml /openapi/widgetic-api-public.json post /workspaces/{workspaceId}/workflows/{workflowId}/publish
openapi: 3.0.0
info:
  title: Widgetic API Gateway
  version: 1.0.0
  description: API documentation for the Widgetic API Gateway
  license:
    name: Widgetic Integration License
    url: https://docs.widgetic.com/resources/license
servers:
  - url: https://api.widgetic.com/v1
    description: Production server
    variables:
      env:
        default: production
        description: Environment
      apiUrl:
        default: https://api.widgetic.com
        description: API URL
      apiVersion:
        default: /v1
        description: API Version path prefix
security: []
tags: []
paths:
  /workspaces/{workspaceId}/workflows/{workflowId}/publish:
    post:
      tags:
        - Workflows
      summary: Publish the Draft of a Workflow
      description: >
        Checks the draft and, when nothing stops it, makes it the next version
        and the one new visitors get. Versions never

        change once published. A visitor already partway through keeps the
        version they started on (for up to 30 days).

        The check reads what each composition can do right now (a table the
        visitor adds to, a goal the widget reports,

        the websites it may be embedded on), so a workflow never goes live
        pointing at something that has gone.

        It is refused with 422 (`BUSINESS_OPERATION_INVALID`) when the draft has
        errors; the `issues` in the error's

        `details` name the blocks to fix: an unconnected trigger, a condition
        without rules, a composition that is not

        published, a field or action that is gone, a composition whose allowed
        websites exclude the site the workflow

        starts on. Nothing is published when the draft has no changes since the
        live version.

        The `revision` is the one the editor read, and a publish of a draft that
        has moved on is refused with 409.

        For personal workspace, use 'personal' as workspaceId.

        For organization workspace, use the organization UUID as workspaceId.
        Any active member can publish.
      operationId: publishWorkspaceWorkflow
      parameters:
        - $ref: '#/components/parameters/WorkflowWorkspaceId'
        - $ref: '#/components/parameters/WorkflowId'
        - $ref: '#/components/parameters/IdempotencyKeyRequired'
        - $ref: '#/components/parameters/ManagedUserScopeId'
        - $ref: '#/components/parameters/ManagedUserScopeExternalId'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - revision
              properties:
                revision:
                  type: integer
                  minimum: 1
      responses:
        '200':
          description: >-
            Published; the answer holds the workflow, the new version and any
            advice
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                    example: true
                  data:
                    $ref: '#/components/schemas/WorkflowPublishResult'
                  meta:
                    $ref: '#/components/schemas/ResponseMeta'
                required:
                  - success
                  - data
        '400':
          description: >-
            The workspace is neither "personal" nor an organization id, or the
            revision is missing
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '403':
          description: >-
            Forbidden - Not a member of this organization, the plan does not
            include workflows (`AUTHZ_PLAN_RESTRICTION`), or the call is made
            for one managed user (`X-Managed-User-Id`) in a workspace other than
            `personal` (`MANAGED_USER_SCOPE_ROUTE_NOT_AVAILABLE`)
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: No such workflow in this workspace
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '409':
          description: >-
            The draft changed since `revision`, it is archived, or there is
            nothing new to publish (BUSINESS_STATE_CONFLICT; `details.reason`
            says which). When the draft changed, `details.currentRevision` is
            the revision to start again from and, for a workflow of an
            organization workspace, `details.lastEditedBy` and
            `details.lastEditedAt` say who saved first and when.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '422':
          description: >-
            The draft cannot be published as it is; `details.issues` lists what
            to fix (WorkflowIssue), and nothing has changed
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '503':
          description: Workflows cannot be used on this server right now
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
      security:
        - apiKeyAuth: []
components:
  parameters:
    WorkflowWorkspaceId:
      name: workspaceId
      in: path
      required: true
      description: >
        The workspace: 'personal' for your own workspace, or the UUID of an
        organization. A call made for one of your

        managed users (`X-Managed-User-Id`) always uses 'personal': a managed
        user has no other workspace, and a call

        that names an organization is refused with 403.
      schema:
        type: string
      example: personal
    WorkflowId:
      name: workflowId
      in: path
      required: true
      description: The workflow's id
      schema:
        type: string
        format: uuid
    IdempotencyKeyRequired:
      in: header
      name: Idempotency-Key
      required: true
      description: >-
        Required: a call without it is refused with `400`. A key of your own
        that names this one request; a UUID is ideal. It is 8 to 50 characters
        of letters, digits, `-` and `_`. Send the same key again when you retry
        (after a timeout, a dropped connection or a `5xx`) and the call is
        carried out once: the retry gets the first answer back, marked
        `X-Idempotency-Cached: true`. The same key with a different body is
        refused with `422`, and a retry that arrives while the first call is
        still running with `409` (see `Retry-After`).
      schema:
        type: string
        minLength: 8
        maxLength: 50
        pattern: ^[a-zA-Z0-9_-]{8,50}$
        example: 9b2d6f0a-3c41-4e5a-8d77-1f2e3a4b5c6d
    ManagedUserScopeId:
      in: header
      name: X-Managed-User-Id
      required: false
      description: >-
        The id Widgetic gave the managed user (`POST /managed-users`). Makes
        this call for one of your managed users, so that a mistake in your own
        code cannot reach another customer's work. Send this header, or the
        other one, never both. Left out, the call works on your whole account,
        as it always has. With it, the call reaches only that user's
        compositions and workflows: a list shows only theirs, a composition or a
        workflow the call makes is filed under them, and one of another user, or
        one that does not exist, answers `404` (the same answer, so the call
        cannot be used to find out what another customer has). A managed user
        that is not yours answers `404` with `MANAGED_USER_NOT_FOUND`. An empty,
        repeated or malformed header is `400` with `MANAGED_USER_SCOPE_INVALID`;
        an empty header is never read as no header. A call that is about the
        whole account, such as the list of your managed users, is refused with
        `403` and `MANAGED_USER_SCOPE_ROUTE_NOT_AVAILABLE`: send it without the
        header. Only your API key can send it. The header is a limit the call
        asks for: whoever holds the key can leave it out, so for a credential
        that a customer's browser holds, use an editor session. An
        `Idempotency-Key` is kept apart for each managed user.
      schema:
        type: string
        format: uuid
        example: 3f2b8c1e-7a4d-4e0b-9c55-2d1a6b7e8f90
    ManagedUserScopeExternalId:
      in: header
      name: X-Managed-User-External-Id
      required: false
      description: >-
        Your own id for the managed user (its `externalId`), when you do not
        keep Widgetic's. Makes this call for one of your managed users, so that
        a mistake in your own code cannot reach another customer's work. Send
        this header, or the other one, never both. Left out, the call works on
        your whole account, as it always has. With it, the call reaches only
        that user's compositions and workflows: a list shows only theirs, a
        composition or a workflow the call makes is filed under them, and one of
        another user, or one that does not exist, answers `404` (the same
        answer, so the call cannot be used to find out what another customer
        has). A managed user that is not yours answers `404` with
        `MANAGED_USER_NOT_FOUND`. An empty, repeated or malformed header is
        `400` with `MANAGED_USER_SCOPE_INVALID`; an empty header is never read
        as no header. A call that is about the whole account, such as the list
        of your managed users, is refused with `403` and
        `MANAGED_USER_SCOPE_ROUTE_NOT_AVAILABLE`: send it without the header.
        Only your API key can send it. The header is a limit the call asks for:
        whoever holds the key can leave it out, so for a credential that a
        customer's browser holds, use an editor session. An `Idempotency-Key` is
        kept apart for each managed user.
      schema:
        type: string
        minLength: 1
        maxLength: 255
        example: customer-1042
  schemas:
    WorkflowPublishResult:
      type: object
      required:
        - workflow
        - version
        - warnings
      properties:
        workflow:
          $ref: '#/components/schemas/WorkflowDetail'
        version:
          $ref: '#/components/schemas/WorkflowVersion'
        warnings:
          type: array
          description: >-
            Advice that does not stop publishing, such as a block nothing leads
            to.
          items:
            $ref: '#/components/schemas/WorkflowIssue'
      example:
        workflow: null
        version: null
        warnings:
          - Example WorkflowIssue
    ResponseMeta:
      type: object
      description: >-
        Extra information about the answer: where a page sits in a list, the
        cursor of the next page, or warnings about a call that succeeded with a
        caveat.
      additionalProperties: true
      properties:
        page:
          type: integer
          description: The page that was read, counting from 1.
          example: 1
        size:
          type: integer
          description: How many items one page holds.
          example: 20
        total:
          type: integer
          description: How many items the whole list has.
          example: 135
        limit:
          type: integer
          description: The same as `size`.
          example: 20
        offset:
          type: integer
          description: How many items come before this page.
          example: 0
        hasNextPage:
          type: boolean
          example: true
        hasPreviousPage:
          type: boolean
          example: false
        nextCursor:
          type: string
          nullable: true
          description: >-
            Pass this as `cursor` to read the next page of a list that is read
            by cursor. `null` on the last page.
        warnings:
          type: array
          items:
            type: string
          description: >-
            Things the call did not do, though it succeeded (for example a table
            that could not be created just now).
    ErrorResponse:
      type: object
      required:
        - success
        - message
        - error
      additionalProperties: true
      properties:
        success:
          type: boolean
          description: Always `false` on a failure.
          example: false
        message:
          type: string
          description: The same text as `error.message`, for a caller that reads one line.
        error:
          $ref: '#/components/schemas/ErrorDetail'
    WorkflowDetail:
      allOf:
        - $ref: '#/components/schemas/Workflow'
        - type: object
          required:
            - graph
            - everPublished
          properties:
            graph:
              $ref: '#/components/schemas/WorkflowGraph'
            liveVersion:
              allOf:
                - $ref: '#/components/schemas/WorkflowVersion'
              nullable: true
              description: >-
                The version visitors get, without its graph; null before the
                first publish.
            everPublished:
              type: boolean
              description: >-
                Whether it was ever published (it then has versions and counts,
                and visitors may have run it).
            lastEditedBy:
              type: object
              nullable: true
              description: >
                Who made the latest change to a workflow of an organization
                workspace (a team), so that a teammate who

                opens it can be told "Anna changed this at 14:32". `null` when
                nobody can be named (a change made before

                this was recorded). Left out for a workflow of a personal
                workspace, and whenever it cannot be read just

                now. A save that someone else got ahead of says it in `details`
                of its 409.
              properties:
                id:
                  type: string
                  format: uuid
                  description: The account that made the latest change
                name:
                  type: string
                  nullable: true
                  maxLength: 120
                  description: >-
                    The name on that account, or `null` when it has none or it
                    could not be read just then. Never an email address.
            lastEditedAt:
              type: string
              format: date-time
              nullable: true
              description: >-
                When that latest change was made. Present whenever
                `lastEditedBy` is.
    WorkflowVersion:
      type: object
      description: >-
        One published version of a workflow. Versions never change once
        published.
      required:
        - id
        - versionNumber
        - publishedAt
        - timezone
        - isLive
      properties:
        id:
          type: string
          format: uuid
        versionNumber:
          type: integer
          minimum: 1
        publishedAt:
          type: string
          format: date-time
        publishedBy:
          type: object
          nullable: true
          description: >-
            Who published it; null once that account is gone, and always null
            for an editor session (it works for one customer of a partner, who
            is not told the name of the partner's person).
          properties:
            id:
              type: string
              format: uuid
            name:
              type: string
              nullable: true
        timezone:
          type: string
          example: Europe/Bucharest
        isLive:
          type: boolean
          description: >-
            Whether this is the version visitors who are new to the workflow
            get.
      example:
        id: 3fa85f64-5717-4562-b3fc-2c963f66afa6
        versionNumber: 42
        publishedAt: '2026-01-15T09:30:00.000Z'
        publishedBy: {}
        timezone: Europe/Bucharest
        isLive: true
    WorkflowIssue:
      type: object
      description: >
        Something the check found in a workflow. An `error` stops it being
        published; a `warning` does not. The block

        (`nodeId`), connection (`edgeId`) or rule (`caseId`) it belongs to is
        named so the editor can highlight it.
      required:
        - code
        - severity
      properties:
        code:
          type: string
          example: trigger_no_target
        severity:
          type: string
          enum:
            - error
            - warning
        nodeId:
          type: string
        edgeId:
          type: string
        caseId:
          type: string
        detail:
          type: string
          description: >-
            A short machine-readable detail such as a column or a table name.
            Never a sentence.
      example:
        code: trigger_no_target
        severity: Example severity
        nodeId: Example nodeId
        edgeId: Example edgeId
        caseId: Example caseId
        detail: Example detail
    ErrorDetail:
      type: object
      required:
        - code
        - message
        - timestamp
      properties:
        code:
          type: string
          description: Machine-readable error code.
          example: RESOURCE_NOT_FOUND
        message:
          type: string
          description: Human-readable explanation.
          example: Composition not found
        param:
          type: string
          description: The field that caused the error, when one did.
          example: name
        docUrl:
          type: string
          description: Where this error is explained.
        suggestedAction:
          type: string
          description: What to do about it.
        retryAfter:
          type: integer
          description: >-
            Seconds to wait before trying again (rate limits). The same number
            is in the `Retry-After` header.
          example: 60
        details:
          type: object
          additionalProperties: true
          description: >-
            More about the error: the fields that failed, a limit that was
            reached.
        correlationId:
          type: string
          description: Quote this when you ask support about the call.
          example: req_123e4567-e89b-12d3-a456-426614174000
        timestamp:
          type: string
          format: date-time
          example: '2026-10-15T10:00:00.000Z'
    Workflow:
      type: object
      description: A workflow as the list shows it (without its graph).
      required:
        - id
        - name
        - status
        - revision
        - unpublishedChanges
        - compositionIds
        - blockCount
        - timezone
        - runsCount
        - createdAt
        - updatedAt
      properties:
        id:
          type: string
          format: uuid
        name:
          type: string
          maxLength: 120
        managedUserId:
          type: string
          format: uuid
          nullable: true
          description: >
            The customer of a partner (a managed user) this workflow was made
            for, or null when it is its workspace's own.

            A customer's editor session lists and opens only the workflows filed
            under that customer; the partner's own

            account sees every customer's and tells them apart by this. It is
            set when the workflow is made and never

            changes.
        status:
          $ref: '#/components/schemas/WorkflowStatus'
        revision:
          type: integer
          minimum: 1
          description: >-
            Rises by one with every save. A save, a publish, a discard and a
            restore each name the revision they started from.
        unpublishedChanges:
          type: boolean
          description: Whether the draft differs from the live version.
        compositionIds:
          type: array
          items:
            type: string
            format: uuid
        blockCount:
          type: integer
        timezone:
          type: string
          description: The zone date and time triggers are read in (stored as UTC).
        runsCount:
          type: integer
          description: Visitors who started the workflow, over its whole life.
        liveVersionId:
          type: string
          format: uuid
          nullable: true
        createdAt:
          type: string
          format: date-time
        updatedAt:
          type: string
          format: date-time
        firstPublishedAt:
          type: string
          format: date-time
          nullable: true
        lastPublishedAt:
          type: string
          format: date-time
          nullable: true
        pausedAt:
          type: string
          format: date-time
          nullable: true
        archivedAt:
          type: string
          format: date-time
          nullable: true
      example:
        id: 3fa85f64-5717-4562-b3fc-2c963f66afa6
        name: Example name
        managedUserId: 3fa85f64-5717-4562-b3fc-2c963f66afa6
        status: null
        revision: 42
        unpublishedChanges: true
        compositionIds: []
        blockCount: 42
        timezone: Example timezone
        runsCount: 42
        liveVersionId: 3fa85f64-5717-4562-b3fc-2c963f66afa6
        createdAt: '2026-01-15T09:30:00.000Z'
        updatedAt: '2026-01-15T09:30:00.000Z'
        firstPublishedAt: '2026-01-15T09:30:00.000Z'
        lastPublishedAt: '2026-01-15T09:30:00.000Z'
        pausedAt: '2026-01-15T09:30:00.000Z'
        archivedAt: '2026-01-15T09:30:00.000Z'
    WorkflowGraph:
      type: object
      description: A whole workflow, as the editor saves it and the gateway publishes it.
      required:
        - schemaVersion
        - nodes
        - edges
      properties:
        schemaVersion:
          type: integer
          enum:
            - 1
        nodes:
          type: array
          maxItems: 100
          items:
            $ref: '#/components/schemas/WorkflowNode'
        edges:
          type: array
          maxItems: 300
          items:
            $ref: '#/components/schemas/WorkflowEdge'
      example:
        schemaVersion: 42
        nodes:
          - Example WorkflowNode
        edges:
          - Example WorkflowEdge
    WorkflowStatus:
      type: string
      enum:
        - draft
        - live
        - paused
        - archived
      description: >
        `draft`: never published. `live`: visitors get the live version.
        `paused`: embeds show only their first

        composition (the live version is kept). `archived`: out of the default
        list, kept. A workflow can be deleted

        in any of the four states, with its versions and counts.
    WorkflowNode:
      type: object
      description: >
        A block. A `composition` block shows one composition (exactly one block
        of a workflow has `startsHere`);

        a `trigger` block waits for one thing to happen while the composition
        before it is shown; a `condition`

        block chooses the next step from what the trigger before it carried. At
        most 25 blocks.
      required:
        - id
        - type
      properties:
        id:
          type: string
          pattern: ^[A-Za-z0-9_-]{1,64}$
        type:
          type: string
          enum:
            - composition
            - trigger
            - condition
        position:
          $ref: '#/components/schemas/WorkflowNodePosition'
        compositionId:
          type: string
          format: uuid
          description: The composition a `composition` block shows.
        startsHere:
          type: boolean
          description: Set on the one composition block a visitor starts at.
        trigger:
          $ref: '#/components/schemas/WorkflowTrigger'
        cases:
          type: array
          description: The rules of a `condition` block, in the order they are read.
          items:
            $ref: '#/components/schemas/WorkflowConditionCase'
      example:
        id: Example id
        type: Example type
        position: null
        compositionId: 3fa85f64-5717-4562-b3fc-2c963f66afa6
        startsHere: true
        trigger: null
        cases:
          - Example WorkflowConditionCase
    WorkflowEdge:
      type: object
      description: >-
        A connection from an output port of one block to the input of another.
        Connections run forward only.
      required:
        - id
        - source
        - sourcePort
        - target
      properties:
        id:
          type: string
          pattern: ^[A-Za-z0-9_-]{1,64}$
        source:
          type: string
        sourcePort:
          type: string
          description: >-
            `out` for compositions and triggers; a rule's id, or `default`, for
            conditions.
        target:
          type: string
      example:
        id: Example id
        source: Example source
        sourcePort: Example sourcePort
        target: Example target
    WorkflowNodePosition:
      type: object
      description: Where a block sits on the editor's canvas. Embeds never read it.
      required:
        - x
        - 'y'
      properties:
        x:
          type: number
        'y':
          type: number
      example:
        x: 42
        'y': 42
    WorkflowTrigger:
      type: object
      description: >
        What a trigger block waits for. `input`: a row the visitor adds to a
        table of the composition (`table`).

        `action`: an action the widget reports (`actionId`). `pageEvent`: an
        event the page sends (`name`, and the

        `values` it promises to carry). `scheduled`: a wait or a date
        (`schedule`).
      required:
        - kind
      properties:
        kind:
          type: string
          enum:
            - input
            - action
            - pageEvent
            - scheduled
        table:
          type: string
        actionId:
          type: string
        name:
          type: string
        values:
          type: array
          items:
            type: object
            required:
              - name
              - type
            properties:
              name:
                type: string
              type:
                type: string
                enum:
                  - text
                  - number
                  - boolean
        schedule:
          $ref: '#/components/schemas/WorkflowSchedule'
      example:
        kind: Example kind
        table: Example table
        actionId: Example actionId
        name: Example name
        values: []
        schedule: null
    WorkflowConditionCase:
      type: object
      description: >
        One rule of a condition block, and one path out of it. Rules are read in
        order and the first that matches wins;

        the block's Default output is taken when none does.
      required:
        - id
        - match
        - tests
      properties:
        id:
          type: string
          pattern: ^[A-Za-z0-9_-]{1,64}$
          description: >-
            The output port of the rule. `default` is reserved for the Default
            output.
        label:
          type: string
        match:
          type: string
          enum:
            - all
            - any
          description: '`all` - every comparison must hold; `any` - one is enough.'
        tests:
          type: array
          items:
            $ref: '#/components/schemas/WorkflowConditionTest'
      example:
        id: Example id
        label: Example label
        match: Example match
        tests:
          - Example WorkflowConditionTest
    WorkflowSchedule:
      type: object
      description: >-
        When a Scheduled trigger fires - a wait counted from reaching the step,
        or a fixed moment.
      required:
        - mode
      properties:
        mode:
          type: string
          enum:
            - after
            - at
        amount:
          type: number
          description: How long to wait (mode `after`).
        unit:
          type: string
          enum:
            - seconds
            - minutes
            - hours
            - days
            - weeks
          description: The unit of `amount` (mode `after`).
        at:
          type: string
          format: date-time
          description: The moment to fire at, as an ISO time in UTC (mode `at`).
      example:
        mode: Example mode
        amount: 42
        unit: Example unit
        at: '2026-01-15T09:30:00.000Z'
    WorkflowConditionTest:
      type: object
      description: >-
        One comparison of a rule - a field, an operator and (for most operators)
        a value to compare with.
      required:
        - field
        - operator
      properties:
        field:
          $ref: '#/components/schemas/WorkflowFieldReference'
        operator:
          type: string
          enum:
            - is
            - isNot
            - contains
            - doesNotContain
            - startsWith
            - endsWith
            - greaterThan
            - atLeast
            - lessThan
            - atMost
            - isEmpty
            - isNotEmpty
          description: >
            Text fields take is, isNot, contains, doesNotContain, startsWith,
            endsWith, isEmpty and isNotEmpty.

            Number fields take is, isNot, greaterThan, atLeast, lessThan,
            atMost, isEmpty and isNotEmpty.

            Yes/no fields take is and isNot.
        value:
          description: >
            What the field is compared with; not used by isEmpty and isNotEmpty.
            A text for a text field, a number for

            a number field, true or false for a yes/no field.
          nullable: true
      example:
        field: null
        operator: Example operator
        value: null
    WorkflowFieldReference:
      type: object
      description: >
        A value a rule reads: a column the visitor filled in (`input`) or a
        value that came with a page event

        (`event`). The type is saved with the reference so the graph can be
        evaluated without the widget's schema.
      required:
        - kind
        - name
        - type
      properties:
        kind:
          type: string
          enum:
            - input
            - event
        name:
          type: string
        type:
          type: string
          enum:
            - text
            - number
            - boolean
      example:
        kind: Example kind
        name: Example name
        type: Example type
  securitySchemes:
    apiKeyAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT

````

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