Skip to main content

README

Transition Period Note

During the transition period, both the Scala Indexer and Rust Indexer will be running in parallel. For the Scala-based indexer, you may see references to indexer in the URL (for example: http://indexer.node-dev-01.dev.midnight.network/api/v1/graphql). For the Rust-based indexer, references to indexer-rs may appear instead (for example: http://indexer-rs.node-dev-01.dev.midnight.network/api/v1/graphql). The plan is to maintain both endpoints until the team completes the transition to Rust.


PubSub Indexer (Scala) API Documentation

Midnight pub-sub indexer API reference - v2.3.0


Metadata API

There are 4 HTTP APIs to get information about the pub-sub indexer instance itself. These are:

  • GET /api/versions - Returns a JSON array containing the API versions that the pub-sub indexer instance supports.
  • GET /status - Returns a JSON object containing the implementation version, the git head commit hash of the pub-sub indexer instance.
  • GET /health - Always returns 200 OK with empty body.
  • GET /ready - Returns a 200 OK 'ready' when the indexer is in full sync with the Midnight node, 500 Internal Server Error with an error message otherwise.

GraphQL API

The pub-sub indexer exposes a GraphQL API for queries and subscriptions. One of the most relevant traits is that we can specify what data we want to have returned.

Up-to-date information about queries, mutations, subscriptions and their parameters and data available can be found in the API pubsub-indexer-api-schema.

In the following description of the API, Insomnia will be used to showcase the examples. There is also an insomnia file with examples that can be imported in a local setup.

Table of Contents

Queries

ProtocolHTTP
Request typePOST
URLhttp://<host>:<port>/api/<version>/graphql
HEADERSContent-Type: application/json

For GraphQL queries in Insomnia, it is required to:

  • Create a GraphQL Request
  • Set it to POST
  • Set URL to http://<host>:<port>/api/<version>/graphql. By default, host and port are localhost:8088

The version is optional and defaults to the latest available version.

Block query

ParameterTypeRequirementDescription
offset: {height}BigIntOptionalBlock height
offset: {hash}StringOptionalBlock hash
Note: Either hash or height offset would be required. If none is provided, latest block will be returned.

Blocks can be retrieved by hash, height or latest (no offset provided).

Example of block query by height

query {
block(offset: {height:3}) {
hash
height
timestamp
}
}

Response

{
"data": {
"block": {
"hash": "3",
"height": 3,
"timestamp": "2023-08-04T13:20:02.282707966Z"
}
},
"extensions": {
"queryCost": 5.0
}
}

Example of block query by hash

query {
block(offset: {hash:"0x3"}) {
hash
height
timestamp
parent {
hash
}
transactions {
hash
block {
height
parent{
hash
}
}
}
}
}

Response

{
"data": {
"block": {
"hash": "3",
"height": 3,
"timestamp": "2023-08-04T13:20:02.282707966Z",
"parent": {
"hash": "2"
},
"transactions": [
{
"hash": "Tx3",
"block": {
"height": 3,
"parent": {
"hash": "2"
}
}
}
]
}
},
"extensions": {
"queryCost": 49.0
}
}

In this example, note that we can access all the block data from the parent block. We can also get data from transactions, and since a transaction is linked to a block, we can also get information of the same block through the transaction.

Example of block query by latest

query {
block {
hash
height
timestamp
}
}

Response

{
"data": {
"block": {
"hash": "3",
"height": 3,
"timestamp": "2023-08-04T13:20:02.282707966Z"
}
},
"extensions": {
"queryCost": 5.0
}
}

Example of error response in case both block hash and height are specified

query {
block(offset: {hash:"0x3", height:3}) {
hash
height
}
}

Response

{
"data": null,
"errors": [
{
"message": "Offset must have either block hash or height and not both"
}
],
"extensions": {
"queryCost": 0.0
}
}

Transactions Query

ParameterTypeRequirementDescription
hashStringOptionalTransaction hash
identifierStringOptionalTransaction identifier
Note: one of the parameters is required

Transactions can be retrieved either by hash or by identifier:

Example of transaction query by hash

query {
transactions(hash: "Tx1") {
hash
block{
height
hash
}
identifiers
contractCalls{
__typename
address
state
}
raw
}
}

Response

{
"data": {
"transactions": [{
"hash": "Tx1",
"block": {
"height": 1,
"hash": "1"
},
"identifiers": [
"Id-Tx1"
],
"contractCalls": [
{
"__typename": "ContractCall",
"address": "0x0",
"state": "new-state"
},
{
"__typename": "ContractDeploy",
"address": "0x1",
"state": "state"
}
],
"raw": "12ffae"
}]
},
"extensions": {
"queryCost": 30.0
}
}

Example of transaction query by identifier

query {
transactions(identifier: "Id-Tx1") {
hash
block{
height
hash
}
identifiers
contractCalls{
__typename
address
state
}
raw
}
}

Response

{
"data": {
"transactions": [{
"hash": "Tx1",
"block": {
"height": 1,
"hash": "1"
},
"identifiers": [
"Id-Tx1"
],
"contractCalls": [
{
"__typename": "ContractCall",
"address": "0x0",
"state": "new-state"
},
{
"__typename": "ContractDeploy",
"address": "0x1",
"state": "state"
}
],
"raw": "12ffae"
}]
},
"extensions": {
"queryCost": 30.0
}
}

In these examples, ContractCalls can be either Call or Deploy, so the _typename is used to return the name of the type (deploy or call).

Example of error response in case both transaction hash and identifier are specified

query {
transactions(identifier: "Id-Tx1", hash: "Tx1") {
hash
raw
}
}

Response

{
"data": null,
"errors": [
{
"message": "Query must provide either hash or identifier and not both"
}
],
"extensions": {
"queryCost": 0.0
}
}

Contract Query

ParameterTypeRequirementDescription
addressStringRequiredContract address
offset: {height}BigIntOptionalHeight of block to fetch contract state from
offset: {hash}StringOptionalHash of block to fetch contract state from
transactionOffset: {identifier}StringOptionalIdentifier of transaction to fetch contract state from
transactionOffset: {hash}StringOptionalHash of transaction to fetch contract state from
Note: Either block offset or transaction offset would be required. If none is provided, latest contract state will be returned.

Contracts require an address, and it can be specified from which block/transaction we want the state, either by block hash, block height, transaction hash or transaction identifier.

Example of contract query without offset

If data related to the Deploy or the Call is required, particular data of each type must be specified

query { 
contract(address: "0x1") {
__typename
state
address
... on ContractDeploy {
address
state
definition
}
... on ContractCall {
address
state
operation
}
}
}

Response

{
"data": {
"contract": {
"__typename": "ContractCall",
"state": "new-state",
"address": "0x1",
"operation": "no-op"
}
},
"extensions": {
"queryCost": 11.0
}
}

Example of contract query with block height offset

query { 
contract(address: "0x1", offset: { height: 1 }) {
state
address
transaction {
hash
block {
hash
height
timestamp
transactions {
hash
}
}
}
}
}

Response

{
"data": {
"contract": {
"state": "new-state",
"address": "0x1",
"transaction": {
"hash": "Tx2",
"block": {
"hash": "2",
"height": 2,
"timestamp": "2023-08-04T13:20:01.231981194Z",
"transactions": [
{
"hash": "Tx2"
}
]
}
}
}
},
"extensions": {
"queryCost": 39.0
}
}

Note that we can obtain information of the transaction and through the transaction, of the block.

Example of contract query with block hash offset

query { 
contract(address: "0x1", offset: { hash: "1" }) {
state
address
transaction {
hash
block {
hash
}
}
}
}

Response

{
"data": {
"contract": {
"state": "new-state",
"address": "0x1",
"transaction": {
"hash": "Tx2",
"block": {
"hash": "2"
}
}
}
},
"extensions": {
"queryCost": 26.0
}
}

Example of contract query with transaction hash offset

query { 
contract(address: "0x1", transactionOffset: { hash: "tx-hash" }) {
state
address
transaction {
hash
block {
hash
}
}
}
}

Response

{
"data": {
"contract": {
"state": "new-state",
"address": "0x1",
"transaction": {
"hash": "Tx2",
"block": {
"hash": "2"
}
}
}
},
"extensions": {
"queryCost": 26.0
}
}

Example of contract query with transaction identifier offset

query { 
contract(address: "0x1", transactionOffset: { identifier: "tx-identifier" }) {
state
address
transaction {
hash
block {
hash
}
}
}
}

Response

{
"data": {
"contract": {
"state": "new-state",
"address": "0x1",
"transaction": {
"hash": "Tx2",
"block": {
"hash": "2"
}
}
}
},
"extensions": {
"queryCost": 26.0
}
}

Mutations

ProtocolHTTP
Request typePOST
URLhttp://<host>:<port>/api/<version>/graphql
HEADERSContent-Type: application/json

For GraphQL mutations in Insomnia, it is required to:

  • Create a GraphQL Request
  • Set it to POST
  • Set URL to http://<host>:<port>/api/<version>/graphql. By default, host and port are localhost:8088

To subscribe to wallet transactions it is required to first establish a session with the connect mutation, which will return the session ID, required for said subscription. The parameter required to obtain such id is a viewing key.

Note: at the moment it does not matter if the viewing key is valid and no filter will be applied over the transactions.

Connect

ParameterTypeRequirementDescription
viewingKeyStringRequiredViewing key to establish session formatted as a hex string
mutation {
connect(viewingKey: "12ffae")
}

Response

{
"data": {
"connect": "1CYq6ZsLmn"
},
"extensions": {
"queryCost": 2.0
}
}

Disconnect

Once the user wishes to end the session, they can use disconnect with the sessionId as parameter.

ParameterTypeRequirementDescription
sessionIdStringRequiredSession ID associated to a viewing key
mutation {
disconnect(sessionId: "bGRHs7c7kd")
}

Response

{
"data": {
"disconnect": {}
},
"extensions": {
"queryCost": 2.0
}
}

Error response in case there is no session associated to the ID

{
"data": null,
"errors": [
{
"message": "Session id '**********' not found",
"locations": [
{
"line": 2,
"column": 3
}
],
"path": [
"disconnect"
]
}
],
"extensions": {
"queryCost": 2.0
}
}

Subscriptions

Protocolws
URLws://<host>:<port>/api/version/graphql/ws
HEADERSConnection: Upgrade, Upgrade: websocket, Sec-WebSocket-Key: <random key>, Sec-WebSocket-Version: 13, Sec-WebSocket-Protocol: graphql-ws

Subscriptions require connection to a web-socket, so you can use something like websocat or as in these examples, the latest Insomnia version.

For a ws connections in Insomnia, it is required to:

  • Create a WebSocket Request
  • Set URL to ws://<host>:<port>/api/version/graphql/ws. By default, host and port are localhost:8088
  • Add header for GraphQL: Sec-WebSocket-Protocol: graphql-ws

It is then required to initialize the connection before starting a subscription:

{
"id":"1",
"type": "connection_init"
}

The expected response is that the connection was acknowledged:

{
"id": 1,
"type": "connection_ack"
}

Note: it is required to explicitly send the request. If using Insomnia, the "Connect" option provided will not initialize the connection, the request must be sent.

Once the connection has been established, subscription requests can be sent.

See this guide for more information on GraphQL and websockets.

Blocks

ParameterTypeRequirementDescription
offset: {height}BigIntOptionalHeight of block to start subscription from
offset: {hash}StringOptionalHash of block to start subscription from
Note: Either hash or height offset would be required. If none is provided, subscription will start from latest block.

Example of blocks subscription from block by height

{
"id": "1",
"type": "start",
"payload": {
"query":"subscription{blocks (offset: {height: 10}) {hash height}}"
}
}

Example of blocks subscription from block by hash

{
"id": "1",
"type": "start",
"payload": {
"query":"subscription{blocks (offset: {hash: \"10\"}) {hash height}}"
}
}

Example of blocks subscription from latest block

{
"id": "1",
"type": "start",
"payload": {
"query":"subscription{blocks {hash height}}"
}
}

Transactions

ParameterTypeRequirementDescription
offset: {hash}StringOptionalTransaction hash - subscription will start from specified transaction
offset: {identifier}StringOptionalTransaction identifier - subscription will start from transaction of specified Identifier

This subscription returns every transaction with no filtering. The data that can be retrieved should be specified the same way as in queries.

The transaction subscription also returns a progress update of synced transactions, so it must be specified if the data requested is from Transaction or ProgressUpdate (in the same fashion as with contract Calls and Deploys).

Example of transactions subscription without parameters

Since no transaction offset is specified, every transaction since the genesis block will be returned.

{
"id": "2",
"type": "start",
"payload": {
"query":"subscription{transactions {__typename ... on TransactionAdded { transaction { hash identifiers block { height hash } }}} }"
}
}

Example of transactions subscription with from transaction by hash

{
"id": "2",
"type": "start",
"payload": {
"query":"subscription{transactions (offset: {hash:\"Tx1\" }) {__typename ... on TransactionAdded { transaction { hash } }} }"
}
}

Example of transactions subscription with from transaction by identifier

{
"id": "2",
"type": "start",
"payload": {
"query":"subscription{transactions (offset: {identifier:\"Id-Tx2\" }) {__typename ... on TransactionAdded { transaction { hash } }} }"
}
}

Example of transaction subscription retuning also ProgressUpdate data

{
"id": "2",
"type": "start",
"payload": {
"query":"subscription{transactions {__typename ... on TransactionAdded { transaction { hash } } ... on ProgressUpdate {synced total}} }"
}
}

Wallet Updates

Subscribe to a wallet's merkle tree collapsed updates and transactions

ParameterTypeRequirementDescription
indexBigIntOptionalEnd index of the ZSwap Chain State in the received updates.
sessionIdStringOptionalSessionId - optionally the session id can be sent as a parameter

The user can subscribe providing an extra header instead of the sessionId parameter, following the Bearer token approach:

HeaderValue
AuthorizationBearer <sessionId>

This subscription returns a new index together with a list of either transactions associated to its viewing key, or merkle tree collapsed updates of the rest of any other transactions. The returned index should be used as index to subscribe again and resume syncing in a new subscription if needed.

The sessionId required in the parameter or Authorization header can be obtained with the connect mutation.

If both the auth header and the sessionId parameter to the wallet subscription are used, the parameter will take precedence.

Example of wallet subscription requesting state with sessionId in header

{
"id": "2",
"type": "start",
"payload": {
"query":"subscription { wallet { ... on ViewingUpdate { index update { ... on MerkleTreeCollapsedUpdate { update } ... on RelevantTransaction { transaction { hash } } } } } }"
}
}

Example of wallet subscription requesting state with sessionId as parameter

{
"id": "2",
"type": "start",
"payload": {
"query":"subscription { wallet(sessionId: \"someSessionId\") { ... on ViewingUpdate { index update { ... on MerkleTreeCollapsedUpdate { update } ... on RelevantTransaction { transaction { hash } } } } } }"
}
}

Example of wallet subscription requesting state with sessionId as parameter, and transaction offset

{
"id": "2",
"type": "start",
"payload": {
"query":"subscription { wallet(sessionId: \"someSessionId\", index: 100) { ... on ViewingUpdate { index update { ... on MerkleTreeCollapsedUpdate { update } ... on RelevantTransaction { transaction { hash } } } } } }"
}
}

Contract

If any subscription will contain offset parameter pointing to not yet indexed data, it will wait for this data to be indexed, before returning it to the caller.

ParameterTypeRequirementDescription
addressStringRequiredContract address
offset: {height}BigIntOptionalHeight of block to fetch contract state from
offset: {hash}StringOptionalHash of block to fetch contract state from
transactionOffset: {identifier}StringOptionalIdentifier of transaction to fetch contract state from
transactionOffset: {hash}StringOptionalHash of transaction to fetch contract state from
Note: Either block offset or transaction offset would be required. If none is provided, every state will be returned

The data that can be retrieved should be specified the same way as in queries.

Example for contract subscription for every state

{
"id": "2",
"type": "start",
"payload": {
"query": "subscription { contract(address: \"0x0\") {address state ...on ContractDeploy { definition } ... on ContractCall { operation }} }"
}
}

Example for contract query from block by height

{
"id": "3",
"type": "start",
"payload": {
"query": "subscription { contract(address: \"0x1\", offset: { height: 1 }) {address state} }"
}
}

Example for contract query from block by hash

{
"id": "3",
"type": "start",
"payload": {
"query": "subscription { contract(address: \"0x1\", offset: { hash: \"1\" }) {address state} }"
}
}

Example for contract query from transaction by hash

{
"id": "3",
"type": "start",
"payload": {
"query": "subscription { contract(address: \"0x1\", transactionOffset: { hash: \"tx-hash\" }) {address state} }"
}
}

Example for contract query from block by hash

{
"id": "3",
"type": "start",
"payload": {
"query": "subscription { contract(address: \"0x1\", transactionOffset: { identifier: \"tx-identifier\" }) {address state} }"
}
}

Query Limits Configuration

The pub-sub indexer exposes certain api configurations to limit query complexity in the application.conf file in the server module.

max-cost: there is a cost assigned to every field that can we requested. By default, each field requested has a cost of 1, and more complex fields have been configured to have extra cost. The extra cost can be found in the pubsub-indexer-api-schema as annotations next to the entities with said added cost. Also, responses return the cost of every query as an extension.

Error response

{
"data": null,
"errors": [
{
"message": "Query costs too much: 30.0. Max cost: 10.0."
}
],
"extensions": {
"queryCost": 30.0
}
}

max-depth: it limits the nested objects that we can have

Error response

{
"data": null,
"errors": [
{
"message": "Query is too deep: 5. Max depth: 2."
}
],
"extensions": {
"queryCost": 39.0
}
}

max-fields: limits the amount of fields we can specify

Error response

{
"data": null,
"errors": [
{
"message": "Query has too many fields: 11. Max fields: 3."
}
],
"extensions": {
"queryCost": 39.0
}
}

timeout: returns an timeout if the query is taking longer than the configured time

Error response

{
"data": null,
"errors": [
{
"message": "Query was interrupted after timeout of 1 ms:\nquery {\t\n\tcontract(address: \"0x1\", offset: { height: 1 }) { \n\t\tstate \n\t\taddress\n\t}\n}"
}
]
}

Midnight Indexer (Rust) API Documentation v1

The Midnight Indexer API exposes a GraphQL interface that enables clients to query and subscribe to blockchain data—blocks, transactions, contracts, and wallet-related events—indexed from the Midnight blockchain. These capabilities facilitate both historical lookups and real-time monitoring.

Disclaimer:
The examples provided here are illustrative and may need updating if the API changes. Always consider rust-indexer-api-schema. as the primary source of truth. Adjust queries as necessary to match the latest schema.

GraphQL Schema

The GraphQL schema is defined in rust-indexer-api-schema. It specifies all queries, mutations, subscriptions, and their types, including arguments and return structures.

Overview of Operations

  • Queries: Fetch blocks, transactions, and contract states.
    Examples:

    • Retrieve the latest block or a specific block by height/hash.
    • Look up transactions by their hash or identifier.
    • Inspect the current state of a contract at a given block or transaction offset.
  • Mutations: Manage wallet sessions.

    • connect(viewingKey: ViewingKey!): Creates a session associated with a viewing key.
    • disconnect(sessionId: HexEncoded!): Ends a previously established session.
  • Subscriptions: Receive real-time updates.

    • blocks: Stream newly indexed blocks.
    • contracts(address, offset): Stream contract state changes.
    • wallet(sessionId, ...): Stream wallet updates, including relevant transactions and optional progress updates.

API Endpoints

HTTP (Queries & Mutations):

POST http://<host>:<port>/api/v1/graphql
Content-Type: application/json

WebSocket (Subscriptions):

ws://<host>:<port>/api/v1/graphql/ws
Sec-WebSocket-Protocol: graphql-transport-ws

Core Scalars

  • HexEncoded: Hex-encoded bytes (for hashes, addresses, session IDs).
  • ViewingKey: A viewing key in hex or Bech32 format for wallet sessions.
  • ApplyStage: Enumerated stages of transaction application (e.g., Success, Failure).
  • Unit: An empty return type for mutations that do not return data.

Example Queries and Mutations

Note: These are examples only. Refer to the schema file to confirm exact field names and structures.

block(offset: BlockOffsetInput): Block

Parameters (BlockOffsetInput is a oneOf):

  • hash: HexEncoded – The block hash.
  • height: Int – The block height (number).

If no offset is provided, the latest block is returned.

Example:

Query by height:

query {
block(offset: {height: 3}) {
hash
height
timestamp
parent {
hash
}
transactions {
hash
applyStage
}
}
}

transactions(hash: HexEncoded, identifier: HexEncoded): [Transaction!]!

Fetch transactions by hash or by identifier. One of the parameters must be provided, but not both. Returns an array since a hash may map to multiple related actions.

Note: This field is deprecated in favour of a future v2/transaction query.

Example:

query {
transactions(hash: "78f3543c77c2...") {
hash
block {
height
hash
}
identifiers
raw
contractCalls {
__typename
... on ContractDeploy {
address
state
zswapChainState
}
... on ContractCall {
address
state
entryPoint
zswapChainState
}
}
}
}

contract(address: HexEncoded!, offset: ContractOffset): ContractCallOrDeploy

Retrieve the latest known state of a contract at a given offset (by block or transaction). If no offset is provided, returns the latest state.

Example (latest):

query {
contract(address: "0x1") {
__typename
address
state
zswapChainState
}
}

Example (by block height):

query {
contract(
address: "0x1",
offset: { blockOffsetInput: { height: 10 } }
) {
__typename
address
state
zswapChainState
}
}

Mutations

Mutations allow the client to connect a wallet (establishing a session) and disconnect it.

connect(viewingKey: ViewingKey!): HexEncoded!

Establishes a session for a given wallet viewing key in either bech32m or hex format. Returns the session ID.

Viewing Key Format Support

  • Bech32m (preferred): A base-32 encoded format with a human-readable prefix, e.g., mn_shield-esk_dev1...
  • Hex (fallback): A hex-encoded string representing the key bytes.

Example:

mutation {
# Provide the bech32m format:
connect(viewingKey: "mn_shield-esk1abcdef...")
}

OR

mutation {
# Provide the hex format:
connect(viewingKey: "000300386224d330...")
}

Response:

{
"data": {
"connect": "sessionIdHere"
}
}

disconnect(sessionId: HexEncoded!): Unit!

Ends an existing session.

Example:

Use this sessionId for wallet subscriptions.

When done:

mutation {
disconnect(sessionId: "sessionIdHere")
}

If the session does not exist, an error is returned.

Subscriptions: Real-time Updates

Subscriptions use a WebSocket connection following the graphql-transport-ws protocol. After connecting and sending a connection_init message, the client can start subscription operations.

Blocks Subscription

blocks(offset: BlockOffsetInput): Block!

Subscribe to new blocks. The offset parameter lets you start receiving from a given block (by height or hash). If omitted, starts from the latest block.

Example:

{
"id": "1",
"type": "start",
"payload": {
"query": "subscription { blocks(offset: {height:10}) { hash height timestamp transactions { hash } } }"
}
}

When a new block is indexed, the client receives a next message:

Contracts Subscription

contracts(address: HexEncoded!, offset: BlockOffsetInput): ContractCallOrDeploy!

Subscribes to state changes of a given contract from a specific point. New contract states (deploys, calls, updates) are pushed as they occur.

Example:

{
"id": "2",
"type": "start",
"payload": {
"query": "subscription { contracts(address:\"0x1\", offset: {height:1}) { __typename address state } }"
}
}

Wallet Subscription

wallet(sessionId: HexEncoded!, index: Int, sendProgressUpdates: Boolean): WalletSyncEvent!

Subscribes to wallet updates. This includes relevant transactions and possibly Merkle tree updates (ZswapChainStateUpdate), as well as ProgressUpdate events if sendProgressUpdates is set to true. The index parameter can be used to resume from a certain point.

Adjust index and offset arguments as needed.

Example:

{
"id": "3",
"type": "start",
"payload": {
"query": "subscription { wallet(sessionId:\"1CYq6ZsLmn\", index:100, sendProgressUpdates:true) { __typename ... on ViewingUpdate { index update { __typename ... on RelevantTransaction { transaction { hash } } } } ... on ProgressUpdate { synced total } } }"
}
}

Responses may vary depending on what is happening in the chain:

  • A ViewingUpdate with new relevant transactions or a collapsed Merkle tree update.
  • A ProgressUpdate indicating synchronization progress.

Query Limits Configuration

The server may apply limitations to queries (e.g. max-depth, max-fields, timeout, and complexity cost). Requests that violate these limits return errors indicating the reason (too many fields, too deep, too costly, or timed out).

Example error:

{
"data": null,
"errors": [
{
"message": "Query has too many fields: 20. Max fields: 10."
}
]
}

Authentication

  • Wallet subscription requires a sessionId from the connect mutation.

Regenerating the Schema

If you modify the code defining the GraphQL schema, regenerate it:

just generate-indexer-api-schema

This ensures the schema file stays aligned with code changes.

Conclusion

This document offers a few hand-picked examples and an overview of available operations. For the most accurate and comprehensive reference, consult the schema file. As the API evolves, remember to validate these examples against the schema and update them as needed.