openapi: 3.1.0
info:
  title: Portal Custodian API
  version: '3.0'
  description: >
    The Portal Custodian API provides endpoints for managing clients, building
    transactions,

    retrieving wallet data, managing delegations, alert webhooks, and gas
    sponsorship.

    All endpoints require authentication via a Portal API Key (also known as a
    Custodian API Key)

    passed as a Bearer token.


    ## Base URL

    `https://api.portalhq.io/api/v3`


    ## Authentication

    Include your Portal API Key as a Bearer token in the `Authorization` header
    of every request.


    ## Chain ID Format

    Chain parameters use either friendly names (e.g. `ethereum`, `solana`) or
    CAIP-2 format

    (e.g. `eip155:1`, `solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp`). When using
    CAIP-2 format

    in URLs, ensure the colon is URI-encoded (`%3A`).
servers:
  - url: https://api.portalhq.io/api/v3
    description: Production
security:
  - bearerAuth: []
tags:
  - name: Clients
    description: Create and manage Portal clients
  - name: Transactions
    description: Build and evaluate blockchain transactions
  - name: Wallet Metadata
    description: Retrieve wallet balances and NFTs
  - name: Wallet Shares
    description: Manage backup shares and wallet ejection
  - name: Delegations
    description: Manage token delegations and delegated transfers
  - name: Session Keys
    description: Build and send EIP-7702 session key user operations
  - name: Alert Webhooks
    description: Manage alert webhooks, external addresses, and replay failed events
  - name: Gas Sponsorship
    description: View and manage gas sponsorship across chains
  - name: Due
    description: Manage Due webhook endpoints and deliveries
paths:
  /custodians/me/clients:
    post:
      operationId: createClient
      summary: Create a client
      description: >
        Registers a new client and returns a client API key, client session
        token,

        and whether account abstraction is enabled.
      tags:
        - Clients
      requestBody:
        required: false
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateClientRequest'
            example:
              isAccountAbstracted: false
      responses:
        '200':
          description: Client created successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CreateClientResponse'
              example:
                id: clientId
                clientApiKey: clientApiKey
                clientSessionToken: clientSessionToken
                isAccountAbstracted: false
        '400':
          description: Bad request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          description: Unauthorized - invalid or missing authentication token
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
    get:
      operationId: listClients
      summary: List clients
      description: >
        Fetches all clients for the authorized custodian with cursor-based
        pagination.
      tags:
        - Clients
      parameters:
        - name: cursor
          in: query
          required: false
          description: >-
            The ID of the last client in the list. Used for cursor-based
            pagination.
          schema:
            type: string
        - name: take
          in: query
          required: false
          description: The number of records to retrieve. Maximum is 100. Default is 100.
          schema:
            type: integer
            default: 100
            maximum: 100
      responses:
        '200':
          description: Clients retrieved successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ClientListResponse'
              example:
                results:
                  - createdAt: '2024-04-16T21:15:06.443Z'
                    custodian:
                      id: custodianId
                      name: Custodian Name
                    ejectedAt: null
                    environment:
                      id: environmentId
                      name: Development
                    id: clientId
                    isAccountAbstracted: false
                    metadata:
                      namespaces:
                        eip155:
                          address: '0x6e818d8f9b6c53c59a2d957d36c2146e28906195'
                          curve: SECP256K1
                    wallets:
                      - createdAt: '2024-04-16T21:15:45.144Z'
                        curve: SECP256K1
                        id: wallet1Id
                        backupSharePairs:
                          - backupMethod: PASSWORD
                            createdAt: '2024-04-16T21:16:48.723Z'
                            id: backupSharePairId1
                            status: completed
                        signingSharePairs:
                          - createdAt: '2024-04-16T21:15:45.151Z'
                            id: signingSharePairId1
                            status: completed
                        publicKey: stringifiedJSON
                metadata:
                  cursor: nextCursorToUse
                  take: 100
                  total: 1000
        '400':
          description: Bad request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          description: Unauthorized - invalid or missing authentication token
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
  /custodians/me/clients/{clientId}:
    get:
      operationId: getClient
      summary: Get a client
      description: >
        Fetches the specified client for the authorized custodian, including
        wallet

        details, backup share pairs, and signing share pairs.
      tags:
        - Clients
      parameters:
        - $ref: '#/components/parameters/clientId'
      responses:
        '200':
          description: Client details retrieved successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ClientDetails'
              example:
                createdAt: '2024-04-16T21:15:06.443Z'
                custodian:
                  id: custodianId
                  name: Custodian Name
                ejectedAt: null
                environment:
                  id: environmentId
                  name: Development
                id: clientId
                isAccountAbstracted: false
                metadata:
                  namespaces:
                    eip155:
                      address: '0x6e818d8f9b6c53c59a2d957d36c2146e28906195'
                      curve: SECP256K1
                wallets:
                  - createdAt: '2024-04-16T21:15:45.144Z'
                    curve: SECP256K1
                    id: wallet1Id
                    backupSharePairs:
                      - backupMethod: PASSWORD
                        createdAt: '2024-04-16T21:16:48.723Z'
                        id: backupSharePairId1
                        status: completed
                      - backupMethod: GDRIVE
                        createdAt: '2024-04-16T21:17:02.074Z'
                        id: backupSharePairId2
                        status: incomplete
                      - backupMethod: ICLOUD
                        createdAt: '2024-04-16T21:18:06.996Z'
                        id: backupSharePairId3
                        status: incomplete
                    signingSharePairs:
                      - createdAt: '2024-04-16T21:15:45.151Z'
                        id: signingSharePairId1
                        status: completed
                    publicKey: stringifiedJSON
        '400':
          description: Bad request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          description: Unauthorized - invalid or missing authentication token
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
  /custodians/me/clients/{clientId}/sessions:
    post:
      operationId: createClientSession
      summary: Create a client session token
      description: >
        Creates a new Client Session Token (CST) for a client. The CST can be
        used

        by the client SDK to authenticate API requests.
      tags:
        - Clients
      parameters:
        - $ref: '#/components/parameters/clientId'
      requestBody:
        required: false
        content:
          application/json:
            schema:
              type: object
              properties:
                isAccountAbstracted:
                  type: boolean
                  description: Whether the client uses account abstraction.
            example:
              isAccountAbstracted: false
      responses:
        '200':
          description: Session token created successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CreateSessionResponse'
              example:
                id: clientId
                clientSessionToken: clientSessionToken
                isAccountAbstracted: false
        '400':
          description: Bad request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          description: Unauthorized - invalid or missing authentication token
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
  /custodians/me/clients/{clientId}/web-otps:
    post:
      operationId: createWebOtp
      summary: Create a web OTP
      description: >
        Generates a one-time password (OTP) for a client using the Web SDK.


        **Note:** The legacy v1 endpoint (`GET
        /api/v1/custodians/clients/{clientId}/web-otp`)

        is still available but this v3 POST endpoint is preferred.
      tags:
        - Clients
      parameters:
        - $ref: '#/components/parameters/clientId'
      responses:
        '200':
          description: OTP created successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/WebOtpResponse'
              example:
                id: clientId
                otp: one-time-password
        '400':
          description: Bad request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          description: Unauthorized - invalid or missing authentication token
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
  /custodians/me/clients/{clientId}/chains/{chain}/assets/send/build-transaction:
    post:
      operationId: custodianBuildTransaction
      summary: Build a transaction
      description: >
        Creates an unsigned transaction for transferring assets to another
        address on a

        specific chain. You can then use this unsigned transaction to sign and
        submit

        the transaction.


        The response shape varies depending on the chain type (EIP-155, Solana,
        Bitcoin,

        Stellar, or Tron).
      tags:
        - Transactions
      parameters:
        - $ref: '#/components/parameters/clientId'
        - $ref: '#/components/parameters/chain'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/BuildTransactionRequest'
            example:
              to: '0xdFd8302f44727A6348F702fF7B594f127dE3A902'
              token: USDC
              amount: '0.01'
      responses:
        '200':
          description: >
            Unsigned transaction built successfully. The response structure
            depends on the

            chain type.
          content:
            application/json:
              schema:
                oneOf:
                  - $ref: '#/components/schemas/Eip155TransactionResult'
                  - $ref: '#/components/schemas/SolanaTransactionResult'
                  - $ref: '#/components/schemas/BitcoinTransactionResult'
              examples:
                eip155:
                  summary: EIP-155 (Ethereum, Polygon, Base, etc.)
                  value:
                    transaction:
                      from: '0x21d8d1d2d9907c051670d8c9a80bd2192d273f8d'
                      to: '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48'
                      data: >-
                        0xa9059cbb000000000000000000000000dfd8302f44727a6348f702ff7b594f127de3a9020000000000000000000000000000000000000000000000000000000000002710
                    metadata:
                      rawAmount: '10000'
                      formattedAmount: '0.01'
                      tokenDecimals: 6
                      tokenAddress: '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48'
                solana:
                  summary: Solana
                  value:
                    transaction: >-
                      AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAUIdDKlh5tOZP...
                    metadata:
                      amount: '0.01'
                      mintAddress: EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v
                      lastValidBlockHeight: '259030944'
                bitcoin:
                  summary: Bitcoin
                  value:
                    transaction:
                      signatureHashes:
                        - signatureHash1
                        - signatureHash2
                      rawTxHex: rawTxHex
                      publicKey: jsonStringifiedPublicKey
                    metadata:
                      chainId: bip122:000000000933ea01ad0ee984209779ba-p2wpkh
                      amount: '0.00001'
                      fromAddress: tb1qpl54na90wlmdxj5z4wtz7cpp6p32dc9tajwa5g
                      toAddress: tb1q7ynrnrywae5ypxk6fqgzqhqy202ehk7hntqc9j
                      rawAmount: '1000'
                      feeInSatoshis: '420'
                      changeInSatoshis: '4584'
                      tokenDecimals: 8
                      tokenSymbol: BTC
        '400':
          description: |
            Bad request - invalid parameters. Common causes include:
            - Invalid destination address format
            - Amount must be greater than zero
            - Unsupported chain
            - Token not supported on the specified chain
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          description: Unauthorized - invalid or missing authentication token
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
  /custodians/me/clients/{clientId}/evaluate-transaction:
    post:
      operationId: custodianEvaluateTransaction
      summary: Evaluate a transaction
      description: >
        Evaluates a transaction using validation and/or simulation to assess
        risk before

        signing. Supports both EVM (EIP-155) and Solana chains. The request body
        format

        differs by chain type.


        For **EVM chains**, provide the transaction fields (`to`, `data`,
        `value`, etc.).

        For **Solana**, provide an array of base58-encoded transactions.
      tags:
        - Transactions
      parameters:
        - $ref: '#/components/parameters/clientId'
        - name: chainId
          in: query
          required: true
          description: >
            Chain ID in CAIP-2 format. For example, `eip155:1` for Ethereum
            mainnet

            or `solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp` for Solana.
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              oneOf:
                - $ref: '#/components/schemas/EvaluateTransactionEip155Request'
                - $ref: '#/components/schemas/EvaluateTransactionSolanaRequest'
            examples:
              evm:
                summary: EVM transaction evaluation
                value:
                  to: '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48'
                  data: 0xa9059cbb000000000000000000000000...
                  value: '0x0'
                  operationType: all
              solana:
                summary: Solana transaction evaluation
                value:
                  transactions:
                    - 5xGh7Abc...
                  operationType: simulation
      responses:
        '200':
          description: Transaction evaluated successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/EvaluateTransactionResponse'
              examples:
                evm:
                  summary: EVM evaluation result
                  value:
                    chain: eip155:1
                    validation:
                      status: Success
                      resultType: Benign
                      description: The transaction is safe
                      reason: ''
                      classification: ''
                      features: []
                    simulation:
                      status: Success
                      assetsDiffs: []
                      totalUsdDiff: '0'
                      exposures: []
                      totalUsdExposure: '0'
                      addressDetails: {}
                      accountSummary: {}
                solana:
                  summary: Solana evaluation result
                  value:
                    chain: solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp
                    validation:
                      status: Success
                      resultType: Benign
                      description: The transaction is safe
                    simulation:
                      status: Success
                      assetsDiffs: []
                      totalUsdDiff: '0'
                      exposures: []
                      totalUsdExposure: '0'
        '400':
          description: Bad request - invalid parameters or mismatched chain type
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          description: Unauthorized - invalid or missing authentication token
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
  /custodians/me/clients/{clientId}/chains/{chain}/assets:
    get:
      operationId: custodianGetAssets
      summary: Get asset balances
      description: >
        Retrieves the native balance, token balances, and NFTs for a specified
        client

        and blockchain.
      tags:
        - Wallet Metadata
      parameters:
        - $ref: '#/components/parameters/clientId'
        - $ref: '#/components/parameters/chain'
      responses:
        '200':
          description: Assets retrieved successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AssetBalancesResponse'
              example:
                nativeBalance:
                  balance: '0.10991767582513721'
                  decimals: 18
                  name: Ether
                  rawBalance: '109917675825137210'
                  symbol: ETH
                  metadata:
                    logo: https://cdn.moralis.io/eth/0x.png
                    thumbnail: https://cdn.moralis.io/eth/0x_thumb.png
                tokenBalances:
                  - balance: '0.0199'
                    decimals: 18
                    name: Wrapped Ether
                    rawBalance: '19900000000000000'
                    symbol: WETH
                    metadata:
                      tokenAddress: '0xfff9976782d46cc05630d1f6ebab18b2324d6b14'
                      verifiedContract: false
                      totalSupply: '48148.648311179713152621'
                      rawTotalSupply: '48148648311179713152621'
                      percentageRelativeToTotalSupply: 0.00004133033989114
        '400':
          description: Bad request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          description: Unauthorized - invalid or missing authentication token
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
  /custodians/me/clients/{clientId}/chains/{chain}/assets/nfts:
    get:
      operationId: custodianGetNfts
      summary: Get NFTs
      description: |
        Retrieves the NFTs held by a specified client on a given blockchain.
      tags:
        - Wallet Metadata
      parameters:
        - $ref: '#/components/parameters/clientId'
        - $ref: '#/components/parameters/chain'
      responses:
        '200':
          description: NFTs retrieved successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/NftListResponse'
              example:
                - nftId: ethereum.0x123abc...def456.1234
                  name: 'Cosmic Kitty #1234'
                  description: >-
                    A rare, interstellar feline NFT from the Cosmic Kitties
                    collection.
                  imageUrl: https://example.com/images/cosmic-kitty-1234.png
                  chainId: eip155:1
                  contractAddress: 0x123abc...def456
                  tokenId: '1234'
                  collection:
                    name: Cosmic Kitties
                    description: A collection of 10,000 unique space-faring felines.
                    imageUrl: https://example.com/images/cosmic-kitties-logo.png
        '400':
          description: Bad request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          description: Unauthorized - invalid or missing authentication token
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
  /custodians/me/clients/{clientId}/enable-eject:
    patch:
      operationId: enableEject
      summary: Enable wallet ejection
      description: >
        Prepare a wallet for ejection of its private keys. This endpoint enables
        a Portal

        client to be ejected for a specified duration.


        **Your custodian must be using Portal-Managed Backups to use this
        endpoint.**
      tags:
        - Wallet Shares
      parameters:
        - $ref: '#/components/parameters/clientId'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/EnableEjectRequest'
            example:
              ejectableUntil: '2025-06-18T15:23:00.470Z'
              walletId: walletId
      responses:
        '200':
          description: Eject window enabled successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/EnableEjectResponse'
              example:
                ejectableUntil: '2025-03-04T15:26:43.123Z'
        '400':
          description: Bad request - ejectableUntil must be at least 1 minute from now
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          description: Unauthorized - invalid or missing authentication token
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
  /custodians/me/clients/{clientId}/wallets/{walletId}/ejectable-backup-shares:
    get:
      operationId: getEjectableBackupShares
      summary: Get ejectable backup shares
      description: >
        Fetches a client's encrypted backup share (if previously sent to Portal)
        and their

        custodian backup share. Used when running eject while using the Enclave
        MPC API

        with a Portal-Managed Backup configuration.


        **Your custodian must be using Portal-Managed Backups to use this
        endpoint.**
      tags:
        - Wallet Shares
      parameters:
        - $ref: '#/components/parameters/clientId'
        - $ref: '#/components/parameters/walletId'
      responses:
        '200':
          description: Backup shares retrieved successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/EjectableBackupSharesResponse'
              example:
                encryptedClientBackupShare: 0351cf2baa54748662a6c89bb032...
                custodianBackupShare: '{"backupSharePairId":"...","share":"...","ssid":"..."}'
        '400':
          description: Bad request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          description: Unauthorized - invalid or missing authentication token
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
  /custodians/me/clients/{clientId}/prepare-eject:
    post:
      operationId: prepareEject
      summary: Prepare a client for eject (deprecated)
      deprecated: true
      description: |
        **Deprecated.** Use the `enable-eject` endpoint instead.

        Prepare a wallet for ejection of its private keys.
      tags:
        - Wallet Shares
      parameters:
        - $ref: '#/components/parameters/clientId'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/PrepareEjectRequest'
            example:
              walletId: walletId
              ejectableUntil: '2025-06-18T15:23:00.470Z'
      responses:
        '200':
          description: Wallet prepared for ejection
          content:
            text/plain:
              schema:
                type: string
                description: The ejectableUntil timestamp
              example: '2025-03-04T15:26:43.123Z'
        '400':
          description: Bad request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          description: Unauthorized - invalid or missing authentication token
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
  /custodians/me/clients/{clientId}/chains/{chain}/delegation/status:
    get:
      operationId: custodianGetDelegationStatus
      summary: Get Solana delegation status
      description: >
        Retrieves the delegation status for a Solana token account, including
        information

        about the token balance, delegate address, and delegated amount.


        **Supported chains:** Solana Mainnet and Solana Devnet only.
      tags:
        - Delegations
      parameters:
        - $ref: '#/components/parameters/clientId'
        - $ref: '#/components/parameters/chain'
      responses:
        '200':
          description: Delegation status retrieved successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/DelegationStatusResponse'
              example:
                data:
                  ownerAddress: 2qcnuxjA5fgMSgaUsg9w4eE2DBkZUTxYXQC8YMyt2XDV
                  tokenAccount: CND4K6vZUZBp743UCD6JH1VHWuYCq4gwGYHi6fmPb7de
                  tokenMint: 4zMMC9srt5Ri5X14GAgXhaHii3GnPAEERYPJgZJDncDU
                  tokenSymbol: USDC
                  balance: '0.010000'
                  balanceRaw: '10000'
                  hasDelegate: true
                  delegateAddress: C9DWdoaACTY7EpHUgMRfKZpExBhnSavn5Nz3vm17Dooa
                  delegatedAmount: '0.001000'
                  delegatedAmountRaw: '1000'
                metadata:
                  chainId: solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1
        '400':
          description: Bad request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          description: Unauthorized - invalid or missing authentication token
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
  /custodians/me/clients/{clientId}/chains/{chain}/assets/{token}/delegations:
    get:
      operationId: custodianGetDelegations
      summary: Get delegation status for a token
      description: |
        Retrieves the current delegation status for a specific client and
        token, including the balance and active delegations. See the
        delegateAddress parameter for per-chain behavior.
      tags:
        - Delegations
      parameters:
        - $ref: '#/components/parameters/clientId'
        - $ref: '#/components/parameters/chain'
        - $ref: '#/components/parameters/token'
        - name: delegateAddress
          in: query
          required: false
          description: |
            The delegate address to check delegation status for. Required on
            EVM (eip155) chains, where the response returns the allowance for
            that spender; omitting it there returns a 400. Optional on Solana
            chains: when omitted, the response returns the account's current
            delegate (SPL token accounts have at most one), and when supplied,
            the response is filtered to that address, with an empty delegations
            array if it is not the current delegate.
          schema:
            type: string
      responses:
        '200':
          description: Delegation status retrieved successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/DelegationsResponse'
              examples:
                evm:
                  summary: EVM delegation status
                  value:
                    chainId: eip155:1
                    token: USDC
                    tokenAddress: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48'
                    balance: '5000.0'
                    balanceRaw: '5000000000'
                    delegations:
                      - address: '0x1234567890abcdef1234567890abcdef12345678'
                        delegateAmount: '1000.0'
                        delegateAmountRaw: '1000000000'
                solana:
                  summary: Solana delegation status
                  value:
                    chainId: solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp
                    token: USDC
                    tokenAccount: 3fGmKg5s8jNzRs5pXfqhSMvZHJMHsoRxmKsQDgZwCx12
                    tokenAddress: EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v
                    balance: '2500.0'
                    balanceRaw: '2500000000'
                    delegations:
                      - address: 7UX2i7SucgLMQcfZ75s3VXmZZY4YRUyJN9X1RgfMoDUi
                        delegateAmount: '500.0'
                        delegateAmountRaw: '500000000'
        '400':
          description: Bad request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          description: Unauthorized - invalid or missing authentication token
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
  /custodians/me/clients/{clientId}/chains/{chain}/assets/{token}/delegations/transfers:
    post:
      operationId: custodianDelegationTransfer
      summary: Transfer as a delegate
      description: >
        Transfers tokens from a client on behalf of another address using
        delegated

        spending authority. Returns unsigned transaction(s) ready for signing.
      tags:
        - Delegations
      parameters:
        - $ref: '#/components/parameters/clientId'
        - $ref: '#/components/parameters/chain'
        - $ref: '#/components/parameters/token'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/DelegationTransferRequest'
            example:
              fromAddress: '0x5e1a0d484c5f0de722e82f9dca3a9d5a421d47cb'
              toAddress: '0x9876543210fedcba9876543210fedcba98765432'
              amount: '100'
      responses:
        '200':
          description: Unsigned delegation transfer transaction(s) built successfully
          content:
            application/json:
              schema:
                oneOf:
                  - $ref: '#/components/schemas/DelegationTransferEvmResponse'
                  - $ref: '#/components/schemas/DelegationTransferSolanaResponse'
              examples:
                evm:
                  summary: EVM delegation transfer
                  value:
                    transactions:
                      - from: '0x1234567890abcdef1234567890abcdef12345678'
                        to: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48'
                        data: 0x23b872dd...
                        value: '0x0'
                    metadata:
                      amount: '100.0'
                      amountRaw: '100000000'
                      chainId: eip155:1
                      delegateAddress: '0x1234567890abcdef1234567890abcdef12345678'
                      ownerAddress: '0x5e1a0d484c5f0de722e82f9dca3a9d5a421d47cb'
                      recipientAddress: '0x9876543210fedcba9876543210fedcba98765432'
                      tokenAddress: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48'
                      tokenSymbol: USDC
                      tokenDecimals: 6
                solana:
                  summary: Solana delegation transfer
                  value:
                    encodedTransactions:
                      - >-
                        AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAIEfGzKdQVmXn0GKjTPBmEMuca3SbUvHjJWvxyrNqRvSgGH4...
                    metadata:
                      amount: '100.0'
                      amountRaw: '100000000'
                      chainId: solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp
                      delegateAddress: 7UX2i7SucgLMQcfZ75s3VXmZZY4YRUyJN9X1RgfMoDUi
                      lastValidBlockHeight: '252435678'
                      needsRecipientTokenAccount: false
                      ownerAddress: Hm64jVjGRz7soPXReLXoXBYDvY5xKmkXjMWkPyLP5gqc
                      recipientAddress: 9aE476sH92Vz7DMPyq5WLPkrKWivxeuTKEFKd2sZZcde
                      tokenAddress: EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v
                      tokenSymbol: USDC
                      tokenDecimals: 6
        '400':
          description: Bad request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          description: Unauthorized - invalid or missing authentication token
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
  /custodians/me/clients/{clientId}/chains/{chain}/session-keys/build-user-operation:
    post:
      operationId: custodianBuildSessionKeyUserOperation
      summary: Build a session key user operation
      description: >
        Builds an unsigned EIP-4337 user operation that can be executed using a
        registered

        session key. The operation targets a specific contract address with
        optional calldata.
      tags:
        - Session Keys
      parameters:
        - $ref: '#/components/parameters/clientId'
        - $ref: '#/components/parameters/chain'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/BuildSessionKeyUserOperationRequest'
            example:
              sessionKeyAddress: 0xabc123...
              to: 0xdef456...
              value: '0'
              data: 0xa9059cbb...
      responses:
        '200':
          description: User operation built successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/BuildSessionKeyUserOperationResponse'
              example:
                data:
                  userOperation:
                    sender: 0x1234...
                    nonce: '0x1'
                    initCode: 0x
                    callData: 0x...
                    callGasLimit: '0x5208'
                    verificationGasLimit: '0x10000'
                    preVerificationGas: '0x5208'
                    maxFeePerGas: '0x3b9aca00'
                    maxPriorityFeePerGas: '0x3b9aca00'
                    paymasterAndData: 0x
                    signature: 0x
                  userOpHash: 0xabcdef...
                  permissionIndex: 0
                  entryPoint: '0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789'
                metadata:
                  chainId: eip155:11155111
                  eoaAddress: 0x1234...
                  sessionKeyValidatorAddress: '0x8Df2bf61F849676f00C6883743E077d391da1dDA'
        '400':
          description: Bad request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          description: Unauthorized - invalid or missing authentication token
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
  /custodians/me/clients/{clientId}/chains/{chain}/session-keys/send-user-operation:
    post:
      operationId: custodianSendSessionKeyUserOperation
      summary: Send a session key user operation
      description: >
        Submits a signed EIP-4337 user operation that was built using the build
        endpoint.

        The operation must be signed by the session key.
      tags:
        - Session Keys
      parameters:
        - $ref: '#/components/parameters/clientId'
        - $ref: '#/components/parameters/chain'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/SendSessionKeyUserOperationRequest'
            example:
              sessionKeyAddress: 0xabc123...
              userOperation:
                sender: 0x1234...
                nonce: '0x1'
                initCode: 0x
                callData: 0x...
                callGasLimit: '0x5208'
                verificationGasLimit: '0x10000'
                preVerificationGas: '0x5208'
                maxFeePerGas: '0x3b9aca00'
                maxPriorityFeePerGas: '0x3b9aca00'
                paymasterAndData: 0x
                signature: 0x
              userOpHashSignature: 0xsignature...
              permissionIndex: 0
      responses:
        '200':
          description: User operation submitted successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SendSessionKeyUserOperationResponse'
              example:
                data:
                  userOperationHash: 0xabcdef...
                  transactionHash: null
                metadata:
                  chainId: eip155:11155111
        '400':
          description: Bad request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          description: Unauthorized - invalid or missing authentication token
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
  /custodians/me/alerts/webhooks:
    get:
      operationId: listAlertWebhooks
      summary: List alert webhooks
      description: >
        Retrieve a list of your alert webhooks configured in your Portal Admin
        Dashboard.
      tags:
        - Alert Webhooks
      responses:
        '200':
          description: Alert webhooks retrieved successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AlertWebhookListResponse'
              example:
                data:
                  - autoAddNewAddresses: true
                    createdAt: '2024-12-19T19:05:04.707Z'
                    events:
                      - EIP_155_TX_V1
                    id: cm4voycw2001f68veade3tr0i
                    updatedAt: '2024-12-19T20:07:16.648Z'
                    url: https://example.com/alerts-webhooks/1/events
        '400':
          description: Bad request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          description: Unauthorized - invalid or missing authentication token
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
  /custodians/me/alerts/webhooks/{alertWebhookId}/delivery-events:
    get:
      operationId: listAlertWebhookDeliveryEvents
      summary: List alert webhook delivery events
      description: >
        Retrieve a cursor-paginated list of delivery events for an alert
        webhook,

        including those that are pending, currently being replayed, delivered,
        or

        failed. Use this endpoint to inspect delivery history and identify
        events

        that need to be retried with

        `POST
        /custodians/me/alerts/webhooks/{alertWebhookId}/delivery-events/{deliveryEventId}/retries`.


        See [Delivery event
        lifecycle](/resources/alert-webhooks#delivery-event-lifecycle)

        for the meaning of each `status` value and how manual retries interact
        with

        the automatic retry loop.
      tags:
        - Alert Webhooks
      parameters:
        - $ref: '#/components/parameters/alertWebhookId'
        - name: take
          in: query
          required: false
          description: >-
            The number of delivery events to retrieve. Min `1`, max `100`.
            Default `100`.
          schema:
            type: integer
            minimum: 1
            maximum: 100
            default: 100
        - name: cursor
          in: query
          required: false
          description: >-
            The delivery event ID to use for cursor-based pagination. Pass the
            `id` of the last item from the previous response.
          schema:
            type: string
        - name: statuses
          in: query
          required: false
          description: |
            Comma-delimited list of delivery event statuses to filter by.
            Valid values: `PENDING`, `DELIVERED`, `FAILED`, `REPLAYING`.
          schema:
            type: string
        - name: eventTypes
          in: query
          required: false
          description: >
            Comma-delimited list of alert webhook event types to filter by.

            Valid values: `EIP_155_TX_V1`, `PRE_SIGN_V1`, `SOLANA_TX_V1`,
            `SOLANA_TX_V2`,

            `SOLANA_APPROVE_V1`, `SOLANA_APPROVE_V2`, `SOLANA_REVOKE_V1`,
            `SOLANA_REVOKE_V2`,

            `SOLANA_DELEGATED_TRANSFER_V2`, `WALLET_EJECT_V1`.
          schema:
            type: string
        - name: orderBy
          in: query
          required: false
          description: Field to order results by. Defaults to `sentAt`.
          schema:
            type: string
            enum:
              - sentAt
              - createdAt
            default: sentAt
        - name: orderDirection
          in: query
          required: false
          description: Sort direction. Defaults to `desc`.
          schema:
            type: string
            enum:
              - asc
              - desc
            default: desc
        - name: since
          in: query
          required: false
          description: >-
            Returns only delivery events created after this Unix timestamp (in
            seconds).
          schema:
            type: number
        - name: until
          in: query
          required: false
          description: >-
            Returns only delivery events created before this Unix timestamp (in
            seconds).
          schema:
            type: number
      responses:
        '200':
          description: Alert webhook delivery events retrieved successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AlertWebhookDeliveryEventsResponse'
              example:
                results:
                  - id: cm5abc123def456ghi789jkl0
                    type: EIP_155_TX_V1
                    event:
                      data:
                        - transactionHash: >-
                            0x4978a4ba15a018532791ba4491e48b1aa8b544309c1ffce062bb1fb7e84dc069
                          chainId: eip155:11155111
                      metadata:
                        deliveryEventId: cm5abc123def456ghi789jkl0
                      type: EIP_155_TX_V1
                    status: DELIVERED
                    sentAt: '2025-01-20T10:30:00.000Z'
                    attempts: 1
                    createdAt: '2025-01-20T10:29:58.000Z'
                  - id: cm5xyz987wvu654tsr321qpo0
                    type: EIP_155_TX_V1
                    event:
                      data:
                        - transactionHash: >-
                            0x9b1c2d3e4f567890abcdef1234567890abcdef1234567890abcdef1234567890
                          chainId: eip155:1
                      metadata:
                        deliveryEventId: cm5xyz987wvu654tsr321qpo0
                      type: EIP_155_TX_V1
                    status: FAILED
                    sentAt: '2025-01-20T11:05:12.000Z'
                    attempts: 10
                    createdAt: '2025-01-20T11:00:00.000Z'
                metadata:
                  alertWebhook:
                    id: cm4voycw2001f68veade3tr0i
                    url: https://example.com/alerts-webhooks/1/events
                  cursor: cm5xyz987wvu654tsr321qpo0
                  take: 100
                  hasMore: true
        '400':
          description: Bad request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          description: Unauthorized - invalid or missing authentication token
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
  /custodians/me/alerts/webhooks/{alertWebhookId}/delivery-events/{deliveryEventId}/retries:
    post:
      operationId: retryAlertWebhookDeliveryEvent
      summary: Retry an alert webhook delivery event
      description: >
        Manually retry the delivery of a single alert webhook event. The event's

        status is set to `REPLAYING` and a one-shot delivery attempt is
        scheduled

        on a dedicated retry queue. On completion, the event moves to
        `DELIVERED`

        (2XX response) or `FAILED` (non-2XX response or timeout).


        **Manual retries replace the automatic retry loop.** If the target event

        is still `PENDING`, retrying it removes it from the normal automatic
        retry

        flow — the manual retry becomes the only remaining attempt. See

        [Delivery event
        lifecycle](/resources/alert-webhooks#delivery-event-lifecycle)

        for the full state machine.
      tags:
        - Alert Webhooks
      parameters:
        - $ref: '#/components/parameters/alertWebhookId'
        - $ref: '#/components/parameters/deliveryEventId'
      responses:
        '204':
          description: Manual retry scheduled successfully. No response body.
        '400':
          description: Bad request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          description: Unauthorized - invalid or missing authentication token
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Alert webhook or delivery event not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
  /custodians/me/alerts/webhooks/{alertWebhookId}/events:
    get:
      operationId: listAlertWebhookEvents
      summary: List alert webhook events
      deprecated: true
      description: >
        Retrieve a list of events sent to your alert webhook, including those
        that

        failed to be delivered.
      tags:
        - Alert Webhooks
      parameters:
        - $ref: '#/components/parameters/alertWebhookId'
        - name: eventTypes
          in: query
          required: false
          description: The alert webhook event types to filter by.
          schema:
            type: string
            enum:
              - EIP_155_TX_V1
        - name: deliveryStatuses
          in: query
          required: false
          description: Filter by delivery status.
          schema:
            type: string
            enum:
              - success
              - failed
              - pending
        - name: since
          in: query
          required: false
          description: Returns only events that occurred after this Unix timestamp.
          schema:
            type: number
        - name: until
          in: query
          required: false
          description: Returns only events that occurred before this Unix timestamp.
          schema:
            type: number
        - name: cursor
          in: query
          required: false
          description: The alert webhook event ID for cursor-based pagination.
          schema:
            type: string
        - name: limit
          in: query
          required: false
          description: The number of events to retrieve. Default is 100.
          schema:
            type: integer
            default: 100
        - name: transactionHash
          in: query
          required: false
          description: Filter by transaction hash.
          schema:
            type: string
        - name: blockNumbers
          in: query
          required: false
          description: Filter by block numbers (comma-delimited).
          schema:
            type: string
        - name: chainIds
          in: query
          required: false
          description: Filter by CAIP-2 chain IDs (comma-delimited).
          schema:
            type: string
      responses:
        '200':
          description: Alert webhook events retrieved successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AlertWebhookEventsResponse'
              example:
                data:
                  - blockNumber: 7313326
                    chainId: eip155:11155111
                    confirmed: 1
                    createdAt: '2024-12-19T20:08:17.086Z'
                    deliveryStatus: success
                    errorMessage: null
                    id: 85f3d2f7-b2ff-417d-b9cb-dc9823b4ae61
                    retries: 0
                    transactionHashes:
                      - >-
                        0x4978a4ba15a018532791ba4491e48b1aa8b544309c1ffce062bb1fb7e84dc069
                    type: EIP_155_TX_V1
                    updatedAt: '2024-12-19T20:08:17.086Z'
                metadata:
                  alertWebhook:
                    id: alertWebhookId1
                    url: https://example.com/alerts/webhooks/1/events
                  cursor: null
                  limit: 100
                  total: 4
        '400':
          description: Bad request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          description: Unauthorized - invalid or missing authentication token
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
  /custodians/me/alerts/webhooks/{alertWebhookId}/events/failed/replay:
    post:
      operationId: replayFailedAlertWebhookEvents
      summary: Replay failed alert webhook events
      deprecated: true
      description: >
        **Deprecated.** Use

        `POST
        /custodians/me/alerts/webhooks/{alertWebhookId}/delivery-events/{deliveryEventId}/retries`

        instead to retry one delivery event at a time. The new endpoint also
        supports

        retrying events that are still `PENDING`, not just those in `FAILED`
        state.


        Replays a list of alert webhook events with a delivery status of
        `"failed"`.

        If a failed event has already been replayed successfully, it cannot be
        replayed again.
      tags:
        - Alert Webhooks
      parameters:
        - $ref: '#/components/parameters/alertWebhookId'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ReplayFailedEventsRequest'
            example:
              eventIds:
                - eventId1
      responses:
        '200':
          description: Replay initiated
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ReplayFailedEventsResponse'
              example:
                data:
                  replaying:
                    - alertWebhookEventId1
                  failed:
                    - alertWebhookEventId2
        '400':
          description: Bad request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          description: Unauthorized - invalid or missing authentication token
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
  /custodians/me/alerts/webhooks/external-addresses:
    get:
      operationId: listExternalAddresses
      summary: List external addresses
      description: >
        Retrieve a list of external addresses configured for alert webhook
        notifications

        in your environment. External addresses are blockchain addresses not
        generated by

        Portal that you still want to monitor for transactions.
      tags:
        - Alert Webhooks
      responses:
        '200':
          description: External addresses retrieved successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ExternalAddressListResponse'
              example:
                data:
                  - id: cm4voycw2001f68veade3tr0i
                    address: '0x1234567890abcdef1234567890abcdef12345678'
                    namespace: EIP155
                    createdAt: '2025-01-15T10:30:00.000Z'
                    updatedAt: '2025-01-15T10:30:00.000Z'
                  - id: cm4voycw2001f68veade3tr0j
                    address: ABC123def456...
                    namespace: SOLANA
                    createdAt: '2025-01-16T14:00:00.000Z'
                    updatedAt: '2025-01-16T14:00:00.000Z'
        '400':
          description: Bad request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          description: Unauthorized - invalid or missing authentication token
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
    post:
      operationId: createExternalAddress
      summary: Create an external address
      description: >
        Add an external blockchain address to receive alert webhook
        notifications for.

        The address is validated for correct format based on the selected
        namespace.

        Blackhole addresses (such as null or dead addresses) are rejected.


        Supported namespaces:

        - `eip155` — EVM-compatible addresses

        - `solana` — Solana addresses
      tags:
        - Alert Webhooks
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateExternalAddressRequest'
            example:
              address: '0x1234567890abcdef1234567890abcdef12345678'
              namespace: eip155
      responses:
        '201':
          description: External address created successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ExternalAddressResponse'
              example:
                data:
                  id: cm4voycw2001f68veade3tr0i
                  address: '0x1234567890abcdef1234567890abcdef12345678'
                  namespace: EIP155
                  createdAt: '2025-01-15T10:30:00.000Z'
                  updatedAt: '2025-01-15T10:30:00.000Z'
        '400':
          description: Bad request - invalid address format or blackhole address
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          description: Unauthorized - invalid or missing authentication token
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '409':
          description: Conflict - external address already exists for this environment
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
  /custodians/me/alerts/webhooks/external-addresses/{externalAddressId}:
    delete:
      operationId: deleteExternalAddress
      summary: Delete an external address
      description: >
        Remove an external address from alert webhook notifications. The address
        will

        no longer be monitored for transactions.
      tags:
        - Alert Webhooks
      parameters:
        - $ref: '#/components/parameters/externalAddressId'
      responses:
        '200':
          description: External address deleted successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/DeleteExternalAddressResponse'
              example:
                success: true
        '400':
          description: Bad request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          description: Unauthorized - invalid or missing authentication token
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
  /custodians/me/gas-sponsorship/chains:
    get:
      operationId: getGasSponsors
      summary: Get gas sponsors
      description: >
        Retrieves all gas sponsors and their usage information across all chains
        for

        your Portal environment. Solana entries also include the gas sponsor's

        on-chain address and current balance.


        **Filtering:** Pass the optional `chains` query parameter to narrow the

        response to a subset of chains. Each entry may be either a friendly

        chain slug (for example `solana`, `solana-devnet`, `base`, `ethereum`)

        or a full CAIP-2 chain ID (for example `eip155:1`,

        `solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp`).


        **Tip — speed up your request:** Only need a subset of chains?

        Passing `chains` skips the data fetches for every chain you leave out,

        which can reduce response times from several seconds to a few

        hundred milliseconds. For example, if you only care about Solana

        gas sponsor info, pass `chains=solana,solana-devnet`.


        **Note:** Gas sponsorship must be enabled for your Portal environment.
      tags:
        - Gas Sponsorship
      parameters:
        - in: query
          name: chains
          required: false
          description: |
            Comma-separated list of chains to include in the response. Each
            entry may be a friendly slug (e.g. `solana`, `base`) or a full
            CAIP-2 chain ID (e.g. `eip155:1`). When omitted, every configured
            chain is returned.
          schema:
            type: string
          examples:
            solanaOnly:
              summary: Solana mainnet + devnet only
              value: solana,solana-devnet
            mixed:
              summary: Mix of slugs and CAIP-2 ids
              value: base,eip155:1,solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp
      responses:
        '200':
          description: Gas sponsors retrieved successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/GasSponsorChainsResponse'
              example:
                - chainId: eip155:11155111
                  currentPeriod:
                    gasAllowanceLimit: '499'
                    gasUsage: '0.35080714673101143'
                    transactionCount: '3005'
                    endsAt: '2026-02-13T17:49:43.000Z'
                - chainId: solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1
                  currentPeriod:
                    gasAllowanceLimit: '5'
                    gasUsage: '0.0053'
                    transactionCount: '12'
                    endsAt: '2026-02-13T17:49:43.000Z'
                  gasSponsor:
                    address: 8K1q5fZcHz3bVExampleSolanaGasSponsorPublicKey
                    balance: '4.927'
                    balanceInBaseUnits: '4927000000'
        '400':
          description: Bad request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          description: Unauthorized - invalid or missing authentication token
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
  /custodians/me/gas-sponsorship/chains/{chainId}:
    patch:
      operationId: updateGasSponsor
      summary: Update gas sponsorship for a chain
      description: >
        Updates the maximum gas allowance limit for a specific chain's gas
        sponsor.

        The `value` parameter is in ETH/SOL units.


        **Note:** Gas sponsorship must be enabled for your Portal environment.
      tags:
        - Gas Sponsorship
      parameters:
        - $ref: '#/components/parameters/chainId'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UpdateGasSponsorRequest'
            example:
              value: '10'
      responses:
        '200':
          description: Gas sponsor updated successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/GasSponsorChainResponse'
              example:
                chainId: eip155:11155111
                currentPeriod:
                  gasAllowanceLimit: '499'
                  gasUsage: '0.35080714673101143'
                  transactionCount: '3005'
                  endsAt: '2026-02-13T17:49:43.000Z'
        '400':
          description: Bad request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          description: Unauthorized - invalid or missing authentication token
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
  /custodians/me/gas-sponsorship/chains/{chainId}/top-off:
    post:
      operationId: topOffGasSponsorByChainId
      summary: Top off a Solana gas sponsor
      description: >
        Tops the chain's gas sponsor back up to its configured allowance by

        transferring SOL from the funding wallet. Returns `toppedOff: false`

        with a `reason` when the call is a no-op (the sponsor was recently

        funded, has no allowance set, or is already at its allowance).


        **Solana only:** Gas sponsor top-off is currently supported only on

        Solana. The `{chainId}` path parameter must be a Solana CAIP-2 chain ID

        (`solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp` for mainnet or

        `solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1` for devnet); any other chain

        returns a `400`.


        **Note:** Gas sponsorship must be enabled for your Portal environment
        and

        your plan must support gas sponsorship.
      tags:
        - Gas Sponsorship
      parameters:
        - $ref: '#/components/parameters/chainId'
      responses:
        '200':
          description: Top-off processed (funded or skipped)
          content:
            application/json:
              schema:
                type: object
                properties:
                  chainId:
                    type: string
                    description: CAIP-2 chain ID of the gas sponsor.
                  toppedOff:
                    type: boolean
                    description: Whether a funding transfer was sent. False on a no-op.
                  amount:
                    type: string
                    nullable: true
                    description: SOL transferred. Null on a no-op.
                  txHash:
                    type: string
                    nullable: true
                    description: Solana transaction hash. Null on a no-op.
                  balance:
                    type: string
                    description: Gas sponsor balance in SOL after the call.
                  balanceInBaseUnits:
                    type: string
                    description: Gas sponsor balance in lamports.
                  reason:
                    type: string
                    enum:
                      - already_at_allowance
                      - no_allowance_set
                      - recently_funded
                    description: >-
                      Why the call was a no-op. Present only when `toppedOff` is
                      false; omitted when a transfer was sent.
              example:
                chainId: solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1
                toppedOff: true
                amount: '0.00011'
                txHash: >-
                  5HspHV2R7df1t9UPMRS4NcXWpeQapSRB1m8EVX2dJ8HCZoepH8B5K9trWTyj8eu17NRQB5AaqxM7VUSmqZbmZEFF
                balance: '0.01'
                balanceInBaseUnits: '10000000'
        '400':
          description: Bad request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          description: Unauthorized - invalid or missing authentication token
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '403':
          description: >-
            Forbidden - account abstraction disabled or plan does not support
            gas sponsorship
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
  /custodians/me/gas-sponsors/chains/{chainId}/usage:
    get:
      operationId: getGasUsage
      summary: Get historical gas sponsorship usage (deprecated)
      deprecated: true
      description: >
        **Deprecated.** Use `GET /custodians/me/gas-sponsorship/chains` instead.


        Retrieves historical gas sponsorship usage by chain for your Portal
        environment.
      tags:
        - Gas Sponsorship
      parameters:
        - $ref: '#/components/parameters/chainId'
      responses:
        '200':
          description: Gas usage retrieved successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/GasUsageResponse'
              example:
                address: 75ZfLXXsSpycDvHTQuHnGQuYgd2ihb6Bu4viiCCQ7P4H
                chainId: solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1
                usageData:
                  - month: June
                    year: 2025
                    usage: '0.011249279999999794'
                    txCount: 921
                  - month: May
                    year: 2025
                    usage: '0.01'
                    txCount: 2
                totalUsage: '0.021249279999999794'
                totalTxsSponsored: 923
        '400':
          description: Bad request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          description: Unauthorized - invalid or missing authentication token
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
  /custodians/me/alerts/wallets/format:
    post:
      operationId: formatWalletAlert
      summary: Format a raw alert webhook event (deprecated)
      deprecated: true
      description: |
        **Deprecated.** Use the alert webhooks endpoints instead.

        Formats a raw webhook request body for a single wallet event.
      tags:
        - Alert Webhooks
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/FormatAlertRequest'
            example:
              chain: eip155
              rawAlert: '{"..."}'
      responses:
        '200':
          description: Alert formatted successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/FormattedAlertResponse'
              example:
                chainName: sepolia
                chainId: eip155:11155111
                from: '0xf428e1f82f18de15ef2861a4bdde42e755998ece'
                to: '0xdfd8302f44727a6348f702ff7b594f127de3a902'
                amount: '0.001'
                tokenSymbol: USDC
                assetType: NON_NATIVE_TOKEN
                direction: OUTBOUND
                metadata:
                  confirmed: true
                  rawAmount: '1000'
                  tokenDecimals: '6'
                  tokenAddress: '0x1c7d4b196cb0c7b01d743fbc6116a902379c7238'
                  tokenName: USDC
                  sentAt: '2024-09-06T20:30:24.000Z'
                  transactionHash: >-
                    0x229c1cc8ed898fae917e0ed90af94c624015e53a790eda1a7d30b1ca2ffd916c
                  blockNumber: '6645168'
        '400':
          description: Bad request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          description: Unauthorized - invalid or missing authentication token
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
  /custodians/me/alerts/format:
    post:
      operationId: formatAlerts
      summary: Format raw alert webhook events (deprecated)
      deprecated: true
      description: |
        **Deprecated.** Use the alert webhooks endpoints instead.

        Formats a raw webhook request body for wallet events, which may include
        one or many transactions at once.
      tags:
        - Alert Webhooks
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/FormatAlertRequest'
            example:
              chain: eip155
              rawAlert: '{"..."}'
      responses:
        '200':
          description: Alerts formatted successfully
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/FormattedAlertResponse'
              example:
                - chainName: sepolia
                  chainId: eip155:11155111
                  from: '0xf428e1f82f18de15ef2861a4bdde42e755998ece'
                  to: '0xdfd8302f44727a6348f702ff7b594f127de3a902'
                  amount: '0.001'
                  tokenSymbol: USDC
                  assetType: NON_NATIVE_TOKEN
                  direction: OUTBOUND
        '400':
          description: Bad request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          description: Unauthorized - invalid or missing authentication token
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
  /custodians/me/alerts/retry-by-block-number:
    post:
      operationId: retryAlertByBlockNumber
      summary: Replay alert by block number (deprecated)
      deprecated: true
      description: >
        **Deprecated.** Use the `replay failed events` endpoint instead.


        Attempts to resend a wallet event scoped by a block number. Supports EVM
        chains only.
      tags:
        - Alert Webhooks
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/RetryAlertByBlockNumberRequest'
            example:
              chainReferenceId: '11155111'
              blockNumber: 7313326
              streamId: streamId
      responses:
        '204':
          description: Alert replayed successfully (no content)
        '400':
          description: Bad request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          description: Unauthorized - invalid or missing authentication token
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
  /custodians/me/integrations/due/webhooks/events:
    get:
      operationId: listDueWebhookEventTypes
      summary: List webhook event types
      description: Lists the Due webhook event types you can subscribe to.
      tags:
        - Due
      responses:
        '200':
          description: Event types retrieved
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/DueWebhookEventTypesResponse'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
  /custodians/me/integrations/due/webhooks:
    get:
      operationId: listDueWebhookEndpoints
      summary: List webhook endpoints
      description: Lists the environment's registered Due webhook endpoints.
      tags:
        - Due
      responses:
        '200':
          description: Endpoints retrieved
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/DueWebhookEndpointsResponse'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
    post:
      operationId: createDueWebhookEndpoint
      summary: Create webhook endpoint
      description: |
        Registers a webhook endpoint. The response includes an Ed25519
        `publicKey` used to verify deliveries from this endpoint.
      tags:
        - Due
      parameters:
        - name: Idempotency-Key
          in: header
          required: false
          schema:
            type: string
          description: Optional key to deduplicate retries.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/DueWebhookEndpointCreateRequest'
      responses:
        '200':
          description: Endpoint created
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/DueWebhookEndpointResponse'
        '400':
          description: Bad request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
  /custodians/me/integrations/due/webhooks/{webhookId}/events:
    get:
      operationId: listDueWebhookEndpointEvents
      summary: List webhook deliveries
      description: >
        Returns the delivery history for a webhook endpoint. The response is

        paginated: when more events exist, `data.next` holds the cursor for the

        next page. Query parameters are forwarded to Due, so pass that value
        back

        as Due's pagination cursor to page through the history.
      tags:
        - Due
      parameters:
        - name: webhookId
          in: path
          required: true
          schema:
            type: string
      responses:
        '200':
          description: Deliveries retrieved
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/DueWebhookEventsResponse'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
  /custodians/me/integrations/due/webhooks/{webhookId}/events/{eventId}/retry:
    post:
      operationId: retryDueWebhookEvent
      summary: Retry webhook delivery
      description: Re-delivers a specific webhook event.
      tags:
        - Due
      parameters:
        - name: webhookId
          in: path
          required: true
          schema:
            type: string
        - name: eventId
          in: path
          required: true
          schema:
            type: string
      responses:
        '200':
          description: Delivery retried
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/DueWebhookEventResponse'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
  /custodians/me/integrations/due/webhooks/{webhookId}:
    post:
      operationId: updateDueWebhookEndpoint
      summary: Update webhook endpoint
      description: >-
        Updates a webhook endpoint. Send any of url, description, events, or
        enabled.
      tags:
        - Due
      parameters:
        - name: webhookId
          in: path
          required: true
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/DueWebhookEndpointUpdateRequest'
      responses:
        '200':
          description: Endpoint updated
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/DueWebhookEndpointResponse'
        '400':
          description: Bad request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
    delete:
      operationId: deleteDueWebhookEndpoint
      summary: Delete webhook endpoint
      description: Removes a webhook endpoint.
      tags:
        - Due
      parameters:
        - name: webhookId
          in: path
          required: true
          schema:
            type: string
      responses:
        '200':
          description: Endpoint deleted
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/DueWebhookEndpointResponse'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
components:
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      description: |
        Portal API Key (Custodian API Key). Pass as a Bearer token in the
        Authorization header.
  parameters:
    clientId:
      name: clientId
      in: path
      required: true
      description: The unique identifier of the client.
      schema:
        type: string
    chain:
      name: chain
      in: path
      required: true
      description: >
        The blockchain chain identifier. Use either a friendly name or CAIP-2
        format.

        When using CAIP-2 format in URLs, ensure the colon (`:`) is URI-encoded
        as `%3A`.


        **Supported chains:**

        - `ethereum` (`eip155:1`)

        - `sepolia` (`eip155:11155111`)

        - `base` (`eip155:8453`)

        - `base-sepolia` (`eip155:84532`)

        - `polygon` (`eip155:137`)

        - `polygon-amoy` (`eip155:80002`)

        - `celo` (`eip155:42220`)

        - `celo-alfajores` (`eip155:44787`)

        - `monad` (`eip155:143`)

        - `monad-testnet` (`eip155:10143`)

        - `solana` (`solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp`)

        - `solana-devnet` (`solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1`)

        - `tron` (`tron:mainnet`)

        - `tron-nile` (`tron:nile`)

        - `tron-shasta` (`tron:shasta`)

        - `stellar` (`stellar:pubnet`)

        - `stellar-testnet` (`stellar:testnet`)

        - `bitcoin-segwit` (`bip122:000000000019d6689c085ae165831e93-p2wpkh`)

        - `bitcoin-segwit-testnet`
        (`bip122:000000000933ea01ad0ee984209779ba-p2wpkh`)
      schema:
        type: string
      examples:
        ethereum:
          value: ethereum
          summary: Ethereum mainnet (friendly name)
        eip155:
          value: eip155:1
          summary: Ethereum mainnet (CAIP-2)
        solana:
          value: solana
          summary: Solana mainnet (friendly name)
    token:
      name: token
      in: path
      required: true
      description: >
        The token symbol (e.g. `USDC`, `ETH`) or contract/mint address on the
        specified chain.
      schema:
        type: string
      examples:
        symbol:
          value: USDC
          summary: Token symbol
        contractAddress:
          value: '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48'
          summary: ERC-20 contract address
    walletId:
      name: walletId
      in: path
      required: true
      description: The unique identifier of the wallet.
      schema:
        type: string
    alertWebhookId:
      name: alertWebhookId
      in: path
      required: true
      description: The unique identifier of the alert webhook.
      schema:
        type: string
    deliveryEventId:
      name: deliveryEventId
      in: path
      required: true
      description: The unique identifier of the alert webhook delivery event.
      schema:
        type: string
    externalAddressId:
      name: externalAddressId
      in: path
      required: true
      description: The unique identifier of the external address.
      schema:
        type: string
    chainId:
      name: chainId
      in: path
      required: true
      description: >
        The CAIP-2 chain ID. Be sure the colon (`:`) is URI-encoded as `%3A` in
        the URL.
      schema:
        type: string
      examples:
        sepolia:
          value: eip155:11155111
          summary: Ethereum Sepolia
  schemas:
    ErrorResponse:
      type: object
      properties:
        error:
          type: string
          description: Error message describing what went wrong
    CreateClientRequest:
      type: object
      properties:
        isAccountAbstracted:
          type: boolean
          description: Whether the client will use ERC-4337 Account Abstraction (AA).
    CreateClientResponse:
      type: object
      properties:
        id:
          type: string
          description: The new client's ID
        clientApiKey:
          type: string
          description: The client API key for SDK authentication
        clientSessionToken:
          type: string
          description: The client session token for SDK authentication
        isAccountAbstracted:
          type: boolean
          description: Whether account abstraction is enabled
    ClientDetails:
      type: object
      properties:
        createdAt:
          type: string
          format: date-time
          description: When the client was created
        custodian:
          type: object
          properties:
            id:
              type: string
            name:
              type: string
        ejectedAt:
          type: string
          format: date-time
          nullable: true
          description: When the client was ejected, or null
        environment:
          type: object
          properties:
            id:
              type: string
            name:
              type: string
              description: Environment name (e.g. "Development", "Production")
        id:
          type: string
          description: Client ID
        isAccountAbstracted:
          type: boolean
          description: Whether the client uses account abstraction
        metadata:
          type: object
          properties:
            namespaces:
              type: object
              description: Chain-keyed map of wallet addresses and metadata.
              additionalProperties:
                type: object
                properties:
                  address:
                    type: string
                  curve:
                    type: string
                    enum:
                      - SECP256K1
                      - ED25519
        wallets:
          type: array
          items:
            $ref: '#/components/schemas/Wallet'
    Wallet:
      type: object
      properties:
        createdAt:
          type: string
          format: date-time
        curve:
          type: string
          enum:
            - SECP256K1
            - ED25519
        id:
          type: string
        ejectableUntil:
          type: string
          format: date-time
          nullable: true
        publicKey:
          type: string
          nullable: true
          description: JSON-stringified public key
        backupSharePairs:
          type: array
          items:
            $ref: '#/components/schemas/BackupSharePair'
        signingSharePairs:
          type: array
          items:
            $ref: '#/components/schemas/SigningSharePair'
    BackupSharePair:
      type: object
      properties:
        backupMethod:
          type: string
          enum:
            - PASSWORD
            - GDRIVE
            - ICLOUD
        createdAt:
          type: string
          format: date-time
        id:
          type: string
        status:
          type: string
          enum:
            - completed
            - incomplete
    SigningSharePair:
      type: object
      properties:
        createdAt:
          type: string
          format: date-time
        id:
          type: string
        status:
          type: string
          enum:
            - completed
            - incomplete
    ClientListResponse:
      type: object
      properties:
        results:
          type: array
          items:
            $ref: '#/components/schemas/ClientDetails'
        metadata:
          type: object
          properties:
            cursor:
              type: string
              nullable: true
              description: Cursor for the next page
            take:
              type: integer
              description: Number of records requested
            total:
              type: integer
              description: Total number of clients
    CreateSessionResponse:
      type: object
      properties:
        id:
          type: string
          description: The client ID
        clientSessionToken:
          type: string
          description: The new client session token
        isAccountAbstracted:
          type: boolean
    WebOtpResponse:
      type: object
      properties:
        id:
          type: string
          description: The client ID
        otp:
          type: string
          description: The one-time password
    BuildTransactionRequest:
      type: object
      required:
        - to
        - token
        - amount
      properties:
        to:
          type: string
          description: The recipient's wallet address.
        token:
          type: string
          description: |
            The token symbol (e.g. `USDC`) or contract/mint address.
        amount:
          type: string
          description: |
            The amount to transfer in the token's primary denomination.
            Must be greater than zero.
    Eip155TransactionResult:
      type: object
      properties:
        transaction:
          type: object
          properties:
            from:
              type: string
            to:
              type: string
            data:
              type: string
        metadata:
          type: object
          properties:
            rawAmount:
              type: string
            formattedAmount:
              type: string
            tokenDecimals:
              type: integer
            tokenAddress:
              type: string
    SolanaTransactionResult:
      type: object
      properties:
        transaction:
          type: string
          description: Base64-encoded Solana transaction
        metadata:
          type: object
          properties:
            amount:
              type: string
            mintAddress:
              type: string
            lastValidBlockHeight:
              type: string
    BitcoinTransactionResult:
      type: object
      properties:
        transaction:
          type: object
          properties:
            signatureHashes:
              type: array
              items:
                type: string
            rawTxHex:
              type: string
            publicKey:
              type: string
        metadata:
          type: object
          properties:
            chainId:
              type: string
            amount:
              type: string
            fromAddress:
              type: string
            toAddress:
              type: string
            rawAmount:
              type: string
            feeInSatoshis:
              type: string
            changeInSatoshis:
              type: string
            tokenDecimals:
              type: integer
            tokenSymbol:
              type: string
    EvaluateTransactionEip155Request:
      type: object
      properties:
        to:
          type: string
          description: Target contract address
        data:
          type: string
          description: Hex-encoded calldata
        value:
          type: string
          description: Wei value to send
        operationType:
          type: string
          enum:
            - validation
            - simulation
            - all
          description: The type of evaluation to perform. Defaults to `all`.
    EvaluateTransactionSolanaRequest:
      type: object
      properties:
        transactions:
          type: array
          items:
            type: string
          description: Array of base58-encoded Solana transactions to evaluate.
        operationType:
          type: string
          enum:
            - validation
            - simulation
            - all
          description: The type of evaluation to perform. Defaults to `all`.
    EvaluateTransactionResponse:
      type: object
      properties:
        chain:
          type: string
          description: CAIP-2 chain ID
        validation:
          type: object
          properties:
            status:
              type: string
            resultType:
              type: string
            description:
              type: string
            reason:
              type: string
            classification:
              type: string
            features:
              type: array
              items:
                type: object
        simulation:
          type: object
          properties:
            status:
              type: string
            assetsDiffs:
              type: array
              items:
                type: object
            totalUsdDiff:
              type: string
            exposures:
              type: array
              items:
                type: object
            totalUsdExposure:
              type: string
            addressDetails:
              type: object
            accountSummary:
              type: object
    AssetBalancesResponse:
      type: object
      properties:
        nativeBalance:
          type: object
          properties:
            balance:
              type: string
            decimals:
              type: integer
            name:
              type: string
            rawBalance:
              type: string
            symbol:
              type: string
            metadata:
              type: object
              properties:
                logo:
                  type: string
                thumbnail:
                  type: string
        tokenBalances:
          type: array
          items:
            type: object
            properties:
              balance:
                type: string
              decimals:
                type: integer
              name:
                type: string
              rawBalance:
                type: string
              symbol:
                type: string
              metadata:
                type: object
                properties:
                  tokenAddress:
                    type: string
                  verifiedContract:
                    type: boolean
                  totalSupply:
                    type: string
                  rawTotalSupply:
                    type: string
                  percentageRelativeToTotalSupply:
                    type: number
        nfts:
          type: array
          items:
            $ref: '#/components/schemas/Nft'
    Nft:
      type: object
      properties:
        nftId:
          type: string
        name:
          type: string
        description:
          type: string
        imageUrl:
          type: string
        chainId:
          type: string
        contractAddress:
          type: string
        tokenId:
          type: string
        collection:
          type: object
          properties:
            name:
              type: string
            description:
              type: string
            imageUrl:
              type: string
        lastSale:
          type: object
          nullable: true
          properties:
            price:
              type: number
            currency:
              type: string
            date:
              type: string
              format: date-time
        rarity:
          type: object
          nullable: true
          properties:
            rank:
              type: integer
            score:
              type: number
        floorPrice:
          type: object
          nullable: true
          properties:
            price:
              type: number
            currency:
              type: string
    NftListResponse:
      type: array
      items:
        $ref: '#/components/schemas/Nft'
    EnableEjectRequest:
      type: object
      required:
        - walletId
      properties:
        ejectableUntil:
          type: string
          format: date-time
          description: >-
            The time the wallet will no longer be ejectable. Must be at least 1
            minute from now.
        walletId:
          type: string
          description: The wallet ID of the wallet to eject.
    EnableEjectResponse:
      type: object
      properties:
        ejectableUntil:
          type: string
          format: date-time
          description: The timestamp until which the wallet is ejectable.
    EjectableBackupSharesResponse:
      type: object
      properties:
        encryptedClientBackupShare:
          type: string
          nullable: true
          description: The encrypted client backup share, or null if not available.
        custodianBackupShare:
          type: string
          description: JSON-stringified custodian backup share data.
    PrepareEjectRequest:
      type: object
      required:
        - walletId
      properties:
        walletId:
          type: string
          description: The wallet ID of the wallet to prepare for eject.
        ejectableUntil:
          type: string
          format: date-time
          description: Optional deadline for ejection.
    DelegationStatusResponse:
      type: object
      properties:
        data:
          type: object
          properties:
            ownerAddress:
              type: string
              description: The Solana address that owns the token account.
            tokenAccount:
              type: string
              description: The Solana PDA of the token account.
            tokenMint:
              type: string
              description: The mint address of the SPL token.
            tokenSymbol:
              type: string
            balance:
              type: string
              description: Total balance (human-readable).
            balanceRaw:
              type: string
              description: Raw balance in smallest unit.
            hasDelegate:
              type: boolean
              description: Whether the token account has a delegate.
            delegateAddress:
              type: string
              description: The delegate address, if any.
            delegatedAmount:
              type: string
              description: Amount delegated (human-readable).
            delegatedAmountRaw:
              type: string
              description: Raw delegated amount.
        metadata:
          type: object
          properties:
            chainId:
              type: string
              description: CAIP-2 chain ID for Solana.
    DelegationsResponse:
      type: object
      properties:
        chainId:
          type: string
        token:
          type: string
        tokenAccount:
          type: string
          description: Solana token account (Solana only).
        tokenAddress:
          type: string
        balance:
          type: string
        balanceRaw:
          type: string
        delegations:
          type: array
          items:
            type: object
            properties:
              address:
                type: string
              delegateAmount:
                type: string
              delegateAmountRaw:
                type: string
    DelegationTransferRequest:
      type: object
      required:
        - fromAddress
        - toAddress
        - amount
      properties:
        fromAddress:
          type: string
          description: The address of the token owner whose tokens will be transferred.
        toAddress:
          type: string
          description: The recipient address.
        amount:
          type: string
          description: The amount to transfer in the token's primary denomination.
    DelegationTransferEvmResponse:
      type: object
      properties:
        transactions:
          type: array
          items:
            type: object
            properties:
              from:
                type: string
              to:
                type: string
              data:
                type: string
              value:
                type: string
        metadata:
          type: object
          properties:
            amount:
              type: string
            amountRaw:
              type: string
            chainId:
              type: string
            delegateAddress:
              type: string
            ownerAddress:
              type: string
            recipientAddress:
              type: string
            tokenAddress:
              type: string
            tokenSymbol:
              type: string
            tokenDecimals:
              type: integer
    DelegationTransferSolanaResponse:
      type: object
      properties:
        encodedTransactions:
          type: array
          items:
            type: string
        metadata:
          type: object
          properties:
            amount:
              type: string
            amountRaw:
              type: string
            chainId:
              type: string
            delegateAddress:
              type: string
            lastValidBlockHeight:
              type: string
            needsRecipientTokenAccount:
              type: boolean
            ownerAddress:
              type: string
            recipientAddress:
              type: string
            tokenAddress:
              type: string
            tokenSymbol:
              type: string
            tokenDecimals:
              type: integer
    UserOperationV06:
      type: object
      properties:
        sender:
          type: string
        nonce:
          type: string
        initCode:
          type: string
        callData:
          type: string
        callGasLimit:
          type: string
        verificationGasLimit:
          type: string
        preVerificationGas:
          type: string
        maxFeePerGas:
          type: string
        maxPriorityFeePerGas:
          type: string
        paymasterAndData:
          type: string
        signature:
          type: string
    BuildSessionKeyUserOperationRequest:
      type: object
      required:
        - sessionKeyAddress
        - to
      properties:
        sessionKeyAddress:
          type: string
          description: Address of the registered session key.
        to:
          type: string
          description: Target contract/address for the inner call.
        value:
          type: string
          description: Wei value to send (decimal string, default '0').
        data:
          type: string
          description: Hex-encoded calldata for the inner call.
    BuildSessionKeyUserOperationResponse:
      type: object
      properties:
        data:
          type: object
          properties:
            userOperation:
              $ref: '#/components/schemas/UserOperationV06'
            userOpHash:
              type: string
              description: Hash of the user operation to be signed.
            permissionIndex:
              type: integer
              description: Permission index for the session key.
            entryPoint:
              type: string
              description: The EIP-4337 EntryPoint contract address.
        metadata:
          type: object
          properties:
            chainId:
              type: string
              description: CAIP-2 chain ID.
            eoaAddress:
              type: string
              description: The client's EOA address.
            sessionKeyValidatorAddress:
              type: string
              description: The session key validator contract address.
    SendSessionKeyUserOperationRequest:
      type: object
      required:
        - sessionKeyAddress
        - userOperation
        - userOpHashSignature
        - permissionIndex
      properties:
        sessionKeyAddress:
          type: string
          description: Address of the session key that signed.
        userOperation:
          $ref: '#/components/schemas/UserOperationV06'
        userOpHashSignature:
          type: string
          description: 65-byte ECDSA signature of the userOpHash.
        permissionIndex:
          type: integer
          description: Permission index from the build endpoint.
    SendSessionKeyUserOperationResponse:
      type: object
      properties:
        data:
          type: object
          properties:
            userOperationHash:
              type: string
            transactionHash:
              type: string
              nullable: true
        metadata:
          type: object
          properties:
            chainId:
              type: string
              description: CAIP-2 chain ID.
    AlertWebhook:
      type: object
      properties:
        autoAddNewAddresses:
          type: boolean
        createdAt:
          type: string
          format: date-time
        events:
          type: array
          items:
            type: string
        id:
          type: string
        updatedAt:
          type: string
          format: date-time
        url:
          type: string
    AlertWebhookListResponse:
      type: object
      properties:
        data:
          type: array
          items:
            $ref: '#/components/schemas/AlertWebhook'
    AlertWebhookEvent:
      type: object
      properties:
        blockNumber:
          type: integer
        chainId:
          type: string
        confirmed:
          type: integer
          nullable: true
        createdAt:
          type: string
          format: date-time
        deliveryStatus:
          type: string
          enum:
            - success
            - failed
            - pending
        errorMessage:
          type: string
          nullable: true
        id:
          type: string
        retries:
          type: integer
        transactionHashes:
          type: array
          items:
            type: string
        type:
          type: string
        updatedAt:
          type: string
          format: date-time
    AlertWebhookEventsResponse:
      type: object
      properties:
        data:
          type: array
          items:
            $ref: '#/components/schemas/AlertWebhookEvent'
        metadata:
          type: object
          properties:
            alertWebhook:
              type: object
              properties:
                id:
                  type: string
                url:
                  type: string
            cursor:
              type: string
              nullable: true
            limit:
              type: integer
            total:
              type: integer
    ReplayFailedEventsRequest:
      type: object
      required:
        - eventIds
      properties:
        eventIds:
          type: array
          items:
            type: string
          description: List of failed alert webhook event IDs to replay.
    ReplayFailedEventsResponse:
      type: object
      properties:
        data:
          type: object
          properties:
            replaying:
              type: array
              items:
                type: string
              description: Event IDs currently being replayed.
            failed:
              type: array
              items:
                type: string
              description: Event IDs that failed to be replayed.
    AlertWebhookDeliveryEvent:
      type: object
      properties:
        id:
          type: string
          description: The unique identifier of the delivery event.
        type:
          type: string
          description: The alert webhook event type.
          enum:
            - EIP_155_TX_V1
            - PRE_SIGN_V1
            - SOLANA_TX_V1
            - SOLANA_TX_V2
            - SOLANA_APPROVE_V1
            - SOLANA_APPROVE_V2
            - SOLANA_REVOKE_V1
            - SOLANA_REVOKE_V2
            - SOLANA_DELEGATED_TRANSFER_V2
            - WALLET_EJECT_V1
        event:
          type: object
          description: >-
            The full payload that was (or will be) POSTed to your alert webhook
            URL. Shape varies by `type`.
          additionalProperties: true
        status:
          type: string
          description: >
            Current delivery status:

            - `PENDING` — awaiting automatic delivery.

            - `DELIVERED` — your webhook returned a 2XX response on some
            attempt.

            - `FAILED` — automatic retries were exhausted, or a manual retry
            failed.

            - `REPLAYING` — a manual retry is currently in flight.
          enum:
            - PENDING
            - DELIVERED
            - FAILED
            - REPLAYING
        sentAt:
          type: string
          format: date-time
          nullable: true
          description: >-
            Timestamp of the most recent delivery attempt. `null` if no attempt
            has been made yet.
        attempts:
          type: integer
          description: >-
            The number of delivery attempts that have been made for this event,
            including both automatic retries and manual retries.
          example: 0
        createdAt:
          type: string
          format: date-time
    AlertWebhookDeliveryEventsResponse:
      type: object
      properties:
        results:
          type: array
          items:
            $ref: '#/components/schemas/AlertWebhookDeliveryEvent'
        metadata:
          type: object
          properties:
            alertWebhook:
              type: object
              properties:
                id:
                  type: string
                url:
                  type: string
            cursor:
              type: string
              nullable: true
              description: >-
                ID of the last delivery event in this page. Pass as `cursor` on
                the next request to fetch the following page. `null` when there
                are no more results.
            take:
              type: integer
            hasMore:
              type: boolean
    ExternalAddress:
      type: object
      properties:
        id:
          type: string
        address:
          type: string
          description: The blockchain address being monitored.
        namespace:
          type: string
          enum:
            - eip155
            - solana
          description: The blockchain namespace of the address.
        createdAt:
          type: string
          format: date-time
        updatedAt:
          type: string
          format: date-time
    ExternalAddressListResponse:
      type: object
      properties:
        data:
          type: array
          items:
            $ref: '#/components/schemas/ExternalAddress'
    CreateExternalAddressRequest:
      type: object
      required:
        - address
        - namespace
      properties:
        address:
          type: string
          description: >-
            The blockchain address to monitor. Must be a valid address for the
            selected namespace.
        namespace:
          type: string
          enum:
            - eip155
            - solana
          description: |
            The blockchain namespace of the address.
            - `eip155` for EVM-compatible addresses
            - `solana` for Solana addresses
    ExternalAddressResponse:
      type: object
      properties:
        data:
          $ref: '#/components/schemas/ExternalAddress'
    DeleteExternalAddressResponse:
      type: object
      properties:
        success:
          type: boolean
    GasSponsorChainResponse:
      type: object
      properties:
        chainId:
          type: string
        currentPeriod:
          type: object
          properties:
            gasAllowanceLimit:
              type: string
            gasUsage:
              type: string
            transactionCount:
              type: string
              description: |
                Stringified integer count of sponsored transactions in the
                current period.
            endsAt:
              type: string
              format: date-time
        gasSponsor:
          nullable: true
          description: |
            Only present on Solana entries. `null` when no gas sponsor has
            been configured for that chain yet. The `balance` and
            `balanceInBaseUnits` fields are `null` when the RPC balance
            lookup fails (the sponsor address is still returned).
          type: object
          properties:
            address:
              type: string
              description: The gas sponsor's on-chain address.
            balance:
              type: string
              nullable: true
              description: |
                Human-readable native-token balance (e.g. SOL on Solana),
                formatted from `balanceInBaseUnits` using the chain's
                decimal precision.
            balanceInBaseUnits:
              type: string
              nullable: true
              description: |
                Stringified integer balance in the chain's base units
                (lamports on Solana).
    GasSponsorChainsResponse:
      type: array
      items:
        $ref: '#/components/schemas/GasSponsorChainResponse'
    UpdateGasSponsorRequest:
      type: object
      required:
        - value
      properties:
        value:
          type: string
          description: The new maximum gas allowance limit in ETH/SOL units.
    GasUsageResponse:
      type: object
      properties:
        address:
          type: string
          description: Your gas sponsor's address.
        chainId:
          type: string
        usageData:
          type: array
          items:
            type: object
            properties:
              month:
                type: string
              year:
                type: integer
              usage:
                type: string
              txCount:
                type: integer
        totalUsage:
          type: string
        totalTxsSponsored:
          type: integer
    FormatAlertRequest:
      type: object
      required:
        - chain
        - rawAlert
      properties:
        chain:
          type: string
          description: The chain the raw webhook event is from (e.g. "eip155").
        rawAlert:
          type: string
          description: The stringified raw webhook event.
    FormattedAlertResponse:
      type: object
      properties:
        chainName:
          type: string
        chainId:
          type: string
        from:
          type: string
        to:
          type: string
        amount:
          type: string
        tokenSymbol:
          type: string
        assetType:
          type: string
        direction:
          type: string
        metadata:
          type: object
          properties:
            confirmed:
              type: boolean
            rawAmount:
              type: string
            tokenDecimals:
              type: string
            tokenAddress:
              type: string
            tokenName:
              type: string
            sentAt:
              type: string
              format: date-time
            transactionHash:
              type: string
            blockNumber:
              type: string
            fee:
              type: object
              properties:
                amount:
                  type: string
                decimals:
                  type: integer
                rawAmount:
                  type: string
                tokenSymbol:
                  type: string
            nftTokenId:
              type: string
              nullable: true
            triggeredBy:
              type: string
            userOperationHash:
              type: string
    RetryAlertByBlockNumberRequest:
      type: object
      required:
        - chainReferenceId
        - blockNumber
        - streamId
      properties:
        chainReferenceId:
          type: string
          description: The EVM chain reference ID (e.g. "11155111" for Sepolia).
        blockNumber:
          type: integer
          description: The block number of the transaction(s) to resend.
        streamId:
          type: string
          description: The ID of the stream configured by Portal.
    DueWebhookEventTypesResponse:
      type: object
      properties:
        data:
          type: array
          items:
            type: string
    DueWebhookEndpointCreateRequest:
      type: object
      required:
        - url
      properties:
        url:
          type: string
          description: HTTPS endpoint that receives webhook deliveries.
        description:
          type: string
        events:
          type: array
          items:
            type: string
          description: Event types to subscribe to. Omit to receive all events.
    DueWebhookEndpointUpdateRequest:
      type: object
      properties:
        url:
          type: string
        description:
          type: string
        events:
          type: array
          items:
            type: string
        enabled:
          type: boolean
          description: Set false to pause deliveries without deleting the endpoint.
    DueWebhookEndpoint:
      type: object
      additionalProperties: true
      required:
        - id
      properties:
        id:
          type: string
        description:
          type: string
        url:
          type: string
        subscribedEvents:
          type: array
          items:
            type: string
        publicKey:
          type: string
          description: >-
            Ed25519 public key (PEM) used to verify deliveries from this
            endpoint.
        enabled:
          type: boolean
    DueWebhookEndpointResponse:
      type: object
      properties:
        data:
          $ref: '#/components/schemas/DueWebhookEndpoint'
    DueWebhookEndpointsResponse:
      type: object
      properties:
        data:
          type: array
          items:
            $ref: '#/components/schemas/DueWebhookEndpoint'
    DueWebhookEvent:
      type: object
      additionalProperties: true
      required:
        - id
      properties:
        id:
          type: string
        occurredAt:
          type: string
          format: date-time
        webhookEndpointId:
          type: string
        eventType:
          type: string
        eventData:
          type: array
          items:
            type: integer
          description: Event payload as a byte array; decode to JSON before reading.
        responseStatusCode:
          type: integer
        responseBody:
          type: string
        attempts:
          type: integer
        lastError:
          type: string
        lastAttemptAt:
          type: string
          format: date-time
    DueWebhookEventResponse:
      type: object
      properties:
        data:
          $ref: '#/components/schemas/DueWebhookEvent'
    DueWebhookEventsResponse:
      type: object
      properties:
        data:
          type: object
          properties:
            items:
              type: array
              items:
                $ref: '#/components/schemas/DueWebhookEvent'
            next:
              type: string
              description: |
                Cursor for the next page, if any. Forward it to Due as the
                pagination cursor on the next request to continue paging.
