Ava Protocol Nodes API

Stand-alone node execution

OpenAPI Specification

ava-protocol-nodes-api-openapi.yml Raw ↑
openapi: 3.0.3
info:
  title: Ava Protocol AVS Auth Nodes 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: Nodes
  description: Stand-alone node execution
paths:
  /nodes:run:
    post:
      tags:
      - Nodes
      summary: Execute a single node with inline input variables
      description: 'Useful for SDK testing flows — run a node definition against

        provided input variables without persisting a workflow. Honors

        `node.config.chainId` (overrides body `chainId`).

        '
      operationId: runNode
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/RunNodeRequest'
      responses:
        '200':
          description: Node execution result.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/RunNodeResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
components:
  schemas:
    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
    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
    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.
    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.
    ETHTransferNode:
      allOf:
      - type: object
        properties:
          type:
            type: string
            enum:
            - ethTransfer
          config:
            $ref: '#/components/schemas/ETHTransferNodeConfig'
    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.
    GraphQLQueryNode:
      allOf:
      - type: object
        properties:
          type:
            type: string
            enum:
            - graphqlQuery
          config:
            $ref: '#/components/schemas/GraphQLQueryNodeConfig'
    BranchNode:
      allOf:
      - type: object
        properties:
          type:
            type: string
            enum:
            - branch
          config:
            $ref: '#/components/schemas/BranchNodeConfig'
    LoopNode:
      allOf:
      - type: object
        properties:
          type:
            type: string
            enum:
            - loop
          config:
            $ref: '#/components/schemas/LoopNodeConfig'
    BranchNodeConfig:
      type: object
      required:
      - conditions
      properties:
        conditions:
          type: array
          items:
            $ref: '#/components/schemas/BranchCondition'
          minItems: 1
    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.
    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'
    RunNodeRequest:
      type: object
      required:
      - node
      properties:
        node:
          $ref: '#/components/schemas/Node'
        inputVariables:
          $ref: '#/components/schemas/InputVariables'
        chainId:
          $ref: '#/components/schemas/ChainId'
        erc20Overrides:
          type: array
          description: 'Optional ERC20 balance/allowance state overrides applied only during this isolated node simulation. Lets callers seed token balances and approvals so contract-write simulations (e.g. Uniswap swaps) don''t revert with "transfer amount exceeds allowance/balance" before the approval/funding transactions have been run. Simulation-only: a real-execution request (isSimulated=false) that sets these is rejected with an error, never silently ignored.

            '
          items:
            $ref: '#/components/schemas/ERC20StateOverride'
    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).
    AwaitNode:
      allOf:
      - type: object
        properties:
          type:
            type: string
            enum:
            - await
          config:
            $ref: '#/components/schemas/AwaitNodeConfig'
    RestAPINode:
      allOf:
      - type: object
        properties:
          type:
            type: string
            enum:
            - restApi
          config:
            $ref: '#/components/schemas/RestAPINodeConfig'
    LoopNodeConfig:
      type: object
      description: 'Iterates over an input array, running an inner Node per item. The

        runner node is one of the chain-aware or chain-agnostic node types;

        a chain-aware runner must specify its own required `chainId` (there is

        no inheritance from the loop or workflow).

        '
      required:
      - inputVariable
      - runner
      properties:
        inputVariable:
          type: string
          description: Template path for the iterable (e.g., `{{settings.addressList}}`).
        iterVar:
          type: string
          default: value
          description: Name of the per-iteration variable (defaults to `value`).
        runner:
          $ref: '#/components/schemas/Node'
    RunNodeResponse:
      type: object
      required:
      - success
      properties:
        success:
          type: boolean
        error:
          type: string
        errorCode:
          type: string
        output:
          additionalProperties: true
        metadata:
          additionalProperties: true
        executionContext:
          additionalProperties: true
    BranchCondition:
      type: object
      required:
      - id
      - expression
      properties:
        id:
          type: string
        type:
          type: string
          enum:
          - if
          - elseIf
          - else
        expression:
          type: string
          description: JavaScript-evaluated boolean expression.
    Node:
      type: object
      required:
      - type
      - id
      - config
      properties:
        id:
          type: string
        name:
          type: string
        type:
          $ref: '#/components/schemas/NodeType'
      discriminator:
        propertyName: type
        mapping:
          ethTransfer: '#/components/schemas/ETHTransferNode'
          contractWrite: '#/components/schemas/ContractWriteNode'
          contractRead: '#/components/schemas/ContractReadNode'
          graphqlQuery: '#/components/schemas/GraphQLQueryNode'
          restApi: '#/components/schemas/RestAPINode'
          customCode: '#/components/schemas/CustomCodeNode'
          branch: '#/components/schemas/BranchNode'
          filter: '#/components/schemas/FilterNode'
          loop: '#/components/schemas/LoopNode'
          balance: '#/components/schemas/BalanceNode'
          await: '#/components/schemas/AwaitNode'
      oneOf:
      - $ref: '#/components/schemas/ETHTransferNode'
      - $ref: '#/components/schemas/ContractWriteNode'
      - $ref: '#/components/schemas/ContractReadNode'
      - $ref: '#/components/schemas/GraphQLQueryNode'
      - $ref: '#/components/schemas/RestAPINode'
      - $ref: '#/components/schemas/CustomCodeNode'
      - $ref: '#/components/schemas/BranchNode'
      - $ref: '#/components/schemas/FilterNode'
      - $ref: '#/components/schemas/LoopNode'
      - $ref: '#/components/schemas/BalanceNode'
      - $ref: '#/components/schemas/AwaitNode'
    BalanceNode:
      allOf:
      - type: object
        properties:
          type:
            type: string
            enum:
            - balance
          config:
            $ref: '#/components/schemas/BalanceNodeConfig'
    ContractWriteNode:
      allOf:
      - type: object
        properties:
          type:
            type: string
            enum:
            - contractWrite
          config:
            $ref: '#/components/schemas/ContractWriteNodeConfig'
    ChainId:
      type: integer
      format: int64
      description: 'Numeric chain ID (e.g. 11155111 for Sepolia, 8453 for Base). On

        chain-aware trigger/node configs this is required and must be a

        configured chain; on query/filter params it is optional.

        '
      example: 11155111
    GraphQLQueryNodeConfig:
      type: object
      required:
      - url
      - query
      properties:
        url:
          type: string
          format: uri
        query:
          type: string
        variables:
          type: object
          additionalProperties:
            type: string
    Problem:
      type: object
      description: 'RFC 7807 problem+json. Returned as `application/problem+json` on any

        4xx/5xx response. `type` and `title` describe the error class; `detail`

        is human-readable; `instance` is a per-request identifier suitable for

        log correlation.

        '
      required:
      - type
      - title
      - status
      properties:
        type:
          type: string
          format: uri
          description: URI identifying the problem type.
          example: https://docs.avaprotocol.org/errors/workflow-not-found
        title:
          type: string
          description: Short, human-readable summary.
          example: Workflow not found
        status:
          type: integer
          format: int32
          description: HTTP status code (echoed for clients that surface only the body).
          example: 404
        detail:
          type: string
          description: Human-readable explanation specific to this occurrence.
          example: No workflow with id 01JG2FE5MDVKBPHEG0PEYSDKAC for owner 0xabc...
        instance:
          type: string
          description: URI / opaque ID identifying this specific occurrence (e.g., request id).
          example: req_01JG2FE5MFKTH0754RGF2DMVY7
        code:
          type: string
          description: 'Machine-readable error code. Stable across releases; clients can

            switch on this for programmatic handling. Mirrors the gRPC-era

            ErrorCode enum vocabulary.

            '
          example: WORKFLOW_NOT_FOUND
    EventMethodCall:
      type: object
      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; resolves against decoded event data.
    CustomCodeNode:
      allOf:
      - type: object
        properties:
          type:
            type: string
            enum:
            - customCode
          config:
            $ref: '#/components/schemas/CustomCodeNodeConfig'
    ERC20StateOverride:
      type: object
      required:
      - tokenAddress
      - ownerAddress
      description: 'Seeds a token''s balanceOf / allowance storage slots for a single simulation. balanceOf[owner] lives at keccak256(abi.encode(owner, balanceSlot)); allowance[owner][spender] at keccak256(abi.encode(spender, keccak256(abi.encode(owner, allowanceSlot)))).

        '
      properties:
        tokenAddress:
          $ref: '#/components/schemas/EthereumAddress'
        ownerAddress:
          $ref: '#/components/schemas/EthereumAddress'
        spenderAddress:
          $ref: '#/components/schemas/EthereumAddress'
        balance:
          type: string
          description: Balance override (hex 0x… or decimal string).
        allowance:
          type: string
          description: Allowance override (hex 0x… or decimal string).
        balanceSlot:
          type: integer
          format: int64
          minimum: 0
          description: Storage slot for the balanceOf mapping. Required when balance is set; ERC20 storage layout varies per token (OpenZeppelin 0, USDC FiatToken 9).
        allowanceSlot:
          type: integer
          format: int64
          minimum: 0
          description: Storage slot for the allowance mapping. Required when allowance is set; ERC20 storage layout varies per token (OpenZeppelin 1, USDC FiatToken 10).
  responses:
    Unauthorized:
      description: Missing or invalid bearer token.
      content:
        application/problem+json:
          schema:
            $ref: '#/components/schemas/Problem'
    BadRequest:
      description: Request validation failed.
      content:
        application/problem+json:
          schema:
            $ref: '#/components/schemas/Problem'
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT
      description: 'JWT bearer token. Obtained via `POST /auth:exchange` (wallet

        signature flow) or via the operator-run `create-api-key` CLI

        (long-lived, server-to-server). Send on every request as

        `Authorization: Bearer <jwt>`.

        '