Skip to content
Launch App >

The indexer tracks Merkle tree state and provides proofs for withdrawals. These endpoints are primarily used internally but available for advanced use cases.

Get the current Merkle tree state.

POST /get_merkle/{mint}/{depth}/{network}
ParameterDescription
mintToken mint address
depthTree depth (always 32)
network”mainnet” or “devnet”
{
"address": "MerkleTreeAccountAddress",
"json": {
"root": [1, 2, 3, ...],
"nextIndex": 1234,
"depth": 32
}
}
const response = await fetch(
`https://worker.turbine.cash/get_merkle/${mint}/32/mainnet`,
{ method: 'POST' }
);
const { json } = await response.json();
console.log('Current root:', json.root);
console.log('Next leaf index:', json.nextIndex);

POST /get_proof/{mint}/{depth}/{index}/{network}

Section titled “POST /get_proof/{mint}/{depth}/{index}/{network}”

Get Merkle proof for a specific leaf.

POST /get_proof/{mint}/{depth}/{index}/{network}
ParameterDescription
mintToken mint address
depthTree depth (32)
indexLeaf index
network”mainnet” or “devnet”
{
"address": "ProofAccountAddress",
"json": {
"path": [[1,2,3,...], [4,5,6,...], ...],
"indices": [0, 1, 0, 1, ...]
}
}

The proof path contains 32 sibling hashes needed to reconstruct the root.

const response = await fetch(
`https://worker.turbine.cash/get_proof/${mint}/32/${leafIndex}/mainnet`,
{ method: 'POST' }
);
const { json } = await response.json();
const proofPath = json.path;

POST /get_node/{mint}/{depth}/{index}/{network}

Section titled “POST /get_node/{mint}/{depth}/{index}/{network}”

Get a specific node from the Merkle tree.

POST /get_node/{mint}/{depth}/{index}/{network}
ParameterDescription
mintToken mint address
depthTree depth (32)
indexNode index
network”mainnet” or “devnet”
{
"address": "NodeAccountAddress",
"json": {
"value": [1, 2, 3, ...]
}
}

POST /get_nullifier/{mint}/{depth}/{network}

Section titled “POST /get_nullifier/{mint}/{depth}/{network}”

Check if a nullifier hash has been spent.

POST /get_nullifier/{mint}/{depth}/{network}
Content-Type: application/json

Body:

{
"nullifierHash": [1, 2, 3, ...]
}

Nullifier spent:

{
"address": "NullifierAccountAddress",
"json": { "spent": true }
}

Nullifier not spent:

{
"address": null,
"json": null
}
async function isNullifierSpent(
mint: string,
nullifierHash: Uint8Array,
network: string = 'mainnet'
): Promise<boolean> {
const response = await fetch(
`https://worker.turbine.cash/get_nullifier/${mint}/32/${network}`,
{
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
nullifierHash: Array.from(nullifierHash),
}),
}
);
const data = await response.json();
return data.json !== null;
}

Use CaseEndpoint
Check current tree state/get_merkle
Generate withdrawal proof/get_proof
Debug tree structure/get_node
Check before withdrawing/get_nullifier

Indexer endpoints have generous rate limits for legitimate use:

EndpointLimit
/get_merkle60/minute
/get_proof60/minute
/get_node120/minute
/get_nullifier60/minute