openapi: 3.1.0
info:
  title: IXS Vault API
  version: 0.1.0
  description: Public HTTP API for discovering vaults, quoting ERC-4626 operations, and building unsigned transaction payloads across any supported EVM chain.
servers:
  - url: https://api-dev-v2.ixs.finance
    description: Deployed development API
tags:
  - name: Vaults
  - name: X402
  - name: Wallet
paths:
  /vaults:
    get:
      tags: [Vaults]
      summary: List available vaults
      operationId: listVaults
      parameters:
        - name: requiresWhitelist
          in: query
          required: false
          schema:
            type: boolean
          description: Filter vaults by whitelist requirement
        - name: page
          in: query
          required: false
          schema:
            type: integer
            minimum: 1
          description: Page number (1-based). Omit for unpaginated response.
        - name: pageSize
          in: query
          required: false
          schema:
            type: integer
            minimum: 1
            maximum: 100
          description: Number of items per page. Omit for unpaginated response.
      responses:
        '200':
          description: Vault list
          content:
            application/json:
              schema:
                type: object
                properties:
                  ok:
                    type: boolean
                    const: true
                  items:
                    type: array
                    items:
                      $ref: '#/components/schemas/VaultMetadata'
                  page:
                    type: integer
                    description: Current page number
                  pageSize:
                    type: integer
                    description: Number of items on this page
                  totalItems:
                    type: integer
                    description: Total number of vaults matching the filter
                  totalPages:
                    type: integer
                    description: Total number of pages
                  hasNextPage:
                    type: boolean
                  hasPreviousPage:
                    type: boolean
                required:
                  [ok, items, page, pageSize, totalItems, totalPages, hasNextPage, hasPreviousPage]
  /vaults/{vaultId}:
    get:
      tags: [Vaults]
      summary: Get vault metadata
      operationId: getVault
      parameters:
        - $ref: '#/components/parameters/VaultId'
      responses:
        '200':
          description: Vault metadata
          content:
            application/json:
              schema:
                type: object
                properties:
                  ok:
                    type: boolean
                    const: true
                  vault:
                    $ref: '#/components/schemas/VaultMetadata'
                required: [ok, vault]
        '404':
          $ref: '#/components/responses/ErrorResponse'
  /vaults/{vaultId}/metrics:
    get:
      tags: [Vaults]
      summary: Get current vault metrics
      operationId: getVaultMetrics
      parameters:
        - $ref: '#/components/parameters/VaultId'
      responses:
        '200':
          description: Vault metrics
          content:
            application/json:
              schema:
                type: object
                properties:
                  ok:
                    type: boolean
                    const: true
                  snapshot:
                    $ref: '#/components/schemas/VaultSnapshot'
                required: [ok, snapshot]
        '404':
          $ref: '#/components/responses/ErrorResponse'
        '502':
          $ref: '#/components/responses/ErrorResponse'
  /vaults/{vaultId}/positions/{wallet}:
    get:
      tags: [Vaults]
      summary: Get wallet position for a vault
      operationId: getVaultPosition
      parameters:
        - $ref: '#/components/parameters/VaultId'
        - name: wallet
          in: path
          required: true
          schema:
            type: string
          description: Wallet address to inspect
      responses:
        '200':
          description: Wallet position
          content:
            application/json:
              schema:
                type: object
                properties:
                  ok:
                    type: boolean
                    const: true
                  position:
                    $ref: '#/components/schemas/VaultPosition'
                required: [ok, position]
        '400':
          $ref: '#/components/responses/ErrorResponse'
        '404':
          $ref: '#/components/responses/ErrorResponse'
        '502':
          $ref: '#/components/responses/ErrorResponse'
  /vaults/{vaultId}/quote-deposit:
    post:
      tags: [Vaults]
      summary: Quote a deposit
      operationId: quoteDeposit
      parameters:
        - $ref: '#/components/parameters/VaultId'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                assetAmount:
                  type: string
                  pattern: '^[0-9]+$'
                  example: '1000000'
              required: [assetAmount]
      responses:
        '200':
          description: Deposit quote
          content:
            application/json:
              schema:
                type: object
                properties:
                  ok:
                    type: boolean
                    const: true
                  quote:
                    $ref: '#/components/schemas/DepositQuote'
                required: [ok, quote]
        '400':
          $ref: '#/components/responses/ErrorResponse'
        '404':
          $ref: '#/components/responses/ErrorResponse'
  /vaults/{vaultId}/quote-mint:
    post:
      tags: [Vaults]
      summary: Quote a mint
      operationId: quoteMint
      parameters:
        - $ref: '#/components/parameters/VaultId'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                shareAmount:
                  type: string
                  pattern: '^[0-9]+$'
                  example: '1000000000000000000'
              required: [shareAmount]
      responses:
        '200':
          description: Mint quote
          content:
            application/json:
              schema:
                type: object
                properties:
                  ok:
                    type: boolean
                    const: true
                  quote:
                    $ref: '#/components/schemas/MintQuote'
                required: [ok, quote]
        '400':
          $ref: '#/components/responses/ErrorResponse'
        '404':
          $ref: '#/components/responses/ErrorResponse'
  /vaults/{vaultId}/quote-withdraw:
    post:
      tags: [Vaults]
      summary: Quote a withdraw
      operationId: quoteWithdraw
      parameters:
        - $ref: '#/components/parameters/VaultId'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                assetAmount:
                  type: string
                  pattern: '^[0-9]+$'
                  example: '1000000'
              required: [assetAmount]
      responses:
        '200':
          description: Withdraw quote
          content:
            application/json:
              schema:
                type: object
                properties:
                  ok:
                    type: boolean
                    const: true
                  quote:
                    $ref: '#/components/schemas/WithdrawQuote'
                required: [ok, quote]
        '400':
          $ref: '#/components/responses/ErrorResponse'
        '404':
          $ref: '#/components/responses/ErrorResponse'
  /vaults/{vaultId}/quote-redeem:
    post:
      tags: [Vaults]
      summary: Quote a redeem
      operationId: quoteRedeem
      parameters:
        - $ref: '#/components/parameters/VaultId'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                shareAmount:
                  type: string
                  pattern: '^[0-9]+$'
                  example: '1000000000000000000'
              required: [shareAmount]
      responses:
        '200':
          description: Redeem quote
          content:
            application/json:
              schema:
                type: object
                properties:
                  ok:
                    type: boolean
                    const: true
                  quote:
                    $ref: '#/components/schemas/RedeemQuote'
                required: [ok, quote]
        '400':
          $ref: '#/components/responses/ErrorResponse'
        '404':
          $ref: '#/components/responses/ErrorResponse'
  /vaults/{vaultId}/intents/deposit:
    post:
      tags: [Vaults]
      summary: Build deposit transaction steps
      operationId: buildDepositIntent
      parameters:
        - $ref: '#/components/parameters/VaultId'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                ownerAddress:
                  type: string
                  example: '0xE8eA6365C329130fd47d4D1Ca0aE59CAf49fA9C4'
                assetAmount:
                  type: string
                  pattern: '^[0-9]+$'
                  example: '1000000'
              required: [ownerAddress, assetAmount]
      responses:
        '200':
          description: Deposit intent
          content:
            application/json:
              schema:
                type: object
                properties:
                  ok:
                    type: boolean
                    const: true
                  intent:
                    $ref: '#/components/schemas/IntentPayload'
                required: [ok, intent]
        '400':
          $ref: '#/components/responses/ErrorResponse'
        '404':
          $ref: '#/components/responses/ErrorResponse'
  /vaults/{vaultId}/intents/mint:
    post:
      tags: [Vaults]
      summary: Build mint transaction steps
      operationId: buildMintIntent
      parameters:
        - $ref: '#/components/parameters/VaultId'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                ownerAddress:
                  type: string
                shareAmount:
                  type: string
                  pattern: '^[0-9]+$'
                  example: '1000000000000000000'
              required: [ownerAddress, shareAmount]
      responses:
        '200':
          description: Mint intent
          content:
            application/json:
              schema:
                type: object
                properties:
                  ok:
                    type: boolean
                    const: true
                  intent:
                    $ref: '#/components/schemas/IntentPayload'
                required: [ok, intent]
        '400':
          $ref: '#/components/responses/ErrorResponse'
        '404':
          $ref: '#/components/responses/ErrorResponse'
  /vaults/{vaultId}/intents/withdraw:
    post:
      tags: [Vaults]
      summary: Build withdraw transaction steps
      operationId: buildWithdrawIntent
      parameters:
        - $ref: '#/components/parameters/VaultId'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                ownerAddress:
                  type: string
                assetAmount:
                  type: string
                  pattern: '^[0-9]+$'
              required: [ownerAddress, assetAmount]
      responses:
        '200':
          description: Withdraw intent
          content:
            application/json:
              schema:
                type: object
                properties:
                  ok:
                    type: boolean
                    const: true
                  intent:
                    $ref: '#/components/schemas/IntentPayload'
                required: [ok, intent]
        '400':
          $ref: '#/components/responses/ErrorResponse'
        '404':
          $ref: '#/components/responses/ErrorResponse'
  /vaults/{vaultId}/intents/redeem:
    post:
      tags: [Vaults]
      summary: Build redeem transaction steps
      operationId: buildRedeemIntent
      parameters:
        - $ref: '#/components/parameters/VaultId'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                ownerAddress:
                  type: string
                shareAmount:
                  type: string
                  pattern: '^[0-9]+$'
                  example: '1000000000000000000'
              required: [ownerAddress, shareAmount]
      responses:
        '200':
          description: Redeem intent
          content:
            application/json:
              schema:
                type: object
                properties:
                  ok:
                    type: boolean
                    const: true
                  intent:
                    $ref: '#/components/schemas/IntentPayload'
                required: [ok, intent]
        '400':
          $ref: '#/components/responses/ErrorResponse'
        '404':
          $ref: '#/components/responses/ErrorResponse'
  /x402/vaults/{vaultId}/info:
    get:
      tags: [X402]
      summary: Get vault info (x402 paywalled)
      operationId: getX402VaultInfo
      description: >
        Returns vault metadata including on-chain metrics and asset info.
        This endpoint is gated by x402 micropayment when x402 is enabled on the server;
        callers must include a valid `PAYMENT-SIGNATURE` header. When x402 is disabled the
        endpoint returns 503.
      parameters:
        - $ref: '#/components/parameters/VaultId'
      responses:
        '200':
          description: Vault info
          content:
            application/json:
              schema:
                type: object
                properties:
                  ok:
                    type: boolean
                    const: true
                  data:
                    $ref: '#/components/schemas/VaultInfo'
                required: [ok, data]
        '404':
          $ref: '#/components/responses/ErrorResponse'
        '503':
          $ref: '#/components/responses/ErrorResponse'
  /vaults/wallet/register:
    post:
      tags: [Wallet]
      summary: Register a wallet address
      operationId: registerWallet
      description: >
        Registers an EVM wallet address in the platform. Idempotent — returns 200
        if the address is already registered, 201 on first registration.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                walletAddress:
                  type: string
                  description: EVM wallet address (checksummed or lowercase)
                  example: '0xE8eA6365C329130fd47d4D1Ca0aE59CAf49fA9C4'
              required: [walletAddress]
      responses:
        '200':
          description: Wallet already registered
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/WalletRegistrationResponse'
        '201':
          description: Wallet registered
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/WalletRegistrationResponse'
        '400':
          $ref: '#/components/responses/ErrorResponse'
components:
  parameters:
    VaultId:
      name: vaultId
      in: path
      required: true
      schema:
        type: string
      example: ixs-tokenized-vault-base-sepolia
  responses:
    ErrorResponse:
      description: Error response
      content:
        application/json:
          schema:
            type: object
            properties:
              ok:
                type: boolean
                const: false
              error:
                type: string
            required: [ok, error]
  schemas:
    AssetInfo:
      type: object
      properties:
        symbol:
          type: string
        decimals:
          type: integer
        address:
          type: string
        explorerUrl:
          type: string
      required: [symbol, decimals, address, explorerUrl]
    VaultMetadata:
      type: object
      properties:
        id:
          type: string
        name:
          type: string
        chainId:
          type: integer
        network:
          type: string
        contractAddress:
          type: string
        explorerUrl:
          type: string
        rpcUrl:
          type: string
          description: RPC endpoint for the chain this vault is deployed on
        requiresWhitelist:
          type: boolean
          description: Whether this vault should enforce the application-level whitelist workflow.
        underlyingAsset:
          $ref: '#/components/schemas/AssetInfo'
        actions:
          type: array
          items:
            type: string
      required:
        [
          id,
          name,
          chainId,
          network,
          contractAddress,
          explorerUrl,
          rpcUrl,
          requiresWhitelist,
          underlyingAsset,
          actions,
        ]
    VaultInfo:
      type: object
      description: Vault metadata returned by the x402 info endpoint
      properties:
        id:
          type: string
        routeId:
          type: string
        name:
          type: string
        symbol:
          type: string
        chainId:
          type: integer
        network:
          type: string
        chainName:
          type: string
        contractAddress:
          type: string
        explorerUrl:
          type: string
        subgraphUrl:
          type: string
        logoUrl:
          type: string
        requiresWhitelist:
          type: boolean
        status:
          type: string
          enum: [active, inactive]
        underlyingAsset:
          $ref: '#/components/schemas/AssetInfo'
        metrics:
          description: Pre-computed metrics snapshot if available, otherwise null
          nullable: true
      required:
        [
          id,
          routeId,
          name,
          symbol,
          chainId,
          network,
          chainName,
          contractAddress,
          explorerUrl,
          requiresWhitelist,
          status,
        ]
    WalletRegistrationResponse:
      type: object
      properties:
        ok:
          type: boolean
          const: true
        walletAddress:
          type: string
          description: EVM address in checksummed form
      required: [ok, walletAddress]
    DisplayAmount:
      type: object
      properties:
        baseUnits:
          type: string
        decimals:
          type: integer
        display:
          type: string
      required: [baseUnits, decimals, display]
    VaultTotals:
      type: object
      properties:
        managedAssets:
          $ref: '#/components/schemas/DisplayAmount'
        totalAssets:
          $ref: '#/components/schemas/DisplayAmount'
        availableAssets:
          $ref: '#/components/schemas/DisplayAmount'
        totalSupply:
          $ref: '#/components/schemas/DisplayAmount'
        totalFeesAccrued:
          $ref: '#/components/schemas/DisplayAmount'
        liquidityShortfall:
          $ref: '#/components/schemas/DisplayAmount'
        liquiditySurplus:
          $ref: '#/components/schemas/DisplayAmount'
      required:
        [
          managedAssets,
          totalAssets,
          availableAssets,
          totalSupply,
          totalFeesAccrued,
          liquidityShortfall,
          liquiditySurplus,
        ]
    VaultSnapshot:
      type: object
      properties:
        vaultId:
          type: string
        chainId:
          type: integer
        contractAddress:
          type: string
        assetAddress:
          type: string
        paused:
          type: boolean
        feeBps:
          type: integer
        custody:
          type: string
        feeRecipient:
          type: string
        totals:
          $ref: '#/components/schemas/VaultTotals'
      required:
        [
          vaultId,
          chainId,
          contractAddress,
          assetAddress,
          paused,
          feeBps,
          custody,
          feeRecipient,
          totals,
        ]
    VaultBalances:
      type: object
      properties:
        asset:
          $ref: '#/components/schemas/DisplayAmount'
        shares:
          $ref: '#/components/schemas/DisplayAmount'
        shareValueInAssets:
          $ref: '#/components/schemas/DisplayAmount'
      required: [asset, shares, shareValueInAssets]
    VaultLimits:
      type: object
      properties:
        allowanceToVault:
          $ref: '#/components/schemas/DisplayAmount'
        maxWithdraw:
          $ref: '#/components/schemas/DisplayAmount'
        maxRedeem:
          $ref: '#/components/schemas/DisplayAmount'
      required: [allowanceToVault, maxWithdraw, maxRedeem]
    VaultPosition:
      type: object
      properties:
        vaultId:
          type: string
        wallet:
          type: string
        balances:
          $ref: '#/components/schemas/VaultBalances'
        limits:
          $ref: '#/components/schemas/VaultLimits'
      required: [vaultId, wallet, balances, limits]
    DepositQuote:
      type: object
      properties:
        vaultId:
          type: string
        operation:
          type: string
          const: deposit
        executableNow:
          type: boolean
        inputs:
          type: object
          properties:
            assetAmount:
              $ref: '#/components/schemas/DisplayAmount'
          required: [assetAmount]
        outputs:
          type: object
          properties:
            estimatedShares:
              $ref: '#/components/schemas/DisplayAmount'
          required: [estimatedShares]
        limits:
          type: object
          properties:
            maxDeposit:
              $ref: '#/components/schemas/DisplayAmount'
          required: [maxDeposit]
      required: [vaultId, operation, executableNow, inputs, outputs, limits]
    MintQuote:
      type: object
      properties:
        vaultId:
          type: string
        operation:
          type: string
          const: mint
        executableNow:
          type: boolean
        inputs:
          type: object
          properties:
            shareAmount:
              $ref: '#/components/schemas/DisplayAmount'
          required: [shareAmount]
        outputs:
          type: object
          properties:
            estimatedAssetCost:
              $ref: '#/components/schemas/DisplayAmount'
          required: [estimatedAssetCost]
        limits:
          type: object
          properties:
            maxMint:
              $ref: '#/components/schemas/DisplayAmount'
          required: [maxMint]
      required: [vaultId, operation, executableNow, inputs, outputs, limits]
    WithdrawQuote:
      type: object
      properties:
        vaultId:
          type: string
        operation:
          type: string
          const: withdraw
        executableNow:
          type:
            - boolean
            - 'null'
        inputs:
          type: object
          properties:
            assetAmount:
              $ref: '#/components/schemas/DisplayAmount'
          required: [assetAmount]
        outputs:
          type: object
          properties:
            estimatedSharesBurned:
              $ref: '#/components/schemas/DisplayAmount'
            estimatedFee:
              $ref: '#/components/schemas/DisplayAmount'
          required: [estimatedSharesBurned, estimatedFee]
      required: [vaultId, operation, executableNow, inputs, outputs]
    RedeemQuote:
      type: object
      properties:
        vaultId:
          type: string
        operation:
          type: string
          const: redeem
        executableNow:
          type:
            - boolean
            - 'null'
        inputs:
          type: object
          properties:
            shareAmount:
              $ref: '#/components/schemas/DisplayAmount'
          required: [shareAmount]
        outputs:
          type: object
          properties:
            estimatedNetAssets:
              $ref: '#/components/schemas/DisplayAmount'
            estimatedFee:
              $ref: '#/components/schemas/DisplayAmount'
          required: [estimatedNetAssets, estimatedFee]
      required: [vaultId, operation, executableNow, inputs, outputs]
    IntentStep:
      type: object
      properties:
        type:
          type: string
        tx:
          type: object
          properties:
            to:
              type: string
            data:
              type: string
            value:
              type: string
          required: [to, data, value]
      required: [type, tx]
    IntentPayload:
      type: object
      properties:
        vaultId:
          type: string
        operation:
          type: string
        chainId:
          type: integer
        ownerAddress:
          type: string
        steps:
          type: array
          items:
            $ref: '#/components/schemas/IntentStep'
      required: [vaultId, operation, chainId, ownerAddress, steps]
