openapi: 3.1.0
info:
  title: VAGAChain Node API
  version: 0.1.0
  description: >
    OpenAPI documentation for the VAGAChain dev-node HTTP and REST surfaces.
    This file focuses on the node's HTTP endpoints and documents the JSON-RPC
    envelope at POST /rpc. For grouped JSON-RPC and gRPC references, see
    docs/api-reference.md.
servers:
  - url: http://127.0.0.1:9944
    description: Local dev node default
tags:
  - name: System
  - name: Events
  - name: REST
  - name: Explorer
  - name: JSON-RPC
paths:
  /health:
    get:
      tags: [System]
      summary: Node health and runtime summary
      operationId: getHealth
      responses:
        '200':
          description: Health summary
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/HealthResponse'
  /state:
    get:
      tags: [System]
      summary: Full runtime snapshot
      operationId: getState
      responses:
        '200':
          description: Runtime snapshot
          content:
            application/json:
              schema:
                type: object
                properties:
                  snapshot:
                    type: object
                    additionalProperties: true
                  persist_path:
                    type: string
                required: [snapshot, persist_path]
  /state/indexer-snapshot:
    get:
      tags: [System]
      summary: Binary snapshot contract for the indexer
      operationId: getIndexerSnapshot
      responses:
        '200':
          description: Binary-encoded snapshot
          content:
            application/octet-stream:
              schema:
                type: string
                format: binary
        '500':
          description: Snapshot encoding error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorBody'
  /events:
    get:
      tags: [Events]
      summary: List runtime event log records
      operationId: listEvents
      parameters:
        - $ref: '#/components/parameters/FromSeq'
        - $ref: '#/components/parameters/Limit'
        - $ref: '#/components/parameters/EventType'
      responses:
        '200':
          description: Event list
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/EventsResponse'
  /api/agent/{agent_id}:
    get:
      tags: [REST]
      summary: Get agent summary
      operationId: getAgentRest
      parameters:
        - $ref: '#/components/parameters/AgentIdPath'
      responses:
        '200':
          description: Agent summary
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
        '400':
          $ref: '#/components/responses/BadRequest'
        '404':
          $ref: '#/components/responses/NotFound'
  /api/balance/{agent_id}:
    get:
      tags: [REST]
      summary: Get balance summary for one agent
      operationId: getBalanceRest
      parameters:
        - $ref: '#/components/parameters/AgentIdPath'
      responses:
        '200':
          description: Balance breakdown
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/BalanceResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
        '404':
          $ref: '#/components/responses/NotFound'
  /api/sla/{sla_id}:
    get:
      tags: [REST]
      summary: Get SLA summary
      operationId: getSlaRest
      parameters:
        - $ref: '#/components/parameters/SlaIdPath'
      responses:
        '200':
          description: SLA summary
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SlaSummary'
        '404':
          $ref: '#/components/responses/NotFound'
  /api/dispute/{dispute_id}:
    get:
      tags: [REST]
      summary: Get dispute summary
      operationId: getDisputeRest
      parameters:
        - $ref: '#/components/parameters/DisputeIdPath'
      responses:
        '200':
          description: Dispute summary
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/DisputeSummary'
        '404':
          $ref: '#/components/responses/NotFound'
  /api/transfers:
    get:
      tags: [REST]
      summary: List treasury transfer events
      operationId: listTransfersRest
      parameters:
        - in: query
          name: from_agent
          schema:
            type: string
          description: Optional sender filter
        - in: query
          name: to_agent
          schema:
            type: string
          description: Optional recipient filter
        - $ref: '#/components/parameters/Limit'
      responses:
        '200':
          description: Transfer list
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TransfersResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
  /api/explorer:
    get:
      tags: [Explorer]
      summary: Explorer overview
      operationId: getExplorerOverview
      parameters:
        - $ref: '#/components/parameters/Page'
        - $ref: '#/components/parameters/PageSize'
        - $ref: '#/components/parameters/Limit'
      responses:
        '200':
          description: Explorer overview with aggregated sections
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
  /api/explorer/transactions:
    get:
      tags: [Explorer]
      summary: List explorer transactions
      operationId: listExplorerTransactions
      parameters:
        - $ref: '#/components/parameters/Page'
        - $ref: '#/components/parameters/PageSize'
        - $ref: '#/components/parameters/Limit'
        - $ref: '#/components/parameters/Q'
        - in: query
          name: agent_id
          schema:
            type: string
        - in: query
          name: tx_type
          schema:
            type: string
      responses:
        '200':
          description: Transaction list
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PaginatedRowsResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
  /api/explorer/transactions/{tx_id}:
    get:
      tags: [Explorer]
      summary: Get one explorer transaction
      operationId: getExplorerTransaction
      parameters:
        - in: path
          name: tx_id
          required: true
          schema:
            type: string
      responses:
        '200':
          description: Transaction detail
          content:
            application/json:
              schema:
                type: object
                properties:
                  transaction:
                    type: object
                    additionalProperties: true
                  event_record:
                    $ref: '#/components/schemas/EventRecord'
                  block:
                    type: object
                    additionalProperties: true
                required: [transaction, event_record, block]
        '404':
          $ref: '#/components/responses/NotFound'
  /api/explorer/wallets:
    get:
      tags: [Explorer]
      summary: List explorer wallets
      operationId: listExplorerWallets
      parameters:
        - $ref: '#/components/parameters/Page'
        - $ref: '#/components/parameters/PageSize'
        - $ref: '#/components/parameters/Limit'
        - $ref: '#/components/parameters/Q'
      responses:
        '200':
          description: Wallet list
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PaginatedRowsResponse'
  /api/explorer/wallets/{agent_id}:
    get:
      tags: [Explorer]
      summary: Get one explorer wallet detail view
      operationId: getExplorerWallet
      parameters:
        - $ref: '#/components/parameters/AgentIdPath'
        - $ref: '#/components/parameters/Page'
        - $ref: '#/components/parameters/PageSize'
        - $ref: '#/components/parameters/Limit'
        - $ref: '#/components/parameters/Q'
      responses:
        '200':
          description: Wallet detail view
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
        '400':
          $ref: '#/components/responses/BadRequest'
        '404':
          $ref: '#/components/responses/NotFound'
  /api/explorer/blocks:
    get:
      tags: [Explorer]
      summary: List explorer blocks
      operationId: listExplorerBlocks
      parameters:
        - $ref: '#/components/parameters/Page'
        - $ref: '#/components/parameters/PageSize'
        - $ref: '#/components/parameters/Limit'
        - $ref: '#/components/parameters/Q'
      responses:
        '200':
          description: Block list
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PaginatedRowsResponse'
  /api/explorer/blocks/{block_number}:
    get:
      tags: [Explorer]
      summary: Get one explorer block detail view
      operationId: getExplorerBlock
      parameters:
        - in: path
          name: block_number
          required: true
          schema:
            type: integer
            minimum: 0
        - $ref: '#/components/parameters/Page'
        - $ref: '#/components/parameters/PageSize'
        - $ref: '#/components/parameters/Limit'
        - $ref: '#/components/parameters/Q'
      responses:
        '200':
          description: Block detail view
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
        '404':
          $ref: '#/components/responses/NotFound'
  /api/explorer/validators:
    get:
      tags: [Explorer]
      summary: List explorer validators
      operationId: listExplorerValidators
      parameters:
        - $ref: '#/components/parameters/Page'
        - $ref: '#/components/parameters/PageSize'
        - $ref: '#/components/parameters/Limit'
        - $ref: '#/components/parameters/Q'
      responses:
        '200':
          description: Validator list
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PaginatedRowsResponse'
  /api/explorer/validators/{validator_id}:
    get:
      tags: [Explorer]
      summary: Get one explorer validator detail view
      operationId: getExplorerValidator
      parameters:
        - in: path
          name: validator_id
          required: true
          schema:
            type: string
          description: 32-byte hex public key
        - $ref: '#/components/parameters/Page'
        - $ref: '#/components/parameters/PageSize'
        - $ref: '#/components/parameters/Limit'
        - $ref: '#/components/parameters/Q'
      responses:
        '200':
          description: Validator detail view
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
        '400':
          $ref: '#/components/responses/BadRequest'
        '404':
          $ref: '#/components/responses/NotFound'
  /rpc:
    post:
      tags: [JSON-RPC]
      summary: JSON-RPC 2.0 endpoint
      operationId: callJsonRpc
      description: >
        Generic JSON-RPC 2.0 entrypoint for VAGAChain write and read methods.
        See docs/api-reference.md for grouped method lists.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/JsonRpcRequest'
            examples:
              systemHealth:
                summary: system_health request
                value:
                  jsonrpc: '2.0'
                  id: 1
                  method: system_health
                  params: {}
              getBalance:
                summary: get_balance request
                value:
                  jsonrpc: '2.0'
                  id: 2
                  method: get_balance
                  params:
                    agent_id: vaga0123456789abcdef0123456789abcdef0123456789abcdef0123456789
      responses:
        '200':
          description: JSON-RPC response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/JsonRpcResponse'
  /ws:
    get:
      tags: [System]
      summary: WebSocket notifications endpoint
      operationId: connectWebSocket
      description: >
        Upgrades to a WebSocket connection. The server sends an initial welcome
        message containing a runtime snapshot and then streams node notifications.
        Sending the text message `ping` returns `{"type":"pong"}`.
      responses:
        '101':
          description: WebSocket upgrade
components:
  parameters:
    AgentIdPath:
      in: path
      name: agent_id
      required: true
      schema:
        type: string
      description: VAGA agent address, usually `vaga...` or legacy `0x...`
    SlaIdPath:
      in: path
      name: sla_id
      required: true
      schema:
        type: integer
        minimum: 1
    DisputeIdPath:
      in: path
      name: dispute_id
      required: true
      schema:
        type: integer
        minimum: 1
    FromSeq:
      in: query
      name: from_seq
      schema:
        type: integer
        minimum: 1
    EventType:
      in: query
      name: event_type
      schema:
        type: string
    Limit:
      in: query
      name: limit
      schema:
        type: integer
        minimum: 1
        maximum: 500
    Page:
      in: query
      name: page
      schema:
        type: integer
        minimum: 1
    PageSize:
      in: query
      name: page_size
      schema:
        type: integer
        minimum: 1
        maximum: 1000
    Q:
      in: query
      name: q
      schema:
        type: string
  responses:
    BadRequest:
      description: Invalid request
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorBody'
    NotFound:
      description: Resource not found
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorBody'
  schemas:
    ErrorBody:
      type: object
      properties:
        error:
          type: string
      required: [error]
    Pagination:
      type: object
      properties:
        page:
          type: integer
        page_size:
          type: integer
        total:
          type: integer
        total_pages:
          type: integer
        has_next:
          type: boolean
        has_prev:
          type: boolean
      additionalProperties: true
    EventRecord:
      type: object
      properties:
        seq:
          type: integer
        block_number:
          type: integer
        timestamp_ms:
          type: integer
        event_type:
          type: string
        event:
          type: object
          additionalProperties: true
      required: [seq, block_number, timestamp_ms, event_type]
      additionalProperties: true
    EventsResponse:
      type: object
      properties:
        from_seq:
          type: integer
        next_cursor:
          type: integer
        latest_seq:
          type: integer
        count:
          type: integer
        total_available:
          type: integer
        events:
          type: array
          items:
            $ref: '#/components/schemas/EventRecord'
      required:
        [from_seq, next_cursor, latest_seq, count, total_available, events]
    HealthResponse:
      type: object
      properties:
        status:
          type: string
        uptime_seconds:
          type: integer
        block_number:
          type: integer
        epoch_index:
          type: integer
        latest_finalized_block:
          type: integer
        latest_finality_certificate_hash:
          type: [string, 'null']
        finality_lag_blocks:
          type: integer
        base_fee:
          type: string
        external_market_cap_reference:
          type: [string, 'null']
        external_market_cap_reported_at:
          type: [integer, 'null']
        persist_pipeline_enabled:
          type: boolean
        persist_pipeline_pending:
          type: boolean
        persist_pipeline_interval_ms:
          type: integer
        rpc_inflight_available:
          type: integer
        rpc_per_ip_max_requests:
          type: integer
        rpc_per_ip_window_ms:
          type: integer
        runtime_event_log_len:
          type: integer
        runtime_event_latest_seq:
          type: integer
      required:
        - status
        - uptime_seconds
        - block_number
        - epoch_index
        - latest_finalized_block
        - finality_lag_blocks
    BalanceResponse:
      type: object
      properties:
        agent_id:
          type: string
        token_symbol:
          type: string
        liquid_balance:
          type: string
        locked_escrow:
          type: string
        locked_collateral:
          type: string
        total_balance:
          type: string
      required:
        - agent_id
        - token_symbol
        - liquid_balance
        - locked_escrow
        - locked_collateral
        - total_balance
    SlaSummary:
      type: object
      properties:
        sla_id:
          type: integer
        client_agent:
          type: string
        provider_agent:
          type: string
        escrow_amount:
          type: string
        provider_collateral:
          type: string
        deadline:
          type: integer
        status:
          type: string
        risk_class:
          type: integer
      required:
        - sla_id
        - client_agent
        - provider_agent
        - escrow_amount
        - provider_collateral
        - deadline
        - status
        - risk_class
    DisputeSummary:
      type: object
      properties:
        dispute_id:
          type: integer
        sla_id:
          type: integer
        challenger_agent:
          type: string
        reason:
          type: string
        opened_at:
          type: integer
        challenge_bond:
          type: string
        jury:
          type: array
          items:
            type: string
        verification_method:
          type: string
        votes_for_challenger:
          type: integer
        votes_for_provider:
          type: integer
        resolved:
          type: boolean
        verdict:
          type: [string, 'null']
      required:
        - dispute_id
        - sla_id
        - challenger_agent
        - reason
        - opened_at
        - challenge_bond
        - jury
        - verification_method
        - votes_for_challenger
        - votes_for_provider
        - resolved
    TransferRecord:
      type: object
      properties:
        event_index:
          type: integer
        from_agent:
          type: string
        to_agent:
          type: string
        amount:
          type: string
        token_symbol:
          type: string
      required: [event_index, from_agent, to_agent, amount, token_symbol]
    TransfersResponse:
      type: object
      properties:
        count:
          type: integer
        transfers:
          type: array
          items:
            $ref: '#/components/schemas/TransferRecord'
      required: [count, transfers]
    PaginatedRowsResponse:
      type: object
      properties:
        count:
          type: integer
        rows:
          type: array
          items:
            type: object
            additionalProperties: true
        filters:
          type: object
          additionalProperties: true
        pagination:
          $ref: '#/components/schemas/Pagination'
      required: [count, rows]
    JsonRpcRequest:
      type: object
      properties:
        jsonrpc:
          type: string
          const: '2.0'
        id:
          oneOf:
            - type: integer
            - type: string
            - type: object
            - type: array
            - type: boolean
            - type: 'null'
        method:
          type: string
        params:
          type: object
          additionalProperties: true
      required: [jsonrpc, id, method]
    JsonRpcError:
      type: object
      properties:
        code:
          type: integer
        message:
          type: string
      required: [code, message]
    JsonRpcResponse:
      type: object
      properties:
        jsonrpc:
          type: string
          const: '2.0'
        id:
          oneOf:
            - type: integer
            - type: string
            - type: object
            - type: array
            - type: boolean
            - type: 'null'
        result:
          oneOf:
            - type: object
              additionalProperties: true
            - type: array
              items: {}
            - type: string
            - type: integer
            - type: number
            - type: boolean
            - type: 'null'
        error:
          oneOf:
            - $ref: '#/components/schemas/JsonRpcError'
            - type: 'null'
      required: [jsonrpc, id]
