> ## Documentation Index
> Fetch the complete documentation index at: https://www.helius.dev/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Solana Privacy Rings API

> Query encrypted UTXOs, shielded transaction history, Merkle proofs, and public user registry records for Solana Privacy Rings.

The Solana Privacy Rings API queries the privacy indexer. It returns encrypted state and public transaction metadata. Your wallet decrypts the payloads to read private balances and history. See the [privacy overview](https://www.helius.dev/docs/privacy.md) for concepts and the [SDK](https://www.helius.dev/docs/privacy/sdk.md) for deposit, transfer, and withdrawal flows.

## Public and Private Balances

A private balance is stored in UTXOs (unspent transaction outputs). A UTXO is not a Solana account.

| | Public balance | Private balance |
| - | - | - |
| Balance | Lamports in a Solana account or the `amount` in an SPL Token account | The sum of unspent UTXOs for one asset |
| Visibility | Public onchain | Encrypted onchain |
| Discover token accounts or outputs | [`getTokenAccountsByOwner`](https://solana.com/docs/rpc/http/gettokenaccountsbyowner) returns SPL Token accounts owned by an address | `getEncryptedUtxosByTags` returns encrypted outputs matching view tags or a ring |
| Read a balance | [`getBalance`](https://solana.com/docs/rpc/http/getbalance) for SOL; [`getTokenAccountBalance`](https://solana.com/docs/rpc/http/gettokenaccountbalance) for an SPL Token account | Your wallet decrypts outputs, checks which are unspent, and sums the amounts for each asset |

See [Private State and UTXOs](https://www.helius.dev/docs/privacy/concepts/utxo.md) for how private balances are stored and spent.

## Endpoint and Authentication

Send a JSON-RPC 2.0 request to the method's path with your Helius API key:

```bash theme={"system"}
curl --request POST \
  --url "https://devnet.helius-rpc.com/v1/spr/getUserRecords?api-key=YOUR_API_KEY" \
  --header "Content-Type: application/json" \
  --data '{
    "jsonrpc": "2.0",
    "id": "1",
    "method": "getUserRecords",
    "params": {
      "owners": ["11111111111111111111111111111111"]
    }
  }'
```

The `method` must match the final URL path segment. Method paths accept a single request; batches, duplicate `method` fields, and path/body mismatches return HTTP 400 before execution.

For local development, use `http://127.0.0.1:8784/{method}` after starting the [local stack](https://www.helius.dev/docs/privacy/endpoints.md).

## Methods

> [card] [getEncryptedUtxosByTags](https://www.helius.dev/docs/api-reference/privacy/getencryptedutxosbytags.md)
>
> Discover encrypted outputs by view tags or ring.

> [card] [getShieldedTransactionsByTags](https://www.helius.dev/docs/api-reference/privacy/getshieldedtransactionsbytags.md)
>
> Query shielded transaction history by view tags or ring.

> [card] [getShieldedTransactionsBySignature](https://www.helius.dev/docs/api-reference/privacy/getshieldedtransactionsbysignature.md)
>
> Retrieve shielded events for one Solana transaction.

> [card] [getShieldedTransactionsByNullifiers](https://www.helius.dev/docs/api-reference/privacy/getshieldedtransactionsbynullifiers.md)
>
> Find the transactions that spent supplied nullifiers.

> [card] [getMerkleProofs](https://www.helius.dev/docs/api-reference/privacy/getmerkleproofs.md)
>
> Fetch inclusion proofs for state tree commitments.

> [card] [getNonInclusionProofs](https://www.helius.dev/docs/api-reference/privacy/getnoninclusionproofs.md)
>
> Fetch non-inclusion proofs for nullifier values.

> [card] [getNullifierQueueElements](https://www.helius.dev/docs/api-reference/privacy/getnullifierqueueelements.md)
>
> Read queued nullifiers in sequence order.

> [card] [getUserRecords](https://www.helius.dev/docs/api-reference/privacy/getuserrecords.md)
>
> Look up public shielded address registrations.

## Pagination

`getEncryptedUtxosByTags`, `getShieldedTransactionsByTags`, and `getShieldedTransactionsByNullifiers` return a page in `result`:

```json theme={"system"}
{
  "jsonrpc": "2.0",
  "id": "1",
  "result": {
    "context": { "slot": 4242, "blockTime": 1730000000 },
    "data": [],
    "paginationToken": null
  }
}
```

* `data` groups results by Solana transaction, ordered by ascending slot and signature. The encrypted UTXO method uses an `outputs` array in each group; the transaction history methods use an `events` array.
* `limit` counts Solana transactions, from 1 to 1,000, and defaults to 1,000. A transaction's matching outputs or events stay together in one page.
* Pass a non-null `paginationToken` back unchanged with the same tags or nullifiers, ring, and slot filters. Continue until the response token is `null`.
* `filters.slot` accepts `gt`, `gte`, `lt`, and `lte` bounds. Supplied bounds combine with AND. After an uncapped read reaches a null token, save that page's `context.slot` and resume later with `filters.slot.gt` set to it. A read capped by `lt` or `lte` covers only slots up to that cap; resume it from the cap, not from `context.slot`.
* Set `minContextSlot` to require a minimum persisted indexer slot. The indexer also requires the slot of your `paginationToken` and of any `gt` or `gte` filter. If it is behind any of these, it returns error `-32016` with `error.data.contextSlot`; retry after it catches up.

History responses can also include `outputTreeId`, the newest unpaused state tree ID. It is omitted when unavailable. Individual outputs identify their own tree with `outputContext.treeId`.

`getNullifierQueueElements` uses sequence-based pagination; see its [method page](https://www.helius.dev/docs/api-reference/privacy/getnullifierqueueelements.md).

## Data Encoding

| Value | Encoding |
| - | - |
| Public keys, hashes, commitments, view tags, nullifiers | Base58 strings representing 32 bytes |
| Solana transaction signatures | Base58 strings representing 64 bytes |
| Ciphertext payloads, `txViewingPk`, `salt`, registry `viewingPubkey` | Base64 strings |
| `context.slot` | Highest Solana slot persisted by the indexer |
| `context.blockTime` | Block time as a Unix timestamp in seconds |

## Errors

Inspect the JSON-RPC `error` field before reading `result`, including when the HTTP status is 200.

| Code | Meaning |
| - | - |
| `-32600` | Request validation failed, a record was not found, an indexed proof root is stale, or the requested history starts before the indexed history. An unreadable request body also returns `-32600` with HTTP 400. Read `message` for the cause. |
| `-32601` | Unknown method, or a method path rejected the request before execution. Path rejections use HTTP 400. |
| `-32602` | Parameters could not be parsed, such as an invalid key encoding or a limit outside its bounds. |
| `-32603` | Internal server error. |
| `-32016` | The indexer has not reached `minContextSlot`, the pagination token's slot, or a `gt`/`gte` slot filter. |

HTTP 429 indicates rate limiting; see [rate limits](https://www.helius.dev/docs/billing/rate-limits.md). See [authentication](https://www.helius.dev/docs/api-reference/authentication.md) for API key setup.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.