> ## Documentation Index
> Fetch the complete documentation index at: https://sdk.umbraprivacy.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Global Notes

> Returns a paginated list of Stealth Pool Note records across all Merkle trees, ordered by absolute index ascending.

Use this endpoint when you need to scan notes globally without knowing which tree they belong to. For tree-specific queries, prefer [Tree Notes](/indexer/api-reference/tree-utxos).

<Note>
  The path retains the legacy `/v1/utxos` segment. The records it serves are V18 Stealth Pool Notes.
</Note>

## Pagination

Use the `next_cursor` from each response as the `start` parameter for the next request. Repeat until the response contains fewer records than `limit`.

```bash theme={null}
# First page
curl "https://utxo-indexer.api.umbraprivacy.com/v1/utxos?start=0&limit=1000"

# Next page
curl "https://utxo-indexer.api.umbraprivacy.com/v1/utxos?start=1000&limit=1000"

# Fetch a specific range (e.g. all notes in tree 1: absolute indices 1,048,576 to 2,097,151)
curl "https://utxo-indexer.api.umbraprivacy.com/v1/utxos?start=1048576&end=2097151&limit=5000"
```

## Response Layouts

Set `X-Response-Layout: columnar` for columnar layout (`UtxoColumnarResponse`). Omit for row-oriented layout (`UtxoResponse`).


## OpenAPI

````yaml GET /v1/utxos
openapi: 3.0.3
info:
  title: Umbra Indexer Read Service
  description: >
    Read-only REST API for querying Umbra mixer tree state, UTXO records,

    and Merkle inclusion proofs.


    ## Response Encoding


    **All endpoints** support `application/x-protobuf` encoding. The encoding

    strategy differs by endpoint category:


    - **Always Protobuf** (no content negotiation): stats, tree metadata, Merkle
    proofs,
      and all UTXO data endpoints. These endpoints always respond with
      `Content-Type: application/x-protobuf` regardless of the `Accept` header.
    - **Content negotiation** (health endpoints only): respond with JSON by
    default,
      or Protobuf when `Accept: application/x-protobuf` is set. Send
      `Accept: application/x-protobuf` for consistent protobuf-only clients.

    ## UTXO Response Layouts


    The three UTXO data endpoints (`GET /v1/utxos`, `GET
    /v1/utxos/{absolute_index}`,

    `GET /v1/trees/{tree_index}/utxos`) support two Protobuf response layouts

    controlled by the `X-Response-Layout` request header:


    - **Row-oriented** (default) -- `UtxoResponse` message: each UTXO is a
      self-contained `UtxoDataItem` sub-message. Easier to iterate record-by-record.
    - **Columnar** (`X-Response-Layout: columnar`) -- `UtxoColumnarResponse`
    message:
      each field across all UTXOs is packed into a parallel array inside a single
      `UtxoColumns` sub-message. Compresses significantly better over the wire and is
      preferred by vectorized consumers (e.g. data pipelines, analytics).

    ## Rate Limiting


    All endpoints are subject to rate limiting. Exceeded limits return `429 Too
    Many Requests`.


    ## Compression


    All responses are compressed. Send `Accept-Encoding: gzip, br`.


    ## Absolute Index


    The **absolute index** is a globally monotonic cursor across all Merkle
    trees:

    ```

    absolute_index = tree_index * MAX_LEAVES_PER_TREE + insertion_index

    ```

    where `MAX_LEAVES_PER_TREE = 1,048,576` (2^20).
  version: 0.1.0
  contact:
    name: Umbra Protocol
servers:
  - url: https://utxo-indexer.api.umbraprivacy.com
    description: Mainnet
  - url: https://utxo-indexer.api-devnet.umbraprivacy.com
    description: Devnet
security: []
tags:
  - name: health
    description: |
      Health and readiness probes for Kubernetes or load-balancer checks.
      Support both JSON and Protobuf via `Accept` header negotiation.
  - name: stats
    description: Aggregate statistics for the UTXO index. Always Protobuf.
  - name: trees
    description: Per-tree Merkle metadata and Merkle inclusion proofs. Always Protobuf.
  - name: utxos
    description: >
      UTXO data queries with absolute-index-based pagination. Always Protobuf.

      Supports row-oriented and columnar response layouts via
      `X-Response-Layout`.
paths:
  /v1/utxos:
    get:
      tags:
        - utxos
      summary: Paginated global UTXO query
      description: >
        Returns a paginated list of UTXO records in ascending `absolute_index`
        order,

        spanning all Merkle trees.


        **Always Protobuf** -- responds with `application/x-protobuf` regardless

        of the `Accept` header.


        ## Response layout


        Set the `X-Response-Layout` header to switch between encoding
        strategies:

        - **Row-oriented** (default): `UtxoResponse` -- self-contained
        `UtxoDataItem`
          sub-messages.
        - **Columnar** (`X-Response-Layout: columnar`): `UtxoColumnarResponse`
        --
          parallel field arrays. Smaller wire size; preferred for bulk transfers.

        ## Absolute Index


        ```

        absolute_index = tree_index * MAX_LEAVES_PER_TREE + insertion_index

        ```

        where `MAX_LEAVES_PER_TREE = 1,048,576`.


        ## Pagination


        Use `next_cursor` from each response as `start` for the next page.

        Default page size: **1,000**. Maximum: **5,000** (`limit > 5000` ->
        `400`).
      operationId: getUtxoData
      parameters:
        - name: start
          in: query
          required: false
          description: |
            Inclusive lower bound of the absolute index range to fetch.
            Defaults to `0`.
          schema:
            type: integer
            format: int64
            minimum: 0
            default: 0
          example: 0
        - name: end
          in: query
          required: false
          description: >
            Inclusive upper bound of the absolute index range.

            When omitted, scans from `start` to end of dataset, bounded by
            `limit`.
          schema:
            type: integer
            format: int64
          example: 999
        - name: limit
          in: query
          required: false
          description: |
            Maximum records per page. Default: `1000`. Maximum: `5000`.
            Passing `0` uses the default.
          schema:
            type: integer
            format: int64
            minimum: 0
            maximum: 5000
            default: 1000
          example: 1000
        - name: X-Response-Layout
          in: header
          required: false
          description: |
            Set to `"columnar"` for `UtxoColumnarResponse` (parallel arrays).
            Omit for the default row-oriented `UtxoResponse`.
          schema:
            type: string
            enum:
              - columnar
      responses:
        '200':
          description: UTXO records for the requested absolute index range.
          content:
            application/x-protobuf:
              schema:
                oneOf:
                  - $ref: '#/components/schemas/UtxoResponse'
                  - $ref: '#/components/schemas/UtxoColumnarResponse'
                discriminator:
                  propertyName: X-Response-Layout
        '400':
          description: |
            Invalid pagination parameters (e.g. `limit > 5000`, `start > end`).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '429':
          description: Rate limit exceeded.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Storage backend error.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
components:
  schemas:
    UtxoResponse:
      type: object
      description: >
        Protobuf `UtxoResponse` message -- row-oriented paginated UTXO response.


        Returned by `GET /v1/utxos` and `GET /v1/trees/{tree_index}/utxos` when

        `X-Response-Layout` is absent or set to any value other than
        `"columnar"`.


        Each UTXO is encoded as a self-contained `UtxoDataItem` sub-message.

        Use `next_cursor` as the `start` (or `cursor`) parameter of the next

        request to retrieve the following page.
      required:
        - items
        - has_more
        - total_count
        - start_index
      properties:
        items:
          type: array
          description: Up to `limit` UTXO records in ascending `absolute_index` order.
          items:
            $ref: '#/components/schemas/UtxoDataItem'
        has_more:
          type: boolean
          description: '`true` if additional records exist beyond this page.'
          example: true
        next_cursor:
          type: integer
          format: int64
          nullable: true
          description: |
            Absolute index to pass as `start` (or `cursor`) for the next page.
            Absent when `has_more` is `false`.
          example: 1001
        total_count:
          type: integer
          format: int64
          description: >-
            Total number of matching records in the requested range across all
            pages.
          example: 5000
        start_index:
          type: integer
          format: int64
          description: Inclusive lower bound of the absolute index range that was queried.
          example: 0
        end_index:
          type: integer
          format: int64
          nullable: true
          description: |
            Inclusive upper bound of the absolute index range that was queried.
            Absent when no explicit `end` (or tree boundary) was provided.
          example: 4999
    UtxoColumnarResponse:
      type: object
      description: >
        Protobuf `UtxoColumnarResponse` message -- columnar paginated UTXO
        response.


        Returned by `GET /v1/utxos` and `GET /v1/trees/{tree_index}/utxos` when

        `X-Response-Layout: columnar` is set.


        All UTXO fields are transposed into parallel arrays inside `columns`.

        This layout eliminates per-field Protobuf metadata overhead on repeated

        records and compresses significantly better than row-oriented encoding
        --

        prefer this layout for bulk data transfers and data pipeline consumers.
      required:
        - count
        - has_more
        - total_count
        - start_index
        - columns
      properties:
        count:
          type: integer
          description: >-
            Number of rows (UTXOs) in this page. Length of every array in
            `columns`.
          example: 1000
        has_more:
          type: boolean
          description: '`true` if additional records exist beyond this page.'
          example: true
        next_cursor:
          type: integer
          format: int64
          nullable: true
          description: Absolute index to use as `start` (or `cursor`) for the next page.
          example: 1001
        total_count:
          type: integer
          format: int64
          description: Total matching records across all pages.
          example: 5000
        start_index:
          type: integer
          format: int64
          description: Inclusive lower bound of the absolute index range queried.
          example: 0
        end_index:
          type: integer
          format: int64
          nullable: true
          description: Inclusive upper bound queried (absent when unbounded).
          example: 4999
        columns:
          $ref: '#/components/schemas/UtxoColumns'
    ErrorResponse:
      type: object
      description: Standard JSON error body returned on 4xx and 5xx responses.
      required:
        - error
        - message
      properties:
        error:
          type: string
          description: |
            Short error category, e.g. `"Bad Request"`, `"Not Found"`,
            `"Too Many Requests"`, `"Internal Server Error"`.
          example: Not Found
        message:
          type: string
          description: Human-readable explanation of what went wrong.
          example: Tree 99 not found
    UtxoDataItem:
      type: object
      description: >
        Protobuf `UtxoDataItem` message -- a single UTXO record as it appears in

        `UtxoResponse.items` and `SingleUtxoResponse.utxo`.


        All binary fields (`final_commitment`, `h1_sender_address`,
        `h1_mint_address`,

        `h1_circuit_provable_hash`, `h1_smart_program_provable_hash`, `h1_hash`,

        `h2_hash`, `aes_encrypted_data`, `depositor_x25519_public_key`) are
        Protobuf

        `bytes` fields carrying the raw little-endian bytes (no base64 or hex
        encoding

        at the wire level).


        The 128-bit integer fields `h1_version` and `h1_commitment_index` are
        encoded

        as Protobuf `bytes` fields containing their **16-byte little-endian**
        binary

        representation.
      required:
        - absolute_index
        - tree_index
        - insertion_index
        - final_commitment
        - h1_version
        - h1_commitment_index
        - h1_sender_address
        - h1_mint_address
        - h1_relayer_fixed_sol_fees
        - h1_year
        - h1_month
        - h1_day
        - h1_hour
        - h1_minute
        - h1_second
        - h1_purpose
        - h1_circuit_provable_hash
        - h1_smart_program_provable_hash
        - h1_hash
        - h2_hash
        - aes_encrypted_data
        - depositor_x25519_public_key
        - timestamp
        - slot
        - event_type
      properties:
        absolute_index:
          type: integer
          format: int64
          description: |
            `tree_index * MAX_LEAVES_PER_TREE + insertion_index`. Monotonically
            increasing pagination cursor. `MAX_LEAVES_PER_TREE = 1,048,576`.
          example: 1048620
        tree_index:
          type: integer
          format: int64
          description: Zero-based Merkle tree index this UTXO belongs to.
          example: 1
        insertion_index:
          type: integer
          format: int64
          description: Zero-based leaf position within `tree_index` (0 to 1,048,575).
          example: 44
        final_commitment:
          type: string
          format: byte
          description: >
            Raw 32-byte `Poseidon(h1_hash, h2_hash)` -- the leaf value inserted
            into

            the Merkle tree (little-endian byte order, Protobuf `bytes`).
        h1_version:
          type: string
          format: byte
          description: >
            16-byte little-endian encoding of the `u128` protocol version used
            as a

            domain separator in the H1 hash circuit (Protobuf `bytes`).
        h1_commitment_index:
          type: string
          format: byte
          description: >
            16-byte little-endian encoding of the `u128` on-chain commitment
            counter

            fed into the H1 circuit (Protobuf `bytes`).
        h1_sender_address:
          type: string
          format: byte
          description: Raw 32-byte sender public key, little-endian (Protobuf `bytes`).
        h1_mint_address:
          type: string
          format: byte
          description: >-
            Raw 32-byte SPL token mint public key, little-endian (Protobuf
            `bytes`).
        h1_relayer_fixed_sol_fees:
          type: integer
          format: int64
          description: Relayer fixed fee in lamports (1 SOL = 1,000,000,000 lamports).
          example: 5000000
        h1_year:
          type: integer
          description: UTC year of the insertion block timestamp.
          example: 2026
        h1_month:
          type: integer
          minimum: 1
          maximum: 12
          description: UTC month (1-12).
          example: 2
        h1_day:
          type: integer
          minimum: 1
          maximum: 31
          description: UTC day (1-31).
          example: 25
        h1_hour:
          type: integer
          minimum: 0
          maximum: 23
          description: UTC hour (0-23).
          example: 12
        h1_minute:
          type: integer
          minimum: 0
          maximum: 59
          description: UTC minute (0-59).
          example: 0
        h1_second:
          type: integer
          minimum: 0
          maximum: 59
          description: UTC second (0-59).
          example: 0
        h1_purpose:
          type: integer
          description: Smart-program-provable domain tag (`u32`).
          example: 1
        h1_circuit_provable_hash:
          type: string
          format: byte
          description: >-
            Raw 32-byte `Poseidon(circuit_provable_inputs)`, little-endian
            (Protobuf `bytes`).
        h1_smart_program_provable_hash:
          type: string
          format: byte
          description: >-
            Raw 32-byte `Poseidon([h1_purpose])`, little-endian (Protobuf
            `bytes`).
        h1_hash:
          type: string
          format: byte
          description: >
            Raw 32-byte `Poseidon([h1_circuit_provable_hash,
            h1_smart_program_provable_hash])`,

            little-endian (Protobuf `bytes`).
        h2_hash:
          type: string
          format: byte
          description: >-
            Raw 32-byte private commitment hash, little-endian (Protobuf
            `bytes`).
        aes_encrypted_data:
          type: string
          format: byte
          description: |
            Raw 96-byte AES-256-GCM encrypted UTXO payload (Protobuf `bytes`):
            - Bytes 0-11: 12-byte random nonce
            - Bytes 12-79: 68-byte ciphertext
            - Bytes 80-95: 16-byte authentication tag
        depositor_x25519_public_key:
          type: string
          format: byte
          description: |
            Raw 32-byte ephemeral X25519 public key. Used to derive the shared
            AES-256-GCM key for decrypting `aes_encrypted_data` via X25519 DH
            with the network's static private key (Protobuf `bytes`).
        timestamp:
          type: integer
          format: int64
          description: Unix block timestamp in seconds (`0` when unavailable).
          example: 1735689600
        slot:
          type: integer
          format: int64
          description: Solana slot number of the confirming block.
          example: 350000000
        event_type:
          type: string
          description: '`"deposit"` or `"callback"` (see `EventType`).'
          example: deposit
    UtxoColumns:
      type: object
      description: >
        Protobuf `UtxoColumns` sub-message used inside `UtxoColumnarResponse`.


        Stores all UTXO fields as **parallel arrays** -- one repeated field per
        column.

        The `i`-th element of every array corresponds to the `i`-th UTXO in the
        page.


        Binary fields (`final_commitment`, hash fields, `aes_encrypted_data`,

        `depositor_x25519_public_key`) are `repeated bytes` in the Protobuf
        encoding.

        The `h1_version` and `h1_commitment_index` fields are `repeated bytes`
        where

        each element is the **16-byte little-endian** encoding of the original
        `u128`.
      properties:
        absolute_index:
          type: array
          items:
            type: integer
            format: int64
          description: Absolute indices for all rows in this page.
        tree_index:
          type: array
          items:
            type: integer
            format: int64
        insertion_index:
          type: array
          items:
            type: integer
            format: int64
        final_commitment:
          type: array
          items:
            type: string
            format: byte
          description: 32-byte `Poseidon(h1, h2)` for each row.
        h1_version:
          type: array
          items:
            type: string
            format: byte
          description: 16-byte little-endian `u128` protocol version per row.
        h1_commitment_index:
          type: array
          items:
            type: string
            format: byte
          description: 16-byte little-endian `u128` commitment index per row.
        h1_sender_address:
          type: array
          items:
            type: string
            format: byte
        h1_mint_address:
          type: array
          items:
            type: string
            format: byte
        h1_relayer_fixed_sol_fees:
          type: array
          items:
            type: integer
            format: int64
        h1_year:
          type: array
          items:
            type: integer
        h1_month:
          type: array
          items:
            type: integer
        h1_day:
          type: array
          items:
            type: integer
        h1_hour:
          type: array
          items:
            type: integer
        h1_minute:
          type: array
          items:
            type: integer
        h1_second:
          type: array
          items:
            type: integer
        h1_purpose:
          type: array
          items:
            type: integer
        h1_circuit_provable_hash:
          type: array
          items:
            type: string
            format: byte
        h1_smart_program_provable_hash:
          type: array
          items:
            type: string
            format: byte
        h1_hash:
          type: array
          items:
            type: string
            format: byte
        h2_hash:
          type: array
          items:
            type: string
            format: byte
        aes_encrypted_data:
          type: array
          items:
            type: string
            format: byte
          description: 96-byte AES-GCM payload per row.
        depositor_x25519_public_key:
          type: array
          items:
            type: string
            format: byte
        timestamp:
          type: array
          items:
            type: integer
            format: int64
        slot:
          type: array
          items:
            type: integer
            format: int64
        event_type:
          type: array
          items:
            type: string
          description: '`"deposit"` or `"callback"` per row.'

````