Ava Protocol Workflows API

Workflow CRUD and lifecycle actions

OpenAPI Specification

ava-protocol-workflows-api-openapi.yml Raw ↑
openapi: 3.0.3
info:
  title: Ava Protocol AVS Auth Workflows API
  version: 1.0.0
  description: 'Public REST API for the Ava Protocol AVS aggregator. Exposes workflow

    creation, execution monitoring, smart-wallet management, and related

    operations.


    Authentication is a single credential type — a JWT bearer token — obtained

    either via the wallet-signing flow (`POST /auth:exchange`) or out-of-band

    via the operator-run `create-api-key` CLI. Every request must include

    `Authorization: Bearer <jwt>`.

    '
servers:
- url: https://gateway.avaprotocol.org/api/v1
  description: Production gateway
- url: https://gateway-staging.avaprotocol.org/api/v1
  description: Staging gateway
- url: http://localhost:8080/api/v1
  description: Local dev
security:
- bearerAuth: []
tags:
- name: Workflows
  description: Workflow CRUD and lifecycle actions
paths:
  /workflows:
    post:
      tags:
      - Workflows
      summary: Create a workflow
      description: 'Persist a new workflow definition. Each chain-aware trigger and node

        carries its own required `chainId` (there is no workflow-level chain);

        the server validates those chains and ensures the smart wallet belongs

        to the authenticated user. Returns the persisted Workflow with its

        server-assigned `id` and `createdAt`.

        '
      operationId: createWorkflow
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateWorkflowRequest'
      responses:
        '201':
          description: Workflow created.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Workflow'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '429':
          $ref: '#/components/responses/RateLimited'
    get:
      tags:
      - Workflows
      summary: List workflows
      operationId: listWorkflows
      parameters:
      - name: smartWalletAddress
        in: query
        description: Filter by smart wallet address. Repeat to OR multiple addresses.
        schema:
          type: array
          items:
            $ref: '#/components/schemas/EthereumAddress'
      - name: status
        in: query
        description: Filter by status. Repeat to OR multiple statuses.
        schema:
          type: array
          items:
            $ref: '#/components/schemas/WorkflowStatus'
      - $ref: '#/components/parameters/PageBefore'
      - $ref: '#/components/parameters/PageAfter'
      - $ref: '#/components/parameters/PageLimit'
      responses:
        '200':
          description: Page of workflows.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/WorkflowList'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '429':
          $ref: '#/components/responses/RateLimited'
  /workflows/{id}:
    parameters:
    - name: id
      in: path
      required: true
      schema:
        $ref: '#/components/schemas/Ulid'
    get:
      tags:
      - Workflows
      summary: Retrieve a workflow
      operationId: getWorkflow
      responses:
        '200':
          description: The workflow.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Workflow'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
    delete:
      tags:
      - Workflows
      summary: Cancel a workflow
      description: 'Permanently cancels and removes the workflow. SDK method is

        `cancel(id)` to align with Stripe-style vocabulary.

        '
      operationId: cancelWorkflow
      responses:
        '204':
          description: Workflow cancelled.
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
  /workflows/{id}:pause:
    parameters:
    - name: id
      in: path
      required: true
      schema:
        $ref: '#/components/schemas/Ulid'
    post:
      tags:
      - Workflows
      summary: Pause a workflow
      description: Transition from `enabled` to `disabled`. Idempotent.
      operationId: pauseWorkflow
      responses:
        '200':
          description: Workflow paused.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Workflow'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
        '409':
          description: Workflow is in a terminal state and cannot be paused.
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
  /workflows/{id}:resume:
    parameters:
    - name: id
      in: path
      required: true
      schema:
        $ref: '#/components/schemas/Ulid'
    post:
      tags:
      - Workflows
      summary: Resume a workflow
      description: Transition from `disabled` to `enabled`. Idempotent.
      operationId: resumeWorkflow
      responses:
        '200':
          description: Workflow resumed.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Workflow'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
        '409':
          description: Workflow is in a terminal state and cannot be resumed.
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
  /workflows/{id}:trigger:
    parameters:
    - name: id
      in: path
      required: true
      schema:
        $ref: '#/components/schemas/Ulid'
    post:
      tags:
      - Workflows
      summary: Manually trigger a workflow
      description: 'Simulate an operator-detected trigger fire. The server enqueues an

        execution; when `isBlocking=true`, the response waits for the

        execution to complete.

        '
      operationId: triggerWorkflow
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/TriggerWorkflowRequest'
      responses:
        '202':
          description: Execution enqueued (async). Returned when isBlocking=false.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TriggerWorkflowResponse'
        '200':
          description: Execution completed (blocking). Returned when isBlocking=true.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TriggerWorkflowResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
        '412':
          description: Workflow is disabled or has reached its max execution count.
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
  /workflows:simulate:
    post:
      tags:
      - Workflows
      summary: Simulate a workflow without persisting it
      description: 'Run a workflow definition end-to-end against the engine (Tenderly

        simulation for chain-writing nodes) and return the full Execution.

        Nothing is persisted.

        '
      operationId: simulateWorkflow
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/SimulateWorkflowRequest'
      responses:
        '200':
          description: Simulated execution.
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
  /workflows:estimateFees:
    post:
      tags:
      - Workflows
      summary: Estimate per-execution fees for a workflow definition
      description: 'Returns the platform execution fee, per-node COGS (gas, external

        API costs), and the workflow-level value-capture fee tier.

        '
      operationId: estimateWorkflowFees
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/EstimateFeesRequest'
      responses:
        '200':
          description: Fee estimate.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/EstimateFeesResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
  /workflows:count:
    get:
      tags:
      - Workflows
      summary: Count workflows
      description: Cheap aggregation over the same filter set as `GET /workflows`.
      operationId: countWorkflows
      parameters:
      - name: smartWalletAddress
        in: query
        schema:
          type: array
          items:
            $ref: '#/components/schemas/EthereumAddress'
      - name: status
        in: query
        schema:
          type: array
          items:
            $ref: '#/components/schemas/WorkflowStatus'
      responses:
        '200':
          description: Workflow count for the filter set.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/WorkflowCount'
        '401':
          $ref: '#/components/responses/Unauthorized'
components:
  schemas:
    SimulateWorkflowRequest:
      type: object
      required:
      - trigger
      - nodes
      - inputVariables
      properties:
        chainId:
          $ref: '#/components/schemas/ChainId'
        trigger:
          $ref: '#/components/schemas/Trigger'
        nodes:
          type: array
          items:
            $ref: '#/components/schemas/Node'
        edges:
          type: array
          items:
            $ref: '#/components/schemas/Edge'
        inputVariables:
          $ref: '#/components/schemas/InputVariables'
    PageInfo:
      type: object
      required:
      - hasNextPage
      - hasPreviousPage
      properties:
        hasNextPage:
          type: boolean
        hasPreviousPage:
          type: boolean
        startCursor:
          type: string
          description: Cursor for the first item in the current page; pass to `before` for the previous page.
        endCursor:
          type: string
          description: Cursor for the last item in the current page; pass to `after` for the next page.
    EventTriggerQuery:
      type: object
      description: Single ethereum.FilterQuery — one subscription per query.
      properties:
        addresses:
          type: array
          items:
            $ref: '#/components/schemas/EthereumAddress'
          description: Contract addresses to filter events from. Empty matches any contract.
        topics:
          type: array
          items:
            type: string
            nullable: true
          description: 'Topic filters (`topics[0]` is the event signature, `topics[1..]`

            are indexed parameter values). `null` means wildcard at that

            position.

            '
        maxEventsPerBlock:
          type: integer
          format: int32
          description: Safety ceiling per query per block. Exceeded → task cancelled.
        contractAbi:
          type: array
          items:
            additionalProperties: true
          description: Contract ABI entries (JSON form) for event decoding.
        conditions:
          type: array
          items:
            $ref: '#/components/schemas/EventCondition'
          description: Filters applied to decoded event data.
        methodCalls:
          type: array
          items:
            $ref: '#/components/schemas/EventMethodCall'
          description: Method calls used to enrich decoded event data (e.g., `decimals`).
    EventCondition:
      type: object
      description: Predicate evaluated against decoded event data.
      required:
      - fieldName
      - operator
      - value
      properties:
        fieldName:
          type: string
        operator:
          type: string
          enum:
          - eq
          - ne
          - gt
          - gte
          - lt
          - lte
          - contains
        value:
          type: string
          description: 'Value to compare against, encoded as a string. The operator

            parses it according to `fieldType` (e.g. `int256` / `uint256`

            → big.Int, `address` → checksummed hex, `bool` →

            "true"/"false"). Matches the proto `EventCondition.value`,

            which is also a string.

            '
        fieldType:
          type: string
    WorkflowStatus:
      type: string
      enum:
      - enabled
      - disabled
      - running
      - completed
      - failed
      description: 'Lifecycle status. `enabled` means actively monitored; `disabled` is

        paused. `running`, `completed`, `failed` are terminal-ish states

        emitted during/after execution.

        '
    FilterNodeConfig:
      type: object
      required:
      - inputVariable
      - expression
      properties:
        inputVariable:
          type: string
          description: Template path for the source array (e.g., `{{custom_code1.data}}`).
        expression:
          type: string
          description: JavaScript predicate evaluated per item.
    ContractReadNode:
      allOf:
      - type: object
        properties:
          type:
            type: string
            enum:
            - contractRead
          config:
            $ref: '#/components/schemas/ContractReadNodeConfig'
    EthereumAddress:
      type: string
      pattern: ^0x[a-fA-F0-9]{40}$
      description: Lowercase or checksummed hex EOA / contract address.
      example: '0x82F2Dd9a552a69f2ceD7Ff2D05c43aB8430158FB'
    InputVariables:
      type: object
      additionalProperties: true
      description: 'Free-form key-value bag of values used to resolve `{{variable.path}}`

        template references inside trigger and node configs. Conventional

        well-known keys: `settings.runner` (smart wallet address),

        `settings.chainId` (chain id). camelCase keys; back-compat support

        for snake_case keys exists during the migration window.

        '
    RestAPINodeConfig:
      type: object
      required:
      - url
      - method
      properties:
        url:
          type: string
          format: uri
        method:
          type: string
          enum:
          - GET
          - POST
          - PUT
          - PATCH
          - DELETE
          - HEAD
          - OPTIONS
        headers:
          type: object
          additionalProperties:
            type: string
        body:
          type: string
        options:
          type: object
          description: 'Generic options bag for backend features on terminal

            RestAPI nodes. `summarize: true` opts a SendGrid /v3/mail/send

            or Telegram /sendMessage node into the aggregator''s

            context-memory summarizer, which composes a subject + HTML

            body from the workflow''s execution context and injects them

            into the outgoing request. Without this field set, the

            aggregator falls back to the deterministic summarizer (no

            LLM polish).

            '
          properties:
            summarize:
              type: boolean
              description: 'When true on a terminal SendGrid or Telegram node,

                ComposeSummarySmart runs at execution time and fills

                in the empty content.value / text slot with an

                AI-generated body. No-op on non-notification URLs.

                '
          additionalProperties: true
    TriggerWorkflowRequest:
      type: object
      required:
      - triggerType
      properties:
        triggerType:
          $ref: '#/components/schemas/TriggerType'
        triggerOutput:
          description: 'Type-specific output payload (BlockTrigger.Output,

            EventTrigger.Output, etc.) that simulates what the operator

            would have observed. Defined alongside execution schemas.

            '
          additionalProperties: true
        triggerInput:
          $ref: '#/components/schemas/InputVariables'
        isBlocking:
          type: boolean
          description: When true, wait for the execution to complete and return its result.
    CustomCodeNodeConfig:
      type: object
      required:
      - lang
      - source
      properties:
        lang:
          $ref: '#/components/schemas/Lang'
        source:
          type: string
    MethodCall:
      type: object
      description: One call to a contract method (used by ContractWrite + ContractRead).
      required:
      - methodName
      properties:
        methodName:
          type: string
        callData:
          $ref: '#/components/schemas/Hex'
        applyToFields:
          type: array
          items:
            type: string
        methodParams:
          type: array
          items:
            type: string
            description: Handlebars template for method args.
    Hex:
      type: string
      pattern: ^0x[a-fA-F0-9]*$
      description: Arbitrary-length hex-encoded byte string.
    ETHTransferNodeConfig:
      type: object
      required:
      - destination
      - amount
      - chainId
      properties:
        destination:
          $ref: '#/components/schemas/EthereumAddress'
        amount:
          type: string
          description: Amount in wei (decimal string for big-int safety). Special value `max` withdraws the entire balance.
        chainId:
          $ref: '#/components/schemas/ChainId'
          description: Chain to execute on. Required — a workflow carries no chain to inherit.
    EventTrigger:
      allOf:
      - type: object
        properties:
          type:
            type: string
            enum:
            - event
          config:
            $ref: '#/components/schemas/EventTriggerConfig'
    TriggerType:
      type: string
      enum:
      - manual
      - fixedTime
      - cron
      - block
      - event
      description: 'Discriminator field for the Trigger union. Mirrors the proto

        `TriggerType` enum but without the `TRIGGER_TYPE_` prefix.

        '
    EstimateFeesRequest:
      type: object
      required:
      - trigger
      - nodes
      - createdAt
      - expireAt
      - maxExecution
      properties:
        chainId:
          $ref: '#/components/schemas/ChainId'
        trigger:
          $ref: '#/components/schemas/Trigger'
        nodes:
          type: array
          items:
            $ref: '#/components/schemas/Node'
        edges:
          type: array
          items:
            $ref: '#/components/schemas/Edge'
        runner:
          $ref: '#/components/schemas/EthereumAddress'
          description: Smart wallet address used for gas estimation (overrides settings.runner).
        createdAt:
          type: integer
          format: int64
        expireAt:
          type: integer
          format: int64
        maxExecution:
          type: integer
          format: int64
        inputVariables:
          $ref: '#/components/schemas/InputVariables'
    EventTriggerConfig:
      type: object
      description: Fires when matching on-chain events are observed.
      required:
      - queries
      - chainId
      properties:
        queries:
          type: array
          items:
            $ref: '#/components/schemas/EventTriggerQuery'
          minItems: 1
        cooldownSeconds:
          type: integer
          format: int32
          minimum: 0
          description: 'Seconds to wait after a fire before allowing the same task to

            trigger again. Default 300. 0 disables cooldown.

            '
        chainId:
          $ref: '#/components/schemas/ChainId'
          description: Chain to watch events on. Required — a workflow carries no chain to inherit.
    EstimateFeesResponse:
      type: object
      required:
      - chainId
      - executionFee
      - cogs
      - valueFee
      properties:
        chainId:
          $ref: '#/components/schemas/ChainId'
        nativeToken:
          $ref: '#/components/schemas/NativeToken'
        executionFee:
          $ref: '#/components/schemas/Fee'
          description: Flat per-execution platform fee (typically USD).
        cogs:
          type: array
          items:
            $ref: '#/components/schemas/NodeCOGS'
          description: Per-node operational costs (gas, external API).
        valueFee:
          $ref: '#/components/schemas/ValueFee'
          description: Workflow-level value-capture fee (PERCENTAGE).
        discounts:
          type: array
          items:
            $ref: '#/components/schemas/FeeDiscount'
        pricingModel:
          type: string
          description: Pricing model label (e.g., `tiered_value_capture_v1`).
    CronTriggerConfig:
      type: object
      description: Fires on one or more cron schedules.
      required:
      - schedules
      properties:
        schedules:
          type: array
          items:
            type: string
            description: Standard cron expression (e.g., `* * * * *`).
          minItems: 1
        timezone:
          type: string
          description: IANA timezone (e.g., `UTC`, `America/New_York`). Default UTC.
    Fee:
      type: object
      required:
      - amount
      - unit
      properties:
        amount:
          type: string
          description: Decimal numeric value, encoded as a string for big-int safety.
        unit:
          type: string
          enum:
          - USD
          - WEI
          - PERCENTAGE
    ETHTransferNode:
      allOf:
      - type: object
        properties:
          type:
            type: string
            enum:
            - ethTransfer
          config:
            $ref: '#/components/schemas/ETHTransferNodeConfig'
    FeeDiscount:
      type: object
      properties:
        discountType:
          type: string
          enum:
          - newUser
          - volume
          - promotional
          - betaProgram
        discountName:
          type: string
        discount:
          $ref: '#/components/schemas/Fee'
        expiryDate:
          $ref: '#/components/schemas/Timestamp'
        terms:
          type: string
    BalanceNodeConfig:
      type: object
      required:
      - address
      - chain
      properties:
        address:
          $ref: '#/components/schemas/EthereumAddress'
        chain:
          type: string
          description: Chain name or numeric ID (e.g., `ethereum`, `base`, `1`, `8453`).
        includeSpam:
          type: boolean
        includeZeroBalances:
          type: boolean
        minUsdValueCents:
          type: integer
          format: int64
          description: Filter out tokens with USD value below this many cents.
        tokenAddresses:
          type: array
          items:
            $ref: '#/components/schemas/EthereumAddress'
          description: Restrict to these tokens. Empty = fetch all.
    BlockTrigger:
      allOf:
      - type: object
        properties:
          type:
            type: string
            enum:
            - block
          config:
            $ref: '#/components/schemas/BlockTriggerConfig'
    GraphQLQueryNode:
      allOf:
      - type: object
        properties:
          type:
            type: string
            enum:
            - graphqlQuery
          config:
            $ref: '#/components/schemas/GraphQLQueryNodeConfig'
    Ulid:
      type: string
      pattern: ^[0-9A-HJKMNP-TV-Z]{26}$
      description: ULID identifier (26-char Crockford base32).
      example: 01JG2FE5MDVKBPHEG0PEYSDKAC
    FixedTimeTrigger:
      allOf:
      - type: object
        properties:
          type:
            type: string
            enum:
            - fixedTime
          config:
            $ref: '#/components/schemas/FixedTimeTriggerConfig'
    TriggerWorkflowResponse:
      type: object
      required:
      - executionId
      - status
      properties:
        executionId:
          $ref: '#/components/schemas/Ulid'
        status:
          $ref: '#/components/schemas/ExecutionStatus'
        startAt:
          type: integer
          format: int64
        endAt:
          type: integer
          format: int64
        error:
          type: string
    BranchNode:
      allOf:
      - type: object
        properties:
          type:
            type: string
            enum:
            - branch
          config:
            $ref: '#/components/schemas/BranchNodeConfig'
    ExecutionStatus:
      type: string
      enum:
      - pending
      - waiting
      - success
      - failed
      - error
      description: 'Outcome of an execution. `pending` is in-flight; `waiting` is suspended

        mid-workflow at an `await` node, durably parked until a signal arrives

        (a human approve/reject or an operator-observed chain event) or the wait

        times out — non-terminal, like `pending`, but distinguishable so a client

        can show "awaiting approval"; `success` is full success; `failed` is

        logical failure (e.g., a node returned an error, or a wait timed out);

        `error` is a system / infrastructure failure (e.g., RPC unreachable).

        '
    Timestamp:
      type: string
      format: date-time
      description: RFC 3339 timestamp.
    LoopNode:
      allOf:
      - type: object
        properties:
          type:
            type: string
            enum:
            - loop
          config:
            $ref: '#/components/schemas/LoopNodeConfig'
    CronTrigger:
      allOf:
      - type: object
        properties:
          type:
            type: string
            enum:
            - cron
          config:
            $ref: '#/components/schemas/CronTriggerConfig'
    BranchNodeConfig:
      type: object
      required:
      - conditions
      properties:
        conditions:
          type: array
          items:
            $ref: '#/components/schemas/BranchCondition'
          minItems: 1
    NodeCOGS:
      type: object
      required:
      - nodeId
      - costType
      - fee
      properties:
        nodeId:
          type: string
        costType:
          type: string
          enum:
          - gas
          - externalApi
          - walletCreation
        fee:
          $ref: '#/components/schemas/Fee'
        gasUnits:
          type: string
          description: Gas units (for `gas` cost type only).
    NodeType:
      type: string
      enum:
      - ethTransfer
      - contractWrite
      - contractRead
      - graphqlQuery
      - restApi
      - customCode
      - branch
      - filter
      - loop
      - balance
      - await
      description: 'Discriminator field for the Node union. Mirrors the proto

        `NodeType` enum but without the `NODE_TYPE_` prefix.

        '
    ContractWriteNodeConfig:
      type: object
      required:
      - contractAddress
      - chainId
      properties:
        contractAddress:
          $ref: '#/components/schemas/EthereumAddress'
        callData:
          $ref: '#/components/schemas/Hex'
        contractAbi:
          type: array
          items:
            additionalProperties: true
        methodCalls:
          type: array
          items:
            $ref: '#/components/schemas/MethodCall'
        isSimulated:
          type: boolean
          description: When true, use Tenderly simulation instead of sending a real UserOp.
        value:
          type: string
          description: ETH value to send with the call (wei, decimal string).
        gasLimit:
          type: string
          description: Custom gas limit (decimal string).
        chainId:
          $ref: '#/components/schemas/ChainId'
          description: Chain to execute on. Required — a workflow carries no chain to inherit.
    NativeToken:
      type: object
      required:
      - symbol
      - decimals
      properties:
        symbol:
          type: string
          example: ETH
        decimals:
          type: integer
          format: int32
    ManualTriggerConfig:
      type: object
      description: User-initiated trigger; no chain context.
      required:
      - lang
      properties:
        data:
          description: Arbitrary structured payload returned in the trigger output.
          additionalProperties: true
        headers:
          type: object
          additionalProperties:
            type: string
          description: HTTP headers (for webhook testing).
        pathParams:
          type: object
          additionalProperties:
            type: string
          description: Path parameters (for webhook testing).
        lang:
          $ref: '#/components/schemas/Lang'
    Lang:
      type: string
      enum:
      - javascript
      - json
      - graphql
      - handlebars
      description: 'Language/format of an inline payload (e.g., custom code source,

        manual trigger data). Mirrors the proto `Lang` enum minus the

        `LANG_` prefix. Wire values are lowercase.

        '
    FilterNode:
      allOf:
      - type: object
        properties:
          type:
            type: string
            enum:
            - filter
          config:
            $ref: '#/components/schemas/FilterNodeConfig'
    WorkflowList:
      type: object
      required:
      - data
      - pageInfo
      properties:
        data:
          type: array
          items:
            $ref: '#/components/schemas/Workflow'
        pageInfo:
          $ref: '#/components/schemas/PageInfo'
    ContractReadNodeConfig:
      type: object
      required:
      - contractAddress
      - chainId
      properties:
        contractAddress:
          $ref: '#/components/schemas/EthereumAddress'
        contractAbi:
          type: array
          items:
            additionalProperties: true
        methodCalls:
          type: array
          items:
            $ref: '#/components/schemas/MethodCall'
        chainId:
          $ref: '#/components/schemas/ChainId'
          description: Chain to read from. Required — a workflow carries no chain to inherit.
    AwaitNodeConfig:
      type: object
      description: 'Pauses the workflow until a wake arrives (durable execution). Two mutually

        exclusive flavors: the external-signal flavor (human approval — set `channel`,

        e.g. a Telegram approve/reject), or the chain-event flavor (cross-chain — set

        `chainEvent` to pause until an operator observes that on-chain event, e.g. a

        bridge arrival on another chain). Exactly one flavor must be configured.

        '
      properties:
        channel:
          type: string
          description: 'External-signal flavor — signal channel: `telegram` or `api`.'
        approvers:
          type: array
          items:
            type: string
          description: External-signal flavor — authorized approver identities. Empty = the workflow owner.
        prompt:
          type: string
          description: External-signal flavor — message shown to the approver.
        chainEvent:
          allOf:
          - $ref: '#/components/schemas/EventTriggerConfig'
          description: 'Chain-event flavor — the on-chain event to wait for (a mid-workflow

            EventTrigger). An operator covering `chainEvent.chainId` watches it and

            resumes the execution when it fires. Mutually exclusive with `channel`.

            '
        timeoutSeconds:
          type: integer
          format: int64
          description: Safety bound; 0 = server default (the wait is never unbounded).
    Edge:
      type: object
      required:
      - id
      - source
      - target
      properties:
        id:
          type: string
        source:
          type: string
          description: Node or trigger ID where this edge starts.
        target:
          type: string
          description: Node ID where this edge ends.
    Workflow:
      type: o

# --- truncated at 32 KB (45 KB total) ---
# Full source: https://raw.githubusercontent.com/api-evangelist/ava-protocol/refs/heads/main/openapi/ava-protocol-workflows-api-openapi.yml